COM+ (Component Services)

COM+ is the next step in the evolution of the Microsoft® Component Object Model and Microsoft Transaction Server (MTS). COM+ handles many of the resource management tasks you previously had to program yourself, such as thread allocation and security. It automatically makes your applications more scalable by providing thread pooling, object pooling, and just-in-time object activation. COM+ also protects the integrity of your data by providing transaction support, even if a transaction spans multiple databases over a network.

You might be interacting with COM+ for a variety of reasons. If you are a system administrator, you will be installing, deploying, and configuring COM+ applications and their components. If you are an application programmer, you will be writing components and integrating them as applications. If you are a tools vendor, you will be developing or modifying tools to work in the COM+ environment.

As described in the following table, the COM+ documentation is organized into comprehensive sections to help you quickly find the information you need.

Section | Description
COM+ Programmer's Guide | Provides information on using COM+ and Microsoft Windows® 2000 services, including information on creating a COM+ application in conjunction with other Microsoft products, including Microsoft SQL Server™ and Microsoft Internet Information Services.
Reference | Provides reference information on interfaces and objects you can use to track and manipulate security and transaction contexts, and to automate administrative tasks.
Tools Developer's Guide | Explains how to develop resource managers and other tools that provide services to COM+ applications and components.
Built on Monday, January 22, 2001


COM+ Start Page

[This is preliminary documentation and subject to change]

COM+ (Component Services)

Version 1.x

Purpose

COM+ is the next evolution of Microsoft® Component Object Model (COM) and Microsoft Transaction Server (MTS). COM+ builds on and extends applications written using COM, MTS, and other COM-based technologies. COM+ handles many of the resource management tasks that developers previously had to program, such as thread allocation and security.

Where Applicable

COM+ can be used to develop enterprise-wide, mission-critical, distributed applications based on the Microsoft Windows® 2000 operating system.

Developer Audience

COM+ is designed primarily for Microsoft Visual C++® and Microsoft Visual Basic® developers. It can also be used to manage and deploy applications.

Run-Time Requirements

COM+ ships with and requires Microsoft Windows 2000. COM+ applications can also be run on Microsoft Windows 98 and Microsoft Windows NT® clients.

See Also

COM Start Page

MTS Start Page

Guide

General information about using COM+.

Reference

Documentation of COM+ interfaces and methods.

Feedback

Make error reports and feature requests directly to Microsoft.

Built on Tuesday, August 01, 2000


What's New in COM+ 1.x

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

What's New in COM+

With this release, COM+ adds new features that are designed to increase the overall scalability, availability, and manageability of COM+ applications for both developers and system administrators. To make it easier to configure and deploy these new features, enhanced documentation and new reference topics have been added to the Platform SDK documentation and Help topics have been updated in the Component Services administrative tool.

COM+ Application Partitions

In this release, COM+ introduces support for application partitions, a feature that allows multiple versions of COM+ applications to be installed and configured on the same machine. This feature can save you the cost and time-consuming effort of using multiple servers to manage different versions of an application. On a single machine, each partition acts, in effect, as a virtual server. After installing the application into each partition, you create partition sets that map users to the logical servers. See Creating and Configuring COM+ Application Partitions for detailed information about how to set up and manage application partitions. Also, see "Administering Application Partitions" in the Component Services Administration Help for step-by-step procedures.

Process Recycling

Process recycling significantly increases the overall stability of your applications, offering a quick fix for known problems and a safeguard against unexpected ones. Because the performance of most applications can degrade over time due to factors such as memory leaks, reliance on third-party code, and nonscalable resource usage, COM+ process recycling provides a simple solution to gracefully shut down a process and restart it. See "Administering Process Recycling" in the Component Services Administration Help for detailed information.

Moving and Copying COM Components

With this release, COM+ allows you to move and copy your components. This means you can configure a single physical implementation of a component many different times. You get component reuse at a binary level rather than at the source code level, which results in less code, lower development costs, and faster time to market. For detailed information, see Moving Components and Copying Components.

Configurable Isolation Levels

COM+ developers can use the new TxIsolationLevel property or the Component Services administrative tool to configure an application's isolation level according to need, helping to increase concurrency, performance, and scalability. This flexibility enables those with the right amount of expertise to get every last ounce of throughput out of their applications.

Running COM+ Applications as NT Services

COM+ developers can now use the Component Services administrative tool to configure and implement a COM+ server application as an NT service. This means that the server can be automatically started or restarted if your application always needs to be running; that your COM+ application can run as the local system account if it needs to perform privileged operations; and that your application's dependent services can now be started automatically. See Configuring a COM+ Server Application as an NT Service for details.

Creating Private Components

In scenarios where you have several helper components in an application that are meant to be called only from other components within that application, this release of COM+ enables you to use a new property, IsPrivateComponent, to mark these components as private. (In the previous release of COM+, all components had to be public to have access to COM+ services, which means that these components could be activated from other applications.) A private component can be seen and activated only by other components in the same application, giving you more control over what functionality to expose. You need only document and maintain the public components, while making use of private components that cannot be accessed from outside the application but that can still take advantage of all COM+ services.

Low-Memory Activation Gates

With this release, Component Services automatically checks memory before creating a COM+ server or object. If the percentage of virtual memory available to the application falls below a fixed threshold, the activation fails before the object is created. By failing these activations that would normally run, the low-memory activation gates feature greatly enhances system reliability. See "Low-Memory Activation Gates" in the Component Services Administration Help for more information.

Pausing and Disabling Applications

COM+ applications are now more manageable. An administrator can pause and resume COM+ server applications or disable and enable COM+ library or server applications, or even individual configured components. Both the pausing and disabling features prevent future activations without affecting existing component instances. See "Administering COM+ Applications" in the Component Services Administration Help for more information.

Process Dumping

It's not easy troubleshooting applications in a production environment. How do you gather information on a problem without disturbing the running processes? COM+ now provides a solution through its new process dump feature. This feature allows the system administrator to dump the entire state of a process without terminating it. See "Administering the Process Dump Tool for Debugging COM+ Applications" in the Component Services Administration Help for more information.


COM+ Programming Overview

COM+ provides a single vision for creating component-based, distributed applications. It provides you with the tools to create transactional, multitier applications. COM+ combines enhancements to the Microsoft Component Object Model (COM) with a new version of the technology called Microsoft Transaction Server 2.0, along with many new services.

The COM enhancements include improvements in both threading and security, along with the introduction of Asynchronous COM. The new services include synchronization, object pooling, and queued components, as well as a new distributed application administration and packaging service (Component Services).

For those familiar with COM programming, the COM+ improvements are significant. COM+ implements a new threading model called neutral apartment threading, which allows a component to have serialized access but also execute on any thread. In addition to the threading model, COM+ provides role-based security, asynchronous object execution, and a new built-in moniker that represents a reference to an object instance running on an out-of-process server.

Role-Based Security

COM+ now supports both role-based security and process access permissions security. In the role-based security model, access to parts of an application are granted or denied based on the logical group or role to which the caller has been assigned. (Examples of roles could include administrator, developer, and clerk.) Also in the role-based security model is the ability to have security at the method, component, and interface levels. For more information on COM+ security, see Security in COM+.

Threading

COM+ includes a new threading model called neutral threading. The neutral model supports execution of objects on any thread type. The benefit of neutral apartment threading is that it does not require the developer of objects running in a neutral apartment to make the object thread safe. For more information, see Concurrency.

Object Pooling

Object pooling allows an application to create objects that can be created and pooled according to application needs. Reusing the elements in a pool of deactivated objects can save on system resources. You can pool almost any kind of object, and object pooling is easy to implement. For more information, see Object Pooling.

Queued Components

The COM+ Queued Components service allows you to create components that can execute immediately, if the client and server are connected, or that can defer execution until a connection is made, if the client and server are not connected. The Queued Components service provides key functionality for line-of-business applications built for enterprises. It augments real-time transactions with the infrastructure necessary to process asynchronous, queued transactions. This technology is effective for creating applications used by clients "in the field" and disconnected from a network; the client can enter transactions that will be executed when the client is again connected to the network. This asynchronous message queuing uses Microsoft® Windows® 2000 Messaging Services. For more information, see Queued Components.

COM+ Events

COM+ events is a component-based event system using publishers and subscribers. Publishers send events to subscribers; subscribers are identified by the publisher through subscriptions. Publishers can be any COM+ object that call an event object, and subscribers can be simple COM+ objects that implement the methods on the event interface. For more information, see COM+ Events.

Automatic Transactions

COM+ supports all Microsoft Transaction Server (MTS) 2.0 semantics and adds "Auto-done," which allows the system to automatically call SetAbort if an exception is triggered or SetComplete if not. In addition, COM+ supports components with a special environment called a context, which provides an extensible set of properties that define the execution environment for the component. For more information, see Contexts, Transaction Processing, and Just-in-Time (JIT) Activation.

Application and Component Administration

In COM+, a new registration database, named RegDB, stores the metadata that describes components. This database is highly optimized for the type of information that COM+ needs for activation of components and is used instead of the system registry. In addition, COM+ exposes a transactional, scriptable interface called the COM+ catalog, which accesses information in the RegDB. Finally, the Component Services administrative tool provides a fully scriptable user interface for developers and administrators to administer components as well as deploy both client-side and server-side multitier applications. For more information, see Deployment and Registration of COM+ Applications.


COM+ Application Overview

This section provides conceptual information on the top-down architecture of COM+ applications, including an application's components and classes and a COM component's interfaces and methods.

What Is a COM+ Application?

A COM+ application is the primary unit of administration and security for Component Services. The application is a group of COM components that, generally, perform related functions. These components further consist of interfaces and methods, as shown in the following illustration.

You can use the Component Services administrative tool to create new COM+ applications, add components to applications, and set the attributes for an application and its components.

By creating logical groups of COM components as COM+ applications, you can take advantage of the following benefits of COM+:

  • A deployment scope for COM components.
  • A common configuration scope for COM components, including security boundaries and queuing.
  • Storage of component attributes not provided by the component developer (for example, transactions and synchronization).
  • Component dynamic-link libraries (DLLs) loaded into processes (DLLHost.exe) on demand.
  • Managed server processes to host components.
  • Creation and management of threads used by components.
  • Access to the context object for resource dispensers, allowing acquired resources to be automatically associated with the context. (For more information on COM components and contexts, see Contexts.)

For more information about the kinds of COM+ applications you can create and about those included with COM+ to provide system services, see Types of COM+ Applications.

For more information on the pieces that make up a COM+ application, see Parts of a COM+ Application.

For general information on the process of building and administering COM+ applications, see Developing COM+ Applications.


Types of COM+ Applications

There are four basic types of COM+ applications:

  • Server applications
  • Library applications
  • Application proxies
  • COM+ preinstalled applications

Server Applications

A server application is a COM+ application that runs in its own process. Server applications can support all COM+ services.

Library Applications

A library application is a COM+ application that runs in the process of the client that creates it. More specifically, the components in a library application are always loaded into the process of the creator. Library applications are not explicitly associated with a server process.

Library applications can use role-based security but do not support remote access or queued components.

Application Proxies

An application proxy is a set of files containing registration information that allows a client to remotely access a server application. When run on a client computer, an application proxy file writes information about the COM+ server application—including CLSIDs, ProgIDs, RemoteServerName, and marshaling information—to the client computer. The server application can then be accessed remotely from the client computer.

COM+ Preinstalled Applications

COM+ includes a set of preinstalled applications that handle internal functions. The preinstalled applications are listed in the COM+ Applications folder in the Component Services administrative tool, but they cannot be modified or deleted. These applications include the following:

  • COM+ System Application
  • COM+ Utilities
  • IIS System Applications


Parts of a COM+ Application

COM+ applications consist of one or more COM components. This section defines the terms class, object, component, interface, and method as they are used in this guide. This section also describes configured and unconfigured components, and details the benefits of component management with COM+.

  • A COM class is a named, concrete implementation of one or more interfaces. A COM class is identified by a CLSID (sometimes a ProgID, too).
  • A COM object is an instance of a COM class.
  • A COM component is a binary unit of code that creates COM objects (which includes packaging and registration code).
  • A COM interface, which is exposed by a COM class, is a group of related functions that specifies a contract. This includes the name, interface signature, interface semantics, and marshaling buffer format. An interface is identified by an IID. The interface syntax is defined in IDL and/or type libraries. The interfaces of a COM class should be divided into manageable, cohesive sets of methods. Remember that COM interfaces are immutable; the COM contract states that they cannot be modified. Any modification (such as adding methods) requires defining a new interface.
  • A COM method, usually one of a set of related functions, is provided by a COM interface.

Configured Components

To take advantage of the services that COM+ applications support (including increased scalability, robustness, and simplified system management), the COM+ environment imposes specific requirements on COM components built for COM+ applications. When added to a COM+ application, a component is known as a configured component.

COM components built for COM+ applications are in-process server components. The component must contain a type library (.tlb file) to describe all classes implemented in the component and declare the interfaces on all classes in the component. You can create and implement these components with Microsoft® Visual Basic®, Microsoft Visual C++®, Microsoft Visual J++®, or any COM-compatible development tool. COM components built for COM+ applications can also run on non-COM+ systems.

An unconfigured component is a component that isn't installed in a COM+ application. You can transform most unconfigured components into configured components simply by integrating them into a COM+ application.


Developing COM+ Applications

When developing COM+ applications, the principal tasks include designing COM components to encapsulate application logic and integrating these components into a COM+ application, creating the COM+ application, and administering the application through deployment and maintenance.

Designing COM Components

The following steps describe a general procedure for good component design:

  1. Define the COM classes and implementation classes.
  2. Group the classes into components.
  3. Integrate the components into a COM+ application. It's good practice at this stage to select the set of COM+ services for your component, even if you do not specify all of them when developing the component. These services can later be specified using the Component Services administrative tool or COM+ administration object model.

For more detailed information on the steps in designing distributed applications, see Designing COM+ Applications.

Creating the COM+ Application

After designing the COM components, the developer integrates the components into a COM+ application and configures the application. The following steps describe the process:

  1. Integrate the components into a COM+ application. You can integrate the components into an existing COM+ application or create a new (empty) application for the components. (See Creating COM+ Applications.)
  2. Specify the correct set of attributes for each of the classes (if any, and if not specified in the development tool). These attributes express the component’s dependencies on any services its implementation might rely on (for example, transactions, queued components, security, object pooling, and just-in-time activation).
  3. Set up the security framework (roles and association of roles to classes, interfaces, and methods).
  4. Configure environment-specific attributes on classes and applications (the default object pool size, for example). These environment-specific attributes can later be set (or modified) by the system administrator.
  5. Export the application for redistribution and/or deployment.

Administering COM+ Applications

A developer typically will deliver a partially configured COM+ application to the system administrator. The administrator can then customize the application for one or more specific environments (for example, by adding user accounts in roles and server names in an application cluster). The administrator's tasks include the following:

  • Installing the partially configured COM+ application on an administrative machine.
  • Providing environment-specific attributes, such as role members and object pool size.
  • Reexporting the fully configured COM+ application.
  • Creating an application proxy (if the application is to be accessed remotely).

After an application is fully configured for a specific environment, the administrator can then deploy it on test or production machines. This involves installing the full configured COM+ application on one or more machines.

For detailed information on the administration procedures, see the Component Services Administrator's Guide.


Designing COM+ Applications

Whether you are designing an application for conducting online commerce, tracking information, accessing data in legacy systems, messaging, resource planning, publishing and knowledge management, or a critical LOB (line of business) application, you can enhance and streamline your middle-tier design by integrating COM+ services. The most common way to do this is by grouping components into COM+ applications.

While a complete methodology review for using COM+ in all situations is beyond the scope of this document, this section presents information you can use when creating a COM+ application. The following table describes the major topics included in this section:

Topic | Description
COM+ Design Assumptions and Principles | Introduces the assumptions and principles necessary to understanding how to create a distributed application using COM+.
Other Microsoft Tools for Building Distributed Applications | Suggests Microsoft technologies you can use in conjunction with COM+ when building distributed applications.
Designing the COM+ Application Using UML | Discusses the preferred design method for creating COM+ applications.
General Design Tips for Using COM+ | Presents tips on designing a COM+ application.
Optimizing Interactions with the COM+ Business Logic Tier | Covers some of the "best practices" for communication between the business logic tier and the presentation and data tiers.


COM+ Design Assumptions and Principles

The Microsoft WinDNA model consists of several technologies, including MSMQ, IIS, DCOM, and COM+. All of these services were designed for use by distributed applications.

COM+ was developed to make creating distributed applications easier. The overall architecture is based on a set of assumptions and principles.

The three assumptions are as follows:

  1. The COM+ application will support multiple users across multiple servers. In other words, you are building a distributed application, and these multiple users are going to be on different host machines from where the code runs. Users are going to access the code via the Internet or via a private network. The user interface is going to be presented via browser or perhaps a custom application, such as a form-based application written with Microsoft® Visual Basic® or MFC. That user interface is going to be located on the client machine.
  2. The COM+ application can be made scalable and can provide greater availability and reliability by deploying the application across multiple server machines. By doing this, you can balance the workload of the application and provide fault tolerance by using Windows Clustering.
  3. If things go wrong, the state of the persisted data, stored in a database, from a COM+ application will be maintained if you are using transactions. The application state must survive accidents that can occur, such as application errors, system crashes, or network failures.

In addition to these three assumptions, the following three principles pervade the COM+ programming model:

  1. The application logic will reside on server machines, not on client machines. There are three major reasons to do this:
    • The client machine may not have the processing power or features needed to run the application logic. In addition, keeping the application logic on the server simplifies deployment.
    • The server machines are often closer to the data, and this data is most often in a database. Because your application is accessing databases, you want to be very sensitive to the cost of database connections. By putting most of the logic on the server machines, you can share database connections and get a significant performance improvement. There are other resources on the server machines that can be shared as well, again with a performance benefit.
    • Having application logic reside on server machines keeps control of the security context with the application. You have more control over security if you maintain that security on application components running on server machines rather than on client machines.
  2. Transactions are the core. By design, transactions so permeate the COM+ programming model that it is very important for you to understand them. While you can make use of many of the services of COM+ without using transactions, if you choose not to use them, you cannot take full advantage of the COM+ services available to you. Some important benefits of using transactions include the following:
    • Transactions are a reasonable solution for the problem of concurrency management. Also, transactions give protection against crashes and have a good error recovery model. In addition, transactions turn out to be a great way to manage tasks across multiple systems.
    • You can design a transaction-based COM+ application to work with a resource manager and a database so that most state information is protected. By keeping state inside a database or some other storage managed by a resource manager, you don't have to keep much state inside the actual objects your application creates. While this is a departure from a pure object-oriented model, it works well for creating distributed applications with error recovery.
  3. Build your application functionality as COM objects and wrap the protocols used to communicate with other systems or technologies. Because you are probably building components that are going to stitch together several technologies or legacy systems, plan on using a variety of communication protocols. Use HTTP for client/server communication or application-to-application communication over the Internet. Use DCOM for application-to-application or component-to-component communication on the server.

See Also

Basic Guidelines for Designing COM+ Applications

Other Microsoft Tools for Building Distributed Applications

Designing the COM+ Application Using UML

General Design Tips for Using COM+

Optimizing Interactions with the COM+ Business Logic Tier


Basic Guidelines for Designing COM+ Applications

To take full advantage of COM+, there are a few basic guidelines you can use when creating an application:

  • Model your durable state as a database schema, using your database tool of choice. Almost every application needs to maintain durable state. Databases provide the services needed to create durable and scalable storage of state. Therefore, the first step in creating a COM+ application is to model the durable state of your application as some sort of database schema. It doesn't really matter what database you use; most commercial databases today talk to COM+. Microsoft® SQL Server™ is a good example of one solution you could use.
  • Model the logic of your COM+ application as a set of COM interfaces. Once you have a schema that represents the state information of the application, model the interchanges that happen in the application as COM interfaces. These interfaces will model the behavior of the application. This is also the development stage when you should determine which COM+ services work best for your application.
  • Build component DLLs that contain components that use the physical data schema and expose a logical view of the data to other components (the first item in this list), as well as components that are implemented in terms of the logical data model (the second item in this list). Once you have the structure of the logic and the state information, you can begin to write code and can now write DLL-based COM components that implement the interfaces in terms of the defined schema. Your components simply act as manipulators for working with your database information, and your component DLLs enable you build a COM+ application that works and that scales successfully.
  • Deploy the components in the COM+ environment using the COM+ services you've selected. Once you have built the application, you can then deploy the application across a network or server cluster. You can now make decisions based on resources available, and you can tailor each component for maximum performance.

See Also

COM+ Design Assumptions and Principles

Other Microsoft Tools for Building Distributed Applications

Designing the COM+ Application Using UML

General Design Tips for Using COM+

Optimizing Interactions with the COM+ Business Logic Tier


Other Microsoft Tools for Building Distributed Applications

In addition to the tools in COM+, Microsoft provides the following tools to assist the developer in creating distributed applications:

  • Microsoft® Visual Modeler—A Unified Modeling Language (UML) design tool that allows you to make a quick model of an application under development, implement it, and then refine it based on the outcome of initial tests. You can use both Visual Modeler and Microsoft Visual Basic® to "round-trip" the application, working back and forth between the model and the application tools as you model and evolve your code. For more information on UML, see Designing the COM+ Application Using UML.
  • Microsoft Data Access Components (MDAC)—Microsoft provides several avenues for retrieving data from a myriad of sources. For example, OLE DB offers a set of COM interfaces for building database components. The interfaces are defined so that data providers can implement different levels of support, based on the capabilities of the underlying data store. Because OLE DB is COM-based, it can easily be extended, and extensions are implemented as new interfaces. OLE DB also includes an application-level programming interface, called ActiveX® Data Objects (ADO). ADO exposes dual interfaces, so it can easily be used from scripting languages as well as Microsoft Visual C++®, Visual Basic, and other developer tools.

    Note Developers can also choose to use a generic, vendor-neutral API such as the Microsoft Open Database Connectivity (ODBC) application programming interface (API). The ODBC API is a C language interface for accessing data in a DBMS by using Structured Query Language (SQL). An ODBC driver manager provides the programming interface and run-time components to locate DBMS-specific drivers. ODBC drivers, typically supplied by the DBMS vendor, translate generic calls from the ODBC driver manager into calls to the native data access method. The primary advantage of using the ODBC API is that you need to learn only one API to access a wide range of DBMSs.

  • Microsoft SQL Server™—In addition to providing a robust and eloquent relational database system, Microsoft SQL Server can provide a distributed application with connection pooling and security that can integrate with the Microsoft Windows® 2000 security model.
  • COM Transaction Integration (COMTI)—COMTI can be used to integrate mainframe systems into Windows systems, including COM+ applications. COMTI uses standard communication protocols (for example, LU 6.2) for communicating between Windows 2000 and mainframe and minicomputers.

See Also

COM+ Design Assumptions and Principles

Designing the COM+ Application Using UML

General Design Tips for Using COM+

Optimizing Interactions with the COM+ Business Logic Tier


Designing the COM+ Application Using UML

Developing a successful COM+ application requires up-front application architectural design. The Unified Modeling Language (UML) is key to this design development. The UML is a modeling notation for application data and processes that combines the best practices of the software industry. Because the UML breaks the application into three views that reflect the application as well as its packaging and implementation, the modeling notation extends well to support enterprise modeling.

The UML addresses three views of the application, as follows:

  • The static view, which is modeled by information taken from user scenarios and class diagrams.
  • The dynamic view, which is modeled using sequence, collaboration, and state transition diagrams.
  • The functional view, which is the more traditional descriptive narrative using pseudocode and specifications.

The information for these views can be gathered by following three design steps that work well with the UML. Before writing a single line of code, you need to create the following models:

  • The conceptual model In the conceptual model design phase, decide what components and services are required.
  • The logical model In the logical model phase, determine which logical design tier they belong in.
  • The physical model In the physical model phase, determine where the components reside physically and how they are to be coded.

These models can then be used with UML-based CASE tools such as Microsoft® Visual Modeler. For more information on these three design models, see the following topics in this section:

  • The Conceptual Model: Application Requirements
  • The Logical Model: Application Definition and Planning
  • The Physical Model: Application Architecture

Note A full discussion of the UML and Microsoft Visual Modeler is beyond the scope of this document. For more information on these topics, see the Visual Modeler documentation that ships with Microsoft Visual Studio®.

See Also

COM+ Design Assumptions and Principles

Other Microsoft Tools for Building Distributed Applications

General Design Tips for Using COM+

Optimizing Interactions with the COM+ Business Logic Tier


The Conceptual Model: Application Requirements

When designing the conceptual model, you need to define the business problems and the functions required to solve those problems. A best-practices approach is to talk with people who will actually use the application, meet with a broad range of users, and include as many business or user scenarios as possible. Determine the identities and number of the system's potential users, as well as the size and scope of the data involved. Although gathering this information may be the least technical aspect of the design process, it is one of the most important. To develop a successful application, you need a clear understanding of the business problems and processes that need to be addressed.

While determining the application requirements, keep the following considerations in mind:

  • Performance requirements—What is the expected response time for application tasks? What failover support for down servers is needed? What are the hours of availability?
  • Environment—What servers are available? Are additional servers planned to handle any scaling requirements?
  • Deployment—How will the application integrate with a current system? What other systems will the application interact with? What operating systems do the other systems use? What communication protocols should be supported? What API can you use to interact with the other systems? Where are the other systems located on the network? What restrictions on machine use are in place? What user accounts are allowed access?
  • Location—Where is the data located in relation to the client? Is the data remotely accessed, or is it local?
  • Security—Are there encryption or integrity checking requirements? Are there authentication or data protection requirements?
  • Access rights—Are there constraints on who is allowed to perform certain operations? If so, you should first document which operations require authorization and then document the types of users who can have authorization. These requirements can have a big impact on how parts of the application are implemented.

See Also

The Logical Model: Application Definition and Planning

The Physical Model: Application Architecture


The Logical Model: Application Definition and Planning

The second step in a COM+ application design process is to break the conceptual model out into the logical tiers of the three-tier architecture: the presentation tier, or user services; the middle tier, or business services; and the data tier, or data services. If you are unfamiliar with three-tier architecture, see Using a Three-Tier Architecture Model.

Begin this process by looking through the conceptual model for nouns and verbs. The nouns can often translate into business objects (classes), and the verbs associated with them can translate into actions (methods of the classes). While it can be difficult to define all the nouns as business objects, omissions or mistakes will become obvious by the time you complete the logical model.

Most of the business objects will end up in the business services tier, with the remaining objects divided between user interface objects in the user services tier and data objects in the data services tier. When creating a logical model using the three-tier architecture, keep the following in mind:

  • Some of the nouns in the conceptual design will not represent actual physical pieces of data but may represent an action on the system or a business object's role on the system. A business object can also be a service that performs some sort of system control, such as a login ID for security.
  • Avoid creating vague business objects by "reading between the lines" in the conceptual model. Such business objects may not be correct, and you should consider them carefully before including them in the logical model. If they appear correct, add them to the conceptual model explicitly.
  • Avoid creating business objects that express the same information or function; duplication can be costly in terms of application speed and performance.
  • Determine object dependencies. Some nouns in the conceptual model may simply be attributes of other business objects. Decide if the attribute can exist independently. If so, it should become its own business object; if not, it should be combined with the appropriate business object.
  • Avoid creating business objects that try to do too much. Overloading business objects can mean more time spent separating code later and can be a maintenance headache. Distinct objects in the conceptual model should not be combined; they should remain separate business objects. You can handle any similarities by using code to delegate their common functions to a business object.
  • Remove any business objects that are not used in any usage scenarios. If the objects are intended to accommodate future growth, consider implementing them after the initial application is completed.

At this point, you can start thinking in terms of the computers and code. From these business services, determine the display and input functionality you need to provide as user services. Define what tables and stored procedures need to be provided as data services. To complete the logical model, define the interfaces for each service and include definitions of each data field and their validation rules. Also include all functions, their syntax, and their parameters.

The service or object definition should not include any aspect of the physical implementation. The intent is to provide a clear guideline for the logical component builders to work from and to enable other programmers to code pieces of the application that may use the component before it is actually completed. In the logical model design, you should document every screen, function, and object. Do not proceed to the physical model or implementation until you meet these criteria. If you proceed while the conceptual model and logical model are not in agreement, you will have serious problems later in the development cycle.

Incremental development of a COM+ application is common. This involves creating a subset of the final, known components and testing them through each layer of the application: client, business, and data tiers—through to data storage. This working model provides insight into additional requirements by the customer and implementation considerations. Often this working model is tested on a single machine.

Products like Microsoft® Visual Modeler, a Unified Modeling Language (UML) design tool, allow you to make a quick model of an application under development, implement it, and then refine it based on the outcome of initial tests. You can use both Visual Modeler and Microsoft Visual Basic® to "round-trip" the application, working back and forth between the model and the two tools as you model and evolve your code. For more information on UML, see The Unified Modeling Language.

See Also

The Conceptual Model: Application Requirements

The Physical Model: Application Architecture

Using a Three-Tier Architecture Model


Using a Three-Tier Architecture Model

The three-tier architecture model, which is the fundamental framework for the logical design model, segments an application's components into three tiers of services. These tiers do not necessarily correspond to physical locations on various computers on a network, but rather to logical layers of the application. How the pieces of an application are distributed in a physical topology can change, depending on the system requirements. Following are brief descriptions of the services allocated to each tier:

  • The presentation tier, or user services layer, gives a user access to the application. This layer presents data to the user and optionally permits data manipulation and data entry. The two main types of user interface for this layer are the traditional application and the Web-based application. Web-based applications now often contain most of the data manipulation features that traditional applications use. This is accomplished through use of Dynamic HTML and client-side data sources and data cursors.

    Note In a three-tiered application, the client-side application will be skinnier than a client-server application because it will not contain the service components now located in the middle tier. This results in less overhead for the user, but more network traffic for the system because components are distributed among different machines.

  • The middle tier, or business services layer, consists of business and data rules. Also referred to as the business logic tier, the middle tier is where COM+ developers can solve mission-critical business problems and achieve major productivity advantages. The components that make up this layer can exist on a server machine, to assist in resource sharing. These components can be used to enforce business rules, such as business algorithms and legal or governmental regulations, and data rules, which are designed to keep the data structures consistent within either specific or multiple databases. Because these middle-tier components are not tied to a specific client, they can be used by all applications and can be moved to different locations, as response time and other rules require. For example, simple edits can be placed on the client side to minimize network round-trips, or data rules can be placed in stored procedures.
  • The data tier, or data services layer, interacts with persistent data usually stored in a database or in permanent storage. This is the actual DBMS access layer. It can be accessed through the business services layer and on occasion by the user services layer. This layer consists of data access components (rather than raw DBMS connections) to aid in resource sharing and to allow clients to be configured without installing the DBMS libraries and ODBC drivers on each client.

During an application's life cycle, the three-tier approach provides benefits such as reusability, flexibility, manageability, maintainability, and scalability. You can share and reuse the components and services you create, and you can distribute them across a network of computers as needed. You can divide large and complex projects into simpler and safer projects and assign them to different programmers or programming teams. You can also deploy components and services on a server to help keep up with changes, and you can redeploy them as growth of the application's user base, data, and transaction volume increases.

See Also

The Logical Model: Application Definition and Planning


The Physical Model: Application Architecture

Once the conceptual and logical models are complete, you can make decisions on the physical implementation of the application. To create the physical model, you must understand where the various services of the application should be located and how they should be implemented. Determining where various services reside should come before how the services will be implemented.

One basic rule for determining where various services reside is this: Put the component where it is being used. If, for example, a component displays information for the base client, it should go on the user's computer. If a component validates information from the base client, it should also reside on the base client's computer. If a component updates information in a database, it should reside on the database server.

There are, of course, additional considerations that make exceptions to this rule. Performance and security issues can also dictate where a component is located. Consider the following:

  • Is a component going to change frequently, making distributing updates difficult?
  • Will the component be used by other applications, such as a common security verification component?
  • Does the component make lengthy calculations or performs functions, such as printing, that can be offloaded to a server?
  • Can the security of a component be enhanced by placing it on a server?

Properly locating components of an application can also insulate the development team from costly recoding if the system or the location of the data changes. For example, by putting the data access rules in a data layer rather than in stored procedures, the application is more easily insulated from dependence on a specific DBMS. Not only are changes confined and testing compartmentalized, but data sources can be changed and data can be distributed without fundamentally changing the application.

Finally, locating components should take advantage of system efficiencies. It is time and cost-effective to place business objects in centralized locations on the network. Objects can be shared among applications, and unit testing can be done before any components are deployed. Maintenance costs can also be decreased because rule changes occur only at a single point.

See Also

The Conceptual Model: Application Requirements

The Logical Model: Application Definition and Planning


General Design Tips for Using COM+

The key to good design is planning. If you are unfamiliar with designing a three-tier application, see the section entitled Designing the COM+ Application Using UML.

How you construct the COM components that make up the middle tier of your COM+ application can dramatically affect performance, scalability, and ease of deployment. The topics in this section, as described in the following table, provide design considerations and implementation tips you should know about when designing COM components.

Topic | Description
Designing for Scalability | Suggests ways to use Microsoft® Windows® 2000 Services to increase the scalability of your COM+ application.
Designing for Availability | Discusses Windows 2000 services you can use to improve the availability your middle-tier functionality in COM+ applications.
Designing for Security | Discusses ways to most efficiently set up security for a COM+ application.
Designing for Deployment | Discusses ways to minimize deployment headaches when designing a distributed application.

Note Also, be sure to see Improving Performance with Object Pooling for ways to most effectively use object pooling.

See Also

COM+ Design Assumptions and Principles

Other Microsoft Tools for Building Distributed Applications

Designing the COM+ Application Using UML

Optimizing Interactions with the COM+ Business Logic Tier


Designing for Scalability

Scalability is the ability of an application to service an additional load with a linear increase in resource usage. Scalability is important in any distributed application. Limits to scalability usually center around resource use and dependencies inadvertently created in the application's design. The following list describes scalability issues and suggests solutions:

  • Intramachine resources—The number of threads and memory available can limit scalability. Use a threading model that is most efficient for your application.
  • Intermachine resources—The number of available machines to distribute the application workload can affect scalability.
  • Client affinity—Two situations of affinity can be inadvertently created by an application: a situation where the application depends on state from data the client sends with its request; and a situation where the application requires a client-specific state. Avoid designing state dependency between the client and the application.
  • Server affinity—A COM+ application can limit its scalability by creating a server affinity, where the application depends on going to a particular server computer for information. This affinity can occur with many database-oriented applications. The best way to avoid a server-affinity bottleneck is to partition data onto various server computers. For example, divide customer data among servers by the most frequently accessed key, or span a customer database over several servers using the customer's last name (for example, Server1: a-f, Server2: g-m, Server3: n-z).

    Note Data partitioning can add a great deal of complexity to the programming logic and should be done only after other options to increase scalability have been tried.

  • Object lifetime—To be scalable, a COM+ application must pay close attention to the life span of objects. While an object exists, it is consuming resources. It is important to make sure that the lifetimes of objects that hold onto expensive resources are carefully managed. For high-demand objects that don't consume expensive resources, object pooling can increase scalability because you can administratively adjust it to take advantage of whatever hardware you might have. And it's a natural way to govern connections: For example, if you have a license for 20 SQL connections, you can dictate that with the Max Pool setting.
  • Application component grouping—To enhance the scalability of a COM+ application, the middle-tier components should be divided into time-dependent and time-independent services. This allows you to focus on possibly using a Microsoft® Windows® 2000 service to implement a required component action. For example, you could elect to use a Windows 2000 service such as MSMQ or Queued Components to handle time-independent, asynchronous tasks.

See Also

Designing for Availability

Designing for Security

Designing for Deployment


Designing for Availability

Availability is the ability of an application to tolerate failures in server resources. This means that the client continues to be served through the failure and that, ideally, the failure is transparent to the client. Obviously, the failure can come from either hardware or software sources, so you must develop for both cases.

Availability can be affected by the following factors:

  • Application model—For highest availability, ensure that the critical application logic is conducted using transactions. In addition, using a compensation mechanism can be effective in ensuring that resources remain in a healthy state after failures.
  • Client model—Integrate "retry on failure" logic into the client application, and strive for a graceful degradation in the application if resources or services are unavailable. Understand what the client is expecting from the application, and create a design that allows for alternatives when a failure occurs.
  • Data/state availability—For consistent access to persistent data, use Windows Clustering to provide failover support. For more information, see "Maintaining Service and Data Availability" below.
  • Service availability—You can use Network Load Balancing to load balance incoming IP requests across a cluster of servers.

See Also

Designing for Scalability

Designing for Security

Designing for Deployment


Designing for Security

Your end-to-end strategy for security obviously depends on the type of distributed application you are developing. Following are several suggestions for addressing security with respect to middle-tier application logic:

  • For efficiency and performance, authenticate as close to the user as you can. If your application involves a browser-to-business-logic-to-database architecture, consider mapping the browser clients to domain identities, run the COM+ application under identities specific to each application, and secure tables in the back end to be accessible only by a particular application identity. This trusted server scenario is more scalable and less problematic than using the back-end DBMS for authenticating.
  • If you are designing a component that will be used in a distributed application using role-based security, you can use COM+ programmatic security . This functionality allows you to call methods such as IObjectContext::IsCallerInRole and IObjectContext::IsSecurityEnabled to protect blocks of code from unauthorized access. You can also use the security call context to get information about an object's callers.
  • If you are designing a component that will be used in a distributed application without using role-based security, security is automatically checked only at the process level. Process access permissions determine who is given access to the application. If you need finer grain control over security settings at the process or at the interface level, use the programmatic security functionality provided by COM.
  • If a component using COM+ programmatic security is run without being integrated into a COM+ application, exceptions will be thrown. Therefore, if you want to ensure that such a component is also capable of being successfully integrated into an application that is not part of the COM+ environment, you must handle all exceptions appropriately.

See Also

Programming Component Security

Designing for Scalability

Designing for Availability

Designing for Deployment


Designing for Deployment

Planning the scope of COM+ applications is an important design task you should consider early on. Distributed systems that are intended to run using COM+ should be designed for deployment with the least amount of individual configuration and to most efficiently use each process. There are also techniques you can use that will enable you to achieve optimal performance when deploying a COM+ application. (For more information, see Deploying for Faster Communication.)

When viewed with the Component Services administrative tool, each COM+ application appears as a folder within which sets of components are logically grouped. While you can move individual components between COM+ application Components folders (in other words, from one application to another), several services set at the COM+ application level, such as security, may differ. These service settings can affect portability.

A COM+ Server Application Defines a Process Boundary

When you create a new COM+ server application, you are really defining a new process boundary. (Note the exception for library applications explained below.) This process becomes the controlling application instance for the components that are contained in the COM+ application. These components all run in-process in a new instance of the COM+ executable program whenever a program calls into a COM+ application for the first time. This means that all of the components within a given COM+ application's Components folder run in a single process space that serves as the DCOM server. Within the COM+ application, COM+ manages memory, coordination with the Microsoft Distributed Transaction Coordinator (DTC), just-in-time component instance activation, crash detection and recovery, and role-based security.

Calling Across COM+ Application Boundaries

Because each COM+ application normally is implemented as a separate executable, the effect of splitting a distributed application across multiple COM+ applications introduces out-of-process COM calls when components in one COM+ application call the components in another COM+ application. This introduces performance degradation due to the extra burden that marshaling COM parameters across processes imposes.

Note There is nothing inherently wrong with incurring this performance penalty; you just need to be aware that it is going to occur. Depending on the required response time, the number of users that will simultaneously request business services, and the added start-up burden that each component adds to each COM+ application, you may find that the performance hit attributable to cross-application calls is acceptable.

One possibility that eliminates the performance penalty of calling across COM+ application boundaries is to mark a given COM+ application as a library application. A COM+ library application runs in the process of the client that creates it. Of course, no performance gain has zero cost. In this case, the trade-off involves the limitations of COM+ library applications. While a library application can use role-based security, it cannot support queued components or remote access.

See Also

Deploying for Faster Communication

Designing for Scalability

Designing for Availability

Designing for Security


Deploying for Faster Communication

Performance is a key consideration when deploying a COM+ application, and component location is the key to getting the best performance from a well-designed application.

It was once widely held that with scalable application architectures, performance could be addressed by simply moving primary components of the application to faster hardware. This has proven not to be true. Performance problems arise not from individual component performance but from the links connecting components.

The primary factor for success is location. Proximity or physical location, time, capacity, and purpose are distinct types of location that apply to the deployment of a COM+ application, all of which affect performance.

The best performance comes when the application components and resources are designed and deployed to match the demands placed upon them by the application workload.

In general, you should deploy components to minimize cross-process, and especially cross-machine, communication between components. If your application design is efficient, classes within a component are grouped by use and function to maximize communications within components. In deploying components, you need to ensure that the components are logically located to make use of the relationships between the components and to reduce the amount of messaging between components.

See Also

Designing for Deployment


Optimizing Interactions with the COM+ Business Logic Tier

The architecture for a distributed application often breaks down the system into three (or more) tiers. Interactions between these tiers can dramatically affect the success of your application. This section discusses how to optimize the interactions between the business logic tier and the presentation and data tiers. See the following topics for more information:

  • Optimizing Interactions Between the COM+ Business Logic Tier and the Presentation Tier
  • Optimizing Interactions Between the COM+ Business Logic Tier and the Data Tier

See Also

COM+ Design Assumptions and Principles

Other Microsoft Tools for Building Distributed Applications

Designing the COM+ Application Using UML

General Design Tips for Using COM+


Optimizing Interactions Between the COM+ Business Logic Tier and the Presentation Tier

Typically, the latency between tiers of a distributed application differs greatly. Calls between the presentation tier and business logic tier are often an order of magnitude slower than calls between the business tier and data tier. As a result, held state is more costly when calling into the business logic tier.

The following topics in this section discuss ways to pass data between the presentation and business logic tiers.

  • Passing Parameters
  • Data Passing Options
  • Using a Factory Pattern to Pass Data

Passing Parameters

For a given set of information to be passed between the presentation tier and the business logic tier, you may have a single row, multiple rows, or a combination of a single row (such as a header) and multiple detail rows of data. The most efficient way to pass this information between tiers is by a single method call. This single call would manage the entire information set to be passed. This is necessary unless you choose to control the transaction from the presentation tier (and make all transaction treatment in the presentation tier identical in function). Microsoft does not recommend conducting transactions from the presentation tier because calls between this tier and the business logic tier are usually the slowest of any calls in a multi-tier application.

One way to create such a method is to pass single rows of information as parameters and pass multiple rows as ADO recordsets. Recordsets are the core of Microsoft's ADO data access methodology, and using ADO recordsets allows you to pass all the information related to a single transaction in one step.

Data Passing Options

There are other options to consider when passing data. These include using a list of parameters and ADO recordsets (as discussed above), just ADO recordsets, XML encoded strings, or arrays of structures. This section discusses each of these options.

The following table shows areas where extra care needs to be taken when using any of the four different argument-passing possibilities. An "X" represents areas where trade-offs need to be understood and weighed against the needs of each project. Try not to make argument-passing decisions on a per-component basis. The benefit of a consistent programming model throughout a project far outweighs the downside of optimizing on a per-method or per-component basis in all but the most extreme circumstances. The columns are described in the list that follows the table.

 | Concurrency | WAN | Deployment | Complexity
Parameters | X |  |  | X
Recordsets |  | X | X | X
XML | X |  | X | X
Arrays | X |  | X | X

The four columns define areas to watch out for when using that option to pass parameters.

  • The Concurrency column represents the need to code or provide a mechanism that manages locking conditions on update operations. Since methods that perform saves can represent updates, concurrency problems can arise.

    Two types of locking are prevalent—optimistic and pessimistic. Pessimistic locks prevent a user from getting data for update while another user has the potential for performing an update. Optimistic locking supports a great many more users by trading against the likelihood that any two users would be updating the same document at the same time. Optimistic locking calls for checking to see that the data that is stored matches the data at the point when a copy of the data was accessed for modification.

    ADO recordsets provide automatic support for optimistic locking. Update scenarios involving single row parameter lists do not provide sufficient support for concurrency checking. XML suffers from this same problem, in that no locking awareness is present in XML data.

  • The WAN column represents conditions where there may be transmission contention on a wide area network (WAN ). When the WAN does not have sufficient capacity to manage all of the data being moved at any one time, application users experience response time delays. To support optimistic concurrency, disconnected ADO recordsets pass two copies of the data from the server to the client. The second copy is used by the client to determine the smallest update row set to pass back when a change is being committed. While this cuts down on traffic from the presentation tier to the data, the extra load of the second copy can be significant. Using recordsets as the sole means of passing all information therefore causes twice as much data to be passed between tiers as is required, except when the update set is being passed back to the data tier from a presentation tier.
  • The Deployment column represents issues associated with data passing when special technology is required on both the caller and component side of the network. For example, using ADO recordsets requires ADO components to be present on both client and server. XML parsers must be present on both sides as well, to avoid having to code parsers into your applications.
  • The Complexity column is indicated for all four choices, and is a matter of preference or prior programming model experience that may be already established in your development organization. Some people find parameter passing to be cumbersome and feel it adds too much complexity to the programming problem. Keeping track of which parameter you are handling, and getting them all visible in one editing window, can create a logistical complexity that some developers find unmanageable.

The parameter-passing method also can have trade-offs, such as the following:

  • Parameters can involve managing multiple arguments and argument types as well as having to decide when it is appropriate to make a recordset a parameter.
  • ADO recordsets can cut hierarchical relationships in method parameters down to one or two arguments. This simplifies the programming model dramatically and supports adding columns at a later time, but it also hides the information hierarchy. Stuffing information into an ADO recordset and later extracting it involves knowing the names of each column or knowing the column order. This situation can add complexity for other component or application developers on the project.
  • XML is a different spin on the hidden hierarchy complication mentioned above. The programmer needs to understand the use of an XML parser to gain access to the information and often must know the names of each item in the data set before the data set can be found.
  • Arrays of structures introduce the need for a common understanding of the information being passed on the part of both caller and component. This need for a map that is shared between two system elements can lead to difficulties when dealing with different versions of components. While the method signature might not change, changes to the expected information can render calling programs incompatible.

Because the complexity issues associated with all four parameter-passing methods are so similar, it is debatable that there is a significant simplification opportunity associated with any one selection.

Using a Factory Pattern to Pass Data

One important design point is ease of use. The moment you decided to use ADO recordsets to pass a structured set of details back to the presentation tier, you introduced a complexity problem. Presentation tier programmers need to understand the structure of those recordsets. A greater complexity issue can arise when you require multiple details for a set of data to be passed in a recordset. To simplify matters, you should consider creating a recordset factory method whenever you intend to require data to be passed in structured ADO recordsets.

The recordset factory should return an empty but writable disconnected recordset to the caller. This recordset should have the proper fields (names and data types) already configured so that the calling client does not need to know how to manufacture the recordset. This approach is often referred to as the factory pattern and is a common solution pattern that solves the need to create an object of a given complexity without having to know the nuances of creating it.

Simple design choices such as choosing the same parameter name for the same piece of data across every method where that information is passed makes it easy to look at a method and know what is expected. Making sure that the order in which like arguments are passed is consistent across an entire family of methods provides a comfort point that enforces a consistent model.

See Also

Optimizing Interactions Between the COM+ Business Logic Tier and the Data Tier


Optimizing Interactions Between the COM+ Business Logic Tier and the Data Tier

The data tier often contains mostly static information—information persisted on durable media. Because this tier encompasses information that is mostly static, it requires a thorough analysis for potential bottlenecks. In addition to the obvious possibility for connection bottlenecks, hot spots can be caused by frequently accessed records, inefficient data access methods, and the need to coordinate access to legacy systems.

Connecting to the Data Tier

Two considerations play an important role in designing a data tier for a COM+ application: connection pooling and Just-in-Time (JIT) activation, and the use of DSNs. Components that make connections to the data tier should use object pooling set on the component.

When creating DSNs, use object constructor strings specified on the component instead of creating a File DSN. File DSNs are slower than a connection using an object constructor string. Object constructor strings can be specified on the component property sheet. For more information, see Using Object Constructor Strings.

If you are using components to access a SQL Server database, use COM+ object pooling instead of SQL connection pooling.

If your component is using ADO to fetch multiple recordsets, establish multiple connections for the component. When ADO retrieves multiple recordsets, it creates multiple connections in the background if you do not create them. If you create them, you can pool them and have more control over the number of the connections used.

See Also

Optimizing Interactions Between the COM+ Business Logic Tier and the Presentation Tier


COM+ Services Primer

For programmers who are new to the COM+ programming model, automatic services and the concepts governing an object's dynamic behavior at runtime might seem complex. On the contrary, COM+ provides a simple programming model for using services.

As you will see in this primer, automatic services are set as declarative attributes on components and their methods. Once you set these attributes, COM+ automatically delivers the requested service to the object as required.

About This Primer

This primer shows COM+ services in action by walking through sample component code in three defined steps. The complexity of the information builds as the steps progress. The code focuses on the simplified programming model, using transaction processing to demonstrate basic COM+ principles.

Each of the following steps illustrates a fundamental aspect of COM+ services:

  • Step 1: Creating a Transactional Component
  • Step 2: Extending a Transaction Across Multiple Components
  • Step 3: Reusing Components

For simplicity, the samples are coded in Microsoft® Visual Basic®, although other programming languages can be used.

Prerequisite Topics

The following topics provide more information on the concepts underlying COM+ services:

  • COM+ Programming Overview
  • COM+ Application Overview
  • Designing COM+ Applications
  • Creating and Configuring COM+ Applications
  • Contexts


Step 1: Creating a Transactional Component

Step 1 Objectives

In this step, you will learn the following:

  • How to write a transactional component in Microsoft® Visual Basic®
  • What are the default settings for COM+ services
  • How to configure COM+ services

Step 1 Related Topics

  • Configuring Transactions
  • Concurrency
  • Creating COM+ Applications
  • How to Set the Transaction Attribute
  • Just-in-Time (JIT) Activation

Step 1 Description

The UpdateAuthorAddress component, the component to be created in this section, updates the address of an existing author in the Pubs database. The Pubs database is a sample database that ships with Microsoft SQL Server™. It contains publishing information, including information on authors.

Note Pubs is the data store that will be used throughout this primer.

Because UpdateAuthorAddress updates a data store, it is advisable to protect the work in a transaction, as shown in the following illustration, so that when a client calls the component, COM+ will automatically start a transaction and enlist the database (resource manager) in that transaction. (For detailed information about transactions in COM+, see Transaction Processing.)

To make UpdateAuthorAddress a transactional component, two things are required:

  • The component must be written. For extra protection, a subroutine will be added, verifying that COM+ did indeed create the object in a transaction. Also, basic error handling will be included in the component to simplify error recovery. Both programming elements—transaction verification and error handling—will enhance the reliability of the component. (See Step 1 Sample Code for a complete listing of the UpdateAuthorAddress component.)
  • Next, after adding the component to a COM+ application and installing the application, the transaction attribute must be set. Setting the transaction attribute on a component defines how COM+ creates each object with regard to transactions. Transaction attribute values are: Ignored, Not Supported, Supported, Required, and Requires New. The transaction attribute value will be set to Required, which guarantees that COM+ will create each UpdateAuthorAddress object in a transaction. The Required value is not one of a component's default attribute values.

    Note The COM+ Programmers Guide provides detailed instructions on how to set the transaction attribute. See Step 1 Related Topics for links to topics containing specific instructions.

COM+ binds the transaction service with two other services: Just-in-Time Activation (JIT) and Concurrency. When you declare a component to be transactional, COM+ also enforces JIT activation and concurrency protection (synchronization).

Step 1 Sample Code

The UpdateAuthorAddress component opens a connection to the Pubs database, allowing the user to modify an author's name, address, or contract status. It also calls a second component, which will be discussed in Step 2: Extending a Transaction Across Multiple Components.

Note All the sample code in this primer is for purposes of illustration and may not be the most efficient for actual staging and production. For example, in the samples you would log in to the database as the system administrator ("sa"). This is seldom the best practice for optimum performance and security.

Option Explicit

'
'  Developer: <name>
'  Date:      <date>
'
'  Purpose:   This class is used for updating an author's address.
'
'  Notes:     IMPT:  This component implicitly assumes that it will
'             always run in a transaction. Undefined results may
'             otherwise occur.
'

'
'  VerifyInTxn
'
'  Verifies that this component is in a transaction.  Throws an
'  error if we are not.
'

Private Sub VerifyInTxn()
  If Not GetObjectContext.IsInTransaction Then
    ' Transactions turned off.
    Err.Raise 99999, "This component", "I need a transaction!"
  End If
  ' We are in a transaction.
End Sub

'
'  UpdateAuthorAddress
'
'  Procedure to update an author's address
'
Public Sub UpdateAuthorAddress(ByVal strAuthorID As String, _
                  ByVal strPhone As String, _
                  ByVal strAddress As String, _
                  ByVal strCity As String, _
                  ByVal strState As String, _
                  ByVal strZip As String)
  Dim conn As Connection
  Dim objcontext As ObjectContext
  Dim contextstate As IContextState

  ' Verify that we are in a transaction.
  VerifyInTxn

  ' Handle any errors.
  On Error GoTo UnexpectedError

  ' Get our object context.
  Set objcontext = GetObjectContext

  ' Get the IContextState object.
  Set contextstate = objcontext

  ' Validate the new address information.
  Dim oValidateAuthAddr As Object
  Dim bValidAddr As Boolean

  Set oValidateAuthAddr = CreateObject("ComplusPrimer.ValidateAuthorAddress")
  bValidAddr = oValidateAuthAddr.ValidateAuthorAddress(strAddress, strCity, _
  strState, strZip)
  If Not bValidAddr Then
    Err.Raise 99999, "The UpdateAuthorAddress component", "The address
    of the author is false!"
  End If

  ' Open the connection to the database.
  Set conn = CreateObject("ADODB.Connection")
  conn.Open "Provider=SQLOLEDB;Data Source=dbserver;Initial Catalog=pubs", "sa", "", -1

  ' Execute the query.
  conn.Execute "update authors set phone= '" & strPhone & "'" & _
               " set address= '" & strAddress & "'" & _
               " set city= '" & strCity & "'" & _
               " set state= '" & strState & "'" & _
               " set zip= '" & strZip & "'" & _
               " where au_id = '" & strAuthorID & "'"

  ' Close the connection.
  conn.Close

  ' Get rid of the connection.
  Set conn = Nothing

  ' Everything works.
  contextstate.SetMyTransactionVote TxCommit
  contextstate.SetDeactivateOnReturn True
  Exit Sub

UnexpectedError:
  ' There's an error.
  contextstate.SetMyTransactionVote TxAbort
  contextstate.SetDeactivateOnReturn True

End Sub

Step 1 Summary

  • COM+ assigns default attribute values. You can reconfigure most service attributes.
  • Setting a component's transaction attribute to Required guarantees that COM+ will create each instance of that component in a transaction but doesn't necessarily start a new transaction.
  • Verifying the presence of a transaction confirms that the component's transaction attribute value wasn't inadvertently reset to a non-transactional value, such as Ignore or Not Supported.
  • Handling errors makes your component more reliable and easier to troubleshoot.
  • COM+ enforces JIT activation and concurrency protection services for transactional components.
  • Closing the database connection as soon as you are done with it allows another component in the same transaction to reuse the connection from the connection pool. (Connection pooling should not be confused with object pooling.)

See Also

Step 2: Extending a Transaction Across Multiple Components

Step 3: Reusing Components


Step 2: Extending A Transaction Across Multiple Components

Step 2 Objectives

In this step, you will learn about the following:

  • Transaction flow
  • How multiple objects vote in a transaction

Step 2 Related Topics

  • Activation
  • Automatic Transactions Through COM+
  • IContextState

Step 2 Description

Step 1: Creating a Transactional Component shows how to write a simple transactional component that updates author information in the Microsoft® SQL Server™ Pubs database. In step 2, you'll learn what happens when a transaction is extended across multiple components.

In keeping with the COM+ programming model, UpdateAuthorAddress calls another component in the course of completing its work. The second component, ValidateAuthorAddress, validates the author's address and returns the results to its caller, UpdateAuthorAddress.

Unlike its caller, ValidateAuthorAddress does not require a transaction, but it certainly won't hurt anything if this object participates in its caller's transaction. In this step, its transaction attribute value will be set to Supported, as shown in the following illustration, which extends the existing transaction to the new object.

The Supported attribute value extends (or flows) an existing transaction only when the caller is transactional. When UpdateAuthorAddress calls ValidateAuthorAddress, COM+ first looks at the caller's context to see whether it is transactional. COM+ then looks at the service attributes that are set on ValidateAuthorAddress and assigns the new object the same transaction identifier it assigned to the caller object. To better understand this process, see Activation.

Because they share the same transaction identifier, both objects must complete their work successfully or COM+ will abort the transaction (undo any changes made to the Pubs database).

All objects participating in a transaction will vote to either commit or abort the transaction. Voting occurs explicitly when you include voting instructions in your code, as shown in the UpdateAuthorAddress component in the step 1 sample code:

  ' Everything works.
  contextstate.SetMyTransactionVote TxCommit
  contextstate.SetDeactivateOnReturn True
  Exit Sub

UnexpectedError:
  ' There's an error.
  contextstate.SetMyTransactionVote TxAbort
  contextstate.SetDeactivateOnReturn True

Voting also occurs implicitly, as is done in the ValidateAuthorAddress component. Unless the object declares otherwise, COM+ assumes an object has completed its work successfully but that it is not ready to be deactivated. COM+ makes the following assumption:

   contextstate.SetMyTransactionVote TxCommit
   contextstate.SetDeactivateOnReturn False

When ValidateAuthorAddress returns to its caller, COM+ reads its vote as a commit. COM+ doesn't count the votes until it deactivates the root object, which is the first object in the transaction—in this case, the UpdateAuthorAddress object.

Step 2 Sample Code

The ValidateAuthorAddress component makes a simple check of the author's address. Because UpdateAuthorAddress does not vote explicitly, COM+ uses the default vote settings.

Option Explicit

'
'   Developer:   <name>
'   Date:        <date>
'
'   Purpose:   This class is used for validating an author's address
'              (presumably right before updating that address in the
'              database).
'
'   Notes:   This component could be in a transaction or not; it doesn't
'            matter since we don't touch any data in a database.
'
Public Function ValidateAuthorAddress( _
                        ByVal strPhone, _
                        ByVal strAddress As String, _
                        ByVal strCity As String, _
                        ByVal strState As String, _
                        ByVal strZip As String) As Boolean

  ' Default is to validate unless we find something wrong.
  ValidateAuthorAddress = True

  '
  '  We invalidate authors who live in New York City
  '  or authors who live in Montana.
  '
  If strCity = "New York" And strState = "New York" Then
    ValidateAuthorAddress = False
  ElseIf strState = "Montana" Then
    ValidateAuthorAddress = False
  End If
  ' Done
End Function

Step 2 Summary

  • Setting a component's transaction attribute to Supported may result in the new object being created in the calling object's transaction. COM+ looks at the caller's context to determine the transactional status of the new object. If the caller is transactional, COM+ flows the transaction to the new object.
  • All objects participating in the same transaction share a common transaction identifier, which COM+ reads from the object's context.
  • Each object in a transaction votes independently of other objects. COM+ counts the votes when the root object is deactivated.
  • You can toggle an object's transaction vote between commit and abort until COM+ deactivates the object or until COM+ deactivates the root object and ends the transaction. Only the last vote setting counts. The IContextState and IObjectContext interfaces provide methods that produce similar voting results as shown in the following table below. You can use either interface to vote explicitly in a transaction.
    IContextState
    Combination Methods     		IObjectContext
    Equivalent Method
    SetMyTransactionVote = TxCommit

    SetDeactivateOnReturn = True

             SetComplete
    SetMyTransactionVote = TxCommit

    SetDeactivateOnReturn = False

             EnableCommit
    SetMyTransactionVote = TxAbort

    SetDeactivateOnReturn = True

             SetAbort
    SetMyTransactionVote = TxAbort

    SetDeactivateOnReturn = False

             DisableCommit
  • COM+ sets an object's vote to the equivalent of EnableCommit unless the component votes explicitly.
  • Voting explicitly can reduce the overall duration of the transaction and release expensive resource locks.

See Also

Step 1: Creating a Transactional Component

Step 3: Reusing Components


Step 3: Reusing Components

Step 3 Objectives

In this step, you will learn about the following:

  • Reusable components
  • How to plan for reusability

Step 3 Related Topics

  • Mapping Transaction Boundaries
  • Designing for Scalability

Step 3 Description

Step 1: Creating a Transactional Component and Step 2: Extending a Transaction Across Multiple Components show how to write one component that calls a second component to assist in completing some work, updating author information in the Microsoft® SQL Server™ Pubs database; all work is protected by a single transaction. The sample components focused on the work, namely updating an author's data and verifying the author's address, and COM+ provided the underlying services: transaction processing, JIT activation, and concurrency protection.

This step will demonstrate how to reuse the components created in the preceding two steps and look at what this means to the design of the existing components. As shown in the following illustration, this will mean creating a new component, AddNewAuthor, that adds new authors to the database by calling UpdateAuthorAddress.

In addition to reusing existing component functionality, AddNewAuthor calls another new component called ValidateAuthorName. As the preceding illustration shows, ValidateAuthorName is non-transactional. The transaction attribute value for this component is left at its default setting (Not Supported) to exclude its work from the transaction. As you'll see in the sample code, ValidateAuthorName performs read-only queries on the database, and the failure of this minor task should not have the potential to abort the transaction. However, the transaction attribute value of the AddNewAuthor component will be set to Required.

AddNewAuthor, UpdateAuthorAddress, and ValidateAuthorAddress objects all vote in the transaction. In this transaction, AddNewAuthor is the root object, not UpdateAuthorAddress. COM+ always makes the first object created in the transaction the root object.

In this example, reusing the UpdateAuthorAddress component is easy—COM+ automatically delivers the expected services. However, the results would be different if the transaction attribute value of the UpdateAuthorAddress component were initially set to Requires New, instead of Required. On the surface, both settings appear similar. Both guarantee a transaction. Requires New, however, always starts a new transaction, whereas Required starts a new transaction only when the object's caller is non-transactional. You can see from this how important it was to configure UpdateAuthorAddress carefully and thoughtfully. Otherwise, COM+ might have interpreted the service request differently, giving two unrelated transactions instead of one, as shown in the following illustration.

Important When you reuse components, make sure the services are configured to support your desired outcome.

Step 3 Sample Code

The AddNewAuthor component performs batch additions of new authors by allowing the object to remain active until the client releases its reference to the object.

Option Explicit

'
'   Developer:   <name>
'   Date:        <date>
'
'   Purpose:   This class is used for adding a new author.
'
'   Notes:    IMPT:  This component implicitly assumes that it will
'             always run in a transaction. Undefined results may
'             otherwise occur.
'
'  VerifyInTxn
'
'  Verifies that this component is in a transaction.  Throws an
'  error if we are not.
'
Private Sub VerifyInTxn()
  If Not GetObjectContext.IsInTransaction Then
    ' Transactions turned off
    Err.Raise 99999, "The AddNewAuthor component", "I need a transaction!"
  End If
  ' We are in a transaction.
End Sub

'
'  AddNewAuthor
'
Public Sub AddNewAuthor(ByVal strAuthorFirstName, _
                        ByVal strAuthorLastName, _
                        ByVal strPhone, _
                        ByVal strAddress As String, _
                        ByVal strCity As String, _
                        ByVal strState As String, _
                        ByVal strZip As String, _
                        ByVal boolContracted As Boolean)
  Dim conn As Connection
  Dim objcontext As ObjectContext
  Dim contextstate As IContextState
  Dim oUpdateAuthAddr As Object

  ' Verify that we are in a transaction.
  VerifyInTxn

  ' Handle any errors.
  On Error GoTo UnexpectedError

  ' Get our object context.
  Set objcontext = GetObjectContext

  ' Get the IContextState object.
  Set contextstate = objcontext

  ' Validate that the author is okay.
  Dim oValidateAuthName As Object
  Dim bValidAuthor As Boolean
  Set oValidateAuthName = CreateObject("ComplusPrimer.ValidateAuthorName")
  bValidAuthor = oValidateAuthName.ValidateAuthorName(strAuthorFirstName, strAuthorLastName)
  If Not bValidAuthor Then
    Err.Raise 999999, "The AddNewAuthor component", "You tried to add an author on the banned list!"
  End If

  ' Open the connection to the database.
  Set conn = CreateObject("ADODB.Connection")
  conn.Open "Provider=SQLOLEDB;Data Source=dbserver;Initial Catalog=pubs", "sa", "", -1

  ' Tell the database to actually add the author;  use empty strings
'   for this part since we will rely on the UpdateAuthorAddress
'   component to validate the address/phone/etc data.
'   Default Contract flag is off
  Dim sUpdateString As String
  sUpdateString = "insert into authors values('555-55-5555'," & _
                     strAuthorLastName & ", " & _
                     strAuthorFirstName & ", " & _
                     "'555 555-5555', '', '', '', '55555', "

  If boolContracted Then
    sUpdateString = sUpdateString + "1)"
  Else
    sUpdateString = sUpdateString + "0)"
  End If

  conn.Execute sUpdateString

  ' Close the connection; we don't need it anymore, and this will
'   potentially allow another component in the same transaction to
'   reuse the connection from the connection pool.
  conn.Close
  Set conn = Nothing

  ' Create the UpdateAuthorAddress component.
  Set oUpdateAuthAddr = CreateObject("ComplusPrimer.UpdateAuthorAddress")

  ' The component will throw an error if anything goes wrong.
  oUpdateAuthAddr.UpdateAuthorAddress "", strPhone, strAddress, strCity, strState, strZip

  Set oUpdateAuthAddr = Nothing

  ' Everything works.
  contextstate.SetMyTransactionVote TxCommit

  '  Design issue:  Do we want to allow batch additions of new
  '  authors in one transaction, or should each new author be added
  '  in a single new transaction?
  contextstate.SetDeactivateOnReturn False
  Exit Sub

UnexpectedError:
  ' There's an error.
  contextstate.SetMyTransactionVote TxAbort
  contextstate.SetDeactivateOnReturn True

End Sub

The ValidateAuthorName component validates author names before AddNewAuthor adds the name to the database. This component throws an error back to its caller if something unexpected happens.

Option Explicit

'
'   Developer:   <name>
'   Date:        <date>
'
'   Purpose:   This class is used for validating authors before
'              adding them to the database.
'
'   Notes:   This component doesn't need to be in a transaction because
'            it is performing read-only queries on the database,
'            especially since these queries are not overlapping with
'            any updates of end-user data. If an unexpected error
'            happens, we let the error go back to the caller who
'            needs to handle it.
'

Public Function ValidateAuthor(ByVal strAuthorFirstName, _
                               ByVal strAuthorLastName) As Boolean

  Dim conn As Connection
  Dim rs As Recordset

  ValidateAuthor = False

  ' Open the connection to the database.
  Set conn = CreateObject("ADODB.Connection")
  conn.Open "Provider=SQLOLEDB;Data Source=dbserver;Initial Catalog=pubs", "sa", "", -1

  ' Let's pretend we have added another hypothetical table to the Pubs
'   database, one that contains a list of banned authors whom we don't
'   want to publish for.
  Set rs = conn.Execute("select * from banned_authors")

  ' Loop thru the banned-author list looking for the specified author.
  While Not rs.EOF
    Dim flds As Fields
    If rs.Fields("FirstName") = strAuthorFirstName And _
       rs.Fields("LastName") = strAuthorLastName Then
       ' This is a banned author.
       Exit Function
    End If
    rs.MoveNext
  Wend

  ' If we get here, we didn't find the author in the banned list.
  ValidateAuthor = True
End Function

Step 3 Summary

  • There are times when you don't want a component to vote in the transaction.
  • COM+ does not enforce JIT activation or concurrency protection on non-transactional components. You may configure these services separately.
  • A calling component's configuration affects how COM+ interprets the service requests of the called component.

See Also

Step 1: Creating a Transactional Component

Step 2: Extending a Transaction Across Multiple Components


Services Provided by COM+

This section provides in-depth information about the key features of COM+. See the topics described in the following table to get more information about each feature.

Topic | Description
Contexts | Describes contexts, the foundation on which COM+ services are provided for configured components running inside of COM+ applications.
Transaction Processing | Introduces general transaction-processing theory, provides a closer look at transactions in COM+, and presents practical tips for writing transactional components.
Concurrency | Describes concurrency as it works in the context of COM+.
Security in COM+ | Provides guidance on using COM+ security features to protect COM+ applications, ranging from services you configure administratively to APIs you can call within code.
Object Pooling | Provides detailed information about object pooling, an automatic service provided by COM+ that enables you to configure a component to have instances of it kept active in a pool, ready to be used by any client that requests the component.
Just-in-Time (JIT) Activation | Provides detailed information about an automatic service provided by COM+ that can help you use server resources more efficiently, particularly when scaling up your application to do high-volume transactions.
Queued Components | Describes the COM+ Queued Components feature, based on Message Queuing Services (MSMQ), which offers an easy way to invoke and execute components asynchronously.
COM+ Events | Describes the COM+ Events feature, which extends the COM+ programming model to support late-bound events or method calls between the publisher or subscriber and the event system.
The Shared Property Manager | Describes a COM+ feature for managing shared transient state for objects.
COM+ Application Partitions | Provides detailed information about creating and using COM+ application partitions, which allow multiple versions of an application to be executed simultaneously on a single machine.
Compensating Resource Managers | Provides a brief description of the Compensating Resource Manager (CRM) feature, which offers a quick and easy way to integrate application resources with Microsoft Distributed Transaction Coordinator (MS DTC) transactions. This topic also links to more detailed information about how to use this tool.


Contexts

Contexts are new with COM+ and Microsoft® Windows® 2000. Every COM object is created with an associated context. For unconfigured components that do not use COM+ services, the context is largely ignored. But for configured components running inside of COM+ applications, contexts are the foundation on which COM+ services are provided.

A context is essentially a set of run-time properties maintained for a collection of one or more objects, and represents the smallest execution context for a component. Every COM object is associated with precisely one context as it runs (that is, between its activation and deactivation). Every context resides within precisely one COM apartment. Multiple objects can run within the same context. Multiple contexts can reside within the same apartment. (One exception is that objects aggregating the free-threaded marshaler run in every context.)

COM+ uses context properties as the basis for providing run-time services. These properties hold state that determines how the execution environment will perform services for objects within the context. In some cases, you will interact directly with an object's context properties to indicate some state relevant to a service being provided for it. For example, you do this when an object that is participating in an automatic transaction votes on the outcome of the transaction.

APIs for Interacting with Context Properties

Each context has an associated object, ObjectContext, that keeps track of its properties. You can access ObjectContext by calling CoGetObjectContext. After you have accessed ObjectContext, you can call methods on the IObjectContext interface it exposes to manipulate context properties.

For example, calling IObjectContext::SetComplete has the effect of setting the transaction consistency bit to "consistent" and the JIT activation done bit to "done" on the context associated with the object. "Consistent" signals to COM+ that you vote to commit the transaction, and "done" indicates that your object is ready to be deactivated when the method returns.

In addition to IObjectContext, other specialized interfaces providing access to context properties are IObjectContextInfo, IContextState, and IObjectContextActivity. To a certain extent, ISecurityCallContext also accesses context properties. You can use CoGetSecurityCallContext to obtain ISecurityCallContext.

Understanding Activation and Interception

Generally, you need to think about context only to the extent that it represents a number of properties, some of which you can set or get, that are used to provide COM+ services for your components. In some circumstances, however, you might need to consider the following two interrelated facets of contexts in greater detail:

  • Activation, or the initialization of an object in an appropriate context.
  • Interception, or what COM+ will do on calls across a context boundary.

Relation to MTS Context Wrappers

Contexts effectively replace the Microsoft Windows NT® MTS context wrappers. The purpose they served—providing automatic services by trapping creation requests—is now an integrated feature of COM+. As a result, you no longer need to use the SafeRef function. In MTS, SafeRef was used to obtain a reference to your object that was safe to pass outside of its context wrapper. In COM+, this is unnecessary; normal object references (this pointers) will work.

See Also

Activation

Interception of Cross-Context Calls


Activation

Every COM object is created with an associated context. This means that either a new context must be created and initialized or an appropriate existing context is used. This process is known as activation. The way activation works in COM+ is that an object either gets activated in its own context or in that of its creator (an object that has requested the object being activated—for example, by calling CoCreateInstance on it).

In some circumstances, such as with object pooling, an object is activated without being created from scratch. In this case, a running instance is activated within a context. Over its lifetime, it will be repeatedly activated in different contexts. The basic mechanism is the same in either case—an object is associated with a context and that context is properly initialized to represent the run-time needs of the object.

Flowing of Context Properties

When an object is being activated in response to a creation request from another object, COM+ needs to mediate between them to properly activate the downstream object. COM+ has to compare the context of the caller with the configuration of the called component and then decide where to activate the downstream component and how to initialize its context properties.

To discover the component's configuration, COM+ will look it up in the COM+ class registration database, which is optimized for extremely fast run-time lookups. (This is determined by how you configured a component when installing it into a COM+ application, setting attributes on it to express how it will use COM+ services.) The component's configuration is then examined against the state of the caller's context properties.

In some cases, the configuration is consistent with the context of the caller and the component can be activated within the caller's context. This can happen only if the caller's context will suffice to satisfy all of the run-time requirements of the new object.

When the downstream component cannot be activated within the caller's context, it will be activated in its own context in an appropriate apartment. When this occurs, certain context properties may flow from caller to callee. For example, if the caller is associated with a transaction and the callee supports transactions, the new object will get its own context (to vote in the transaction, it needs to have its own consistent flag) and it will inherit the caller's transactionID and activityID (which reside within the same transaction and synchronization domain).

Ignored Context Properties

Depending on how a component is configured, some context properties may play no role in determining whether it is activated in the creator's context or its own context. For example, the Transactions Disabled and Synchronization Disabled settings, indicating the presence of a transaction or a synchronization domain, will play no role whatsoever in the component's activation. These properties are fundamentally ignored when context is flowed. Or if a component uses only process-level access checking, its security context property is ignored—the component's security configuration will never play a role in its activation.

Forcing Activation in the Caller's Context

In some circumstances, you may want an object to be activated only in its caller's context—that is, never activated in its own context. This would be motivated by details of how the object would behave when it's called across a context boundary.

You can ensure that an object cannot be activated in its own context by setting the "Must be activated in caller's context" property. When you set this, if the object cannot be activated in the caller's context, CoCreateInstance will fail, returning CO_E_ATTEMPT_TO_CREATE_OUTSIDE_CLIENT_CONTEXT.

Default Context

Default contexts exist to support unconfigured components—that is, COM components not installed in COM+ applications and not registered in the COM+ class registration database. If unconfigured components have a compatible threading model, they will be activated in the caller's context. Otherwise, they are activated in a default context in the appropriate apartment. Each apartment will have a default context to support COM objects not utilizing COM+ services.

Hooking Activation

To a certain extent, you can hook activation and deactivation and perform special initialization in the new context. You can do this by implementing IObjectControl::Activate and IObjectControl::Deactivate. These methods are called by COM+ at certain points in an object's lifecycle, when it is configured to use JIT activation or object pooling. See the topics Just-in-Time (JIT) Activation and Object Pooling for more detail.

See Also

Contexts

Interception of Cross-Context Calls


Interception of Cross-Context Calls

Once an object is activated in a given context, subsequent calls to or from it, within the context, are handled differently than calls across the context boundary. Calls across context are handled with lightweight proxies. These proxies will handle whatever mediation is required to adjust the run-time environment from one that accommodates the caller to one that accommodates the callee. This process is known as interception.

Cross-context call interception is necessary because objects in different contexts have different run-time requirements—that is precisely the reason for contexts. COM will intercept any object references that you pass as method parameters and automatically convert them to proxies so that they are usable in the new context.

If you share object references across context boundaries by other means—for example, in global variables—you should always use CoMarshalInterface and CoUnMarshalInterface. These functions will translate an object reference into a proxy usable in a different context. Never share a raw object reference across context boundaries.

The behavior of calls across context can have bad consequences in the case of objects exposing interfaces that cannot be marshaled. In this circumstance, you are likely to want to insist that the object that cannot be marshaled get activated only in the context of its caller and never in its own context. You can do this by selecting the "Must be activated in caller's context" attribute for a component.

See Also

Contexts

Activation


Transaction Processing

When you purchase a book from an online bookstore, you trade money (in the form of credit) for a book. If your credit is good, a series of related operations ensures that you get the book and that the bookstore gets your money. However, if a single operation in the series fails during the exchange, the entire exchange fails. You do not get the book, and the bookstore does not get your money.

The technology responsible for making the exchange balanced and predictable is called transaction processing. Transactions ensure that resources are not permanently updated unless all operations within the transaction complete successfully. By binding a set of related operations together in a transaction that either completely succeeds or completely fails, you can vastly simplify error recovery.

The topics in this section, described in the following table, introduce general transaction processing theory, provide a closer look at transactions in COM+, and present practical tips for writing transactional components.

Topic | Description
Transaction Fundamentals | Presents basic terms and concepts.
Distributed Transactions | Briefly describes the foundation technology supporting COM+ distributed transaction processing.
Automatic Transactions Through COM+ | Introduces automatic transaction processing in COM+.
Programming Transactions | Provides practical information on writing transactional components.


Transaction Fundamentals

Although COM+ handles many of the tedious programming details associated with transaction processing, there are elements of the theory and practice that you must understand to program transactions in COM+.

The topics described in the following table cover the basic terms and concepts that apply to transaction processing.

Topic | Description
ACID Properties | Lists and describes atomic, consistent, isolated, and durable properties.
Transaction Processing System | Identifies the key elements of an end-to-end transaction processing system.
Transaction Processing Application | Presents the characteristics of a traditional transaction processing application.
Transaction Boundaries | Contrasts traditional and automatic transaction boundaries.

See Also

Distributed Transactions

Automatic Transactions Through COM+

Programming Transactions


ACID Properties

The term ACID is useful in conveying the role transactions play in mission-critical applications. Coined by transaction processing pioneers, ACID stands for atomic, consistent, isolated, and durable. These properties ensure predictable behavior, reinforcing the role of transactions as all-or-none propositions designed to reduce the management load when there are many variables.

Atomic

A transaction is a unit of work in which a series of operations occur between the BEGIN TRANSACTION and END TRANSACTION statements of an application. A transaction executes exactly once and is atomic—either all of the work is done or none of it is.

Operations within a transaction usually share a common intent and are interdependent. By performing only a subset of these operations, the system could compromise the overall intent of the transaction. Atomicity eliminates the chance of processing a subset of operations.

Consistent

Because a transaction preserves the consistency of data, transforming one consistent state of data into another consistent state of data, you can regard a transaction as a unit of integrity.

Consistency requires that data bound by a transaction be semantically preserved. Much of the responsibility for maintaining consistency falls to the application developer. Your application must enforce integrity constraints. For example, a money-transfer application should not arbitrarily move decimal points during the transfer.

Isolated

A transaction is a unit of isolation—allowing concurrent transactions to behave as though each was the only transaction running in the system.

Isolation requires that each transaction appear to be the only transaction manipulating the data store even though other transactions may be running at the same time. A transaction should never see the intermediate stages of another transaction.

Transactions attain the highest level of isolation when they are serializable. At this level, the results obtained from a set of concurrent transactions are identical to the results obtained by running each transaction serially. Because a high degree of isolation can limit the number of concurrent transactions, some applications reduce the isolation level in exchange for better throughput.

Durable

A transaction is also a unit of recovery. If a transaction commits, the system guarantees that its updates will persist even if the computer crashes immediately after the commit. Specialized logging allows the system's restart procedure to complete unfinished operations, making the transaction durable.

See Also

Transaction Processing System

Transaction Processing Application

Transaction Boundaries


Transaction Processing System

A transaction processing (TP) system consists of computer hardware and software hosting a transaction processing application to perform routine transactions necessary to conduct business. The term implies the complete system from end to end. Examples include systems that manage sales order entry, airline reservations, payroll, employee records, and shipping.

A transaction processing application leverages the features of a transaction processing system. Developing such an application is extremely complex and can be hard to scale.

To streamline application development, software vendors began producing transaction-based software specifically designed to manage system-level services. Two such product categories are database servers and TP monitors.

Database Servers

Most relational database management systems (RDBMS) provide transaction processing features. Clients call stored procedures in a database to make transaction-protected requests. Database servers work well in a two-tier client/server implementation, as long as the request volume remains low.

Transaction Processing (TP) Monitors

When you create COM+ applications to manage transactions, you are using COM+ as a TP monitor. A TP monitor is a software environment that sits between a transaction processing application and a collection of system services, such as user interface, operating system, communications, and database services. Instead of writing an application that manages each independent service, you write an application to run as part of a TP monitor environment.

COM+ supports object-based applications and automatic transactions, which are particularly suited to TP monitor environments for two reasons. First, TP monitors manage much of the system-level processing for you. When combined with automatic transactions, the effort required to program a scalable transaction-based application eases significantly, making transaction processing more practical to implement.

Second, TP monitors facilitate distributed transactions across heterogeneous databases. While some database servers support distributed transactions, their support extends only to a single database product. TP monitors, on the other hand, allow multiple database products to participate in a single transaction.

See Also

ACID Properties

Transaction Processing Application

Transaction Boundaries


Transaction Processing Application

A transaction processing application is a collection of transaction operations that automate a given business task. A person typically initiates the task, which often accesses shared data. When the task completes—either successfully or unsuccessfully—the application returns some form of result to the person.

Regardless of its size or purpose, a transaction processing application performs the following activities:

  • Collects requests to execute a transaction
  • Processes each request
  • Returns the result

A request message is a request to execute an operation. Although a person typically makes the request, this is not necessarily the case. A message can come from a factory-control system, telecommunications satellite, component object in an object-oriented application, or a bar code reader.

It is the application's job to execute the appropriate operation, based on the request message. The structure of the application depends on many factors, such as the type of transaction processing system that hosts it. Well-designed applications typically route the results of the operation execution back to the application and then to the requestor. Returning results to the requestor is neither required nor appropriate in some cases.

See Also

ACID Properties

Transaction Processing System

Transaction Boundaries


Transaction Boundaries

A transaction has a beginning, an end, and occurs exactly once. During its execution, a transaction may call on resources to accomplish one or more tasks. Each resource, such as a database or queue, falls within the boundary of the transaction. All resources within a transactional boundary share a single transaction.

You can design transactions to span processes and computers. Thus, a transactional boundary is an abstraction for managing consistency across process and computer boundaries.

In a traditional transaction processing application, you control transaction boundaries with explicit instructions to begin and end the transaction. From within one transaction boundary, you can begin a second transaction, called a nested transaction. The parent transaction does not commit until all its subordinate transactions commit.

COM+ manages transaction boundaries automatically, based on a declarative attribute that you set for each component. A transaction automatically flows to objects instructed to participate in a transaction and bypasses objects instructed to execute outside a transaction. COM+ does not support nested transactions. Instead, COM+ transactions are distinct and short-lived.

See Also

ACID Properties

Transaction Processing System

Transaction Processing Application


Distributed Transactions

When a transaction updates data on more than one networked computer, it is called a distributed transaction. Many aspects of a distributed transaction are identical to a transaction whose scope is a single database. For example, a distributed transaction provides predictable behavior by enforcing the ACID properties that define all transactions.

As you might expect, providing a transaction across multiple systems requires more coordination. Each computer participating in the transaction manages its own resources and data but also acts in concert with other computers in the transaction. Above all, a distributed transaction must commit or abort its work entirely on all participating computers.

Acting as a transaction processing monitor, COM+ reduces the complications associated with distributed transactions. For example, through the Microsoft Distributed Transaction Coordinator (MS DTC), COM+ uses the OLE Transactions protocol to coordinate transactions that span multiple networked computers. COM+ also supports transaction coordination by X/OPEN XA-compliant transaction managers.

The topics in this section, described in the following table, apply to distributed transactions.

Topic | Description
MS DTC Architecture | Describes the software elements that perform specialized tasks within a distributed transaction.
Two-Phase Commit | Describes the protocol that ensures that the outcome of a transaction is consistent across all transaction managers participating in the transaction.

See Also

Transaction Fundamentals

Automatic Transactions Through COM+

Programming Transactions


MS DTC Architecture

On Microsoft® Windows® 2000, MS DTC is a system service tightly integrated with COM+. In essence, to help make distributed transactions work more seamlessly, COM+ directs MS DTC on behalf of an application. This makes it possible to scale transactions from one to many computers without adding special code.

When a COM+ application requires a transaction that will span multiple computers, MS DTC provides it by generating a transaction ID, managing transaction-related communications, and enlisting resources. As MS DTC enlists a resource in a transaction, it extends the transaction's protection to that resource.

MS DTC architecture includes the software elements to perform specialized tasks within a distributed transaction. These include the following:

  • Transaction manager (TM)—In a distributed transaction, each computer has a local transaction manager to track incoming and outgoing transactions on that computer. MS DTC assigns one TM the additional task of coordinating all activities among local TMs. The TM that coordinates transaction activities is called the root or coordinating TM. A TM knows how to coordinate and manage transactions, but it doesn't know how to manage data.
  • Resource manager (RM)—A resource manager is a system service that manages persistent or durable data in databases, durable message queues, or transactional file system. It is the resource manager that knows how to store data and perform disaster recovery.
  • Resource dispenser—A resource dispenser manages nondurable state that can be shared. The ODBC Resource Dispenser, for example, manages pools of database connections, reclaiming each connection when it is no longer needed.

For additional information on transaction managers, resource managers, and resource dispensers, see the Tool Developer's Guide.

See Also

Distributed Transactions

Two-Phase Commit


Two-Phase Commit

Used only in distributed transactions, the two-phase commit protocol ensures that the outcome of a transaction is consistent across all transaction managers participating in the transaction. As the name suggests, the protocol operates in distinct phases to ultimately commit or abort a transaction.

Phase one evaluates the condition of each resource manager. The coordinating transaction manager (TM) communicates with each local TM to determine whether the local resource managers (RMs) are prepared to commit the transaction. To be prepared, a resource manager must guarantee that it can commit the update. Each RM responds that it can (yes) or cannot (no) guarantee its results. A transaction can commit only when all participating resources agree during phase one of the two-phase commit.

The following illustration shows a two-phase commit protocol committing a transaction.

Phase two completes the transaction. Based on the response from each RM, the coordinating TM instructs all participating resources to commit the transaction if all agree or to roll back the transaction if at least one disagrees. A transaction aborts when at least one participating resource disagrees during phase one of the two-phase commit. Regardless of the instruction (commit or abort), each RM complies and responds when it is done.

The following illustration shows a two-phase commit protocol aborting a transaction.

See Also

Distributed Transactions

MS DTC Architecture


Automatic Transactions Through COM+

In keeping with the COM+ programming model, components focus on what they do best—enabling business logic or establishing a database connection—and rely on the transaction processing framework of Microsoft® Windows® 2000 to automate transactions.

Automatic transaction processing assumes that COM components are either transaction-aware or transaction-unaware. Transaction-aware components are called transactional components. COM+ looks at the component's transaction requirement (stored as an attribute) before activating an object based on the component. (In a COM+ application, a component has several declarative attributes, including a transaction attribute. COM+ uses the transaction attribute value—unless it has been disabled—to determine the component's transactional requirement.)

Note When you declare a component to be transactional, COM+ sets support for just-in-time (JIT) activation and synchronization on the component. As long as the component remains transactional, COM+ will enforce the requirement for JIT activation and synchronization.

Transactional components can support a transaction, require a transaction, or require a new transaction, as follows:

  • By supporting a transaction, the component agrees to participate in a transaction only if its client provides one.
  • A component that requires a transaction can participate in its client's transaction. However, if the client is non-transactional, COM+ will create a transaction before activating the object.
  • A transactional component that requires a new transaction will always begin a transaction, regardless of its client's transactional status.

Any client can call a component that isn't transactional, but because COM+ activates the object instance outside a transaction boundary, none of the resources touched by the object will benefit from transaction protection. A component that is not transactional can never participate in a transaction and still incurs the overhead of context creation. In contrast, a programmer can disable a component's transaction requirement altogether and eliminate the overhead of context creation. Disabling a component's transaction requirement is useful to programmers who prefer to use the COM+ framework without making their application transactional.

The following topics in this section provide more information about automatic transactions in COM+:

  • Life Cycle of an Automatic Transaction
  • Consistency and Doneness
  • Casting a Vote
  • Setting the Transaction Flag
  • Transactional Components and State

See Also

Transaction Fundamentals

Distributed Transactions

Programming Transactions


Life Cycle of an Automatic Transaction

The life cycle of an automatic transaction is similar to the life cycle of any transaction. It begins, it does some work, and it ends. The trick is in understanding how it begins and how it ends.

Starting a Transaction

COM+ automatically begins a transaction when it encounters either of the following conditions:

  • When a non-transactional client calls a component that requires a transaction or requires a new transaction.
  • When a transactional client calls a component that requires a new transaction.

If COM+ determines that an object should have a new transaction, it begins the transaction first and then places the object in it. An overview of the process includes the following steps:

  1. COM+ creates a context object, sets JIT activation and synchronization attributes to Required, and sets the consistent and done bits. (See Consistency and Doneness for more information about each bit.)
  2. COM+ communicates with the Microsoft Distributed Transaction Coordinator (MS DTC) to begin a transaction. MS DTC coordinates the physical transaction.
  3. MS DTC generates a transaction identifier and passes it back to COM+. The transaction identifier establishes a transactional boundary. All objects participating in the transaction share the same identifier.
  4. When the client creates the object, COM+ activates it in the transactional boundary.

The first object in a transactional boundary is special to the transaction. This object is called the root of the transaction. There can be only one root object in a transaction. All other objects in the transactional hierarchy under the root object are called interior objects.

Ending a Transaction

COM+ ends a transaction—by committing or aborting it—when one of the following conditions occurs:

  • The transaction exceeds its time-out threshold. COM+ transactions will abort automatically if not committed within the transaction time-out period, deactivating all objects associated with the transaction. The transaction time-out default is 60 seconds.
  • The root object of the transaction completes its work, and COM+ releases it. After the root object deactivates, the transaction attempts to commit.
  • The client releases the root object. Without a reference, the root object deactivates and the transaction attempts to commit.

See Also

Automatic Transactions Through COM+

Consistency and Doneness

Casting a Vote

Setting the Transaction Flag

Transactional Components and State


Consistency and Doneness

COM+ always creates a context before activating a transactional object. The context holds object-related information, such as its creator and its transaction identifier. Each context also contains consistent and done bits. Together these bits determine status of the object. You set these bits indirectly through methods exposed by the IObjectContext and IContextState interfaces.

The consistent bit indicates that the object is either consistent or inconsistent. The specific details of what makes an object's state consistent is up to the programmer. When a method call sets this bit to True, the object is consistent. False indicates that the object is inconsistent. COM+ sets the bit to True when it creates an object instance. A consistent object is ready to move forward with the transaction.

The done bit determines how long the object hangs around after finishing its work and can affect the duration of a transaction. When a method call returns, COM+ inspects the done bit. If the method sets this bit to True, COM+ deactivates the object and notes the consistent bit. COM+ neither deactivates the object nor notes the consistent bit when the done bit is False. Thus, while an object remains active, subsequent method calls can switch the consistent bit to True and False. COM+ sets the done bit to False when it creates an object instance.

See Also

Automatic Transactions Through COM+

Life Cycle of an Automatic Transaction

Casting a Vote

Setting the Transaction Flag

Transactional Components and State


Casting a Vote

The consistent bit casts a vote to commit or abort the transaction in which it executes, and the done bit finalizes the vote. COM+ inspects the consistent bit when the done bit is set to True on a method call return or when the object deactivates. Although an object's consistent bit can change repeatedly within each method call, only the last change counts.

You can set the consistent and done bits by invoking methods on either the IObjectContext or IContextState interfaces. The strategies used by these two interfaces differ significantly. IObjectContext methods bind the consistent and done bits together in unique combinations. The following table provides a description of each method.

IObjectContext Method | Consistent Bit | Done Bit
SetComplete | True | True
SetAbort | False | True
EnableCommit (default) | True | False
DisableCommit | False | False

For independent control of each bit, IContextState provides a method to set the consistent bit to True or False and a method to set the done bit to True or False. These methods are SetMyTransactionVote and SetDeactivateOnReturn, respectively. The IContextState interface also includes methods to retrieve the current value of each bit.

One configuration property can affect how you cast a vote: the auto-done property, which is set at the method level. This feature can simplify the process of casting a vote. For more information regarding auto-done, see Enabling Auto-Done for a Method and Setting the Done Bit.

See Also

Automatic Transactions Through COM+

Life Cycle of an Automatic Transaction

Consistency and Doneness

Setting the Transaction Flag

Transactional Components and State


Setting the Transaction Flag

An object's consistency affects the Transaction flag, which governs the entire transaction. COM+ sets the Transaction flag to false at the beginning of a transaction. False indicates that the transaction should attempt to commit. True causes the transaction to abort. Any object executing within a transaction can change the flag from False to True by calling IObjectContext::SetAbort.

Because the Boolean value is a little confusing, the Transaction flag is sometimes called the Doomed flag. The flag may be said to ask the question, "Is the transaction doomed to fail?" If the answer is "False," the transaction will attempt to commit. If the answer is "True," the transaction will abort. The flag remains false until an object within the transaction boundary deactivates in an inconsistent state (consistency = False) and sets the Transaction flag to True, which dooms the transaction. Once an object votes to doom the transaction by setting the transaction flag to True, the transaction can never commit.

COM+ inspects the Transaction flag when the root object returns control to its client or when the root object deactivates. Although the transaction flag can request that COM+ commit the transaction, there is no guarantee that MS DTC can do so. Other factors besides the transaction flag can doom a transaction to failure.

See Also

Automatic Transactions Through COM+

Life Cycle of an Automatic Transaction

Consistency and Doneness

Casting a Vote

Transactional Components and State


Transactional Components and State

COM+ helps manage state by tying the life of the root object to the life cycle of the transaction. Transactional objects live within a transaction boundary. A root object initiates the transaction and then goes on to create interior objects within the running transaction. After the transaction terminates, COM+ deactivates all objects associated with a transaction, eliminating all acquired state as part of the cleanup process. By eliminating the state of each transactional component, COM+ enforces transactional isolation and consistency.

See Also

Automatic Transactions Through COM+

Life Cycle of an Automatic Transaction

Consistency and Doneness

Casting a Vote

Setting the Transaction Flag


Programming Transactions

As a general rule, any component that updates persistent state should support transactions. Components that combine the operations of two or more objects into a single task should use transactions to simplify error recovery. Also, to release resources, such as database connections, transactions in COM+ should be as short as you can make them.

Transactions are automatic in COM+. You are responsible for creating and configuring objects that participate in automatic transactions.

The topics in this section, described in the following table, discuss specific programming considerations related to transaction processing.

Topic | Description
Mapping Transaction Boundaries | Provides a guide for selecting transaction attribute values.
Creating Transactional Objects | Shows how to create objects that participate in a transaction.
Calling SetComplete | Identifies how and when to use the SetComplete method exposed by the IObjectContext interface.
Handling Errors in Transactions | Describes basic error handling techniques for automatic transactions.
Using the IContextState Interface | Shows how to use the IContextState interface to influence the outcome of a transaction.
Using the Transaction Context Object | Describes how to use the generic transaction object to begin and end a transaction manually.
Limitations of the Transaction Context Object | Describes the implementation constraints incurred when using the transaction context object.

See Also

Transaction Fundamentals

Distributed Transactions

Automatic Transactions Through COM+


Mapping Transaction Boundaries

One way to ensure that an object participates in the right transaction is to map the transaction boundaries. By mapping transaction boundaries, you can determine the best setting for each component you write. The more certain you are about how your components will be used, the easier it will be to select the correct transaction attribute value.

At run time, COM+ looks at the transaction attribute to determine whether an object should be the root of a new transaction, be created in an existing transaction, or be created as a non-transactional object. A visual map shows you how a transaction flows (or fails to flow) among objects.

Mapping transaction boundaries should be straightforward—typically less complex than the example shown in the following illustration.

The transaction map in the preceding illustration shows two potential problem areas. First, the majority of work is split between two distinct transactions. If Transaction 1 fails after Object 4 calls Object 6, Transaction 2 will run unaffected by the outcome of Transaction 1. You might prefer to fold the operations of both transactions into a single transaction, which you can accomplish by changing the transaction attribute of Object 6 to Required.

The example map also shows that Object 3 and Object 5 are non-transactional, running completely outside the scope of Transactions 1 and 2. If Object 5 updates persistent data, you might reconsider its non-transactional status.

See Also

Programming Transactions

Creating Transactional Objects

Calling SetComplete

Handling Errors in Transactions

Using the IContextState Interface

Using the Transaction Context Object

Limitations of the Transaction Context Object


Creating Transactional Objects

Transactional components typically use other components to perform tasks. Some tasks might require transaction protection, and others might not. A component that extends its caller's transaction causes the transaction to flow from the caller object to the newly created object.

COM+ always places the first object, or root object, of a transaction within a new transactional boundary. A transaction can have only one root object, and COM+ automatically designates it. Any object that requires a transaction can be the root. Objects that require a new transaction are always the root of the transaction.

A transaction flows from the root object to an interior object, based on the interior object's transaction attribute setting. Prior to COM+ 1.0, an object had to call the CreateInstance method of the IObjectContext interface to flow the transaction to an interior object. While this method still works, it is no longer necessary.

In COM+, you use the standard creation function CoCreateInstance (or the CreateObject function in Microsoft® Visual Basic®) to flow a transaction to interior objects as appropriate.

The following example shows how to create an interior object from within a transactional object:

Sub MyObjMethod1()
  Dim InteriorObj1 As Cinterior  'Cinterior is a user-defined object.
  Set InteriorObj1 = CreateObject ("MyDll.Cinterior")
End Sub

In COM+, as opposed to MTS, you can create the object without first getting the object context.

See Also

Programming Transactions

Mapping Transaction Boundaries

Calling SetComplete

Handling Errors in Transactions

Using the IContextState Interface

Using the Transaction Context Object

Limitations of the Transaction Context Object


Calling SetComplete

To use automatic transactions effectively, each transactional component should indicate that it has completed its work. When an object instance completes its task successfully, it should set its consistent bit to True and its done bit to True by calling the SetComplete method of the IObjectContext interface.

The following example shows how to indicate that a transactional object has completed its work successfully:

Sub MyObjMethod1()
  Dim ObjCtx As ObjectContext
  Dim InteriorObj1 As Cinterior  'Cinterior is a user-defined object.

  Set ObjCtx = GetObjectContext()
  Set InteriorObj1 = CreateObject ("MyDll.Cinterior")
  InteriorObj1.Method1
  ' If the call completed successfully, then...
  objCtx.SetComplete
End Sub

The most efficient way to terminate an automatic transaction is to explicitly deactivate the root object using the SetComplete method. By explicitly indicating that a root object has completed its work, you can reduce the length of the transaction.

For more information on how the consistent and done bits determine the status of an object, see Consistency and Doneness.

See Also

Programming Transactions

Mapping Transaction Boundaries

Creating Transactional Objects

Handling Errors in Transactions

Using the IContextState Interface

Using the Transaction Context Object

Limitations of the Transaction Context Object


Handling Errors in Transactions

When an object method fails, the object should set its consistent bit to False and its done bit to True by calling the SetAbort method of the IObjectContext interface. By calling the SetAbort method, an object returns control to its caller and sets the transaction flag to true to doom the transaction.

Unless the object calling IObjectContext::SetAbort is the root of the transaction, the transaction itself continues to run even though nothing can save it from eventually aborting. To speed up the end of a failed transaction, you can raise an error to alert the root object to also call SetAbort. For completion, the root object should then send an error message to its client.

While there are many different approaches you can take to handle errors, your approach should clearly coordinate the communications between interior objects and the root object.

The following code fragments show one approach to error handling. In the first fragment, an interior object calls SetAbort, raises an error, and generates an error message:

Dim ObjCtx As ObjectContext
Dim ErrorCode As Long, Description As String

Set ObjCtx = GetObjectContext()
ObjCtx.SetAbort
ErrorCode = vbObjectError + 5
Description = "Some meaningful message"
Err.Raise ErrorCode, , Description

In the second fragment, the root object handles the error and passes the message to its client:

Sub MyObjMethod1()
  On Error GoTo MyObjMethod1_err
  Dim ObjCtx As ObjectContext
  Dim InteriorObj1 As Cinterior

  Set ObjCtx = GetObjectContext()
  Set InteriorObj1 = CreateObject ("MyDll.Cinterior")
  InteriorObj1.Method1
  ' If the call completed successfully, then...
  ObjCtx.SetComplete
Exit Sub
  MyObjMethod1_err:
  ' Doom the transaction and exit now.
  ObjCtx.SetAbort
  ' Pass the message back to client.
  Err.Raise Err.Number, , Err.Description
End Sub

See Also

Programming Transactions

Mapping Transaction Boundaries

Creating Transactional Objects

Calling SetComplete

Using the IContextState Interface

Using the Transaction Context Object

Limitations of the Transaction Context Object


Using the IContextState Interface

You can set the consistent and done bits by using methods exposed by the IContextState interface, which sets each bit independently of the other. The following example shows how to use IContextState methods to set the consistent bit to False and the done bit to True, producing the same semantic results as using the IObjectContext::SetAbort method:

Dim IObjCtxState As IContextState
Set IObjCtxState = GetObjectContext()
IObjCtxState.SetDeactivateOnReturn True
IObjCtxState.SetMyTransactionVote txAbort
Set IObjCtxState = Nothing

In addition to providing finer control of the consistent and done bits, the IContextState interface provides two useful features for transactions.

First, when you set the IContextState::SetMyTransactionVote method value to txCommit, COM+ verifies the presence of a transaction. If COM+ does not detect a transaction, it generates an error that you can capture in a log file. Suppose someone inadvertently configures your component's transaction attribute to Not Supported, but you expected it to be set to Required. By setting the value to Commit with the SetMyTransactionVote method, you can identify the conflict and take action.

Second, with the IContextState::GetMyTransactionVote method, you can look at the current status of the consistent bit. While the consistent bit can change with each method call and becomes final only when COM+ releases the object, this method gives you an opportunity to preview an object's vote before it really counts.

See Also

Programming Transactions

Mapping Transaction Boundaries

Creating Transactional Objects

Calling SetComplete

Handling Errors in Transactions

Using the Transaction Context Object

Limitations of the Transaction Context Object


Using the Transaction Context Object

The transaction context object is a generic object that allows non-transactional clients to combine the work of multiple COM objects into a single transaction, without your having to develop a new component specifically for that purpose. In contrast to an automatic transaction, the transaction context object requires its client to explicitly commit or abort the transaction.

The transaction context object's methods use its context object as follows:

  • CreateInstance—Calls the CreateInstance method exposed by the IObjectContext interface and returns a reference to the newly created object.

  • Commit—Calls the SetComplete method exposed by the IObjectContext interface and returns.

  • Abort—Calls the SetAbort method exposed by the IObjectContext interface and returns.

By default, the transaction attribute value of the transaction context object is set to Required. COM+ aborts the transaction if the client releases the transaction context object without explicitly issuing a commit or abort call.

You cannot use the transaction context object to enlist in an existing transaction. For example, suppose you have two components, Walk and ChewGum. Each component is defined as supporting transactions, and each calls IObjectContext::SetComplete when it is finished with its work. A non-transactional client can compose the work done by each component in a single transaction, as follows:

Dim objTxCtx As TransactionContext
Dim objWalk As MyApp.Walk
Dim objChewGum As MyApp.ChewGum

' Get TransactionContext.
Set objTxCtx = _
  CreateObject ("TxCtx.TransactionContext")

' Create instances of Walk and ChewGum.
Set objWalk = _
  objTxCtx.CreateInstance ("MyApp.Walk")
Set objChewGum = _
  objTxCtx.CreateInstance ("MyApp.ChewGum")

' Both components do work.
objWalk.Walk
objChewGum.ChewGum

' Commit the transaction.
objTxCtx.Commit

See Also

Programming Transactions

Mapping Transaction Boundaries

Creating Transactional Objects

Calling SetComplete

Handling Errors in Transactions

Using the IContextState Interface

Limitations of the Transaction Context Object


Limitations of the Transaction Context Object

When using a transaction context object, the application logic that composes the work into a single transaction is tied to a specific non-transactional client implementation and the advantages of using COM components are lost. These advantages include the following:

  • Ability to reuse the application logic as part of an even larger transaction
  • Imposition of declarative security
  • Flexibility to run the logic remotely from the client

Location Transparency Limitations

The transaction context object runs in-process with the non-transactional client, which means that COM+ must exist on the non-transactional client computer. This may not be a problem, for example, when the transaction context object is used from an Active Server Pages (ASP) page that is running on the same server as COM+.

Client Does Not Have Context

You do not get a context for the non-transactional client when you create a transaction context object. Transactional work can only be done indirectly, through COM objects created by using the transaction context object. In particular, the non-transactional client cannot use COM+ resource dispensers (such as ODBC) and have the work included in the transaction. For example, developers may be familiar with the following syntax for doing transactional work on relational database systems:

BEGIN TRANSACTION
  DoWork
COMMIT TRANSACTION

Using the transaction context object in a similar way does not yield the desired result:

Set objTxCtx = CreateObject ("TxCtx.TransactionContext")
  DoWork
  objTxCtx.Commit
Set objTxCtx = Nothing

The call to DoWork in this example will not be enlisted in a transaction. You must build a COM component that calls DoWork, create an object instance of that component using the transaction context object, and then call that object from the non-transactional client for the work to be part of the client-controlled transaction.

See Also

Programming Transactions

Mapping Transaction Boundaries

Creating Transactional Objects

Calling SetComplete

Handling Errors in Transactions

Using the IContextState Interface

Using the Transaction Context Object


Concurrency

COM+ divides a process into contexts, which are collections of objects with the same requirements. Processes often contain more than one context to separate objects with different requirements from each other. Each context in a process has a unique COM object, called the object context, which provides various services such as transaction processing and Just-in-Time (JIT) activation. To access an object's context, call CoGetObjectContext. For additional information on using contexts, see Contexts.

An apartment is a collection of contexts contained in a process, as shown in the following illustration.

A context is the smallest execution context for a component. It is essentially a set of run-time properties maintained for a collection of one or more objects. Every COM object is associated with precisely one context for its lifetime; every context resides within precisely one COM apartment. Multiple objects can run within the same context; and multiple contexts can reside with the same apartment. There can be multiple apartments with an apartment containing one or more contexts.

To manage concurrency in COM+, apartments associate specific threads in the process to particular contexts, as shown in the following illustration.

While apartments determine which threads are dispatched to the object, setting the synchronization attribute controls when these calls are dispatched. An activity groups one or more contexts with the same concurrency requirements. Activities span more than a single context and object, but while each context in a process belongs to just one activity, some contexts do not belong to any activity. If the context does not belong to an activity, any thread in the apartment can enter the context at any time. If the apartment is a single-threaded apartment, only one thread can enter. In the case of a neutral apartment or multithreaded apartment, there can be concurrent access to the context.


Components and Threading

COM+ manages threads for you. Every COM+ component has a ThreadingModel registry attribute that you can specify when you develop the component. This attribute determines how the component's objects are assigned to threads for method execution. You can use the Component Services administrative tool to view the threading-model attribute by right-clicking a component in the Components folder, clicking Properties, and then clicking the Concurrency tab. Under Threading Model, the possible values are as follows:

  • Main Thread Apartment
  • Single Thread Apartment (Apartment)
  • Free Thread Apartment (Free)
  • Neutral Apartment (N/A)
  • Any Apartment (Both)

The preferred threading model for COM+ is the neutral apartment. However, if you do not specify a threading model for your component, COM+ uses the main thread apartment, which is the default.

The following table shows the programming model for apartments in COM+.

Model | Apartment | Free | Both | Neutral | Not Specified
Single-threaded, not main | Created in current apartment | Created in multithreaded apartment | Created in current apartment | Created in neutral apartment | Created in main threaded apartment
Single-threaded, main | Created in current apartment | Created in multithreaded apartment | Created in current apartment | Created in neutral apartment | Created in current apartment
Multithreaded | Created in host single-threaded apartment | Created in multithreaded apartment | Created in multithreaded apartment | Created in neutral apartment | Created in main threaded apartment
Neutral (on STA thread) | Created in host single-threaded apartment for this thread | Created in multithreaded apartment | Created in neutral apartment | Created in neutral apartment | Created in main threaded apartment
Neutral (on MTA thread) | Created in host single-threaded apartment | Created in multithreaded apartment | Created in neutral apartment | Created in neutral apartment | Created in main threaded apartment


COM+ Apartment Models

COM+ threading models are designed around an object collection called an apartment. Calls within an apartment are direct, while calls across apartments (out-of-process) are indirect and require proxy and stub code. Apartments allow for objects with different synchronization and reentrancy properties and have two categories: single-threaded and multithreaded. Objects in a single-threaded apartment (STA) execute on the particular thread in which they were created. STAs allow only one method to execute at a time. They are designed for user interfaces and rely on the Microsoft® Windows® message queue to process incoming calls.

Objects in a multithreaded apartment (MTA) execute on any thread and allow any number of methods to occur simultaneously. MTAs support reentrance implicitly.

COM+ classes are marked with a ThreadingModel registry attribute that allows COM+ to create the object in the proper apartment. To determine which apartment an object is created in, CoCreateInstance uses the ThreadingModel attribute.

Threads must call CoInitializeEx before they can use COM+. This creates them inside the correct apartment and context. The main thread apartment is determined to be the first STA called by CoInitializeEx. This is usually associated with the main thread of a process. CoInitializeEx indicates the type of apartment required by the thread by setting the following flags:

  • COINIT_MULTITHREADED—Locates the thread in the single multithreaded apartment.
  • COINIT_APARTMENTTHREADED—Places the thread into a new STA.


Neutral Apartments

COM+ introduces neutral apartments to simplify programming in multithreaded environments. Neutral apartments are the preferred model for COM+ for components with no user interface. (Components that have user interfaces should continue to use "ThreadingModel=Apartment" as the preferred model.) In the past, to prevent bottlenecks, COM+ developers requiring server scalability had to implement free-threaded components; however, free-threading models are complicated to implement because they must deal with interlocking access. In neutral apartments, objects follow the guidelines for multithreaded apartments but can execute on any kind of thread.

Each process can have only one neutral apartment. To select a neutral apartment, set ThreadingModel=Neutral in the registry. When a thread is running in a neutral apartment, the object's context is received without causing a thread switch.


Using the Free-Threaded Marshaler

While COM+ supplies the ability to handle cross-apartment calls, most cross-apartment calls must be marshaled. A proxy and stub for each interface handles the marshaling and unmarshaling of calls. To override this marshaling behavior, COM+ allows a direct pointer (no proxy and stub) to be produced when calls are unmarshaled in a destination apartment. The object must indicate at run time that it is context-neutral by aggregating the free-threaded marshaler (FTM) and delegating it for marshaling (CoCreateFreeThreadedMarshaler). Context-neutral objects contain no context of their own.

The FTM should be used only in specific cases—and even then, only when all the implications of doing so are carefully considered. While the FTM can eliminate the overhead of a proxy and stub, using it can cause the object to simulate a neutral apartment. In the case where you require an interface pointer (which is apartment-relative), you must marshal the interface pointer to the proper apartment for each method on the component using the FTM. The COM global interface table (GIT) does this for you. The GIT holds interface pointers and returns apartment-independent interface pointer identifiers (GIT cookies). To use the GIT, call CoCreateInstance with CLSID_StdGlobalInterfaceTable.


Synchronization

COM+ provides synchronization that flows from component to component and prohibits more than one caller from entering the component at any given time. Synchronization determines when threads can dispatch calls to an object.

Generally, synchronization is not required when you have a single-threaded apartment (STA) because the apartment provides the synchronization for you. Synchronization becomes important when you have a multithreaded apartment (MTA) and a free-threaded object. In the past, free-threaded objects have had to handle locking. You can eliminate the need to use locking by setting the synchronization attribute for a component.

Synchronization has the following properties:

  • Allows one caller to enter the component at a time.
  • Prohibits flow across process or across computer.
  • Flows from component to component within a process.
  • Allows reentrancy from the same caller.

Unlike apartments, activities span contexts from multiple processes and hosts. Synchronization determines which activity will contain an object. Objects can reside in any of the following activities:

  • Creator's activity
  • New activity
  • No activity

COM+ ensures concurrency by a series of locks for each activity. If a caller tries to enter a COM+ synchronized component that is already being used by another caller, the call is blocked until the lock is released. This blocking behavior will not time out and cannot be configured to time out. If the lock is not in use, the lock is acquired and the call is processed. After completing, the lock is released for the next caller. To prevent deadlock, COM+ manages access to all objects across activities by a nested series of calls chained throughout the network.

COM+ provides the following synchronization settings:

  • Disabled
  • Not Supported
  • Supported
  • Required
  • Requires New

Note Some synchronization settings work in conjunction with other COM+ component settings. For example, synchronization is required if Just-in-Time (JIT) activation is enabled. JIT is required if you enable transactions; therefore, transaction processing requires synchronization as well. So, classes with the setting of JIT=True must also have the setting of either Synchronization=Required or Synchronization=RequiresNew.

For additional information on setting synchronization options through the Component Services administrative tool, see Configuring Synchronization.

To obtain more information on using the COM+ 1.0 Administration Library to set synchronization options, see Automating COM+ Administration.


Security in COM+

COM+ provides several security features that you can use to protect your COM+ applications, ranging from services you configure administratively to APIs you can call within code.

The automatic security services that COM+ offers—role-based security and authentication—make it possible for you to leave all security-related functionality out of your components. When you can turn on the services and configure them appropriately, COM+ will handle the details of enforcing the security policy you specify. However, when these automatic services don't do precisely what you need them to do, you can extend them, building on the automatic security platform provided by COM+.

Which mechanisms you use to secure a given application will depend on the particular requirements of that application. Some security choices can affect how you write components, and some can significantly affect the application's design. Before you make any decisions about how to secure an application, you should consider its security requirements in the context of its overall design—performance requirements, data access, physical design—and choose the most suitable combination of security features.

Brief descriptions of COM+ security categories, features, and issues are provided here, with links to topics in this section that provide a detailed discussion of each of the important areas.

Note Although not discussed in this section, queued components also have particular issues relating to what security features are available to them. For details, see Using Queued Components Security and Development Constraints.

Role-Based Security

Role-based security is the central feature of COM+ application security. Using roles, you can administratively construct an authorization policy for an application, choosing (down to the method level, if necessary) which users can access which resources. Additionally, roles provide a framework for enforcing security-checking within code if your application requires finer-grained access control.

Role-based security is built on a general mechanism that enables you to retrieve security information regarding all upstream callers in the chain of calls to your component. This facility is useful particularly if you wish to do detailed auditing and logging. For a description of the auditing features provided by COM+, see Accessing Security Call Context Information.

For a description of role-based security and administration issues that you should consider when using it, see Role-Based Security Administration .

For information about implementing programmatic security from within your components, see Programmatic Component Security.

Client Authentication

Before you can authorize clients to be able to access resources, you must be confident that they are who they say they are. To enable this identity verification, COM+ provides authentication services. While these services are actually provided at a more fundamental level by COM and Microsoft® Windows® 2000, a COM+ application lets you simply turn on the authentication service administratively so that it works under the covers, transparent to the application. For a description of authentication services, see Client Authentication.

Client Impersonation and Delegation

In some cases, your application needs to do work on behalf of a client using the client's identity—for example, when accessing a database that is going to authenticate the original client. This requires your application to impersonate the client. COM+ provides facilities to enable various levels of impersonation. Impersonation is configured administratively, but you also must provide support for impersonation with the code of your application's components. For a description of impersonation and issues concerning its use, see Client Impersonation and Delegation.

Library Application Security

Library applications have special security considerations. Because these applications run in the client's process, they are affected by the security enforced by the hosting process while unable to control process-level security. For a description of factors to consider for library applications, see Library Application Security.

Multi-Tier Application Security

COM+ applications are typically middle-tier applications; that is, they move information between clients and back-end resources such as databases. Difficult choices can be involved in determining where security should be enforced and to what degree. Security inherently involves performance trade-offs. Some of the most severe of these occur when you must enforce security checking at both the data tier and the middle-tier. For a discussion of issues to consider, see Multi-Tier Application Security.


Role-Based Security Administration

Role-based security is an automatic service provided by COM+ that enables you to administratively construct and enforce an access control policy for your COM+ application. With a flexible and extensible security configuration model, role-based security offers a considerable advantage over enforcing all security within your components and provides the following benefits:

  • You can configure security administratively, using either the Component Services administrative tool or the Administrative SDK functions.
  • You don't have to write security-related logic into your components when role protection at the method level provides you with fine enough access control.
  • You don't have to factor security into interface or component design. Instead, you can set security on a method-by-method basis.
  • You can focus on the structure of the security policy you want to enforce, and through roles, that policy can be clearly expressed to the administrators deploying your application.
  • You can easily modify a security policy to adapt to evolving security requirements for an application.
  • You can build more granular security policies programmatically if you need to, using role-based security as a supporting platform.
  • You can leverage role-based security to do detailed auditing, because you can obtain caller security information for an entire chain of upstream calls.

See the following topics in this section for information about how role-based security works and issues to consider when using it to construct a security policy for an application:

  • Using Roles for Client Authorization
  • Designing Roles Effectively
  • Security Boundaries
  • Security Call Context Information
  • Security Context Property

Note For detailed how-to descriptions of the steps involved in configuring role-based security for an application, see Configuring Role-based Security.

See Also

Programmatic Component Security

Client Authentication

Client Impersonation and Delegation

Library Application Security

Multi-Tier Application Security


Using Roles for Client Authorization

You use role-based security to establish an authorization policy, determining which client or clients to let in and with what authority. You are deciding who should be able to perform which actions and access which resources.

Roles facilitate this by acting as an access control mechanism invoked whenever a user attempts to access any application resource. A role is basically a list of users—more precisely, a symbolic category of users that share the same security privilege. When you assign a role to an application resource, you are granting access permission for that resource to whoever is a member of that role.

Therefore, you can define a very particular security privilege by declaring it as a role and then assigning the role to specific resources. When the application is deployed, the system administrator can populate the role with actual users and user groups. When the application runs, COM+ will enforce the policy by carrying out role checks.

Fundamentally, roles protect your code—that is, the methods that can be called by clients of a COM+ application. Role membership is checked whenever a client attempts to call a method exposed by a component in an application. If the caller is in a role assigned to the called method, or resource, the call succeeds; otherwise, it fails.

Declarative Role-Based Security

With declarative role-based security, you administratively declare roles—using either the Component Services administrative tool or the Administrative SDK functions—and administratively assign them to application resources. Where and how you set declarative security will determine where security boundaries are drawn for your application. For more detail, see Security Boundaries.

You can assign a given role to the entire application, to a particular component, to a particular interface in a component, or to a particular method on an interface. Role assignments are inherited down the natural chain of inclusion—that is, if you assign a role to a component, it is implicitly assigned to every interface and method exposed by that component.

With the availability of method-level role assignments, you can effectively secure components and interfaces that have not been designed with security in mind. However, if the methods themselves are not securable with declarative role assignments, you might need to do programmatic role checking. It is generally a good idea to keep security in mind when deciding how to factor business functionality through methods; otherwise, you could find yourself adding in security-related code at the last minute.

For detailed procedures for setting role-based security, see Configuring Role-Based Security.

Programmatic Security

In some circumstances you may want to put security logic into components while still using role-based security. It might be that you're not able to—or choose not to—factor all access decisions through methods. For example, you might have a private application resource, perhaps a particular database, that you want to allow only some callers of a method to access while excluding others. Or you might have a single TransferMoney method and want to restrict some callers by limiting the amount they can transfer.

In such circumstances, you can do role checking in code. A simple API is provided, enabling you to check whether security is turned on and whether a caller or a particular user is in a given role. This functionality is available only when role-based security is enabled. This means that you can still take advantage of declarative role-based security where it suffices, and then you can programmatically extend it to a finer level of granularity when necessary.

Additionally, when you use role-based security, you have programmatic access to information regarding all upstream callers in the chain of calls to your component. This is especially useful when you want to keep a detailed audit trail.

For descriptions of how to do role checking in code and how to access security call context information, see Programmatic Component Security.

Authorization vs. Authentication

Meaningful authorization presupposes that you are confident that clients are actually who they say they are. The verification of client identity is handled separately by an authentication service. Without authentication, you are basically letting callers in on the honor system. For descriptions of authentication as it impacts COM+ applications, see Client Authentication.

See Also

Designing Roles Effectively

Security Boundaries

Security Call Context Information

Security Context Property


Designing Roles Effectively

In many scenarios, role-based security is a very effective mechanism, but there are situations where it is less effective. You should take a number of factors into consideration when deciding where and how to apply role-based security to a particular application.

User vs. Data Characteristics and the Suitability of Roles

Roles work very well to characterize groups of users and, on that basis, filter what actions those users can perform. Often, this is carried out in practice by creating roles that reflect a user's place within an organization—for example, the roles "Managers" and "Tellers," "Administrators" and "Readers," "Project One Employees" and "Project Two Employees." In such cases, where the data being accessed is fairly generic relative to the users, roles can be used efficiently to enforce business rules such as the following:

"Managers can transfer any amount of money. Tellers can transfer only up to $10,000."

"Administrators can change anything. Everyone else can only read."

"Project One employees can access a certain database. No one else can."

Users might naturally fall into multiple roles, depending on how the roles model the organizational structure of a business.

However, roles don't work very well when a security access decision rests on the characteristics of a particular piece of data. For example, it would be difficult to use roles to reflect complicated user-data relationships such as the following:

"A particular manager can access personnel data for only her reports."

"Joe Consumer can look up his account balance."

In such cases, security checking must often be done at the database itself, where it is easier to take into account innate characteristics of the data being accessed. This means that you must use impersonation to pass the client identity along to the database and let the database validate the request. This can affect performance and can affect the application's design—for example, connection pooling might not work when a connection is opened under a particular user identity. For a discussion of issues involved, see Multi-Tier Application Security and Client Impersonation and Delegation.

Complexity and Scalability of a Role-Based Authorization Policy

Whatever security policy you put in place will be only as effective as its implementation by the system administrators deploying your application. If administrators make mistakes in assigning users to the correct roles according to your security policy, your policy won't work as intended. Problems are most likely to occur under the following circumstances:

  • You have made a very intricate role-based policy, with many roles and users mapping to numerous roles.
  • You create roles with ambiguous criteria for who should belong to them.
  • There are many users at the site where the application is installed, and users are frequently moving within the organization, changing with respect to the roles you have created.
  • There are many administrators at the site where the application is installed, with division of responsibilities, so that an administrator familiar with the security requirements of your application is potentially unfamiliar with the large groups of users that must use it. This is of particular concern as users move within the organization—such information needs to be well communicated.

Additionally, as the number of roles assigned to an application increases, so does the amount of time COM+ must spend looking up caller membership in those roles, with a likely degradation in performance.

To manage complexity and mitigate these concerns, you can use the following guidelines:

  • Choose role names that are self-descriptive. Make it as obvious as possible which users should belong to which roles.
  • Make your role-based policy as simple as possible (and no simpler). Choose as few roles as you can, while maintaining an effective policy.
  • Clearly document the role-based policy that you construct for administrators, whether or not role membership is obvious (to you). In particular, use the description field available for each role to describe the intent of the role. If you can't describe generally who should belong to the role in a couple of sentences, it is probably too complicated.
  • Strongly suggest that administrators of your application populate roles with Microsoft® Windows® 2000 user groups instead of individual users. This is a much more scalable solution. It makes it easier to reassign or remove users as they move within the organization and insulates administrators from a certain amount of oversight and problems in communication.

See Also

Using Roles for Client Authorization

Security Boundaries

Security Call Context Information

Security Context Property


Security Boundaries

Security is checked only at application boundaries. That is, for two components in the same application, when one component calls the other, no security check will be done. However, if two applications share the same process and a component in one calls a component in the other, a security check is done because an application boundary is crossed. Likewise, if two applications reside in different server processes and a component in the first application calls a component in the second application, a security check is done.

Therefore, if you have two components and you want security checks to be done when one calls the other, you need to put the components in separate COM+ applications.

Because COM+ library applications are hosted by other processes, there is a security boundary between the library application and the hosting process. Additionally, the library application doesn't control process-level security, which affects how you need to configure security for it. For more information, see Library Application Security.

Determining whether a security check must be carried out on a call into a component is based on the security property on the object context created when the configured component is instantiated. For more information, see Security Context Property.

Component-Level Access Checks

For a COM+ server application, you have the choice of enforcing access checks either at the component level or at the process level.

When you select component-level access checking, you enable fine-grained role assignments. You can assign roles to components, interfaces, and methods and achieve an articulated authorization policy. This will be the standard configuration for applications using role-based security.

For COM+ library applications, you must select component-level security if you want to use roles. Library applications cannot use process-level security.

You should select component-level access checking if you are using programmatic role-based security. Security call context information is available only when component-level security is enabled. For more information, see Security Call Context Information.

Additionally, when you select component-level access checking, the security property will be included on the object context. This means that security configuration can play a role in how the object is activated. For more information, see Security Context Property.

Process-Level Access Checks

Process-level checks apply only to the application boundary. That is, the roles that you have defined for the whole COM+ application will determine who is granted access to any resource within the application. No finer-grained role assignments apply. Essentially, the roles are used to create a security descriptor against which any call into the application's components is validated. In this case, you would not want to construct a detailed authorization policy with multiple roles. The application will use a single security descriptor.

For COM+ library applications, you would not select process-level access checks. The library application will run hosted in the client's process and hence will not control process-level security. For more information, see Library Application Security.

With process-level access checks enabled, security call context information is not available. This means that you cannot do programmatic security when using only process-level security. For more information, see Security Call Context Information.

Additionally, the security property will not be included on the object context. This means that when using only process-level access checks, security configuration will never play a role in how the object is activated. For more information, see Security Context Property.

See Also

Using Roles for Client Authorization

Designing Roles Effectively

Security Call Context Information

Security Context Property


Security Call Context Information

Role-based security is built on a general mechanism that enables you to retrieve security information regarding all upstream callers in the chain of calls to your component. This information is available only when you have component-level role checking enabled. For details about how to set component-level security, see Setting a Security Level for Access Checks.

You can use the ISecurityCallContext interface to access security call context information programmatically. For a description, see Programmatic Component Security.

Security call context is passed along every time a security boundary is crossed. For calls between components within an application, which reside within the same security boundary, no call context information is passed. For calls between processes or between applications within a process, call context information flows along.

This facility is particularly useful if you wish to do detailed auditing and logging. You can retrieve and record security information for every upstream caller.

See Also

Using Roles for Client Authorization

Designing Roles Effectively

Security Boundaries

Security Context Property


Security Context Property

As with every automatic service provided by COM+, automatic role checking is based on properties included on the object context. The determination of whether a security check must be carried out on a call into a component is based on the security property on the object context created when the configured component is instantiated.

You generally don't need to be concerned with this property; it is used directly by COM+, not you. However, in some circumstances, you might want strict control over the activation of an object. In this case, the security property can affect which context your object is activated in. That is, if an object has a configuration incompatible with the context of its creator, it will be activated in its own context. The security property can influence this, as can any property on the object context.

If you wish to ensure that security never influences activation, you can choose process-level access checking only. This will suppress the security property on the object context, although it effectively disables role-based checking and makes security call context information unavailable.

For more information about process-level access checks, see Security Boundaries. To see how to set process-level security, see Setting a Security Level for Access Checks.

For more information about object context, see Contexts.

See Also

Using Roles for Client Authorization

Designing Roles Effectively

Security Boundaries

Security Call Context Information


Programmatic Component Security

If role-based security will be used in the COM+ application that contains your component, you have access to programmatic security functionality from within your component. You can check role membership to determine whether particular sections of code are executed, you can access security information using the security call context object, and you can determine whether security is enabled for the current call. You can perform all of these tasks by using a reference to the SecurityCallContext object (for Microsoft® Visual Basic® applications) or a pointer to the ISecurityCallContext interface (for C and Microsoft Visual C++® applications).

For more information regarding programmatic role-based security, see the following topics in this section:

  • Checking Role Membership
  • Determining Whether Role-Based Security Is Enabled
  • Accessing Security Call Context Information

Impersonation and COM Security Features

If your component will be used in a COM+ application that does not use role-based security, programmatic role checking and security call context information will not be available. However, you can use the programmatic security functionality provided by COM. For more information, see Security in COM.

Although you can use most of the security functionality provided by COM, you cannot call CoInitializeSecurity from a component that is part of a COM+ application because CoInitializeSecurity is called by the surrogate that the COM+ application runs in. However, you can call other security functions, such as CoQueryClientBlanket, which retrieves information about the client.

In particular, when you need to use the client's identity to access some resource—for example, accessing a file protected by a security descriptor, or propagating the client's identity through to a database—you can perform impersonation programmatically. For more detail about when and how to do this, see Client Impersonation and Delegation.

See Also

Role-Based Security Administration

Client Authentication

Client Impersonation and Delegation

Library Application Security

Multi-Tier Application Security


Checking Role Membership

You can call the ISecurityCallContext::IsCallerInRole method to determine whether an object's direct caller is a member of a particular role. This functionality is useful when you want to ensure that a certain block of code is not executed unless the caller is a member of a particular role.

For example, you could use ISecurityCallContext::IsCallerInRole to ensure that transactions over a specified amount, such as $1000, are performed only by members of a Managers role. If the caller is not a Manager and the transaction is over $1000, the transaction is not performed and an error message is displayed.

The preferred way to access ISecurityCallContext::IsCallerInRole is through the security call context object because you can use the same reference to the security call context object to obtain security properties. However, you can also access the IsCallerInRole method from the ObjectContext object. (See ObjectContext Object or IObjectContext for more information.)

If you are developing components for a Microsoft® Visual Basic® application, you call the GetSecurityCallContext function and then use the security call context to call IsCallerInRole, as shown in the following example:

If (GetSecurityCallContext.IsCallerInRole("Manager")) Then
   ' Go ahead and perform the transaction
Else
   ' Display an error message
End If

If you are developing a C or Microsoft Visual C++® application, you use CoGetCallContext to retrieve a pointer to the ISecurityCallContext interface. Then you call ISecurityCallContext::IsCallerInRole, as shown in the following example:

ISecurityCallContext* pSecCtx;
VARIANT_BOOL fIsInRole;

hr = CoGetCallContext(IID_ISecurityCallContext,
     (void**)&pSecCtx);
if (pSecCtx == NULL)
  {
     // No security call context available.
     // Display an error message and return.
     return E_FAIL;
  }
hr = pSecCtx->IsCallerInRole(myRole, &fIsInRole);
return hr;

See Also

Programmatic Component Security

Determining Whether Role-Based Security Is Enabled

Accessing Security Call Context Information


Determining Whether Role-Based Security Is Enabled

By using the ISecurityCallContext::IsSecurityEnabled method available from the security call context object, you can determine whether security is enabled for the current object. You should call IsSecurityEnabled before you use ISecurityCallContext::IsCallerInRole to check role membership because IsCallerInRole returns True if security is not enabled.

Microsoft® Visual Basic® developers call GetSecurityCallContext to obtain a reference to the SecurityCallContext object and then call IsSecurityEnabled, as shown in the following example:

Dim secCallCtx As SecurityCallContext
Dim x As Boolean
Set secCallCtx = GetSecurityCallContext()
x = secCallCtx.IsSecurityEnabled()

Microsoft Visual C++® developers can call ISecurityCallContext::IsSecurityEnabled by calling CoGetCallContext to obtain a pointer to ISecurityCallContext and then calling ISecurityCallContext::IsSecurityEnabled. A brief example follows:

ISecurityCallContext* pSecCtx;
VARIANT_BOOL fIsEnabled;
hr1 = CoGetCallContext(IID_ISecurityCallContext, (void**)&pSecCtx);
if (pSecCtx == NULL)
  {
  // Display error message
  return E_FAIL;
  }

hr2 = pSecCtx->IsSecurityEnabled(&fIsEnabled);
return hr2;

Although the preferred way to call IsSecurityEnabled is by using the security call context object, you can also call IsSecurityEnabled through the object context. (See ObjectContext Object or IObjectContext for more information.)

See Also

Programmatic Component Security

Checking Role Membership

Accessing Security Call Context Information


Accessing Security Call Context Information

When role-based security is being used, the security call context object can be used to access security information about the current call. The following collections of properties are available from the security call context object:

SecurityCallContext Collection

NumCallers | The number of callers in the chain of calls.
MinAuthenticationLevel | The least secure authentication level of all callers in the chain.
Callers | Information about the identity of upstream callers, in the form of a SecurityCallers collection.
DirectCaller | The caller that called the object directly (with no intervening callers).
OriginalCaller | The caller that originated the chain of calls to the object.

For more information about how to use this collection, Microsoft® Visual Basic® developers should see SecurityCallContext Object. C and Microsoft Visual C++® developers should refer to ISecurityCallContext.

SecurityCallers Collection

The SecurityCallers collection represents callers that can be retrieved by using an index between 0 and 1 less than NumCallers, inclusive. Each caller is represented by a SecurityIdentity object.

For more information about this collection, Visual Basic developers should see SecurityCallers Object. C and C++ developers should refer to ISecurityCallersColl.

SecurityIdentity Collection

SID | The security identifier for the caller.
AccountName | The account name of the caller.
AuthenticationService | The authentication service used, such as NTLMSSP, Kerberos, or SSL.
AuthenticationLevel | The authentication level used, which represents the amount of protection used when communicating with the object.
ImpersonationLevel | The level of impersonation set by the client, if impersonation was used. This level indicates the amount of authority given to the server by the client.

For more information on this collection, Visual Basic developers should see SecurityIdentity Object. C and C++ developers should refer to ISecurityIdentityColl.

See Also

Programmatic Component Security

Checking Role Membership

Determining Whether Role-Based Security Is Enabled


Client Authentication

Authentication is the process of determining that callers are actually who they say they are—verifying the authenticity of a claim of identity. In general, this can be done by both server and client, each authenticating the other. But it is especially important for a server application that is authorizing clients, as with role-based security, to do authentication as well. Authenticating clients is a prerequisite for a meaningful authorization policy. You can do all the role checking you want, but if you don't know for certain that the client identity you are checking is authentic, your application is basically relying on the honor system.

For COM+ applications, authentication is something you can turn on and configure administratively, after which it works transparently to the application. You specify an authentication level administratively by using the Component Services administrative tool or the Administrative SDK functions. For details of setting authentication, see Setting Authentication.

For a COM+ server application, you can choose from several authentication levels that provide varying degrees of security, ranging from no authentication to encryption of every packet and all method call parameters. Higher security comes with some performance cost, however, which you should take into consideration when configuring your application. COM+ will negotiate between the authentication level specified by client and server. The way this negotiation is carried out has the benefit of enabling you to administratively control authentication from the server side alone. For details, see the topic Negotiation of Authentication Level in this section.

Note You should never specify an authentication level programmatically by using CoInitializeSecurity within a COM+ application. COM+ calls CoInitializeSecurity for you, and this can be called only once per process.

The underlying authentication services are provided by COM and Microsoft® Windows® 2000. In an authentication service, a third party supplies a certificate for a user, attesting to the authenticity of the user's identity. This certification is as credible as the certifying authority, and—in much the same way as a driver's license or a passport serves as a certifying document—it depends on the issuer's authority. For more detailed information about authentication services, see COM and Security Packages in the COM documentation.

For a COM+ library application, authentication is largely controlled by the hosting process. However, you can configure the library application so that it will not participate in authentication. That is, calls into the application can be authenticated or unauthenticated, and in the latter case, "authentication" of clients always succeeds. For information on this, see Library Application Security.

Additionally, you may want or be required to authenticate the client at the database or at some downstream application—authenticating clients at the COM+ application alone might not suffice. If this is the case, you need to impersonate the client so that the client's identity is propagated downstream. For detailed information about impersonation, see Client Impersonation and Delegation. For a discussion of issues involved in deciding whether to do authentication at the data tier, see Multi-Tier Application Security.

See Also

Role-Based Security Administration

Programmatic Component Security

Client Impersonation and Delegation

Library Application Security

Multi-Tier Application Security


Negotiation of Authentication Level

Both client and server must participate in authentication, and each party indicates that it wants to perform a certain level of authentication. At the beginning of a call, the authentication level is negotiated between the two parties, an appropriate service is chosen, and the call is authenticated and proceeds (with possible encryption, depending on the authentication level chosen). The authentication level negotiated between client and server is determined as Maximum(Client preference, Server preference). The effect of this means that the server can always dictate a minimum level of authentication that it is comfortable with; that is, authentication can be administratively dictated from the server.

The client specifies that it wants to perform authentication at a certain level as with any COM application. The client authentication level can be indicated as follows:

  • Per client machine, with the machine-wide COM authentication level set by using either DCOMCNFG or the Component Services administrative tool (if the client machine is running Microsoft® Windows® 2000).
  • Per client application administratively, using DCOMCNFG or using the Component Services administrative tool if the client should be a COM+ application.
  • Per client process programmatically, with CoInitializeSecurity.
  • At any point programmatically, using CoSetProxyBlanket.

The COM+ server application specifies an authentication level administratively by using the Component Services administrative tool (or through an administrative script).

Negotiating authentication for a call proceeds in the following sequence:

  1. Authentication level is chosen as MAX(client, server).
  2. Negotiation of authentication protocol.
  3. Server authenticates client identity.
  4. Optionally, client authenticates server identity, depending on the authentication protocol.
  5. Protect method calls as indicated by authentication level.

See Also

Client Authentication


Client Impersonation and Delegation

In some circumstances, a server application needs to present a client's identity to resources it accesses on the client's behalf, usually to cause access checks or authentication to be performed against the client's identity. To a certain extent, the server can act under the client's identity—an action referred to as impersonating the client.

Impersonation is the ability of a thread to execute in a security context different from that of the process owning the thread. The server thread uses an access token representing the client's credentials, and with this, it can access resources that the client can access.

Using impersonation ensures that the server can do precisely what the client can do. Access to resources may be either restricted or expanded, depending on what the client has permission to do.

You might choose to have a server impersonate a client when connecting to a database so that the database can authenticate and authorize the client for itself. Or, if your application accesses files that are protected with a security descriptor and to ensure that the client can obtain authorized access only to information in these files, the application can impersonate the client before accessing the files.

How to Implement Impersonation

Impersonation requires participation by both client and server (and, in some cases, system administrators). The client must indicate its willingness to let the server use its identity, and the server must explicitly assume the client's identity programmatically. For details, see the topics Client-Side Requirements for Impersonation and Server-Side Requirements for Impersonation in this section.

Administrative Requirements for Delegate-Level Impersonation

To effectively use the most powerful form of impersonation, delegation, which is the impersonation of clients over the network, the client and server user accounts must be properly configured in the Active Directory Service to support it (in addition to the client granting authority to do delegate-level impersonation), as follows:

  • The server identity must be marked as "Trusted for delegation" in the Active Directory Service.
  • The client identity must not be marked as "Account is sensitive and cannot be delegated" in the Active Directory Service.

These configuration features give the domain administrator a high degree of control over delegation, which is desirable, given how much trust (and hence security risk) is involved. For more detail about delegation, see Delegation and Impersonation.

Cloaking

Along with the authority a client grants a server through the impersonation level, the server's cloaking capability largely determines how impersonation will behave. Cloaking affects what identity is actually presented by the server when it makes calls on the client's behalf—its own or the client's. For details, see Cloaking, in this section.

Performance Implications

Impersonation can significantly affect performance and scaling. It is generally more expensive to impersonate a client on a call than to make the call directly. Following are some of the issues to consider:

  • The computational overhead of passing around identity in complicated patterns, particularly if dynamic cloaking is enabled.
  • The general complexity of enforcing redundant security checking in numerous places, instead of just centrally in the middle tier.
  • Resources such as database connections, when opened impersonating a client, cannot be reused across multiple clients—a very large roadblock to scaling well.

Sometimes the only effective solution to a problem is to use impersonation, but this decision should be carefully weighed. For a further discussion of these issues, see Multi-Tier Application Security.

Queued Components

Queued components do not support impersonation. When a client makes a call to a queued object, the call is actually made to the recorder, which packages it as part of a message to the server. The listener then reads the message from the queue and passes it to the player, which invokes the actual server component and makes the same method call. As such, when the server receives the call, the original client token is unavailable via impersonation. Role-based security still applies, however, and programmatic security using the ISecurityCallContext interface will work. For details, see Using Queued Components Security.

See Also

Role-Based Security Administration

Programmatic Component Security

Client Authentication

Library Application Security

Multi-Tier Application Security


Client-Side Requirements for Impersonation

The following two settings can be specified relative to impersonation on the client side:

  • Impersonation level, which indicates the client's willingness to have the server use its identity.
  • A setting in the Active Directory Service through which the client account can be marked "Account is sensitive and cannot be delegated," which will disable delegation.

The impersonation level can be set in a variety of ways. If the client does not indicate an impersonation level, the machine-wide default will be used by COM. The machine-wide default can be set using either the Component Services administrative tool or Dcomcnfg.exe. The client can also indicate a preferred impersonation level administratively with Dcomcnfg.exe.

The client can indicate the impersonation level programmatically, using either CoSetProxyBlanket—equivalent to IClientSecurity::SetBlanket, which can be called as often as necessary—or CoInitializeSecurity, which can be called once per process.

If the client indicates delegate-level impersonation—the broadest authority it can grant to the server—the client should be running under an identity that is properly configured in the Active Directory Service to enable its identity to be delegated.

For more detail regarding impersonation levels and the requirements for delegation to work, see Delegation and Impersonation.

COM+ applications can always act as clients, of course. When the COM+ application makes a call to another application or resource, it expresses an impersonation level. For COM+ server applications, you can set an impersonation level administratively. COM+ library applications cannot set their own impersonation level; they use that of the host process instead. To learn how to set impersonation for a COM+ application, see Setting an Impersonation Level.

See Also

Client Impersonation and Delegation

Server-Side Requirements for Impersonation

Cloaking


Server-Side Requirements for Impersonation

The server performs impersonation programmatically. It explicitly assumes the client's security credentials by using CoImpersonateClient. When the client has granted the server sufficient authority, this has the effect of substituting the client's security credentials with the server thread token, in place of the process token.

When this has been done, the server can, for example, use the client token to access resources guarded with a security descriptor. Or it can make calls under the client identity, if cloaking is enabled.

The server can explicitly set cloaking programmatically, or it can rely on an administrative setting. By default, COM+ applications are configured to use dynamic cloaking. For more detail, see Cloaking.

If the server is implementing delegation on behalf of the client—using the client identity over network—the server process identity must be marked as "Trusted for delegation" in the Active Directory Service; otherwise, delegation will fail.

When it has finished using the client's identity, the server can revert to its own process token using CoRevertToSelf.

For details on implementing impersonation and delegation, see Delegation and Impersonation.

See Also

Client Impersonation and Delegation

Client-Side Requirements for Impersonation

Cloaking


Cloaking

There are two ingredients in determining the behavior of impersonation: the authority the client explicitly grants the server through an impersonation level and the server's ability to mask its own identity when making calls on the client's behalf. This latter capability is known as cloaking. Cloaking has to do with the security identity under which the server makes calls.

When the server impersonates the client, it has direct access to the client's security credentials. In a very local sense, the server thread takes on the identity of the client. But when the server makes calls outside of its process, the client identity will not necessarily be projected as the identity under which the call is made.

When cloaking is enabled, calls made by the server impersonating the client can be made under the client's identity. When cloaking is disabled, calls by the server will be made under the server's identity.

Moreover, there are two forms of cloaking, static cloaking and dynamic cloaking, which can be described as follows:

  • Impersonation with static cloaking—The original client identity (realized as the server thread token) can be presented once to a downstream server on a call using CoSetProxyBlanket, setting the original client identity once on the proxy, and that thread token will be used on subsequent method calls.
  • Impersonation with dynamic cloaking—The original client identity is discovered as the server thread token on each method call to the downstream server. In effect, the identity that is presented can be determined dynamically. The overhead required to do this can be considerably more expensive.

For COM+ applications, the default configuration is for dynamic cloaking capability. This can be changed programmatically and administratively. While dynamic cloaking can have performance overhead, it provides the flexibility that is usually required by circumstances that necessitate using impersonation in the first place.

For more detail regarding cloaking and precise descriptions of possible behaviors, see the topic Cloaking in the COM documentation.

See Also

Client Impersonation and Delegation

Client-Side Requirements for Impersonation

Server-Side Requirements for Impersonation


Library Application Security

Because a COM+ library application is hosted by another process, which may have its own security settings, security for library applications requires special consideration. The following constraints apply to library application security:

  • Library applications run under the client process security token rather than under their own user identity. They have only as much privilege as the client has.
  • Library applications do not control process-level security. No users in roles will be added to the security descriptor for the process. The only way for a library application to perform its own access checks is to use component-level security. (See Security Boundaries.)
  • Library applications can be configured to either participate or not participate in host process authentication, by enabling or disabling authentication. (See Enabling Authentication for a Library Application.)
  • Library applications cannot set an impersonation level; they use that of the host process.

Using Library Applications to Limit Application Privilege

In some cases, you may want to configure an application specifically as a library application so that it runs under the identity of the hosting process. Doing so fundamentally limits the application so that it can access only those resources that its client, the host process, can access. The threads that the library application components run on will use the process token by default, and therefore when they make calls outside of the application or access resources such as files guarded with a security descriptor, they will appear to be the client. For applications that perform sensitive work, this may be an easy way to control the scope of their actions.

Effectively Securing Library Applications

There are special considerations in configuring role-based security and authentication for library applications so that they run securely and perform as expected. For details, see the topic Configuring Security for Library Applications in this section.

See Also

Role-Based Security Administration

Programmatic Component Security

Client Authentication

Client Impersonation and Delegation

Multi-Tier Application Security


Configuring Security for Library Applications

There are special considerations in configuring role-based security and authentication for library applications.

Enabling or Disabling Authentication

One of the factors to consider is whether callers of the library application should be subject to the process-level security checks of the hosting process—that is, whether to enable or disable authentication.

For example, if the library application will be hosted by a browser, it might need to receive unauthenticated callbacks. To address this need, you can disable authentication so that the hosting process does not perform security checks for callers of the library application. When you disable authentication, the library application effectively goes unauthenticated—all calls to it will succeed. Callers of the library application are not subject to the security checks of the hosting process. Basically, the library application is tagged as "unauthenticated", and security checks are omitted for calls to the library application.

For information about how to enable or disable authentication, see Enabling Authentication for a Library Application.

Enforcing Role Checks

Another decision to make is whether or not the library application should use role-based security. If role-based security is used, you must be using component-level security for any access checks to be carried out. The roles assigned to the library application are not reflected in the process security descriptor. The only authorization that the library application can control is at the component level. For more information about component-level security, see Security Boundaries.

To see how to set component-level security, see Setting a Security Level for Access Checks.

Configuration Scenarios

To better understand the implications of deciding whether the library application should use role-based security and whether the library application should be unauthenticated, consider the following scenarios:

  • Authentication is enabled, and role-based security is used. In this scenario, security checks are made by the hosting process and some callers are denied access at the process level. Also, role checking is done at the library application level so that some callers who make it through the process-level security check are denied access to the library application when role membership is checked. This is the usual scenario for a COM+ library application that uses role-based security.

    The following illustration shows the scenario where authentication is enabled and role checking is used.

  • Authentication is enabled, and role-based security is not used. In this scenario, security checks are done at the process level but role membership is not checked at the library application level. Therefore, any caller of the library application that makes it through the process-level security check will be given access to the library application because role membership is not being checked. This situation would exist when a COM application that doesn't use role-based security is migrated to a COM+ library application.

    The following illustration shows the scenario where authentication is enabled and role checking is not being used.

  • Authentication is disabled, and role-based security is used. In this scenario, security checks are being done at the process level but callers to the library application are unauthenticated. In effect, callers of the library application are exempt from the process-level security check. Because role checking is enabled, role membership alone determines who is given access to the library application. This scenario might be appropriate when the security check that would be done by the hosting process is too restrictive but you need to have some access restriction on the library application or on specific interfaces or methods. This scenario enables you to effectively turn off process security and still have an appropriate level access checks using role-based security.

    The scenario where authentication is disabled and role checking is being used is shown in the following illustration.

  • Authentication is disabled, and role-based security is not used. In this scenario, security checks are still done at the process level but, as in the preceding scenario, callers of the library application always pass this security check. Because role checking is also disabled, role membership is not checked at the library application level. Essentially, anyone can call the library application. This scenario should be chosen when your COM object needs to receive unauthenticated callbacks, as might be the case with an ActiveX® control hosted by Internet Explorer and with a Microsoft® Management Console snap-in. Of course, this COM object must be trusted to behave appropriately when receiving unauthenticated calls. For example, it should not access arbitrary files on behalf of its callers.

    The scenario where authentication is disabled and role checking is not being used is shown in the following illustration.

After you have decided whether to enable or disable authentication for your COM+ library application, see Enabling Authentication for a Library Application for a step-by-step procedure that explains how to disable (or enable) authentication using the Component Services administrative tool. If your library application will use role-based security, see Configuring Role-based Security.

See Also

Library Application Security


Multi-Tier Application Security

You can face difficult choices in deciding precisely where to enforce security in a multi-tier, component-based application: At the database? At the middle tier? In the components? Somewhere else? Everywhere? As security mechanisms increase in number and complexity, performance declines and application behavior becomes less predictable. Nevertheless, you must ensure that data is protected, business rules are followed, and significant activity is logged, and still have your application work for clients as intended. You must be certain that every client path through your application is correct and that the security checkpoints you have in place will suffice.

The hardest decision is often whether or not to enforce security at the database. Historically, this is where security is tightest, because it is perceived as the one truly secure kingdom and database administrators are very reluctant to trust someone else to enforce security for them. But enforcing security at the database can be quite expensive and difficult to scale, which is precisely the point of writing multi-tier applications in the first place.

The general rule to follow with scalable multi-tier applications using COM+ is that, whenever possible, you should enforce detailed security in the COM+ application at the middle tier. Doing so enables you to fully leverage the scalable services provided by COM+. Authenticate at the database only when you absolutely need to, and fully weigh the performance implications of doing so.

For a discussion of issues to consider in deciding where to perform security checks, see Deciding Where to Enforce Security.

For a discussion of some basic scenarios in securing multi-tier applications, see Basic Scenarios for Securing Data in Multi-Tier Applications.

See Also

Role-Based Security Administration

Programmatic Component Security

Client Authentication

Client Impersonation and Delegation

Library Application Security


Deciding Where to Enforce Security

Trade-offs are inherent in enforcing security. A database can be a natural place to put security logic, given that ultimately that data is the most important thing to protect. However, doing so has significant performance implications. Enforcing security at the database can be very expensive, scales poorly, and is inflexible.

Enforcing Security in the Middle Tier

The general rule to follow with scalable multi-tier applications using COM+ is that, whenever possible, you should enforce detailed security in the COM+ application at the middle tier. Doing so enables you to fully leverage the scalable services provided by COM+. Enforce authentication at the database only when you absolutely need to, and fully weigh the performance implications of doing so.

The optimal situation is to be able to secure database tables so that the COM+ application is able to access them under its own identity. The database should just authenticate the COM+ application and trust it to correctly authenticate and authorize clients that will be accessing data. The benefits of this approach are as follows:

  • It enables connection pooling among all clients, as connections are completely generic.
  • It generally optimizes data access, often a problematic choke point when scaling applications.
  • It can minimize the logic overhead for enforcing security, particularly if declarative role-based security can be used.
  • It can provide great flexibility in a security policy. You can configure and reconfigure it easily, as described in Role-Based Security Administration.

But, as discussed in Designing Roles Effectively, while roles can be easily and effectively applied to some user-data relationships, they are not a universal solution for security access decisions.

Enforcing Security at the Database

Despite the preferability of enforcing security at the middle tier, there are a number of reasons to enforce security at the database, such as the following:

  • You don't have a choice, perhaps for legacy reasons or perhaps because the decision is simply not in your hands.
  • The database is accessed by a wide variety of applications, and its security can't be configured on the basis of a single application.
  • A database can be made predictably secure. If you keep enterprise-critical data in a database, you can draw a tight wagon around it and control precisely who gets to see it.
  • Authenticating original clients at the database enables detailed logging of who has done what in the database.
  • Some data is innately bound to particular users, and the logic of making extremely fine-grained access decisions might be most efficiently carried out at the database itself, close to the data.

When you do have the luxury of designing the security of the database and the COM+ application in tandem, most of these issues pertain to characteristics of the data itself and its relationship to the users accessing it. With data that can be accessed by predictable categories of users, it is efficient to control access in the middle tier using roles. With data that is intricately bound to very small classes of users, those relationships must often be expressed with the data itself and hence you must enforce some security at the database.

Performance Implications of Enforcing Security at the Database

If you authenticate or authorize users at the database, the user identity needs to be propagated through to the database to support this. If the database trusts the middle-tier application to do so, it is possible to pass in user security information in parameters. Otherwise, the call through to the database must be made under the user's identity, meaning that the server application must impersonate the client. This can have performance implications such as the following:

  • Impersonating the client can be much slower than making the call directly under the application identity. For more detail, see Client Impersonation and Delegation.
  • A database connection made under a specific user identity cannot be pooled.
  • Adding logic in the database itself runs the risk of creating a scaling bottleneck.

See Also

Multi-Tier Application Security

Basic Scenarios for Securing Data in Multi-Tier Applications


Basic Scenarios for Securing Data in Multi-Tier Applications

This topic presents a few building-block scenarios, illustrating the criteria discussed in Deciding Where to Enforce Security.

Trusted Server Scenario

  • The database fully trusts the COM+ application to authenticate and authorize end users to access data in the database.
  • Preferably, the database is secured against any access except through the application.
  • The COM+ application uses role-based security to authorize users.
  • Connections are opened under the COM+ application's identity and are fully poolable.
  • Auditing and logging can be done by the COM+ application, or this information can be passed into the database by the application.

This scenario works best for data that can be accessed by predictable categories of users that can be encapsulated in roles. For example, only "Managers," "Tellers," and "Accountants" have permission to access accounts. The business logic of what precisely each is enabled to do is enforced in the middle tier.

Impersonation Scenario

  • The database does its own authentication and authorization of end users to secure access to data in the database.
  • The COM+ application impersonates clients whenever it is accessing the database.
  • Connections are made on a per-call basis and can't be reused.

This scenario works best for data that is closely bound to very small classes of users. For example, each employee can access only his own personnel file, and each manager can access only the personnel files of her reports.

Hybrid Scenario

A combination of the preceding two scenarios, where impersonation is used only when it is needed.

This scenario works best in situations where you have hybrid user-data relationships. For example, you have "Managers," "Tellers," "Accountants," and thousands of individual Web clients who can access just their own accounts. You can separate logic paths through the application, potentially with separate components, to handle the latter class of users, particularly where performance assumptions for those users are different.

Trusted Scenario Using Microsoft SQL Server 7 Roles

  • Microsoft® SQL Server™ 7.0 can authorize access to specific rows using roles but trusts the COM+ application to authenticate and authorize users and to map them to the correct roles in the database.
  • The COM+ application authorizes users using role-based security, and the application roles correspond well to database roles.
  • Connections can be opened that are specific to a particular database role. These connections can be reused if they are held by pooled objects in the COM+ applications. For details on how to do this, see Object Pooling.
  • Auditing and logging can be done by the COM+ application, or this information can be passed in to the database by the application.

This scenario works best for generally the same kinds of users and data in the first trusted server scenario because the COM+ application is still being largely trusted to handle authorization correctly. However, it does allow the database to be secured against unauthorized access while allowing access potentially from multiple sources outside the COM+ application, without incurring the scaling and performance penalties present with the impersonation scenario.

See Also

Multi-Tier Application Security

Deciding Where to Enforce Security


Object Pooling

Object pooling is an automatic service provided by COM+ that enables you to configure a component to have instances of itself kept active in a pool, ready to be used by any client that requests the component. You can administratively configure and monitor the pool maintained for a given component, specifying characteristics such as pool size and creation request time-out values. When the application is running, COM+ manages the pool for you, handling the details of object activation and reuse according to the criteria you have specified.

You can achieve very significant performance and scaling benefits by reusing objects in this manner, particularly when they are written to take full advantage of reuse. With object pooling, you gain the following benefits:

  • You can speed object use time for each client, factoring out time-consuming initialization and resource acquisition from the actual work that the object performs for clients.
  • You can share the cost of acquiring expensive resources across all clients.
  • You can preallocate objects when the application starts, before any client requests come in.
  • You can govern resource use with administrative pool management—for example, by setting an appropriate maximum pool level, you can keep open only as many database connections as you have a license for.
  • You can administratively configure pooling to take best advantage of available hardware resources—you can easily adjust the pool configuration as available hardware resources change.
  • You can speed reactivation time for objects that use Just-in-Time (JIT) activation, while deliberately controlling how resources are dedicated to clients.

Writing Poolable Objects

Poolable objects must meet certain requirements to enable a single object instance to be used by multiple clients. For example, they can't hold client state or have any thread affinity. Transactional objects also have particular requirements, in that managed resources held by a pooled object must be manually enlisted in a transaction.

Pooled objects can implement IObjectControl to control how they are reused. This enables them to perform initialization when activated in a given context, to clean up any client state on deactivation, and to indicate when they are in a non-reusable state.

Often, it useful to write poolable objects in a somewhat generic fashion so that they can be administratively customized with a constructor string. For example, an object might be written to hold a generic ODBC connection, with a particular DSN administratively specified in a constructor string.

The topics in this section, described in the following table, provide information about how object pooling works in COM+, as well as information about how to write, configure, and implement poolable objects.

Topic | Description
How Object Pooling Works | Presents basic concepts.
Improving Performance with Object Pooling | Provides specific details on how you can use object pooling most effectively.
Requirements for Poolable Objects | Provides details on how to write an object that is to be pooled.
Pooling Transactional Objects | Provides details about the special requirements that apply to poolable transactional objects.
Controlling Object Lifetime and State | Describes how pooled objects can be implemented to control how they are reused.
Using Object Constructor Strings | Describes how poolable objects can be administratively customized by using a constructor string.

Note For details on how to configure a component to be pooled, see Configuring Object Pooling.


How Object Pooling Works

When you configure a component to be pooled, COM+ will maintain instances of it in a pool, ready to be activated for any client requesting the component. Any object creation requests will be handled through the pool manager.

Pools are configured and maintained on a per-component basis. A pool will consist of homogeneous objects all of the given CLSID. The only exception is for transactional objects, for which subpools are maintained containing objects that have transaction affinity while a transaction is pending.

When the application starts, the pool will be populated up to the minimum level that you have administratively specified, as long as object creation succeeds. As client requests for the component come in, they are satisfied on a first-come first-served basis from the pool. If no pooled objects are available and the pool is not yet at its specified maximum level, a new object is created and activated for the client.

When the pool reaches its maximum level, client requests are queued and will receive the first available object from the pool. The number of objects, including both activated and deactivated, will never exceed the maximum pool value. Object creation requests will time out after an administratively specified period so that you can control how long clients will wait for object creation. Upon a time-out failure, the client will get back the error E_TIMEOUT from CoCreateInstance.

Whenever possible, COM+ will attempt to reuse an object after a client releases it, until the pool reaches its maximum level. The object is responsible for monitoring its state to determine whether it can be reused and should return an appropriate value for IObjectControl::CanBePooled.

When a pooled object is created, it is aggregated into a larger object that will manage the object's lifetime. The outer object calls methods on IObjectControl at appropriate times in the object's life cycle, as follows:

  • The IObjectControl::Activate method is called whenever the object is returned to a client, activated in a specific context.
  • The IObjectControl::Deactivate method is called whenever an object is released by the client or, in the case of a JIT-activated object, when it is deactivated.
  • The IObjectControl::CanBePooled method is called whenever an object is to be returned to the general pool. If the object detects that some reusable resource is in a bad state, it should return FALSE for this method and the pool manager will discard the object.

An object does not necessarily need to implement IObjectControl. If it does not, instances will always be reused, until the pool maximum level is reached.

For details about how to configure components to be pooled, see Configuring Object Pooling.

See Also

Improving Performance with Object Pooling

Requirements for Poolable Objects

Pooling Transactional Objects

Controlling Object Lifetime and State

Using Object Constructor Strings


Improving Performance with Object Pooling

Object pooling can be extremely effective in certain circumstances, yielding substantial increases in performance. The general idea for reusing objects to best advantage is to pool as many resources as possible, factoring out initialization from actual work performed, and then to administratively tailor the pool characteristics to actual hardware at deployment time. That is, you should proceed according to the following steps:

  1. Write the object so as to factor out expensive initialization and resource acquisition that is performed for any client as a prerequisite to doing actual work on the client's behalf. Write heavy object constructors to pool as many resources as possible so that these are held by the object and immediately available when clients get an object from the pool.
  2. Administratively configure the pool to achieve the best balance in available hardware resources, usually trading the memory dedicated to maintaining a pool of a certain size in exchange for faster client access and use of objects. At a certain point, pooling will achieve diminishing returns and you can get good enough performance while limiting possible resource usage by a particular component.

Doing Actual Work vs. Acquiring Resources

If you have a component that clients will use briefly and in rapid succession, where a significant portion of object use time is spent in acquiring resources or initializing prior to doing specific work for the client, chances are that writing your component to use object pooling will be a big win for you.

You can write the component so that in the object's constructor you perform as much of the time-consuming work that is uniform for all clients as possible—acquiring one or several connections, running scripts, fetching initialization data from files or across a network, and so forth. This has the effect of pooling every such resource. You are pooling the combination of resources and generic state necessary to perform some work.

In this circumstance, when clients get an object from the pool, they have those resources immediately available. Typically, they will use the object to do some small unit of work, pushing or pulling data, and then the object will call IObjectContext::SetComplete or IObjectContext::SetAbort and return. With rapid-fire use patterns such as this, pooling yields excellent performance benefits. You can fully leverage the simplicity of the stateless automatic transaction programming model yet achieve performance on par with traditional stateful components.

However, if clients use an object for a long time each time they call it, pooling will make less sense. The speed advantage that you gain is marginal as use time increases relative to initialization time. You get diminishing returns that may not justify the cost of the memory necessary to hold a pool of active objects.

Sharing Cost Across Multiple Clients

A variation on factoring out initialization is that you can use pooling to statistically amortize the cost of acquiring expensive resources. If you take the hit of acquisition or initialization once and then reuse the object, you share that cost across all clients that use the object during its lifetime. Heavy construction time is incurred only once per object.

Preallocating Objects

If you specify a nonzero minimum pool size, that minimum number of objects will be created and pooled when the application starts, ready for any clients that call in to the application.

Governing Resource Use with Pool Management

You can use the maximum pool size to govern very precisely how you use resources. For example, if you have licensed a certain number of database connections, you can control how many connections you have open at any time.

When you take into consideration client use patterns, object use characteristics, and physical resources such as memory and connections, you are likely to find some optimal balance point when you do performance tuning. Pooling objects will yield diminishing returns after a certain point. You can determine what level of performance you require and balance that against what resources are necessary to achieve it.

To facilitate performance tuning when you configure object pooling, you can monitor object statistics for the components in an application. For details, see Monitoring Object Statistics.

Improve Performance of JIT-Activated Components

Object pooling works very well with JIT activation. By pooling objects that are being JIT-activated, you can speed object reactivation. You get the benefits of holding the channel open by JIT activation while mitigating the cost of reactivation. You can use pooling in this case to govern how much memory you wish to allocate to objects that have references active.

You are most likely to be pooling JIT-activated components when they are transactional. Object pooling is optimized to handle transactional components. For more detail, see Pooling Transactional Objects.

See Also

How Object Pooling Works

Requirements for Poolable Objects

Pooling Transactional Objects

Controlling Object Lifetime and State

Using Object Constructor Strings


Requirements for Poolable Objects

Poolable objects must meet certain requirements to enable a single object instance to be used by multiple clients.

Stateless

To maintain security, consistency, and isolation, poolable objects should hold no client-specific state from client to client. You can manage any per-client state by using IObjectControl, performing context-specific initialization with IObjectControl::Activate and cleaning up any client state with IObjectControl::Deactivate. For more detail, see Controlling Object Lifetime and State.

No Thread Affinity

Poolable objects cannot be bound to a particular thread; otherwise, performance could be potentially disastrous. For this reason, poolable objects cannot be marked to run in the apartment model; they must run in the multithreaded apartment or the neutral apartment. In addition, poolable objects should not use thread local storage nor should they aggregate the free-threaded marshaler. For more detail about threading in COM+, see Concurrency.

Note Currently, the Microsoft® Visual Basic® development environment can create only apartment model components. For this reason, Visual Basic components cannot be pooled.

Aggregatable

Poolable objects must support aggregation—that is, they must support being created with a pUnkOuter. When COM+ activates a pooled object, it will create an aggregate to manage the lifetime of the pooled object and to call methods on IObjectControl. For details on writing aggregatable objects, see Aggregation.

Transactional Components

Poolable objects that participate in transactions must manually enlist managed resources. While it is pooled, if your object holds a managed resource such as a database connection, there will be no way for the resource manager to automatically enlist in a transaction when the object is activated in given context. Therefore, the object itself must handle the logic of detecting the transaction, turning off the resource manager's auto-enlistment and manually enlisting any resources that it holds. In addition, a transactional pooled object should reflect the current state of its resources in the parameter values of IObjectControl::CanBePooled. For more detail, see Pooling Transactional Objects.

Implement IObjectControl to Manage the Object Lifetime

Poolable objects should implement IObjectControl, although it is not strictly necessary to do so. Transactional components that are pooled, however, must implement IObjectControl. These components should monitor the state of the resources they hold and indicate when they can't be reused; when IObjectControl::CanBePooled returns false, it will doom a transaction. For more detail, see Controlling Object Lifetime and State.

Language Restrictions

Currently, components developed using Microsoft Visual Basic cannot be pooled because these components will be apartment-model threaded.

Legacy Components

As long as they are non-transactional and conform to the appropriate preceding requirements, components can be pooled even if they were not specifically written with pooling capability in mind. It is not necessary to implement IObjectControl; a component that does not do so simply won't participate in managing its lifetime. If IObjectControl::CanBePooled is not implemented, the object will continue to be reused until the pool attains maximum size.

See Also

How Object Pooling Works

Improving Performance with Object Pooling

Pooling Transactional Objects

Controlling Object Lifetime and State

Using Object Constructor Strings


Pooling Transactional Objects

Transactional components that are to be pooled have special requirements.

Manually Enlisting Resources

Poolable objects that participate in transactions must manually enlist managed resources. If an object holds managed resources between clients, there will be no way for the resource manager to automatically enlist in a transaction when the object is activated in a given context.

The object itself must handle the logic of detecting the transaction, turning off the resource manager's auto-enlistment, and manually enlisting any resources that it holds. The steps for doing this are specific to the resource manager that you are using. If you need to do manual enlistment, consult the documentation for your resource manager.

As described below, objects can be pooled with transaction affinity while a transaction is active and can be activated with transaction affinity if called by a client associated with that transaction. Before enlisting resources, you should first check for transaction affinity. If the object has been taken from the pool specific to that transaction, it has already done work in that transaction and enlisted its resources.

Turning Off Automatic Enlistment

Automatic enlistment should be turned off after the resource is acquired, usually in the object's constructor. That is, you disable automatic enlistment and then connect.

Disabling auto-enlistment can sometimes be a subtle procedure, particularly in the case of layered data access providers. Auto-enlistment is sometimes coupled with connection pooling, as with ODBC, and sometimes not, as with OLE DB. You might need to ensure that auto-enlistment is off at several levels of providers.

Implementing IObjectControl

Poolable objects that participate in transactions must monitor the current state of resources they are holding. If the object detects that it is in a non-reusable state—for example, if a connection is bad—it should return False for IObjectControl::CanBePooled. This will have the effect of both discarding the object instance and dooming the current transaction.

Transaction-Specific Pools

A pool of objects is generally homogenous, and any pooled object not currently in use is good to return to any client. The only exception to this rule is in the case of transactional objects, for which object pooling is optimized. When the client requesting an object has an associated transaction, COM+ will scan the pool for an available object that is already associated with that transaction. If an object with transaction affinity is found, it is returned to the client; otherwise, an object from the general pool is returned.

In this manner, special subpools are maintained containing objects with affinity for a particular transaction. When the transaction commits or aborts, these objects are returned to the general pool with no transaction affinity, ready to be used by any client.

For this reason, when your component manually enlists its managed resources in a transaction, it should first check to see whether they are already enlisted. If so, there is no need to enlist.

See Also

How Object Pooling Works

Improving Performance with Object Pooling

Requirements for Poolable Objects

Controlling Object Lifetime and State

Using Object Constructor Strings


Controlling Object Lifetime and State

A pooled object can participate in how COM+ manages its activity in the pool by implementing IObjectControl. When a pooled object is created, it is aggregated into a larger object that will manage the object by calling the following methods on IObjectControl at regular points in the object's lifecycle:

  • IObjectControl::Activate—Called whenever the object is returned to a client, activated in a specific context.
  • IObjectControl::Deactivate—Called whenever an object is released by the client or, in the case of a JIT-activated object, when it is deactivated.
  • IObjectControl::CanBePooled—Called whenever an object is to be returned to the general pool.

Implementing IObjectControl is optional, except for transactional objects, which should always implement IObjectControl::CanBePooled to monitor the state of the resources they hold. However, it is advisable to implement IObjectControl in most cases because it provides an efficient way to manage the behavior of a pooled object, as described below.

Performing Context-Specific Initialization

Using IObjectControl::Activate, you can initialize the object in the context in which it is activated for a given client. For example, to determine whether the object has transaction affinity (its resources may already be enlisted), you might get the transaction ID associated with the context.

Typically you would use IObjectControl::Activate to perform initialization that is consistent across any methods exposed by the object, treating it as the context-specific portion of the object's constructor.

Cleaning Up Any Client State

Using IObjectControl::Deactivate, you can get rid of any client-specific state that might exist. You should ensure that your object returns to the pool in a completely generic state so that it can be used by any client without compromising security or isolation.

Controlling Reuse of the Object

Using IObjectControl::CanBePooled, you can monitor the internal state of your object and report on whether it is fit for its reuse. If CanBePooled returns True and the pool maximum has not been reached, the object is placed back in the general pool. If CanBePooled returns False, the object is discarded. In the case of transactional components, returning False will doom the current transaction.

Typically, you would keep some global data member for the object, and if you detect a connection to be bad or a resource of some kind to be in a bad state, set this to reflect the current situation and return it through CanBePooled.

If an object does not implement CanBePooled, instances will continue to be reused until the pool maximum level is reached.

See Also

How Object Pooling Works

Improving Performance with Object Pooling

Requirements for Poolable Objects

Pooling Transactional Objects

Using Object Constructor Strings


Using Object Constructor Strings

Object constructor strings are a feature of COM+ that supports generic programming. You can write a single component with a degree of generality so that it can be customized for a particular task using administratively specified constructor strings; that is, you can perform parameterized object construction.

For example, you might use this feature to write a component that holds a generic ODBC connection and later specify an exact DSN for the component administratively. If the system configuration changes, you can change the constructor string accordingly.

When object construction is administratively enabled for your component, COM+ will call the IObjectConstruct::Construct method that it implements. Within that method, you can access the constructor string using IObjectConstructString.

For details on setting a constructor string for a component, see Specifying an Object Constructor String.

For details on writing a component to use constructor strings, see IObjectConstruct and IObjectConstructString.

Using Object Pooling and Constructor Strings Together

You can use object constructor strings in conjunction with pooling to achieve a greater degree of granularity in how you pool and reuse resources. For example, you might create several distinct components, identical except for constructor strings and CLSIDs, to maintain distinct pools of objects holding connections usable by distinct groups of clients. For example, this would be useful if connections are opened in a manner that binds them to particular security roles—such as when the connections are opened with some specific authentication at the database—rendering them non-reusable in the general case.

To do this, you can write a single generic component that relies on object constructor strings, using IObjectConstruct, and recompile it to produce several customizable components each with a distinct CLSID. You can then administratively tailor each component to open an appropriate connection with a constructor string, configure them to be pooled, and they will be maintained in distinct pools per CLSID.

See Also

How Object Pooling Works

Improving Performance with Object Pooling

Requirements for Poolable Objects

Pooling Transactional Objects

Controlling Object Lifetime and State


Just-in-Time (JIT) Activation

Just-in-Time (JIT) activation is an automatic service provided by COM+ that can help you use server resources more efficiently, particularly when scaling up your application to do high-volume transactions. When a component is configured as JIT activated, COM+ can deactivate an instance of it while a client still holds an active reference to the object. The next time the client calls a method on the object, which the client believes to be still active, COM+ will reactivate the object transparently to the client, just in time.

The advantage of JIT activation is that you enable clients to hold references to objects for as long as they need them, without necessarily tying up server resources—such as memory—to do so. Other benefits include the following:

  • From the client perspective, JIT activation greatly simplifies the programming model—the client doesn't have to think about how it uses expensive server objects and server resources. Without JIT activation, when clients are aggressive about releasing server objects, they can incur a significant penalty in frequently calling and releasing objects.

    Note You can refine this performance benefit further by using object pooling. By pooling JIT-activated objects, you can greatly speed object reactivation for clients while reusing whatever resources they might be holding. And doing this gives you more precise control over how much memory is used by a given object on the server. For more detail, see Object Pooling and JIT Activation.

  • By holding long-lived object references, clients keep open the channel to the object for as long as they need it. The farther the client is from the server, the greater the benefits of JIT activation become—because without JIT activation, the cost of activating and marshaling the server object, opening the channel, setting up the proxy and stub, and so on is much greater. With distributed applications, an expensive network round-trip is required with every object creation. As the volume of client calls increases, you want to minimize the frequency of object creation because it can significantly affect the performance of your application.
  • When you JIT activate those objects to which clients hold long-lived references, but which they aren't necessarily using all the time, server memory is not always tied up keeping those objects alive. With lazy activation, memory is used only when the objects are actually needed. This can significantly increase the scalability of your application. The only performance hit that clients see is the time it takes COM+ to reactivate the object—usually just marginally more than the time it takes to allocate memory for the object, and substantially less than the network round-trip for remote object creation.

Enabling JIT Activation

You can enable JIT activation for a component by using either the Component Services administrative tool or the Administrative SDK functions. For details on how to do this, see Configuring JIT Activation.

JIT activation can interact with other configuration properties as follows:

  • When your component requires transactions, JIT activation is necessarily enabled for it. For greater detail, see Transactions and JIT Activation.
  • When your component enables JIT activation, synchronization is automatically set to required. This is described below.

How Deactivation Is Triggered

COM+ deactivates an object based on the status of the doneness bit on the object context. Your object can use this to signal whether or not it is done—that is, ready to be deactivated—during a given method call. For details on doing this, see Setting the Done Bit.

How to Hook Activation and Deactivation

You have the option of having your object manage itself on deactivation and reactivation by implementing the IObjectControl interface. If an object implements this interface, COM+ will call IObjectControl::Deactivate when it deactivates the object and IObjectControl::Activate when it reactivates it. You might use this to do some form of context initialization or cleanup of state.

If you are pooling objects that use JIT activation, it is highly recommended that you implement IObjectControl. For more detail, see Object Pooling and JIT Activation.

Synchronization Requirements

When your component enables JIT activation, synchronization is automatically set to required. The reason for this is straightforward: If two clients were simultaneously calling a JIT-activated component and a method call for one of them returned, causing the object to be deactivated, the other would be left stranded. Therefore access to them must be synchronous.

Statelessness

Using JIT activation does not make sense when your object holds state. You would use JIT activation only when your object holds no state that is going to be lost on deactivation.

Transactional objects are necessarily stateless—you cannot share state across a transaction boundary; otherwise, you violate the isolation of the transactions. Due to the natural use patterns of transactional objects—they do some unit of work and kill the object when the transaction commits or aborts—JIT activation and automatic transactions are closely related. As noted above, configuring an object to require transactions will enable JIT activation automatically. For greater detail, see Transactions and JIT Activation.


Transactions and JIT Activation

JIT activation is closely bound to automatic transactions. When you configure a component so that it requires a transaction or requires a new transaction, JIT activation is automatically enabled as well. The two features naturally work in conjunction. Transactional, JIT-activated components share the following characteristics:

  • Stateless—You would not hold state that would violate transaction isolation, nor would you hold state that would be lost on object deactivation.
  • Rapid use—The canonical use pattern for an object performing work in an automatic transaction is to do some small unit of work, vote, and exit.
  • Repeated use—When transactional work is properly broken up, clients will use the same objects over and over to perform little parcels of atomic work.
  • Deactivated on commit or abort—The way automatic transactions work in COM+, all objects within the transaction boundary are deactivated when the transaction commits or aborts.

Note The ways that you vote in transactions and signal doneness are also closely bound together. For more information, see Setting the Done Bit.

In conjunction with transactional components, JIT activation serves as a big performance enhancement by keeping the channel open as clients hold long-lived references to transactional objects. As further enhancements, you can elect to pool the transactional objects to reuse the resources they hold, speed object reactivation time, and closely manage how you use memory resources for given objects.

See Also

Just-in-Time (JIT) Activation

Setting the Done Bit

Object Pooling and JIT Activation

Configuring JIT Activation


Setting the Done Bit

COM+ will deactivate a JIT-activated object based on the status of a context property—the done bit—as follows:

  • When the done bit is set to True, COM+ will deactivate the object when the current method call returns.
  • When the done bit is set to False, the object will remain active when the current method call returns.

By default, the done bit is set to False when an object is created and its context initialized. (Any object that is JIT activated will be created in its own context so that it will have its own done bit to set.) However, you can change this default setting on a per-method basis by using the auto-done property. You can set the done bit in the following ways:

  • Using IContextState
  • Using IObjectContext
  • Using the auto-done property

Using IContextState

You can use IContextState::SetDeactivateOnReturn to set the done bit to True or False.

You can use IContextState::GetDeactivateOnReturn to get the current status of the done bit from the object context.

Using IObjectContext

You can use the following methods on IObjectContext to set the done bit while simultaneously setting the consistent bit used for voting in transactions:

  • IObjectContext::SetComplete signals both that you are done and that you vote to commit the current transaction. It sets both the done bit and the consistent bit to True.
  • IObjectContext::SetAbort signals that you are done and dooms the current transaction. It sets the done bit to True and the consistent bit to False.
  • IObjectContext::EnableCommit signals that you are not done but that you vote to commit the transaction. It sets the done bit to False and the consistent bit to True.
  • IObjectContext::DisableCommit signals that you are not done and that you vote not to commit the transaction at this time, usually because the state is inconsistent. It sets both the done bit and the consistent bit to False.

Using the Auto-Done Property

You can administratively configure a method such that the object will automatically be deactivated on method return. The auto-done property appears in the Component Services administrative tool, on the General tab of the method Properties page, as Automatically deactivate this object when this method returns. The effect of selecting this check box is to change the default setting on the done bit to be True whenever that method is called.

If you check auto-done and then take no action to set the done bit, it will be True on method return and COM+ will deactivate the object. By selecting this option, you can eliminate the repetitive method calls for voting in transactions. Because the default setting for the consistency bit is True and you have changed the done bit to True as well, if you take no action to change these you will automatically be calling IObjectContext::SetComplete.

However, there is one caveat to this behavior: COM+ will examine the HRESULT that the method returns. If that HRESULT indicates failure, the consistency bit will be set to False and it will be as though you had called IObjectContext::SetAbort.

To summarize, if you select auto-done for a method and don't take any action to set any bits, and if an HRESULT(hr) is returned, the following will be true:

  • If SUCCEEDS(hr), it is as though you called SetComplete.
  • If FAILED(hr), it is as though you called SetAbort.

For more information about voting in transactions, see Automatic Transactions Through COM+.

See Also

Just-in-Time (JIT) Activation

Transactions and JIT Activation

Object Pooling and JIT Activation

Configuring JIT Activation


Object Pooling and JIT Activation

JIT activation exists essentially to strike a compromise between greedy clients and greedy servers for the sake of getting optimal performance—clients get to keep object references, while servers get to more closely manage memory utilization.

You can refine this further by using object pooling. By pooling objects that are JIT activated, you can dedicate a certain amount of memory to hold a certain number of objects active in memory, ready for immediate reuse. This makes the most sense when objects are expensive to create, as in the case where they hold multiple resources.

Pooling JIT-activated objects in this manner, you can achieve the following benefits:

  • Greatly accelerated object reactivation times.
  • Reuse of any expensive resources the objects are holding.
  • More precise governing of memory and resource use for the pooled objects.
  • Retention of administrative flexibility so that your application can scale to use available resources and adapt to changing performance requirements.

See Also

Just-in-Time (JIT) Activation

Transactions and JIT Activation

Setting the Done Bit

Configuring JIT Activation

Object Pooling


Queued Components

Queued Components, a key feature of COM+ based on Microsoft® Message Queuing Services (MSMQ), provides an easy way to invoke and execute components asynchronously. Processing can occur without regard to the availability or accessibility of either the sender or the receiver.

A shop-at-home television network is an example of asynchronous processing. Viewers call in their purchases, and the information is taken by order processors—who may or may not be connected to the server. In an asynchronous, disconnected scenario, the orders are taken as quickly as they can be phoned in and are queued for later retrieval and processing by the server.

In COM terms, a queue is a storage area that saves messages for later retrieval. Queuing provides a mechanism for connectionless communication. That is, the sender and receiver are not connected directly and communicate only through queues. Queuing provides a way to hold the information until the receiver is ready to obtain it. The sender and receiver are indirectly communicating so that each can operate independently, unaffected by the other.

In the past, an in-depth knowledge of marshaling was necessary to queue, send, and receive asynchronous messages. Now, using method calls that are easily understood and used by component developers, the COM+ Queued Components service automatically marshals data in the form of an MSMQ message. And because the Queued Components service offers built-in support for transactions, an inconsistent state cannot compromise data if a server failure occurs.

The following topics in this section contain information required for designing and writing queued components:

  • Benefits of Queued Processing
  • Queued Components Architecture
  • Transactional Message Queuing
  • Creating and Providing Security for Queues
  • MSMQ Message Authentication
  • Queued Components Sample
  • Developing Queued Components
  • Starting Queued Components
  • Identifying Queued Components
  • Using the Queue Moniker to Activate Queued Components
  • Using the New Moniker to Activate Queued Components
  • Handling Server-Side Errors
  • Handling Client-Side Errors
  • Persistent Client-Side Failures
  • Using Queued Components Security
  • Queued Components Interdependencies


Benefits of Queued Processing

When designing new applications, developers must consider the implication of coding components for real-time (or synchronous) processing versus queued (or asynchronous) processing. Ultimately, the choice depends on the requirements of the specific application and determining which method better serves the underlying business logic of the application. As a guideline, queued processing offers the following advantages over real-time processing:

  • Reduced dependency on component availability
  • Shorter component lifetimes
  • Uninterrupted productivity when using disconnected applications
  • Message reliability
  • Efficient server scheduling

Component Availability

In a real-time processing application, if just one component of the transaction is not available—perhaps because of server overload or networking problems—the entire process is blocked and cannot complete. However, an application using the COM+ Queued Components service separates the transaction into activities that must be completed now and those that can be completed at a later time. Messages are safely queued for later processing, and the requesting component is free for other tasks.

Component Lifetimes

An application using the Queued Components service allows the server component to operate independently of the client. As a result, server components can complete more quickly. In a real-time system, the server component exists from the time it is created until the object is finally released. The server waits for the client to make method calls and for results to be returned, which negates the rapid cycling of server objects and limits server scalability.

Disconnected Applications

Sales of laptops, notebooks, and palm computers have created a need for applications that service occasionally disconnected clients or mobile users. In a queued system, these users can continue to work in a disconnected scenario or when not connected to the server, and they can later connect to the databases or servers to process their requests. For example, a salesperson can take orders from customers and later connect to the shipping department to process those orders.

If you have a component that can be run either connected or disconnected, messages are traveling in one direction and there is rarely a need to switch back and forth. For example, in the order-taking scenario, the shipping component receives the message and processes it. It may generate another component for billing or auditing. The client commits before the server ever starts. The message isn't sent until the application commits.

The following illustration shows the flow of information in a disconnected scenario:

Message Reliability

The MSMQ queue manager is a powerful tool that uses database techniques to protect data in a robust way. In the event of a server failure, the queue manager ensures that transactions are rolled back so that messages are not lost.

Server Scheduling

An application using queued components is well suited to time-shifted component execution, which defers uncritical work to an off-peak period. This is the same useful concept that was applied to traditional batch mode processing. Similar requests can be deferred for contiguous execution by the server rather than requiring the server to react immediately to a wide variety of requests.

See Also

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Queued Components Architecture

The COM+ Queued Components service enhances the COM programming model by providing an environment in which a component can be invoked either synchronously (real-time) or asynchronously (queued)—the component need not be aware of this environment.

Messaging applications are like transacted e-mail between programs. The requestor sends a message to the server; when the server gets to it, the message is processed and a response is sent back to the requestor. Like e-mail, a messaging system must handle the network details and ensure that only one copy of the message is flowing from client to server and back. The queue manager is responsible for this. Different queue managers provide various levels of service, such as determining how many copies of the message are delivered—for example, at most one, at least one, or exactly one.

The COM+ Queued Components service supports the delivery of a specific message exactly once. The message is delivered one time from the client to the server and executes a transaction to receive the message, update the database, and commit. The input message is deleted as part of that transaction. If the transaction fails after adding a message to a queue, MSMQ rolls back so that the message send operation is discarded. If the transaction fails after removing a message from the queue (which can happen at the receive side), MSMQ rolls back so that the message receive operation is undone and the message is not lost. A subsequent server-side transaction will again have a chance to process the message.

The COM+ Queued Components service consists of the following parts:

  • Recorder (for the client or send side).
  • Listener (for the server or receive side).
  • Player (for the server or receive side).
  • Message mover utility for moving messages from one queue to another.

The Recorder

In a typical Queued Components scenario, the client calls a queued component. The call is made to the Queued Components recorder, which packages it as part of a message to the server and puts it in a queue. The recorder marshals the client's security context into the message and records all of the method calls for an object. In its role as proxy for the server component, the recorder selects interfaces from the queuable interfaces in the COM+ catalog.

A representation of the recording is sent to MSMQ as a message to be sent to a server. When the queued component has the transacted attribute "Requires transaction" or "Transaction supported", MSMQ accepts delivery of the message only if the client-side transaction commits and the MSMQ queue is transacted, which is the default normally established. In the "Requires new transaction" case, MSMQ can accept the message even if the client-side transaction aborts.

The Listener

The Queued Components listener retrieves the message from the queue and passes it to the Queued Components player.

The Player

The player unmarshals the client's security context at the server side and then invokes the server component and makes the same method calls. The method calls are not played back by the player until the client component completes and the transaction that recorded the method calls commits.

The Message Mover Utility

The Queued Components message mover is a tool that moves all failed MSMQ messages from one queue to another so that they can be retried. The message mover utility is an Automation object that can be invoked with a VBScript.

See Also

Benefits of Queued Processing

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Transactional Message Queuing

The COM+ Queued Components service is developed on transactional message queuing. Often, applications can be developed using a business transaction or workflow that is split into several smaller transactions or activities. These activities are separated in time and then connected using reliable message queues.

A shop-at-home television network is a business example that lends itself to using transactional message queuing. Orders are collected from the phone as quickly as possible. The orders are captured now and will be sent to a variety of vendors sometime later. The application is separated into parts that you must do right now and parts that you must do but can do later. The following illustration shows a workflow divided into three transactions or activities:

  1. The first transaction involves the order entry database and the queue manager. MSMQ moves the message from one queue to another queue, exactly one time, using transacted capabilities. If the database is updated, there is a message on the queue. If the message doesn't reach the queue, it is aborted and the database update is backed out.
  2. Sometime later, the queue manager discovers that the server is available. There is no application polling for the existence of the server. The queue manager handles this as the second transaction.
  3. The third transaction involves a shipping database query and the update of the shipping database. If the server fails in the middle of this transaction, the message is not lost on the input queue. It is undone or rolled back. This ensures that the integrity of the data and databases is maintained during the transactions.

The following illustration shows a more detailed flow process for the three transactions:

See Also

Benefits of Queued Processing

Queued Components Architecture

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Creating and Providing Security for Queues

This topic explains how to create a queue and how the COM+ Queued Components service provides security for queues.

Creating a Queue

COM+ automatically creates a queue when the user selects the Queued check box on the Queuing tab of the Application property page. COM+ run-time always uses the name of the application for its queue name. If a queue name matches that of an existing application when the Queued check box is selected, COM+ uses the existing queue—whether the queue is transacted or nontransacted.

Note The MSMQ PathName parameter is a combination of the Remote Server Name (RSN) and the COM+ application name. The RSN refers to the target of a remote activation. You specify an RSN during the installation of a client exportable application on a client computer. The installation procedure uses the RSN to direct activation to a specified client computer. For more information about queue names, refer to the table of parameters in the "Queue Moniker Parameters" section in Using the Queue Monike to Activate Queued Components. For more information about queue attributes, see Developing Queued Components.

MSMQ Transactional Behavior

Queues that are created by the COM+ 1.0 Administration Library or the Component Services administrative tool are created with the MSMQ transactional attribute. MSMQ does not permit modification of a queue's transactional attribute—if modification is necessary, the queue must be deleted and re-created.

There is an option for creating nontransactional MSMQ queues. The queue can be generated with MSMQ Explorer, and you can use the Component Services administrative tool to mark the application queued. The Queued Components service will use the queue generated by MSMQ Explorer if the name of the queue is the same as the name of the application.

Providing Security for a Queue

COM+ creates queues with the permissions described in the following table.

Permission | Type | Description
Send | Everyone | Everyone has permission to send transactions to the queue.
Read | Owner, members of the Administrators group, and a Local System Account | Only members of these groups can read messages from the application queue.

If the COM+ application has any security requirements other than Authentication level for calls set to None, the Queued Components service will use MSMQ message authentication. However, with Windows 2000 64-bit Edition, you can set the Authentication level for calls to None for the secured application and the authentication level will be honored.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


MSMQ Message Authentication

If the COM+ application has any security requirements other than Authentication level for calls set to None, the COM+ Queued Components service will use the MSMQ message authentication. However, with Windows 2000 64-bit Edition, you can set the Authentication level for calls to None for the secured application and the authentication level will be honored.

Normally, the Queued Components service depends on the MSMQ message authentication mechanism, which uses certificates and digital signatures to assure that the received message came from the person designated as the sender. Certificates and authentication are not available in the MSMQ workgroup environment because there is no central Active Directory to store and dispense the certificates upon which message authentication is based. Applications in the MSMQ workgroup environment may not be invoked if they require a security level other than none.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Queued Components Sample

The Microsoft® Platform SDK includes a queued components sample that illustrates how to develop components and applications that are queuable. The sample includes a tour file that provides build instructions and documentation on the sample.

Click the buttons below to jump to the queued components sample.

Queued Components Sample SDK Not Installed SDK Not Installed

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Developing Queued Components

From a development perspective, the COM+ Queued Components service consists of the following:

  • The new moniker to create object instances directly, or pass a CLSID to the "queue" moniker.
  • The queue moniker to create the queued components recorder for a CLSID.
  • Recorder for the client or send side.
  • Listener for the server or receive side.
  • Player for the server or receive side.
  • Message mover tool that moves messages from one queue to another.

With synchronous out-of-process method calls, COM records a method call on the proxy (client) side and plays back the method call on the stub (server) side. In contrast, using queued components makes a recording of all of the method calls for an object and does not play them back until after the client component completes its use of the server object and the transaction that recorded the method calls commits. The recording is sent to Message Queuing Services (MSMQ) as a message to be sent to a server. MSMQ accepts the message for delivery only if the transaction commits.

Client-Side Architecture

The recorder, as the proxy for the server component, selects interfaces from the COM+ catalog (maintained by the Component Services administrative tool or the COM+ administrative interfaces). Generally, this is a straightforward operation in which the client issues QueryInterface presenting an IID that the Queued Components recorder looks up in the list of available, queuable interfaces.

Note The Queued Components service supports interfaces derived from IDispatch. If one or more interfaces inherit from IDispatch, the Queued Components recorder chooses one of the existing interfaces to return. The following rules are used when the Queued Components service receives a QueryInterface for IDispatch:

  1. If the default interface inherits from IDispatch, the default interface is selected.
  2. If no interface is marked as default but only one interface inherits from IDispatch, that interface is selected.
  3. If no interface is marked as default and multiple interfaces inherit from IDispatch, the Queued Components recorder returns a NULL interface pointer and E_NOINTERFACE error code. The Queued Components recorder does not attempt to guess which interface should be selected.

Server-Side Architecture

To process messages from the queue, a COM+ application must be running on the server side. When messages arrive on the queue, a player thread is scheduled and the player creates the server object and makes all the method calls that were recorded. For additional information on starting queued applications, see Starting Queued Components.

Queue Attributes

Queues created with the Component Services administration tool are marked "transactional."

The following users and groups have full control over the queue:

  • The owner, who is the logged-in user marking the application as queued with the Component Services administrative tool.
  • All local administrators.
  • The local system account.

The following topics in this section discuss special development considerations and other specific areas that developers should be aware of when working with the Queued Components service:

  • Special Development Considerations for Queued Components
  • Poison Messages
  • Passing Objects as Parameters
  • Threading Considerations
  • Receiving a Response

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Special Development Considerations for Queued Components

The COM+ Queued Components service requires all application methods to contain only in parameters, with no return values. Because the server object is not necessarily available when the client makes the call, server results can be returned by sending a message that creates another object. In this way, two-way communication occurs not in every case but only when it is required, by a series of one-way messages between objects.

To use queued components, you must have Windows Message Queuing Service (MSMQ) already installed. MSMQ must be selected during the operating system setup or by using Add/Remove programs. MSMQ is not installed automatically; you must specifically request it to be installed. An internal MSMQ certificate is created as part of the NT logon by the current NT build.

Queued Components Security Limitations

The MSMQ workgroup configuration does not permit the Queued Components service to support application security. If you've installed MSMQ with the Workgroup configuration, you must also disable security on each queued application accessed in this configuration. This must be done at both client and server if the application has already been exported.

To disable security on a queued application

  1. In the Component Services administration tool, right-click the queued application.
  2. Click Properties, and then click the Security tab.
  3. Change Authentication level for calls to None.

Normally, the Queued Components service depends on the MSMQ message authentication mechanism, which uses certificates and digital signatures to assure that the received message came from the person designated as the sender. Certificates and authentication are not available in the MSMQ workgroup environment because there is no central Active Directory to store and dispense the certificates upon which message authentication is based. Applications in the MSMQ workgroup environment may not be invoked if they require security other than None.

Note The default for Authentication level for calls is Packet, which will not work with an MSMQ workgroup configuration.

See Also

Developing Queued Components

Poison Messages

Passing Objects as Parameters

Threading Considerations

Receiving a Response


Poison Messages

A poison message is a message that cannot be processed for some reason, perhaps because of a problem with the server or queuing system. The transaction is rolled back, and the message goes to the top of the queue. When the message is dequeued again, the same condition occurs. This message can continue looping indefinitely unless something is done to correct the problem.

The Queued Components service handles the poison message by using a series of retries. After several retries, the message is moved to a final resting queue. Messages stay in the resting queue until they are manually moved by using the queued components message mover utility. For more information on using the message mover, see Exception Handling.

The poison message situation can also be resolved programmatically, using the FinalServerRetry method of the IPlaybackControl interface, which informs the server-side component author that all attempts to play back the deferred activation have failed.

If you discover a poison message, you might be able to solve the underlying cause of the problem quickly. For example, if the server was offline for some reason, you can bring the server back online. If you cannot solve the problem quickly, you can automatically generate another transaction that notifies the requestor that the transaction did not occur. The requestor can then make a compensating transaction that reverses the effect of a transaction that has already committed.

See Also

Developing Queued Components

Special Development Considerations for Queued Components

Passing Objects as Parameters

Threading Considerations

Receiving a Response


Passing Objects as Parameters

The COM+ Queued Components service does not enable queuing for every existing COM component. There are restrictions on the types of methods that can be queued. Because of messaging constraints, methods must adhere to the following rules:

  • Contain input parameters only
  • Return no application-specific result

Additionally, there are restrictions on the types of input parameters that can be passed to a queued component. At run time, the Queued Components service packages the arguments at the client and passes them to the server component by using MSMQ. Simple types, such as integers and Booleans, can be marshaled easily—more complex types cannot be marshaled without help.

In the case of passing an object through a queued component's method call as a parameter, the client passes the object to the recorder. The recorder marshals the object into an MSMQ message and passes it to the listener. After the listener picks up the message and passes it to the player, the player must reinstantiate the object to dispatch it to the method call specified by the client. Based on the lifetimes of the client and server in a queued environment, the implication is that these objects must be able to marshal by value. Since COM+ does not provide pass-by-value semantics for standard COM objects, the recorder and player need help from the component to marshal and unmarshal the object.

Object references that support IPersistStream can be used as parameters to method calls on queued components. The object cannot make assumptions about when it will be reinstantiated. For example, the server may be unavailable or the server component may not be started until later in the day. Objects that do not support IPersistStream will return an error.

A recorder can be passed as a parameter to a method call made to another recorder and is implicitly passed when a queued component object reference is passed as a parameter to a method call. This is useful when a client wants notification of the results of a queued call. The client can make a set of method calls on a queued component. As one of the method calls, the client can pass a notification object as a parameter. The notification object can be used as a component that notifies the client about the success or failure of the set of method calls made on the queued component. The queue associated with the notification object can be local to the client. The queued component makes a method call on the notification object reference indicating whether the set of method calls passed or failed. The notification object can store the results in a database for auditing purposes and perhaps send an e-mail to the user if the result was a failure. By using a notification object, the result can be posted to the original client computer without requiring the client application to be running.

Visual Basic Persistable Objects

Microsoft® Visual Basic® 6 allows persistable objects to be created. These objects support IPersistStream and can be passed as parameters to queued component method calls. Before a Visual Basic object can be passed to a queued component, the persistable object must be initialized. This can be done in one of the following two ways:

  • If the application creating the persistable object is written in Visual Basic, the Visual Basic run-time handles the object initialization automatically.
  • If the application that creates the Visual Basic persistable object is written in a language other than Visual Basic, such as Microsoft Visual C++®, the application must explicitly initialize the component by either querying for the persistable object's IPersistStream interface or calling IPersistStream::Init, IPersistStream::InitNew, or IPersistStream::Load.

ADO Recordsets and OLE DB Rowsets

Passing recordsets or rowsets between components allows one component to process the results of queries executed by another component. This is helpful when deploying an application across multiple computers. Recordsets and rowsets can be passed as method parameters to queued components, with the following restrictions:

  • Server-side recordsets cannot be marshaled using IPersistStream. Only client-side recordsets can be passed as parameters to a queued component method call. The following example shows how to create a client-side record set:
    dim rs as new adodb.recordset
rs.cursorlocation = adUseClient
rs.open "select * from products", "DSN=advWorks", adOpenStatic, adLockOptimistic
  • If you work directly with OLE DB, the OLE DB rowset must be defined as a client-side rowset.

See Also

Developing Queued Components

Special Development Considerations for Queued Components

Poison Messages

Threading Considerations

Receiving a Response


Threading Considerations

The Queued Components recorder is capable of running in the process's multithreaded apartment (MTA) or in a single-threaded apartment (STA). When the recorder is run in the STA, COM+ requires that each apartment containing objects must have a Windows message queue to handle calls from other processes and apartments within the same process. This means that the thread's work function must have a message loop. When a queued component is instantiated, the interface pointer returned is always a proxy interface pointer rather than a direct interface pointer. The pointer is actually a reference to an instance of the recorder. If this recorder interface reference is passed to another thread, the original thread must still be running the Windows message loop so that the receiving thread can unmarshal the interface. If this is not the case, the receiving thread hangs in a call to CoUnmarshalInterface.

If you are using Win32® primitives to synchronize the threads, consider using MsgWaitForMultipleObjects instead of other synchronization functions. This checks for messages in the queue as well as the state of the synchronization object.

See Also

Developing Queued Components

Special Development Considerations for Queued Components

Passing Objects as Parameters

Poison Messages

Receiving a Response


Receiving a Response

There are a variety of ways to write applications to receive a response. On occasion, you may want to receive notification from the server when the transaction completes. In some cases, you need an answer for every component that lets you know that the transaction really has been processed. It may also be feasible for an application not to require any notification from the server. Frequently it is sufficient to check results only for exceptional cases.

When transacted components communicate through message queues, the requestor and server have different lifetimes. After the requestor sends a message to the server, the message does not leave the queue manager until the transaction commits. Participating components have all terminated or become stateless before the transaction commit completes. After the first transaction commits, the queue manager moves the message exactly one time to the destination queue. Then the server-side transaction begins. Messages between the requestor and server are one-way, consisting of input values rather than pointers to places for the server-side components to store results.

If a notification from the server is required, another one-way message can be formed. The server can create a response object. For example, an order entry system might have an order object, ship object, and notify object that goes back to the client to update the client-side database and notify the requestor that shipping has occurred.

See Also

Developing Queued Components

Special Development Considerations for Queued Components

Passing Objects as Parameters

Poison Messages

Threading Considerations


Starting Queued Components

Making method calls on a queued component does not directly execute the method. Rather, MSMQ marshals and stores method calls and parameters in a queue where they are later retrieved and executed by the queued component. Unlike activating a remote DCOM object, the queued component is not instantiated when a method is called. This is the basic idea behind queued components—queued components need not be instantiated at the same time as the calling application.

Following are the three ways to activate an application containing queued components:

  • Manually
  • Using scripting and the task scheduler
  • Programmatically

Note The descriptions for activating a queued application assume that the application is marked as queued and that the listener check box is enabled.

Manually Starting a Queued Application

You can use the Component Services administration tool to start a queued application.

To manually start a queued application

  1. From the COM+ Applications folder in the Component Services administration tool, select the application you want to start.
  2. Right-click the application.
  3. Click Start.

Starting a Queued Application with Scripting

All COM+ administration tasks are available by scripting. You can use scripting to start and stop an application. The following example shows how to start two applications (QCShip and QCNotify):

dim cat
set cat = CreateObject ("COMAdmin.COMAdminCatalog")
cat.StartApplication ("QCShip")
cat.StartApplication ("QCNotify")

You can put this script under the control of the task scheduler to execute it as required. For example, the script can be run on system reboot if the applications are to be permanently available. If the application is to process transactions in batch mode, the script can be run at a certain time each day in conjunction with a shutdown script to be sure the batch processing stops at a specific time.

Programmatically Starting a Queued Application

The complete set of COM+ Administrative SDK functions is available by using COM objects. This allows any program to start and stop COM+ applications as required.

Note When a COM+ application is started, it is the application that is running, not the individual components within the application. If an application calls a nonqueued component, the COM+ application that contains the component is started. If the listener check box is enabled, the listener also starts and begins processing for messages for queued components. While the Queued Components service can be started in this way, if you package queued and nonqueued components into a single COM+ application, be sure that you really want queued components to start if a nonqueued component is executed. If this is not the case, package the queued components into a COM+ application that is separate from the other components.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Identifying Queued Components

The Component Services administrative tool allows you to specify whether an application is queued and when to start a queue listener. Additionally, a queuable component can be identified as such by adding the QUEUEABLE attribute macro to the Interface section of the Interface Definition Language (IDL) source file for all interfaces that are queuable.

#include "mtxattr.h"
[ object, dual, uuid(…), helpstring(IShiphip"), QUEUEABLE ]
interface IShip:IDispatch{
   [propput, id(1)] HRESULT CustomerId ([in] long CustId);
   [propput, id(2)] HRESULT OrderId ([in] long OrderID);
   [id(3)] HRESULT LineItem ([in] long Qty);
   [id(4)] HRESULT Process ();
}
[ uuid(…), helpstring("QCSamp1 TypeLib") ]
library QCSamp1 {
   [ uuid (…), helpstring("Cship") ]
   coclass Ship { [default] interface IShip;}
};

If the interface satisfies the queuable constraints, you can select the check box in the Component Services administrative tool.

Remember that a queuable interface must contain only in parameters—no out parameters and no return values. These characteristics are verified by analyzing the type information during component installation. If the interface is not queuable, the check boxes are disabled. For additional information on using the Component Services administrative tool to specify queued applications, see "Administering Queued Components" in the Component Services online help.

A component with at least one queuable interface is a queuable component. For a component to be invoked by a queue, the interfaces must be marked queuable and the component must be installed in a queued application. However, a queuable component can be a component of a nonqueued application.

After the queued application is installed at the server, it can be made available to clients by exporting the application and then importing the application at each client.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Using the Queue Moniker to Activate Queued Components

The queue moniker is used to activate a queued component. The queue moniker requires that it receive the class ID (CLSID) of the object to be invoked from the new moniker directly to the right of it. When left-prefixed, the new moniker passes the CLSID to the moniker to the left of it.

The CoGetObject display name parameter is "queue:/new", followed by the program ID or string-form GUID, with or without braces, of the server object to be instantiated. The following examples show three valid activations of a component with the queue moniker:

  1. CoGetObject (L"queue:/new:QCShip.Ship", NULL, IID_IShip, (void**) &pShip);
  2. CoGetObject (L"queue:/new:{812DF40E-BD88-11D0-8A6D-00C04FC340EE}", NULL, IID_IShip, (void**) &pShip);
  3. CoGetObject (L"queue:/new:812DF40E-BD88-11D0-8A6D-00C04FC340EE", NULL, IID_IShip, (void**) &pShip);

Queue Moniker Parameters

The queue moniker accepts optional parameters that alter the properties of the message sent to MSMQ. For example, to cause the MSMQ message to be sent with a priority 6, the queued component would be activated as follows:

CoGetObject (L"queue:Priority=6,ComputerName=foo/new:QCShip.Ship", NULL, IID_IShip, (void**) &pShip);

The following table lists the queue moniker parameters that affect the destination queue.

Parameter | Description
ComputerName | Specifies the computer name portion of an MSMQ queue path name. The MSMQ queue path name is formatted as ComputerName\QueueName. If not specified, the computer name associated with the configured application is used.
QueueName | Specifies the MSMQ queue name. The MSMQ queue path name is formatted as ComputerName\QueueName. If not specified, the queue name associated with the configured application is used. To get a nontransacted queue, you can specify the queue name first and then create a COM+ application of the same name.
PathName | Specifies the complete MSMQ queue path name. If not specified, the MSMQ queue path name associated with the configured application is used. The path can be specified in the following form for an MSMQ workgroup installation and the destination name will be overridden: Queue:PathName=ComputerName\PRIVATE$\AppName/new:Myproject.CMyClass Note Both the C and Microsoft® Visual C++® programming languages require two backslashes to represent one backslash within string literals—for example, chicago\\payroll.
FormatName | When you mark a COM+ application as queued, COM+ creates an MSMQ queue whose name is the same as the application. The MSMQ format name of that queue is in the COM+ catalog, associated with the COM+ application. The format name can be specified in the following form for an MSMQ workgroup installation and the destination name will be overridden: Queue:FormatName=DIRECT=OS:ComputerName\PRIVATE$\AppName/new:ProgId In an Active Directory configuration, "PRIVATE$" is not specified as part of the queue name.

Note Optional queue moniker parameters are processed left-to-right. Specify each keyword only one time. Specifying the PathName parameter replaces both the ComputerName and QueueName parameters. A specific FormatName parameter deletes prior knowledge of a ComputerName, QueueName, and PathName parameter.

Associating the Queued Components Listener to a Specific Private Queue

The Queued Components listener receives only from queues associated with the COM+ application marked queued. When you mark a COM+ application as queued, COM+ creates an MSMQ queue whose name is the same as the application. The MSMQ format name of that queue is in the COM+ catalog, associated with the COM+ application. When the COM+ application is started and marked as listen, a listener in the COM+ application process is started and the queue is opened. The following table lists the queue moniker parameters that affect the MSMQ message.

Parameter | Description
AppSpecific | Specifies an unsigned integer—for example, AppSpecific=12345.
AuthLevel | Specifies the message authentication level. An authenticated message is digitally signed and requires a certificate for the user sending the message. Acceptable values: MQMSG_AUTH_LEVEL_NONE,0 MQMSG_AUTH_LEVEL_ALWAYS,1
Delivery | Specifies the message delivery option. This value is ignored for transacted queues. Acceptable values: MQMSG_DELIVERY_EXPRESS,0 MQMSG_DELIVERY_RECOVERABLE,1
EncryptAlgorithm | Specifies the encryption algorithm to be used by MSMQ to encrypt and decrypt the message. Acceptable values: CALG_RC2, CALG_RC4 Any integer value that is acceptable to MSMQ for an EncryptAlgorithm.
HashAlgorithm | Specifies a cryptographic hash function. Acceptable values: CALG_MD2, CALG_MD4, CALG_MD5, CALG_SHA, CALG_SHA1, CALG_MAC, CALG_SSL3_SHAMD5, CALG_HMAC, CALG_TLS1PRF Any integer value that is acceptable to MSMQ for a HashAlgorithm.
Journal | Specifies the MSMQ message journal option. Acceptable values: MQMSG_JOURNAL_NONE,0 MQMSG_DEADLETTER,1 MQMSG_JOURNAL,2
Label | Specifies a message label string up to MQ_MAX_MSG_LABEL_LEN characters.
MaxTimeToReachQueue | Specifies a maximum time, in seconds, for the message to reach the queue. Acceptable values: INFINITE LONG_LIVED Number of seconds
MaxTimeToReceive | Specifies a maximum time, in seconds, for the message to be received by the target application. Acceptable values: INFINITE LONG_LIVED Number of seconds
Priority | Specifies a message priority level, within the MSMQ values permitted. Acceptable values: MQ_MIN_PRIORITY,0 MQ_MAX_PRIORITY,7 MQ_DEFAULT_PRIORITY,3 Number between 0 and 7
PrivLevel | Specifies a privacy level, used to encrypt messages. Acceptable values: MQMSG_PRIV_LEVEL_NONE, NONE, 0 MQMSG_PRIV_LEVEL_BODY, BODY, MQMSG_PRIV_LEVEL_BODY_BASE, BODY_BASE, 1 MQMSG_PRIV_LEVEL_BODY_ENHANCED, BODY_ENHANCED, 3
Trace | Specifies trace options, used in tracing MSMQ routing. Acceptable values: MQMSG_TRACE_NONE,0 MQMSG_SEND_ROUTE_TO_REPORT_QUEUE,1

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Using Queued Components in Workgroup mode

To use Queued Components in workgroup mode, the COM+ application's Authentication level for calls has to be None to allow for unsigned MSMQ messages. When creating your queued component, you can do it by using the queue moniker in two ways for an MSMQ workgroup mode, using the CLSID or ProgID of the object:

  1. Set oMyQC = GetObject("queue:/new:MyProject.CMyClass")
  2. Set oMyQC = GetObject ("queue:/new:812DF40E-BD88-11D0-8A6D-00C04FC340EE")

Note The Visual Basic GetObject function, in the examples above, can also be used with the queue and new moniker to call a queued component from an Active Server Pages (ASP) page. The examples require that the MyProject component be installed as a queued component and the COM+ application be configured as queued in the Component Services administration tool.

However, if overriding the destination name in an MSMQ workgroup configuration, the completed FormatNam or PathName parameter should be specified. The following example demonstrates how to specify the format name by overriding the destination name:

set hw = GetObject("Queue:FormatName=direct=OS:ComputerName\PRIVATE$\AppName/new:Myproject.CMyClass")

The following example demonstrates how to specify the path name by overriding the destination name:

set hw = GetObject("Queue:PathName=ComputerName\PRIVATE$\AppName/new:Myproject.CMyClass")

The QueueName and ComputerName parameters cannot be overridden because of the naming requirements of MSMQ. The queue moniker tries to form an MSMQ path name by forming the path name string "computername\queuename." The queue moniker attempts to get the MSMQ format name, necessary for opening the queue, through the MQPathNameToFormatName function. However, this function fails in an MSMQ workgroup configuration because of the lack of an Active Directory.


Using the New Moniker to Activate Queued Components

A component can be directly activated by using the COM library function CoGetObject and the new moniker. The new moniker accepts a Program ID or a CLSID (with or without braces) for the component to be activated. The new moniker can be used with any COM component supporting IClassFactory, not just a queued component. When not left-prefixed, the new moniker calls CoCreateInstanceEx.

The following examples show three valid activations of a component with the new moniker:

  1. CoGetObject (L"new:QCShip.Ship", NULL, IID_IShip, (void**) &pShip);
  2. CoGetObject (L"new:{812DF40E-BD88-11D0-8A6D-00C04FC340EE}", NULL, IID_IShip, (void**) &pShip);
  3. CoGetObject (L"new:812DF40E-BD88-11D0-8A6D-00C04FC340EE", NULL, IID_IShip, (void**) &pShip);

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Handling Server-Side Errors

The listener and player work together to deal with poison messages. If a transaction that is being played back fails, MSMQ moves the input message back to the input queue. The player aborts the transaction if it receives a failed HRESULT from the server component or if it catches an exception. If the problem persists, the listener can loop continuously in the following pattern:

  • Dequeues the message
  • Instantiates the object
  • Suffers a rollback
  • Puts the message back on the top of the queue

The Queued Components service handles this failure by using a series of application-specific retry queues. Created when the component is installed, there are seven queues for each application:

  1. The normal input queue. The name of this queue is the COM+ application name. This is an MSMQ public queue.
  2. The first retry queue. Messages are moved here if the transaction repeatedly fails when processing messages from the normal input queue. Messages on this queue are processed after one minute. A message can be retried three times on this queue before being moved to the back of the second retry queue. This queue is named ApplicationName_0. This queue is a private MSMQ queue.
  3. The second retry queue. Messages are moved here if the transaction repeatedly fails when processing messages from the first retry queue. Messages on this queue are processed after two minutes. A message can be retried three times on this queue before being moved to the back of the third retry queue. This queue is named ApplicationName_1. This queue is a private MSMQ queue.
  4. The third retry queue. Messages are moved here if the transaction repeatedly fails when processing messages from the second retry queue. Messages on this queue are processed after four minutes. A message can be retried three times on this queue before being moved to the back of the fourth retry queue. This queue is named ApplicationName_2. This queue is a private MSMQ queue.
  5. The fourth retry queue. Messages are moved here if the transaction repeatedly fails when processing messages from the third retry queue. Messages on this queue are processed after eight minutes. A message can be retried three times on this queue before being moved to the fifth retry queue. This queue is named ApplicationName_3. This queue is a private MSMQ queue.
  6. The fifth retry queue. Messages are moved here if the transaction repeatedly fails when processing messages from the fourth retry queue. Messages on this queue are processed after sixteen minutes. A message can be retried three times on this queue before being moved to the final resting queue. This queue is named ApplicationName_4. This is a private MSMQ queue.
  7. An application-specific final resting queue. Messages are moved here if the transaction repeatedly aborts when attempted on the fifth retry queue. This queue is named ApplicationName_DeadQueue. This is a private MSMQ queue. The final resting queue is not serviced by a queue listener. Messages stay here until they are manually moved (perhaps by the Queued Components message mover utility) or are purged by MSMQ Explorer.

Messages that are not playable because it is clear that every retry attempt will fail can be moved directly to the application-specific final resting queue without being advanced through all the retry levels.

The player issues a COM+ event to notify interested parties that messages cannot be played. COM+ events are issued in the following situations:

  • When a transaction aborts
  • When a message is moved from one queue to another
  • When a message is deposited onto the final resting queue

Messages can be modified before moving from one queue to another. The Queued Components security mechanism allows a message to be moved to retry queues and then reinserted to the application's initial input queue. For more information on Queued Components security, see Using Queued Components Security.

Retry queues are created along with the main application queue when the application is either marked as queued by the Component Services administration tool or by using the COM+ Administrative SDK functions. The Queued Components service allows for flexibility in the retry mechanism by allowing retry queues to be deleted. For example, if all the retry queues are deleted, a message that persistently aborts will be moved directly from the application queue to the application-specific final resting queue. By removing one or more of the retry queues, the number and length of the retries can be reduced. If queues are removed from the retry sequence, the timing of the remaining queues correspond to the position in the sequence of retry queues. For example, if you remove retry queue ApplicationName_1, ApplicationName_2, and ApplicationName_3, the messages on ApplicationName_4 would be processed as if the queue was the second retry queue.

The retry mechanism is designed to complete a message if at all possible. In some cases, it may not be possible for the message to succeed. For example, a client may be attempting to withdraw money from an account that has insufficient funds. In these circumstances, you can handle the error in a number of ways, including the following:

  • Generate a diagnostic and issue a warning
  • Create a compensating transaction
  • Ignore the problem and dismiss the message

Like client-side persistent failures, the Queued Components service allows an exception class to be associated with a component. The exception class is associated with the component by using the Advanced tab in the component properties page of Component Services administration tool or by using the COM+ Administrative SDK functions. The exception class allows the developer to have control after a message has been retried and before that message is moved to the application-specific final resting queue. For more information on the exception class, see Persistent Client-Side Failures.

The following is the sequence of events for server-side exception handling:

  1. The message is moved through the available application-specific retry queues.
  2. The final retry on the last retry queue fails.
  3. The Queued Components service run-time retrieves the target component from the message and checks for an exception class.
  4. The run-time instantiates the exception class.
  5. The run-time queries IPlaybackControl on the exception class.
  6. The run-time calls IPlaybackControl::FinalServerRetry in the exception class.
  7. The run-time plays back all property and method calls from the message to the exception class.
  8. If steps 4 through 6 do not succeed, the run-time moves the message onto the application-specific final resting queue.

For more information on the message mover utility that moves messages from one queue to another when necessary see Exception Handling.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Exception Handling

Occasionally, a situation occurs in which a message cannot be successfully delivered to its intended destination, usually due to a problem with the system or configuration. For example, the message may be directed to a queue that does not exist or the destination queue may not be in a state to receive. The message mover is a tool that moves all failed MSMQ messages from one queue to another so that they can be retried. The message mover utility is an Automation object that can be invoked with a VBScript. The following sample code shows how to create the object, set the required properties and initiate the transfer. To use it from Visual Basic, add a reference to the COM+ Services Type Library:

Dim OMessageMover

Dim cMessages

Set OMessageMover = Wscript.CreateObject("QC.MessageMover")

OMessageMover.SourcePath = ".\private$\AppName_deadqueue"

OMessageMover.DestPath = ".\AppName"

cMessages = OMessageMover.MoveMessages

Wscript.Echo cMessages, "messages moved from", OMessageMover.SourcePath, "to", OMessageMover.DestPath

The source path of the message is the final resting queue. It is the dead queue, which is a private MSMQ queue and is called AppName_deadqueue. Messages are moved here if the transaction repeatedly aborts when attempted on the fifth retry queue. With the message mover tool, you can move the message back to the first queue, which is called AppName. For more information on retry queues, see Handling Server-Side Errors.

If queue attributes permit, the message mover moves messages transitionally so that messages are not lost or duplicated in the event of failure during the move. The tool preserves all the message properties that can be preserved when moving messages from one queue to another.

If the messages are generated by COM+ Queued Components calls, the message mover utility will preserve the original caller's security identifier as it moves messages between queues. If both the destination and source queues are transacted the whole operation will be done transitionally. If either the source or destination queues are not transacted, the operation will not run under a transaction. An unexpected failure (such as a crash) and restart of a non-transactional move could duplicate the message being moved at the time of the failure.

COM+ handles server-side (player) aborts by moving the message that is failing onto a different "final resting" queue, to get it out of the way. The listener and player cannot continually loop on a message that aborts. However, in many cases, the aborted transaction can be fixed by taking action at the server (perhaps a resource is unavailable).


Handling Client-Side Errors

Client-side failures are handled in a way that is similar to server-side failures. MSMQ can move a message to its destination queue if, for example, the message cannot be moved from client to server. In this case, the message is moved to the client-side queue manager's Xact dead letter queue.

The Queued Components service monitors the dead letter queue. If messages have been moved, the Queued Components service creates an instance of the exception class and calls QueryInterface to request IPlaybackControl. If this is successful, the dead letter queue monitor invokes IPlaybackControl::FinalClientRetry.

The object can take some action to reverse the effect of a prior transaction. If the playback commits, the message is removed from the Xact dead letter queue. If the playback fails or the required CLSID and interface are not available, the message remains on the Xact dead letter queue.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Persistent Client-Side Failures

Using Queued Components Security

Queued Components Interdependencies


Persistent Client-Side Failures

In some cases, MSMQ can move a message to the destination queue. For example, if the queue access controls do not permit the message to be moved from client to server, the offending message is moved to the client-side queue manager's Xact dead letter queue. When this occurs, the Queued Components service allows an exception class to be associated with a component. To associate the exception class with the component, use the Advanced tab in the component properties page of the Component Services administration tool. You can also associate the exception class programmatically, by using the ExceptionClass catalog component attribute of the COM+ Administrative SDK functions.

The exception class is defined as either the ProgID or the CLSID of a component implementing IPlaybackControl. The Queued Components service has a dead letter queue monitor that scans the Xact dead letter queue. If there is a message on the queue, the dead letter queue monitor instantiates the exception handler associated with the target component and calls IPlaybackControl::FinalClientRetry, indicating that there has been a client-side, unrecoverable error.

In addition to IPlaybackControl, the exception handler should implement the same set of interfaces as the server component for which it is handling exceptions. When IPlaybackControl::FinalClientRetry is called, the Queued Components run-time plays back the failing message to the exception handler. This allows the exception handler to implement an alternative behavior for messages that cannot be moved to the server—for example, by generating a compensating transaction.

If the exception handler completes all the method calls played back, the message is removed from the Xact dead letter queue and is dismissed. If, however, the exception handler aborts the message by returning a failure status from one of the method calls, the message is returned to the Xact dead letter queue. The following sequence of events shows how client-side exceptions are handled:

  1. MSMQ fails to deliver a message to the server and puts the message onto the Xact dead letter Queue.
  2. The dead letter queue listener (DLQL) finds a message on the Xact dead letter queue.
  3. The DLQL retrieves the target component CLSID from the message and checks for an exception class.
  4. The DLQL instantiates the exception class.
  5. The DLQL queries for IPlaybackControl for the exception class.
  6. The DLQL calls the IPlaybackControl::FinalClientRetry method in the exception class.
  7. The DLQL plays back all property and method calls from the message to the exception class.
  8. The DLQL deletes the message if the exception handler completes the transaction successfully. The exception handler may issue IObjectContext::SetAbort, and the message will remain on the dead letter queue.

If any of the preceding steps fail, the message is left on the Xact dead letter queue.

The COM+ QCDL is provided as a COM+ application during the Microsoft® Windows® 2000 installation. It is not automatically started. When started, the DLQL reads each message on the MSMQ transactional dead letter queue and instantiates the exception class for each Queued Components message. After one pass through the queue, it waits for new messages. It then processes each new dead letter queue message as it arrives.

Note There is currently no dead letter queue listener for nontransacted messages.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Using Queued Components Security

Queued Components Interdependencies


Using Queued Components Security

Queued components support role-based security semantics just like other components built to use with COM+ applications. Components of a queued application can use the programmatic interfaces to discover the role membership of their caller (ISecurityCallContext::IsCallerInRole) or a specific user (ISecurityCallContext::IsUserInRole). However, queued components do not support impersonation-style security, which allows a server to obtain an access token corresponding to the client identity and use it either to perform access control checks or to act under the client security context.

When a client makes a call to a queued object, the call is actually made to the recorder, which packages it as part of a message to the server. The listener reads the message from the queue and passes it to the player. The player invokes the actual server component and makes the same method call. The server component must observe the security call context of the client (not the player's security call context) when the player makes the method call. The recorder marshals the client's security call context into the message and the player unmarshals it at the server before making the method call. As far as the server object is concerned, there is no difference in security context between a direct call from the client and an indirect call from the player.

This mechanism works only if the process that queues the message can be trusted. There is a remote possibility that an untrustworthy source could generate a message whose format resembles that of a message to a queued component. In this case, the marshaled security call context may have been constructed to attempt access to the server object. The recorder places the client's SID in the message and sets the appropriate MSMQ properties so that MSMQ carries the sender's SID as well. The user cannot change the MSMQ SID. The player compares the MSMQ SID with the SID in the message. If there is a match, the process that reads the message from the queue is the same as the process that made the method calls to the queued component.

Caller Identity

The caller identity is the identity associated with a method call. Caller identity is used by role-based security and is present in the security call context. In queued components, the caller identity is represented as data in the MSMQ message. MSMQ authenticates the message sender identity. When the caller identity and the message sender identity are the same, MSMQ authenticates both the message and the caller. When the caller and message identity are different, MSMQ authenticates the message sender. COM+ restricts the identities that are allowed to represent others. In cases where the caller identity and message sender identity are different, this mechanism verifies that the message sender is a member of the QC Trusted User role in the system application of the computer hosting the queued component.

In most cases, the caller and the message sender (recorder) have the same identity. MSMQ authenticates that identity. However, when the caller of a queued component is interacting with a component through an out-of-process recorder, the identity of the caller and message sender (recorder) are often different. In this case, the recorder identity must be mapped to the QC Trusted User role on the system application of the machine hosting the queued component. Additionally, the out-of-process recorder requires a certificate because it is being authenticated by MSMQ. For additional information on using COM+ security, see Security in COM+.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Queued Components Interdependencies


Queued Components Interdependencies

The COM+ Queued Components service interacts with other COM+ features in the following ways:

  • Queued Components issues COM+ events for a number of instances, including every message enqueue and every message dequeue, queue open and close, and moving messages from queue to queue during the poison message retry mechanism.
  • MSMQ has queue parameters that control the maximum queue depth. The maximum number of messages that are allowed to build up in a queue is not affected by COM+ threading guidelines at all.

See Also

Benefits of Queued Processing

Queued Components Architecture

Transactional Message Queuing

Creating and Providing Security for Queues

MSMQ Message Authentication

Queued Components Sample

Developing Queued Components

Starting Queued Components

Identifying Queued Components

Using the Queue Moniker to Activate Queued Components

Using the New Moniker to Activate Queued Components

Handling Server-Side Errors

Handling Client-Side Errors

Persistent Client-Side Failures

Using Queued Components Security


COM+ Events

COM+ Events extends the COM+ programming model to support late-bound events or method calls between the publisher or subscriber and the event system. Rather than repeatedly polling the server, the event system notifies interested parties as information becomes available.

COM+ Events handles most of the event semantics for the publisher and subscriber. Publishers offer to publish event types, and subscribers request event types from specific publishers. Subscriptions are maintained outside of the publisher and subscriber and are retrieved when needed. In this way, the programming model for the publisher and subscriber is simplified. The subscriber does not need to contain the logic for building subscriptions—building a subscriber is as easy as building a COM component. The life cycle of the subscription is separate from that of either the publisher or the subscriber. Subscriptions can be built prior to either the subscriber or publisher being active.

The following topics in this section provide detailed information about the COM+ Events feature.

  • COM+ Events Model
  • COM+ Events Architecture
  • Subscriptions
  • Offering Events
  • Delivering Events
  • Filtering Events
  • Composing Events with Queued Components
  • COM+ Events Sample

See Also

Registering an Event Class

Registering a Subscription


COM+ Events Model

Notifying interested parties that there have been changes to information is a fundamental issue of distributed computing. In the past, subscribers were provided with an interface on which a method call could periodically be made to determine whether changes had taken place. Such a procedure is known as polling the publisher.

While polling is a simple way to obtain the required information, there are some disadvantages. Polling wastes time for both the publisher and the subscriber. The subscriber must send a method call to the publisher, and the publisher has to relay an answer to the subscriber even if there have been no changes in the information. Polling also involves a time lag between when the information actually changes and when the subscriber polls for it.

Ideally, an events system should provide a way to initiate the notification when information changes for interested parties. The publisher is provided with an interface on which to call a method when a change occurs. This is known as a tightly coupled event (TCE). COM connection points are an example of a TCE system. The subscriber knows which publisher to request notification from and the interfaces that are exposed.

A TCE system requires that both the publisher and the subscriber be running at all times. Additionally, the mechanism used to connect the callback interface must be known in advance, and these mechanisms can be widely divergent. TCEs also provide no way to filter or intercept an event. Filtering is a way to designate event notification only when certain changes occur or when certain values are reached. For example, you may want to know about your favorite stock only when it reaches a predetermined price.

COM+ Events is a loosely coupled event (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. Subscribers query this store and select the events that they want to hear about. Selecting event information from the event store creates a subscription. When an event occurs, the event system looks in this database and finds the interested subscribers, creates a new object of each interested class, and calls a method on that object.

COM+ Events allows publishers and subscribers to be developed, deployed, and executed separately. The publisher is written without knowledge of the number and location of the subscribers. The subscribers use COM+ Events to find the publisher and manage their subscription to it. The lifetime of the subscription is independent of when the publisher and subscriber are executing.

The publisher does not need to be active when a subscriber subscribes to an event. The publisher's identity can be persistent—the event system allows subscribers to find the publisher even when the publisher is not active. Similarly, subscriptions can also be persistent. Subscriptions can be created, modified, or removed before a publisher is known to the event system.

See Also

COM+ Events Architecture

Subscriptions

Offering Events

Delivering Events

Filtering Events

Composing Events with Queued Components

COM+ Events Sample


COM+ Events Architecture

COM+ Events matches and connects publishers and subscribers. A publisher makes the method call to initiate an event, and a subscriber receives these calls from the publisher. COM+ Events maintains the list of interested subscribers who will receive the calls and directs those calls without requiring the knowledge of the publisher.

Note An event is identified by a method in a COM+ interface, known as an event method, and is originated by a publisher and dispatched to the correct subscriber or subscribers. Event methods must be uniquely named and can contain only input parameters (no output or input/output parameters). The return value must be an HRESULT.

The connection between publisher and subscriber(s) is managed by an EventClass object, which is a COM+ component that contains the interfaces and methods used by a publisher to fire events. The subscriber must implement these interfaces to receive events. You specify the interfaces and methods you want an EventClass to contain by providing a type library. EventClass objects are stored in the COM+ event store (COM+ catalog), either by using the Component Services administration tool or by publishers using the COM+ Administrative SDK functions. For more information on EventClass objects, see Registering an Event Class.

To register an event in the event system, a publisher creates one or more EventClass objects. This EventClass object indicates the events that can occur and, optionally, identifies the publisher. Then the publisher instantiates the EventClass by calling CoCreateInstance or the Microsoft® Visual Basic® CreateObject method and requesting the event interface be returned. The instantiated EventClass object contains the event system's implementation of the requested interface.

By invoking the appropriate method through the event interface, the publisher fires an event on the EventClass object. COM+ Events searches the subscription database (COM+ catalog) to find all the subscribers who have registered subscriptions to that interface and method. It connects to those subscribers (by direct creation, monikers, or queued components) and calls the method. To support more than one subscriber notification for an event, methods can contain only input parameters and must return only success or failure HRESULTs.

Note This version of COM+ Events does not support a distributed event store. A subscriber must subscribe to an event on each computer from which it wants to receive notification. As an alternative, you can register the EventClass and subscriptions on a central computer and instantiate this EventClass from the remote computers on which you will publish events. Delivery of events is provided either by DCOM or queued components. For more information on using queued components, see Composing Events with Queued Components.

The event system manages the following:

  • EventClass objects
  • Events
  • Subscriptions

The EventClass is a persistent object that is managed and stored by the event system. While the subscription object is also managed and stored in the event system, it can be either persistent or transient.

See Also

COM+ Events Model

Subscriptions

Offering Events

Delivering Events

Filtering Events

Composing Events with Queued Components

COM+ Events Sample


EventClass Objects

EventClass objects are COM+ configured components, and they provide a persistent record in the event system that describes the publishers and the firing interfaces associated with those publishers. Publishers register EventClass objects with the event system by calling ICOMAdminCatalog::InstallEventClass or ICOMAdminCatalog::InstallMultipleEventClasses. You can also use the Component Services administration tool to register these objects.

Because the EventClass object is a configured component, other attributes such as queuing, transactions, security, and so on can be configured by using either the Component Services administration tool or the COM+ Administrative SDK functions.

The EventClass object contains the following properties:

  • EventCLSID
  • EventClassName
  • TypeLibrary
  • Publication attributes

The EventCLSID and EventClassName properties are unique identifiers that enable subscribers to request the events offered by a particular EventClass object. The EventCLSID is specified as the CLSID of the component, and the EventClassName is specified as the PROGID of the component. There is no need to implement the firing interfaces specified in the type library.

The TypeLibrary property provides a list of interfaces offered by the EventClass object, while publication attributes determine the way events are published through the EventClass object.

Note COM+ Events uses type library marshaling. This places some restrictions on EventClass interfaces. For example, the type library marshaler does not support the MIDL attributes size_is and length_is.

You should provide a self-registering DLL, which exports the DllRegisterServer and DllUnregisterServer functions. The DllRegisterServer function registers a COM class, and the DllUnregisterServer function unregisters the component.

When the EventClass object is instantiated, the event system associates the appropriate subscriptions with it. Information held in the request data of the subscription is matched to the data held in the EventClass object. The list of subscribers is maintained for the lifetime of the EventClass object. The same event can be delivered to multiple subscribers either serially or in parallel.

To publish an event, a publisher instantiates an event object by calling CoCreateInstance or CoGetObject with a specific EventClass object using EventClassID or EventClassName. The publisher calls QueryInterface on the event object to obtain the interfaces supported by the EventClass object and invokes a method on the event object through the interface to publish the event. For information on registering EventClass objects, see Registering an Event Class.

See Also

COM+ Events Architecture

Registering an Event Class

Registering a Subscription


Subscriptions

Subscriptions reside in the subscription COM+ Events store. Subscribers create subscription objects in the event system to request and manage the delivery of events. The subscriber component is installed using ICOMAdminCatalog::InstallComponent.

The SubscriptionsForComponent collection is used to add, delete, or change information pertaining to subscription objects. The SubscriptionsForComponent collection is a child collection to a component. To add a subscription, you get the component's SubscriptionsForComponent collection and use the Add method to add an entry to the collection. To set up the various properties of the subscription object, you use the put_Value calls. To save the changes, you use SaveChanges on the SubscriptionsForComponent collection object.

For transient subscriptions, you can use the TransientSubscriptions collection, whose parent object is the root catalog object.

You can also use the Component Services administration tool to modify some, but not all, of the subscription properties.

Subscriptions specify the following information:

  • Identity and location of the subscriber
  • Delivery method
  • Event methods to deliver
  • EventClass object and PublisherID property of an event class component from which the subscriber wants to receive events

Subscriptions exist independently from EventClass objects. You can disable a subscription by setting the Enabled property. A disabled subscription will not be called by COM+ Events.

The three types of subscriptions are as follows:

  • Persistent
  • Transient
  • Per User

See Also

COM+ Events Model

COM+ Events Architecture

Offering Events

Delivering Events

Filtering Events

Composing Events with Queued Components

COM+ Events Sample


Persistent Subscriptions

Persistent subscriptions reside in the COM+ catalog and are independent from the subscriber's lifetime. Persistent subscriptions survive a system restart. Generally, a persistent subscription is created when an application is installed on a subscriber's computer and removed when the application is removed. After a persistent subscription is created, COM+ Events activates the subscriber each time an event should be delivered to it.

When a publisher instantiates and makes a call on an EventClass object, the object looks for all the persistent subscriptions in the COM+ catalog and creates a new instance of each object. The creation process can be either direct or through a moniker for queued components. Specify the subscriber object by the SubscriberCLSID or SubscriberMoniker properties of the subscription. Subscriber objects created by a persistent subscription are always released after each event call.

See Also

Subscriptions

Transient Subscriptions

Per User Subscriptions


Transient Subscriptions

Transient subscriptions request an event for a specific subscriber object that already exists. Transient subscriptions are stored in the COM+ catalog, but the subscription is deleted if the event system or operating system is stopped. Unlike persistent subscriptions, transient subscriptions are tied to a particular object and are stored only in the event system. If there is a problem with the event system or operating system, the subscription disappears. Transient subscriptions can be more efficient than persistent subscriptions, but you must manage their object life cycles.

Transient subscriptions cannot be set by using the Component Services administration tool. You must use the COM+ administrative interfaces to create or update a transient subscription.

The following procedure describes how to create a transient subscription using Microsoft® Visual Basic®:

  1. Specify a subscription as transient by adding a new entry to the TransientSubscriptions collection and setting the SubscriberInterface property to the IUnknown interface of the subscriber object. COM+ Events will not create a new instance of the subscriber object when firing an event but rather will use the instance you specify. COM+ Events will hold a reference count for the subscriber object until the subscription is removed from the system.
  2. Create a COM+ server application (an .exe, a .dll, or an .ocx file) with an object that implements the interfaces or methods you want to subscribe to.
  3. Create your transient subscription using the following code, by passing in the CLSID of the EventClass object and the instance of the subscriber object. Using the Component Services administrative tool, you can get the EventCLSID property by right-clicking on the COM+ component, selecting Properties, and selecting the General tab.
    Public Function CreateTransientSubscription(ByVal clsid As String, ByVal objref As Object) As String
Dim oCOMAdminCatalog As COMAdmin.COMAdminCatalog
Dim oTSCol As COMAdminCatalogCollection
Dim oSubscription As ICatalogObject
Dim objvar As Variant
On Error GoTo CreateTransientSubscriptionError
Set oCOMAdminCatalog = CreateObject("COMAdmin.COMAdminCatalog.1")
'Gets the TransientSubscriptions collection
Set oTSCol = oCOMAdminCatalog.GetCollection("TransientSubscriptions")
Set oSubscription = oTSCol.Add
Set objvar = objref
oSubscription.Value("SubscriberInterface") = objref
oSubscription.Value("EventCLSID") = clsid
oSubscription.Value("Name") = "TransientSubscription"
oTSCol.SaveChanges
CreateTransientSubscription = oSubscription.Value("ID")
Set oSubscription = Nothing
Set oTSCol = Nothing
Set oCOMAdminCatalog = Nothing
Set objvar = Nothing

Exit Function
CreateTransientSubscriptionError:
CreateTransientSubscription = ""
Err.Raise Err.Number, "[CreateTransientSubscription]" & Err.Source, Err.Description
End Function

The following is a procedure for calling the CreateTransientSubscription function to subscribe to an interface called IStockTicker, which has a method called UpdateStock.

  1. Create an event class that supports the interface IStockTicker, which has one method, UpdateStock.
  2. In your subscriber project, add a class that implements the IStockTicker interface.
  3. When you want to subscribe execute the following code:
    Dim oMyTicker As Object
Dim sSubscriptionID As String
Set oMyTicker = CreateObject("TheProject.CMyTicker")
sSubscriptionID = CreateTransientSubscription("{..CLSID for the Event Class..}", oMyTicker)

The CreateTransientSubscription function returns a string, which is a GUID that can be used as a handle or a cookie to revoke the subscription later. To remove the subscription, call the Remove method of ICatalogCollection on the TransientSubscriptions collection, passing in the index corresponding to the subscription with the GUID previously received.

See Also

Subscriptions

Persistent Subscriptions

Per User Subscriptions


Per User Subscriptions

Per User subscriptions can deliver events only when the subscriber is logged on to the event system's computer. When the subscriber logs on, the event system enables all subscriptions on which the PerUser flag is set to TRUE and UserName is set to the name of the user who is logged on. When the subscriber logs off, the subscriptions are disabled.

Note Per User subscriptions are effective only when the publisher and subscriber are on the same computer. Logon and logoff are detected only at the publisher's computer—not the computer on which the subscriber object resides.

See Also

Subscriptions

Persistent Subscriptions

Transient Subscriptions


Offering Events

To offer an event, a publisher calls CoCreateInstance on an EventClass object. The event system then publishes events on the event class CLSID_EventObjectChange with the interface ID IID_IEventObjectChange. The event system notifies interested subscribers whenever EventClass objects or subscriptions are created, modified, or removed through meta-events. A subscriber is any COM or COM+ object that can implement event methods.

Note Creating and maintaining subscriptions is an activity separate from raising and receiving events.

To receive meta-events from the event system, applications must create a subscription that does the following:

  • Resides on the event system's computer
  • Specifies the firing interface ID (IID_IEventObjectChange)

See Also

COM+ Events Model

COM+ Events Architecture

Subscriptions

Delivering an Event

Filtering Events

Composing Events with Queued Components

COM+ Events Sample


Delivering Events

COM+ Events does not provide a way to specify the order in which an event is delivered to multiple subscribers. By default, events are fired one at a time in no determined or repeatable order. Publishers that need to control the order in which subscribers receive an event can implement a publisher filter. (For more information, see Filtering Events.)

By setting the FireInParallel parameter of the EventClass object to TRUE, publishers can request that the event system use multiple threads to deliver an event to more than one subscriber. Selecting an in-parallel delivery mechanism does not guarantee that the event will be delivered at the same time to multiple subscribers, but it instructs COM+ Events to permit this to happen.

See Also

COM+ Events Model

COM+ Events Architecture

Subscriptions

Offering Events

Filtering Events

Composing Events with Queued Components

COM+ Events Sample


Filtering Events

COM+ Events provides two ways to filter events, as described in the following topics in this section:

  • Publisher Filtering
  • Parameter Filtering

See Also

COM+ Events Model

COM+ Events Architecture

Subscriptions

Offering Events

Delivering Events

Composing Events with Queued Components

COM+ Events Sample


Publisher Filtering

Publisher filtering controls the order and firing of an event method by an EventClass object. Publisher filtering allows the publisher to determine which subscribers will receive a particular event.

An example of effective use of publisher filtering is that of a stock exchange. Most subscribers want to know when a new stock is added. However, these same subscribers probably do not want to know whenever each stock price changes—they are probably interested in price changes for only a select group of stocks. Publisher filtering provides the granularity required to effectively deliver events to only the subscribers who want this information.

There are two methods to establish the publisher filter, as follows:

  • Because it allows you to compose the event object with the COM+ Queued Components service, the preferred method is to use the MultiPublisherFilterCLSID property in the EventClass to set the publisher filter. This establishes one filter object for all the methods of the event interfaces for an event object. The event object activates the publisher filter when the EventClass object is instantiated using CoCreateInstance.
  • You can establish the publisher filter by using IEventControl::SetPublisherFilter. However, if you choose this method, remember that the interface is not queuable—it cannot compose the event object with queued components between the publisher and the EventClass object. For additional information about using the Queued Components service with COM+ Events, see Composing Events with Queued Components.

An event can have one or more filter objects—or none at all. The publisher filter objects must support either IPublisherFilter or IMultiInterfacePublisherFilter, depending on whether you have a single firing interface or multiple firing interfaces on the EventClass object. The IPublisherFilter and IMultiInterfacePublisherFilter interfaces both specify an Initialize method. The Initialize method is called by the event class object immediately after creating the filter object.

When an event method is invoked on the instantiated EventClass object, it collects any publisher filters on that method. The filter forces the event object to fire the event method to a specific subscriber. The filter determines which subscriptions to fire and in which order to fire them. For example, the filter could read the subscription list and create the order based on some application criteria and then fire the subscriptions in that order.

Note Delivery can be affected by standard parameter filtering. For more information, see Parameter Filtering.

COM+ Events tries to invoke two methods on the filter. First, it calls IPublisherFilter::PrepareToFire and passes an IFiringControl interface pointer to the filter. Then it queries the filter object for the event interface. If the filter supports the event interface, it invokes a method on it. This provides access to the publisher parameters for an event. The filter can use these parameters to determine which subscriptions to fire.

See Also

Parameter Filtering


Parameter Filtering

In contrast to publisher filtering, COM+ Events provides an optional subscriber parameter filtering for each subscription and each event method invocation. Parameter filtering evaluates the subscription FilterCriteria property against the parameters of the event method. This type of filtering is used on a per-method, per-subscription basis and provides a level of subscriber filtering at the event source. The filter criteria string recognizes relational operators for checking equality (=, ==, !, !=, ~, ~=, <>), nested parentheses, and logical keywords AND, OR, or NOT.

Parameter filtering occurs after any publisher filtering and when the standard event object is fired for a given subscription. If publisher filtering is used, parameter filtering occurs only when the publisher filter invokes IFiringControl::FireSubscription. Because of this, publisher filtering and parameter filtering can compose together but publisher filtering takes precedence.

See Also

Publisher Filtering


Composing Events with Queued Components

Events are used to manage a connection between a publisher and one or more subscribers and then manage the delivery of events to those subscribers. The COM+ Queued Components service is used to make the publisher and subscriber processing time independent by queuing the publisher's message and later replaying it to the subscriber. Whether or not you need to use the Queued Components service depends on the underlying business logic of your application. If you need to have events that are time independent, you can create them by composing COM+ Events with COM+ Queued Components.

Note For additional information about using the COM+ Queued Components service, see Queued Components. To write components that are queuable, see Writing Queued Components.

The Queued Components service maintains order-of-method invocation within a single message. The recorder batches all method invocations into a message, and then the player invokes those methods in order when the message is processed.

A Queued Components recorder and player can be composed in the following two places:

  • Between the publisher and event object
  • Between the event object and subscriber

If you compose the recorder and player between the publisher and event object, you are making the EventClass component queuable. The EventClass component must be marked for queuing and be activated by the player in a process that is separate from the publisher.

To deliver events asynchronously, compose the recorder and player between the event object and subscriber and set the Queued attribute of the subscription object. This sets SubscriberMoniker as follows:

“queue:/new:/{12345678-1234-1234-1234-123456789012}”

There is an order of delivery implication to consider when using queued components in an event situation. Because the Queued Components service records and plays back all of the calls within the lifetime of a single object in one message, all calls will be replayed in the order in which they were made. However if there is more than one session with more than one object, order cannot be guaranteed. If order is important, make sure that calls that need to be played back in order reside on the same object instance.

See Also

COM+ Events Model

COM+ Events Architecture

Subscriptions

Offering Events

Delivering Events

Filtering Events

COM+ Events Sample


COM+ Events Sample

The Platform SDK includes an events sample that illustrates how to develop components and applications that use events. The sample includes a tour file that provides build instructions and documentation on the sample.

Click the buttons below to jump to the COM+ Events samples.

Event Monitor Sample SDK Not Installed SDK Not Installed

Event News Sample SDK Not Installed SDK Not Installed

See Also

COM+ Events Model

COM+ Events Architecture

Subscriptions

Offering Events

Delivering Events

Filtering Events

Composing Events with Queued Components


The Shared Property Manager

In COM+, shared transient state for objects is managed by using the Shared Property Manager (SPM). The SPM is a resource dispenser that you can use to share state among multiple objects within a server process.

You cannot use global variables in a distributed environment because of concurrency and name collision issues. The Shared Property Manager eliminates name collisions by providing shared property groups, which establish unique namespaces for the shared properties they contain. The SPM also implements locks and semaphores to protect shared properties from simultaneous access, which could result in lost updates and leave properties in an unpredictable state.

Note Shared transient state is state information kept in memory that does not survive system failures. The information is designed to be shared by multiple objects across transaction (but not across process) boundaries.

Shared properties stored in the SPM are available only to objects running in the same process. This means that the objects that will use the SPM for storing values and that will need to have access to these values must be installed as part of the same COM+ application. It is possible for system administrators to move COM+ classes from one package to another after your COM+ application has been deployed. If you rely on several objects sharing properties through the SPM, you should clearly document that they must be installed in the same COM+ application.

It's also important for components sharing properties to have the same activation attribute. If two components in the same package have different activation attributes, they generally won't be able to share properties. For example, if one component is configured to run in a client process and the other is configured to run in a server process, their objects will usually run in different processes even though they're in the same package.

You should always instantiate the SharedPropertyGroupManager, SharedPropertyGroup, and SharedProperty objects from COM+ components rather than from a base client. If a base client creates shared property groups and properties, the shared properties are inside the base-client process, not in a server process. This means the COM+ objects cannot share the properties unless the objects are also running in the client process (which is generally not a good idea).

See Also

Understanding the Shared Property Manager


Understanding the Shared Property Manager

To prevent name collisions among properties created by different objects, the Shared Property Manager (SPM) uses shared property groups. A shared property group is simply a namespace for a set of shared properties. Each property within a shared property group consists of a name, a value, and a position within the shared property group. Either the name or the position can be used to retrieve the property value. You can access and create shared property groups through the shared property group manager.

The SPM object model is shown in the following illustration.

The following are interfaces of the Shared Property Manager:

  • ISharedPropertyGroupManager is used to create shared property groups and to obtain access to existing shared property groups. You can access the ISharedPropertyGroupManager interface by creating an instance of the SharedPropertyGroupManager object by using either IObjectContext::CreateInstance or CoCreateInstance.
  • ISharedPropertyGroup is used to create and access the shared properties in a shared property group. You can access the ISharedPropertyGroup interface by creating a SharedPropertyGroup object with the ISharedPropertyGroupManager::CreatePropertyGroup method. As with any COM object, you must release a SharedPropertyGroup object when you have finished using it.
  • ISharedProperty is used to set or retrieve the value of a shared property. A shared property can contain any data type that can be represented by a Variant. You can access the ISharedProperty interface by creating a SharedProperty object with the ISharedPropertyGroup::CreateProperty method or the ISharedPropertyGroup::CreatePropertyByPosition method. A SharedProperty object can be created or accessed only from within a SharedPropertyGroup object. Again, you must release a SharedProperty object when you have finished using it.

See Also

The Shared Property Manager


COM+ Application Partitions

One of the challenges that many computing environments deal with today is the need for separate groups of users to run different versions or configurations of the same application simultaneously. Companies that offer Web services to customers particularly need a way to segment their customer base into user groups that can access different versions of an application simultaneously on the same Web server.

In the past, the only way to satisfy this requirement was to run each version of the application on its own machine. Such an approach was both costly and inefficient, because it increased hardware costs and required more administrative overhead. Fortunately, Microsoft has solved this problem by providing a feature called COM+ application partitions.

Administrators will want to understand COM+ application partitions because of the enormous benefit that partitions offer to users in a domain. Application programmers will want to understand partitions to ensure that their distributed applications work seamlessly within a partitioned environment.

To understand and use this feature, see the following topics:

  • What Are COM+ Application Partitions?
  • Partitions and Partition Sets
  • Activating Components Within Partitions
  • COM+ Queued Components and Partitions
  • Application Design Restrictions


What Are COM+ Application Partitions?

The COM+ application partitions feature allows multiple versions of an application to be executed simultaneously on a single machine. Each version of the application is installed in a separate partition and can be separately configured and managed according to the specific needs of its users.

For example, a single organization that has separate Test, Production, and Training groups could implement COM+ application partitions as a way to allow all three groups to use different versions of an application on the same machine. As another example, an application service provider (ASP) could install and manage multiple versions of an application as a way to accommodate the disparate needs of its customer base..

Benefits of Using COM+ Application Partitions

The use of COM+ application partitions offers several advantages:

  • Computing organizations can significantly lower their Total Cost of Ownership (TOC). By using COM+ application partitions to provide different versions of software to users, organizations no longer need multiple application servers to satisfy the varying needs of their users.
  • COM+ application partitions are particularly well-suited for Web-based scenarios. For example, a corporation might need to offer different versions or configurations of an application to different customers. The varying needs of customers or other types of user groups can easily be met by using COM+ application partitions.
  • Administrative overhead is reduced. Instead of having to configure and manage multiple machines, administrators need only configure and manage multiple partitions on the same machine. Furthermore, through the addition of a new programming interface and three new administrative collections, partitions can be managed programmatically.
  • Security can be implemented and managed on a partition-by-partition basis, either for users on a local machine or for users spread across a domain.
  • Programmers and administrators can manage partitions with the same development and administrative tools that that they use today, such as Microsoft's Platform SDK, Active Directory Users and Computers, and Component Services. The COM+ application partitions feature is fully integrated into these tools.

See Also

Partitions and Partition Sets

Activating Components Within Partitions

COM+ Queued Components and Partitions

Application Design Restrictions


Partitions and Partition Sets

In addition to application partitions, which contain one or more applications, COM+ also includes partition sets, which contain one or more partitions. During creation, each partition set is assigned, or mapped, to a specific user or Organizational Unit (OU).

Partition sets can be created either on a specific machine, for local users, or within Active Directory, for users in a domain. Partition sets created locally are available only to users on that machine. Partition sets created within Active Directory are domain-based, meaning that they can be mapped to users or OUs throughout a domain.

Because there is a one-to-one correlation between a user identity or OU and a partition set, a single user or OU can access multiple partitions and their applications; without a partition set, a user or OU would need multiple user identities to access applications.

For more information about partitions and partition sets, see the following topics in this section:

  • Partition Properties
  • Local Partition Sets
  • Partition Sets and Active Directory
  • Default Partitions
  • Base Application Partitions

See Also

What Are COM+ Application Partitions?

Activating Components Within Partitions

COM+ Queued Components and Partitions

Application Design Restrictions


Partition Properties

When a COM+ application partition is created, five partition properties are automatically assigned to it. These properties are viewable by right-clicking a partition name within the Component Services administrative tool and choosing Properties. Following are descriptions of the five partition properties:

  • Partition Name—A text string associated with the partition
  • Partition ID—A GUID that the system uses to correlate a machine's partition with a user-to-partition mapping in Active Directory
  • Description—A textual description of the partition
  • Disable Deletion—A mechanism for prohibiting a user from deleting a partition
  • Disable Changes—A mechanism for prohibiting a user from making changes to a partition

For more information on the partition ID property, see Activating Components Within Partitions.

See Also

Local Partition Sets

Partition Sets and Active Directory

Default Partitions

Base Application Partitions


Local Partition Sets

If an application needs to be made available to local users only—that is, users working on the machine where the application resides—then mapping the user identities to partitions in Active Directory is not required. Administrators can create local partitions and partition sets by using the Component Services administrative tool.

Note Because the COM+ application partitions feature is most useful in an enterprise environment, it is recommended that local partitions be used strictly for development and testing purposes only and not for production use.

See Also

Partition Properties

Partition Sets and Active Directory

Default Partitions

Base Application Partitions


Partition Sets and Active Directory

A partition set can be made available to an entire domain of users by creating the partition set within Active Directory on a domain controller. You can then map the partition set to user identities or Organizational Units (OUs) within the domain, specifying the partitions that the partition set should contain. Because the COM+ application partitions feature is designed for implementation in domain environments, partition sets defined within Active Directory, as opposed to partition sets defined locally, are the primary way that application partitions should be deployed.

Note To create and manage partition sets within Active directory, the domain controller must be running Microsoft® Windows® 2000 Advanced Server.

A partition set can be mapped either to a single user identity or to an OU. By mapping partition sets to OUs, an administrator can associate multiple users to a partition set at one time instead of having to map many individual user identities to the same partition set. A single user identity or OU can be mapped to one partition set only.

In general, mapping user identities or OUs to partition sets does the following:

  • Ensures that applications are available to users throughout the domain
  • Helps COM+ in determining the partition in which an application is located
  • Establishes a user's right to access a particular application

The following illustration shows how users are mapped to partitions sets within Active Directory:

To create partitions and partition sets within Active Directory and to perform the user-to-partition-set mapping, administrators use the Active Directory Users and Computers and the Component Services administrative tools. After a partition is created within Active Directory, an administrator needs to locally configure that partition on the machine where the relevant COM+ application is to be installed. This local configuration of domain-based partitions is done through the Component Services administrative tool.

If a domain user identity is not mapped to a partition set, the user is granted access to the partition mapped to the user's OU. If the user's OU is not mapped to a partition set, the user is granted access to the partition mapped to the next highest OU.

The following illustration shows a scenario in which users are not mapped directly to partition sets but are mapped indirectly to a partition set for their OU. They therefore have access to the applications in their particular OU partition set.

The following illustration shows a scenario in which neither users nor their OU are mapped directly to a partition set. In this case, the users have access to the applications in the higher-level OU in which their OU resides.

See Also

Partition Properties

Local Partition Sets

Default Partitions

Base Application Partitions


Default Partitions

When a user identity's partition set contains multiple partitions, one of those partitions is designated as the user's default partition. Therefore, when a partition moniker is not being used to activate a component, COM+ always searches the user's default partition when attempting to activate a component.

See Also

Partition Properties

Local Partition Sets

Partition Sets and Active Directory

Base Application Partitions


Base Application Partitions

In addition to administrator-defined partitions and partition sets, there is a special partition on each machine called a Base Application Partition. A Base Application Partition is automatically created when COM+ is installed. The Base Application Partition is designed to contain systemwide applications that need to be accessible to all users in the domain. Installing an application into the Base Application Partition removes the need to install a copy of the application into each individual user's partition set.

If a user's partition set does not include a specific application that the user is attempting to access, but that application is installed in the Base Application Partition, the application is activated from the Base Application Partition. In this case, however, all components of the application installed in the Base Application Partition must be marked as public, not private, components.

The following illustration shows how an application can be activated from the Base Application Partition when the application is not directly included in a user's partition. Following the illustration is a brief explanation of the steps that occur when a user attempts to invoke a COM+ application that does not reside in the user's partition set but does reside in the Base Application Partition.

  1. A user attempts to invoke an application.
  2. COM+ searches the user's default partition set; the requested application is not found.
  3. COM+ searches the Base Application Partition; the requested application is found.
  4. User successfully invokes the application.

See Also

Partition Properties

Local Partition Sets

Partition Sets and Active Directory

Default Partitions


Activating Components Within Partitions

Besides understanding how to install and configure applications within partitions, application developers and administrators should understand how COM+ binds application partitions to component activations.

When the client program calls the CoCreateInstance or CoGetObject function to instantiate an object, COM+ performs two distinct steps, as follows:

  1. Locates the partition in which the component resides
  2. Locates the correct component within that partition

The following topics in this section describe these steps in detail:

  • Locating Partitions During Activation
  • Locating a Component for Activation

See Also

What Are COM+ Application Partitions?

Partitions and Partition Sets

COM+ Queued Components and Partitions

Application Design Restrictions


Locating Partitions During Activation

Locating the correct partition in which to activate a component depends on the following:

  • The function call and parameters used in the calling program to activate the component
  • Whether the component being activated is local or remote
  • The internal use of the partition cache

The Calling Program

The partition that COM+ selects for component activation is determined by how that the calling program activates the component.

There are three different actions that COM+ can take when selecting a partition for component activation. The action taken depends on how the calling program instantiates the object—that is, whether the function call includes a partition moniker, which consists of a partition ID and a CLSID, or includes a CLSID only.

The following table shows the various actions that COM+ can take, in order of precedence, to locate a partition.

Function call | Parameter | COM+ Action
CoGetObject | Partition moniker (includes partition ID and CLSID) | Uses the partition ID specified in the partition moniker.
CoCreateInstance | CLSID | Uses either the partition ID of the user identity's default partition or the partition ID that was added to the context during a previous component activation in the same process.

The COM+ actions listed in the preceding table are explained in the following sections.

Use of Partition Monikers

A partition can be selected explicitly within a function call by using a partition moniker. If a partition moniker is used to locate the partition, the activation occurs from that partition. That is, the partition ID included in the moniker takes precedence over the user's default partition or over a partition ID that exists in the caller's context.

Use of Default Mapping

When the CoCreateInstance function is used to activate a component, using the component's CLSID, COM+ uses the default user-identity mapping—that is, the partition set that the user is mapped to within Active Directory. However, if the user is not mapped to a partition set within Active Directory, the Base Application Partition is selected.

Use of Partition IDs and Object Context

One of the five properties assigned to a partition when the partition is created is the partition ID. When the client program calls the CoCreateInstance function to instantiate an object, the partition ID is added to the context. Using the partition ID from the context to locate the partition is important because it ensures that after a chain of activations has begun, the partition ID remains the same unless it is changed explicitly through a partition moniker.

For additional information on locating partitions during activation, see COM+ Queued Components and Partitions.

Local vs. Remote Activation

  • If the component being called exists on another machine, the partition properties (including the partition ID) are marshaled to the other machine and the component is activated from the marshaled partition. If no partition ID was marshaled, COM+ uses the default partition set mapped to the user identity within Active Directory.

The Partition Cache

In a domain environment, COM+ uses the mappings in Active Directory to locate the correct partition for component activation. However, frequent lookups in Active Directory can result in excessive network traffic. To minimize network traffic resulting from frequent lookups of user-to-partition-set mapping in Active Directory, COM+ uses a partition cache.

The partition cache contains the mappings that were made in Active Directory between user identities or OUs and their partition sets. This partition cache is located on the application server on which the COM+ applications reside.

When COM+ needs to determine a user's default partition or validate a user's access rights to a partition, it checks the partition cache locally to look up the user's mapping, instead of checking Active Directory remotely.

If the lookup in the partition cache fails, COM+ then checks Active Directory. If the lookup is successful in Active Directory, COM+ stores that mapping in the partition cache. The next time a lookup is done for that user-to-partition mapping, COM+ will find it in the partition cache.

The following illustration shows the process that COM+ uses to locate a partition for component activation.

The size of the cache and the expiration time for the cache entries are set via registry keys. For information on configuring these registry keys, see Creating and Configuring COM+ Application Partitions.

Note If a server machine is disconnected from the network and the user-to-partition mapping is changed while the server is disconnected, the partition cache might contain outdated user-to-partition mapping. This could result in an activation error if user-to-partition mapping is the mechanism used to activate a component.

See Also

Locating a Component for Activation


Locating a Component for Activation

When COM+ has located the correct partition—through the user identity's default partition set, a partition moniker, or the partition ID in the object's context—COM+ must then locate the correct component within that partition. The following illustration shows how a component is found and activated when that component resides in a partition.

Note Prior to any component activation, COM+ performs a validation to verify that the user identity attempting to activate the component has rights to access the partition set in which the component resides.

The preceding illustration shows the following:

  • If the component being called resides in a partition and is in the same application as the calling component, the component is activated whether or not the component being called is marked as public or private.
  • If the component being called resides in a partition but does not exist in the same application as the calling component, COM+ checks to see whether the component is marked as public. If no public version is found, COM+ searches the Base Application Partition to find a public version of the component. If no public version of the component is found in the Base Application Partition or if the user identity has no rights to the partition, the activation fails.

See Also

Locating Partitions During Activation


COM+ Queued Components and Partitions

The COM+ Queued Components service fully supports the concept of application partitions. That is, when a queued component within a partition is executed, the message is queued and the component is eventually executed within the component's partition.

Queue Names for Partitioned Components

Traditionally, the Queued Components service uses the application name as the queue name. This means that in a non-partitions scenario, where only one instance of an application name exists on a machine, each application name has its own message queue.

In the case of partitions, however, where multiple instances of the same application name can exist on a machine, the Queued Components service uses the same queue for any queued components that share the same application name.

Activating Queued Components

The same set of rules for how the partition ID is used to activate a non-queued component applies to a queued component, as follows:

  • If a moniker is used to activate the queued component and a partition ID is included, this partition ID is used to locate the application partition. This partition ID takes precedence over any partition ID that might exist in the context for the component being activated.
  • If no moniker is being used to activate the component, the partition ID that is in the object's context is used.
  • If no partition ID exists in the object's context, the default user-to-partition mapping within Active Directory is used.

Note If a server machine is disconnected from the network and if the user-to-partition set mapping is changed while the server is disconnected, the partition cache might contain outdated user-to-partition set mapping. This could result in an activation error if user-to-partition set mapping is the mechanism used to activate a component.

COM+ events are fully integrated into partitions. This means that a subscriber can subscribe to a publisher whose application resides within a partition. To allow this subscription, the subscriber class collection includes two partition-related properties—an event class partition ID and an event class application ID.

See Also

What Are COM+ Application Partitions?

Partitions and Partition Sets

Activating Components Within Partitions

Application Design Restrictions


Application Design Restrictions

Some applications are designed in a way that prevents multiple instances of the application from being installed on a machine. With such a limitation, an application cannot make use of the partitions feature. The following application design features might need to be modified before partitions can be used for that application.

Tables and Arrays

Some applications create database tables, in-memory tables, or arrays that use a CLSID as a unique registry key. On a machine without partitions, this registry key is typically machine/CLSID (one CLSID per machine).

Conversely, on a machine with partitions, this registry key is machine/partition ID/application ID/CLSID (multiple instances of a CLSID per machine). Because the partitions feature allows multiple instances of a CLSID to exist on a machine, applications that contain design elements that require a unique CLSID per machine might be adversely affected.

Global Resources

Some applications use global resources such as shared memory, data files, and registry entries. This could cause problems if multiple instances of such an application are executing simultaneously.

For example, if a component uses shared memory for interacting with other components, the component will need to be modified so that each instance of the component allocates its own shared memory.

Type Libraries

Type libraries are useful for providing information about a component's interfaces and methods. This information is used for several purposes, including the following:

  • Marshaling data between components when function calls are made
  • Helping the COM+ Queued Components and COM+ Events services
  • Providing the correct information within a Microsoft® Visual Basic® editor

References to a type library are installed in the registry of a machine. When developing applications that will be invoked from within partitions, it is important that the latest version of a type library is installed in the registry. This ensures that the Visual Basic editor being used will get accurate information about the methods available for that component.

See Also

What Are COM+ Application Partitions?

Partitions and Partition Sets

Activating Components Within Partitions

COM+ Queued Components and Partitions


Compensating Resource Managers

The Compensating Resource Manager (CRM) feature of COM+ provides a quick and easy way to integrate application resources with Microsoft® Distributed Transaction Coordinator (DTC) transactions. It is an alternative to developing a full resource dispenser. By developing a pair of COM components and implementing specific interfaces, your application resources can vote on the outcome of the transaction and can receive final notification of the transaction outcome. A durable log is provided so that your application resources can write records that survive failures. Recovery on this log file is provided automatically by the CRM feature when the application restarts.

For more detailed information, including information on developing and using a CRM, see The Compensating Resource Manager.


Writing COM+ Application Components

This section provides introductory information on writing components for use in COM+ applications. See the topics described in the following table to get more information.

Topic | Description
Writing Transactional Components | Introduces considerations for writing components that support automatic transactions.
Writing Secure Components | Provides tips for choosing, testing, and documenting security.
Writing Poolable Components | Provides an overview of requirements for poolable objects.
Writing Queued Components | Introduces requirements for components that will be queued.
Writing Components for COM+ Events | Introduces requirements for components designed to support Queued Components.
Handling Errors in COM+ | Provides strategies for handling errors in components you write for use in COM+ applications.
Debugging COM+ Applications | Provides step-by-step guidelines for setting up debugging.


Writing Transactional Components

Automatic transactions allow you to create complex behavior without writing a lot of transaction-specific code. By designing COM components with automatic transactions in mind, you can ensure that your business object receives error-management protection even if the object's client is non-transactional.

In general, transactional components should do the following:

  • Perform work (or call other components to perform work against a resource manager).
  • Call the ObjectContext object's SetComplete method when the work is done.
  • Handle errors.

You must declare how you expect your component to behave in regard to transactions. See Configuring Transactions for additional information.

See Also

Writing Secure Components

Writing Poolable Components

Writing Queued Components

Writing Components for COM+ Events

Handling Errors in COM+

Debugging COM+ Applications


Writing Secure Components

Whenever possible, for COM+ applications, it is better to use automatic security, such as declarative role-based security and authentication, rather than configuring security within components. Using automatic security makes it easier to write and maintain components, easier to design security across an entire application, and, because it is configured administratively, easier to modify an application's security policy.

However, in some cases, you may choose not to use automatic security or you may use it but need to build on it to suit your application's security requirements. With COM+, you have the following options for configuring security programmatically:

  • Programmatic role-based security—for example, role checking, which is available when role-based security is enabled for your application.
  • Impersonation—for when you want to use a client's identity to access a protected resource.
  • Auditing features based on security call context information—also available when role-based security is enabled.

For a description of security in COM+ in general, see Security in COM+.

For a description of the programmatic security features available in COM+, see Programming Component Security.

COM Security Features

If your component will be used in a COM+ application that does not use role-based security, programmatic role checking and security call context information will not be available. However, you can use the programmatic security functionality provided by using COM. For more information, see Security in COM.

Although you can use most of the security functionality provided by COM, you cannot call CoInitializeSecurity from a component that is part of a COM+ application because CoInitializeSecurity is called by the surrogate that the COM+ application runs in. However, you can call other security functions, such as CoQueryClientBlanket, which retrieves information about the client.

Testing Security Functionality

If you use COM+ programmatic security in your component, you must integrate the component into a COM+ application when you are ready to test the component's security functionality. If a component using COM+ programmatic security is run without being integrated into a COM+ application, exceptions will be thrown. Therefore, if you want to ensure that such a component is also capable of being successfully integrated into an application that is not part of the COM+ environment, you must ensure that these exceptions are handled appropriately.

Documenting Security Requirements

If you are writing a stand-alone component for COM+ applications that use role-based security, you need to document the component so that security can be configured appropriately when the component is integrated into a COM+ application. For example, you should identify the roles that must be added and explain which methods and interfaces each role should be assigned to. In addition, if a method such as IsCallerInRole("Teller") is called, you should describe the functionality that only Tellers have access to. You should also specify whether a role is required to protect access to the entire component.

See Also

Writing Transactional Components

Writing Poolable Components

Writing Queued Components

Writing Components for COM+ Events

Handling Errors in COM+

Debugging COM+ Applications


Writing Poolable Components

Poolable objects must meet the following requirements to enable a single object instance to be used by multiple clients and to work in conjunction with the pool manager:

  • They must be stateless. They should carry no state between clients.
  • They must have no thread affinity. They should be able to execute on any thread.
  • They must be aggregatable. They will be aggregated on object creation, so they must support aggregation.
  • They must implement IObjectControl : While this is optional in non-transactional components, objects can use this interface to control their lifetime and state.

In addition, the following special considerations apply to poolable objects:

  • Transactional components must turn off auto-enlistment with their resource manager and manually enlist any managed resources held between clients.
  • Because of threading model requirements, you cannot use Microsoft® Visual Basic® to write poolable components.

For more detail about pooling in general, see Object Pooling.

For more detail about the requirements of poolable objects, see Requirements for Poolable Objects.

See Also

Writing Transactional Components

Writing Secure Components

Writing Queued Components

Writing Components for COM+ Events

Handling Errors in COM+

Debugging COM+ Applications


Writing Queued Components

The Queued Components service extends the existing COM development model by adding the capability of using message queues to invoke a component asynchronously. Processing can occur without regard to the availability or accessibility of either the sender or the receiver.

Following are some requirements for using the Queued Components service:

  • Application methods must contain only input parameters.
  • Application methods cannot contain return values.
  • Windows Message Queuing Service (MSMQ) must be installed.

For a detailed description of the restrictions imposed by the Queued Components service, see Development Constraints.

For information about how to develop queued components, see Developing Queued Components.

To look at a sample of how to code queued components, see Queued Components Sample.

See Also

Writing Transactional Components

Writing Secure Components

Writing Poolable Components

Writing Components for COM+ Events

Handling Errors in COM+

Debugging COM+ Applications


Writing Components for COM+ Events

COM+ Events is a loosely coupled event (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. Subscribers query this store and select the events that they want to hear about. COM+ Events extends the COM+ programming model to support late-bound events or method calls between the publisher or subscriber and the event system. Rather than repeatedly polling the server, the event system notifies interested parties as information becomes available.

For a more detailed description on the COM+ Events model and architecture, see COM+ Events model and COM+ Events Architecture.

For information about how to offer or deliver an event, see Offering Events or Delivering Events.

To look at a sample about how to develop components and applications that use events, see COM+ Events Sample.

See Also

Writing Transactional Components

Writing Secure Components

Writing Poolable Components

Writing Queued Components

Handling Errors in COM+

Debugging COM+ Applications


Handling Errors in COM+

The most problematic part of writing components is dealing with possible errors. Trying to determine what can go wrong and what to do about it can be challenging under the best conditions. Common errors that your component might check for and handle are failed network connections, security errors, and failures associated with unreachable objects.

Additionally, you can develop your own error codes to report interface-specific errors—such as when a business rule has been violated.

In keeping with the COM+ programming model, an object can (and often does) call interface methods on other objects to perform work. Because programmers can write components in the different programming languages, COM+ requires that all error-handling mechanisms be language neutral, like HRESULTs and ErrorInfo objects.

This section includes topics, described in the following table, that discuss techniques for handling errors in COM+ applications, features in COM+ that affect failure behavior, and suggestions for diagnosing COM+ errors.

Topic | Description
Strategies for Handling Errors in COM+ | Lists and describes basic guidelines for handling errors in COM+, including when to use HRESULTs and ErrorInfo objects.
How COM+ Modifies Return Values | Identifies the single condition in which COM+ converts a standard HRESULT to a COM+ error code before passing it back to the caller.
Fault Isolation and Failfast Policy | Shows how fault isolation and the failfast policy affect COM+ behavior.
Finding the Source of an Error | Describes how you can diagnose the source and obtain a description of application errors by using a combination of Microsoft® Windows® 2000, COM+, and other tools.
Interpreting Error Codes | Identifies the predominant error-handling mechanism for Microsoft Visual C++®, the Java language, and Microsoft Visual Basic®.
Troubleshooting | Provides additional assistance in diagnosing errors.
Contacting Support | Identifies important problem-solving information you should provide when contacting support.

For detailed information on handling errors associated with various COM+ services, see the following sections:

  • Handling Errors in Transactions
  • Exception Handling (for queued components)

See Also

Writing Transactional Components

Writing Secure Components

Writing Poolable Components

Writing Queued Components

Writing Components for COM+ Events

Debugging COM+ Applications


Strategies for Handling Errors in COM+

This topic identifies several error-handling strategies to keep in mind as you develop components for COM+.

  • Return an HRESULT value for all methods in all component interfaces.

    COM+ uses HRESULTs to report on any errors in making function calls or interface method calls. An HRESULT indicates whether a method succeeded or failed and identifies the facility associated with the error, such as RPC, WIN32, or ITF for interface-specific errors. Also, system APIs provide a lookup from an HRESULT to a string that describes the error condition.

    Using methods that return HRESULTs are fundamental to well-written components and are essential to the debugging process. Microsoft® Visual Basic® automatically defines each method with an HRESULT as a return. In Microsoft Visual C++®, you must explicitly return an HRESULT.

    For additional information on HRESULTs, see Structure of COM Error Codes in the COM documentation in the Platform SDK.

  • Initiate the ErrorInfo object by whatever means your development tool provides.

    ErrorInfo objects are often called COM exceptions because they allow an object to pass (or throw) rich error information to its caller, even across apartment boundaries. The value of this generic error object is that it supplements an HRESULT, extending the type of error information that you can return to a caller. Each ErrorInfo object returns a contextual description, the source of the error, and the interface identifier of the method that originated the error. You can also include pointers to an entry in a help file.

    Automation provides three interfaces to manage the error object. Your component must implement the ISupportErrorInfo interface to advertise its support for the ErrorInfo object. When an error occurs, the component uses the ICreateErrorInfo interface to initialize an error object. After the caller inspects the HRESULT and finds that the method call failed, it queries the object to see whether it supports the ErrorInfo object. If it does, the caller uses the IErrorInfo interface to retrieve the error information.

    Visual Basic programmers have easy access to the ErrorInfo object, which is exposed through the Err object. You can raise errors with the Err Raise function and catch errors with the On Error statement. The Visual Basic run-time layer takes care of the mapping for you. If you are using the Visual C++ COM compiler support, you can use the _com_raise_error class to report an error and the _com_error class to retrieve error information. COM+ will not propagate traditional C++ exceptions as extended IErrorInfo information.

    For additional information on the ErrorInfo object, see "Error Handling" in the Automation guide.

    Note COM requires that all ErrorInfo objects will marshal by value, implying that components that implement the IErrorInfo interface must also implement and support the IMarshal interface. The IMarshal interface implementation must support marshal by value for the component.

  • Use transactions to manage shared resource failures.

    Automatic transactions can significantly reduce the amount of error-handling code you must write when using state-managed resource managers. However, transactions do not eliminate the need for error handling altogether. You still need to return error codes from your interface methods and check those error codes within the caller to avoid doing unnecessary work for a doomed transaction.

    For additional information on combining error handling with transaction processing, see Handling Errors in Transactions.

  • Raise errors explicitly.

    Avoid letting error information leave an object unless the object explicitly raises the error. Catch all tool-generated errors and handle them in your component code. At the very least, include a standard handler to report unexpected errors in a consistent manner.

  • Use the FACILITY_ITF range of errors to report interface-specific errors.

    Interface-specific errors should be in the FACILITY_ITF range of errors, between 0x0200 and 0xFFFF. You can define a custom error code in Visual Basic as an offset from vbObjectError. Use the MAKE_HRESULT macro in C++ to introduce an interface-specific error code, as shown in the following example:

    const HRESULT ERROR_NUMBER =
MAKE_HRESULT (SEVERITY_ERROR, FACILITY_ITF, 10);

See Also

How COM+ Modifies Return Values

Fault Isolation and Failfast Policy

Finding the Source of an Error

Interpreting Error Codes

Troubleshooting

Contacting Support


How COM+ Modifies Return Values

COM+ never changes the return value of an HRESULT that indicates failure, such as E_UNEXPECTED or E_FAIL. However, when an object using COM+ functionality returns an HRESULT value indicating success (such as S_OK, S_FALSE, or NOERROR), COM+ sometimes converts the HRESULT into a COM+ error code before it returns to the caller.

For example, when an application returns S_OK after calling IObjectContext::SetComplete, if the object is the root of a transaction that fails to commit, the HRESULT is converted to CONTEXT_E_ABORTED.

When COM+ converts an HRESULT value, it clears all of the method's output parameters. Returned references are released, and the values of the returned object pointers are set to NULL.

See Also

Strategies for Handling Errors in COM+

Fault Isolation and Failfast Policy

Finding the Source of an Error

Interpreting Error Codes

Troubleshooting

Contacting Support


Fault Isolation and Failfast Policy

COM+ performs extensive internal integrity and consistency checks. If COM+ encounters an unexpected internal error condition, it immediately terminates the process. This policy, called failfast, facilitates fault containment and results in more reliable and robust systems.

Consider a case in which COM+ detects that one of its data structures is in a corrupted state. At this point, both the cause and the magnitude of the corruption are unknown, and unfortunately, COM+ cannot tell how far the damage has spread. However, although COM+ is in an indeterminate state, it does not run in isolation. Like other DLLs, it is hosted in a process environment and shares a single address space with the main program executable and many other DLLs. Therefore, to be safe, COM+ assumes that the entire process has been corrupted, and the process is immediately terminated to prevent it from spreading potentially corrupted information to other processes or, worse yet, from allowing corrupted data to be committed and made durable.

COM+ does not allow exceptions to propagate outside of a context. If an exception occurs while executing within a COM+ context and the application doesn't catch the exception before returning from the context, COM+ catches the exception and terminates the process. Using the failfast policy in this case is based on the assumption that the exception has put the process into an indeterminate state—it is not safe to continue processing.

As a developer or administrator, you should inspect the Microsoft® Windows® 2000 Event Viewer Application log for details on any failfast action or serious application errors.

See Also

Strategies for Handling Errors in COM+

How COM+ Modifies Return Values

Finding the Source of an Error

Interpreting Error Codes

Troubleshooting

Contacting Support


Finding the Source of an Error

You can diagnose the source and obtain a description of application errors by using a combination of Microsoft® Windows® 2000, COM+, and other tools. If you discover that the application error is caused by COM+, you can interpret the error message viewing the winerror.h file or by using the Microsoft Visual C++® error utility.

If your server application is failing or causing unexpected behavior, you must first determine where the error occurred. Windows 2000 provides a system Event Viewer that tracks application, security, and system events. Many "silent" errors are recorded here. However, not all errors are shown in the Event Viewer.

You should first refer to the Application log in the Event Viewer to check the application associated with the event message. (Because you can also archive event logs, you can track an event history of the error.) Double-clicking an entry in your log activates an Event Properties page, which provides further information about the system event.

For example, if you attempt to run the Sample Bank client without starting the Microsoft Distributed Transaction Coordinator (DTC), an error will be returned. To find out which application caused the failure, you should refer to the Application log in the Event Viewer, which shows that the error was caused by COM+.

For more information on debugging a COM+ application, see Debugging COM+ Applications.

See Also

Strategies for Handling Errors in COM+

How COM+ Modifies Return Values

Fault Isolation and Failfast Policy

Interpreting Error Codes

Troubleshooting

Contacting Support


Interpreting Error Codes

After you have determined which application is the source of a problem, you need to find out what error has occurred. Errors are raised and reported in different formats, depending on the language your application uses.

In Microsoft® Visual C++®, success, warning, and failure values are returned using a 32-bit number known as a result handle, or HRESULT. For a list of system-defined HRESULT values, see the header file winerror.h included with the Platform SDK. This file includes all COM+ error codes and descriptions. For more information about HRESULTs, see "Error Handling" in the COM documentation in the Platform SDK.

In the Java language, an instance of com.ms.com.ComFailException is thrown to indicate failure, where the ComFailException object specifies an HRESULT. An instance of com.ms.com.ComSuccessException indicates success with a return value of False. For information about interpreting these exceptions, see the Microsoft Visual J++® documentation.

Note COM+ application server processes that are hosting Visual J++ objects will not idle down (even with zero active objects) unless you turn off JIT debugging in the VJ6 IDE. For information on how to do so, see the Visual J++ documentation.

In Visual Basic, you can retrieve HRESULTs by examining the Err.Number property. For more information, see the Visual Basic documentation.

You can also use the ERRLOOK utility in Microsoft Visual Studio® 97 to retrieve a system error message or module error message. ERRLOOK retrieves the error message text automatically if you drag-and-drop a hexadecimal or decimal value from the Visual Studio debugger or other Automation-enabled application. You can also enter a value by either typing it in or pasting it from the IDE clipboard and clicking the Look Up option.

The following table provides descriptions of common error codes in COM+.

Error Codes | Definitions
COMADMIN_E_ALREADYINSTALLED | The object is already registered.
COMADMIN_E_APP_FILE_READFAIL | Error occurred reading the application file.
COMADMIN_E_APP_FILE_VERSION | Invalid version number in application file.
COMADMIN_E_APP_FILE_WRITEFAIL | Error occurred writing to the application file.
COMADMIN_E_APPDIRNOTFOUND | Application install directory was not found.
COMQC_E_APPLICATION_NOT_QUEUED | Only COM+ applications marked "queued" can be created using the "queue" moniker.
COMADMIN_E_APPLICATIONEXISTS | The application is already installed.
COMADMIN_E_APPLID_MATCHES_CLSID | A CLSID with the same GUID as the new application ID is already installed on this machine.
COMADMIN_E_APP_NOT_RUNNING | The specified application is not currently running.
COMADMIN_E_AUTHENTICATIONLEVEL | Unable to set required authentication level for update request.
COMADMIN_E_BADPATH | The file path is invalid.
COMADMIN_E_BADREGISTRYLIBID | The registered type library ID is invalid.
COMADMIN_E_BADREGISTRYPROGID | The component's ProgID is missing or corrupt.
COMADMIN_E_CAN_NOT_EXPORT_APP_PROXY | The application proxy is not exportable.
COMADMIN_E_CAN_NOT_START_APP | Failed to start application because it is either a library application or an application proxy.
COMADMIN_E_CAN_NOT_EXPORT_SYS_APP | The system application is not exportable.
COMADMIN_E_CANT_SUBSCRIBE_TO_COMPONENT | The user cannot subscribe to this component because the component may have been imported.
COMADMIN_E_CANTCOPYFILE | An error occurred copying the file.
COMADMIN_E_CLSIDORIIDMISMATCH | Application file CLSIDs or IIDs do not match corresponding DLLs.
COMADMIN_E_COMP_MOVE_BAD_DEST | The component move failed because the destination application no longer exists.
COMADMIN_E_COMP_MOVE_LOCKED | The component move was disallowed because the source or destination application either is a system application or is currently locked against changes.
COMADMIN_E_COMPFILE_BADTLB | The type library could not be loaded.
COMADMIN_E_COMPFILE_CLASSNOTAVAIL | The DLL does not support the components listed in the type library.
COMADMIN_E_COMPFILE_DOESNOTEXIST | This file does not exist.
COMADMIN_E_COMPFILE_GETCLASSOBJ | The GetClassObject method failed in the DLL.
COMADMIN_E_COMPFILE_LOADDLLFAIL | The DLL could not be loaded.
COMADMIN_E_COMPFILE_NOREGISTRAR | The component registrar referenced in this file is not available.
COMADMIN_E_COMPFILE_NOTINSTALLABLE | The file does not contain components or component information.
COMADMIN_E_COREQCOMPINSTALLED | A component in the same DLL is already installed.
COMADMIN_E_DLLLOADFAILED | The DLL could not be loaded.
COMADMIN_E_DLLREGISTERSERVER | The DllRegisterServer function failed when the component was installed.
COMADMIN_E_EVENTCLASS_CANT_BE_SUBSCRIBER | An event class cannot be configured as a subscriber component. When an attempt is made to create a subscription with an event class as a subscriber, this error is returned.
COMADMIN_E_INVALIDUSERIDS | One or more users in the application file are not valid.
COMADMIN_E_KEYMISSING | The object was not found in the catalog.
COMADMIN_E_LIB_APP_PROXY_INCOMPATIBLE | Library applications and application proxies are incompatible. This error is returned when an attempt is made to export an application proxy and the application's activation property is a library.
COMADMIN_E_NOREGISTRYCLSID | The component's CLSID is missing or corrupt.
COMADMIN_E_NOSERVERSHARE | No server file share is available.
COMADMIN_E_NOTCHANGEABLE | Changes to this object and its sub-objects have been disabled.
COMADMIN_E_NOTDELETEABLE | The delete function has been disabled for this object.
COMADMIN_E_NOTINREGISTRY | Object was not found in registry.
COMADMIN_E_NOUSER | One or more users are not valid.
COMADMIN_E_OBJECT_DOES_NOT_EXIST | One of the specified objects cannot be found.
COMADMIN_E_OBJECT_PARENT_MISSING | One of the objects being inserted or updated does not belong to a valid parent collection.
COMADMIN_E_OBJECTERRORS | Errors occurred accessing one or more objects. For more information, see the ErrorInfo collection.
COMADMIN_E_OBJECTEXISTS | The object you are attempting to add or rename already exists.
COMADMIN_E_OBJECTINVALID | One or more of the object's properties are missing or invalid.
COMADMIN_E_OBJECTNOTPOOLABLE | This object is cannot be pooled.
COMADMIN_E_PROPERTYSAVEFAILED | One or more property settings are either invalid or in conflict with each other.
COMADMIN_E_PROPERTY_OVERFLOW | The property value is too large.
COMADMIN_E_REGFILE_CORRUPT | The registration file is corrupt.
COMADMIN_E_REGISTERTLB | The system was unable to register the type library.
COMADMIN_E_REGISTRARFAILED | Errors occurred while in the component registrar.
COMADMIN_E_REMOTEINTERFACE | Interface information is either missing or changed.
COMADMIN_E_REQUIRES_DIFFERENT_PLATFORM | This operation is not enabled on this platform
COMADMIN_E_ROLE_DOES_NOT_EXIST | A role assigned to a component, interface, or method does not exist in the application.
COMADMIN_E_ROLEEXISTS | The role already exists.
COMADMIN_E_SERVICENOTINSTALLED | The service is not installed.
COMADMIN_E_SESSION | The server catalog version is not supported.
COMADMIN_S_SOMEALREADYPAUSED | One or more of the specified application processes were already paused.
COMADMIN_S_SOMEALREADYRUNNING | One or more of the specified application processes were already running.
COMADMIN_E_START_APP_NEEDS_COMPONENTS | To start the application, you must have components in an application.
COMADMIN_E_SVCAPP_NOT_POOLABLE_OR_RECYCLABLE | The COM+ applications running as an NT service may not be marked as pooled or recycled.
COMADMIN_E_SYSTEMAPP | This operation cannot be performed on the system application.
COMADMIN_E_USER_IN_SET | One or more users are already assigned to a local partition set.
COMADMIN_E_USERPASSWDNOTVALID | The identity or password set on the application is not valid.

See Also

Strategies for Handling Errors in COM+

How COM+ Modifies Return Values

Fault Isolation and Failfast Policy

Finding the Source of an Error

Troubleshooting

Contacting Support


Troubleshooting

If you are having trouble diagnosing your application errors, refer to the following of troubleshooting tips:

  • Make sure that the Distributed Transaction Coordinator (DTC) is running on all servers.
  • Check network communication by first testing on a local computer to verify that the application works. If you are running TCP/IP on your network, you can use the Microsoft® Windows® 2000 ping.exe utility to verify that the machines are on the network.
  • Make sure that SQL and DTC are located on the same computer or that the DTC Client Configuration program specifies that the DTC is on another computer. If not, SQLConnect will return an error internally when called from a transactional component.
  • Set the transaction time-out to a higher number than the default 60 seconds. After the transaction time-out has elapsed, COM+ aborts the transaction. All subsequent calls to the component return immediately with CONTEXT_E_ABORTED.
  • Make sure that your ODBC drivers are thread-safe and do not have thread affinity.
  • If you have difficulty getting an application to work over several servers, reboot the client and then verify that your Windows 2000 domain controller is configured properly.

See the COM documentation in the Platform SDK and the COM-related Knowledge Base articles if you are experiencing application errors that you suspect are caused by DCOM.

See Also

Strategies for Handling Errors in COM+

How COM+ Modifies Return Values

Fault Isolation and Failfast Policy

Finding the Source of an Error

Interpreting Error Codes

Contacting Support


Contacting Support

If you run into a problem that you cannot solve, you can contact Microsoft technical support with the following information:

  • Topography of the application where the error occurred, such as a description of applications, components, and interfaces.
  • Application event log on all computers.
  • Description of how to reproduce the error, if possible.

See Also

Strategies for Handling Errors in COM+

How COM+ Modifies Return Values

Fault Isolation and Failfast Policy

Finding the Source of an Error

Interpreting Error Codes

Troubleshooting


Debugging COM+ Applications

Debugging techniques for COM+ applications depend on the language in which you choose to write your component.

If you code in Microsoft® Visual C++®, you can launch the debugger in C++ or, with a remote client, you can debug by using OLE remote procedure control (RPC) and just-in-time (JIT) debugging. You can always use the Component Services administrative tool to debug your component with the COM+ Launch in debugger setting on the Advanced tab of the COM+ application's Properties dialog box. For more information on debugging components coded in C++, see Debugging Components Written in Visual C++.

Unless you are currently debugging multithreading, component tracking, remote calls, or process isolation, you can use the Microsoft Visual Basic® environment for debugging purposes. Debugging Components Written in Visual Basic describes the debugging process within a Visual Basic environment.

The topic Debugging in the Visual Basic IDE provides a general overview with guidelines, tips and a procedure on debugging in the integrated development environment (IDE).

To view more information about debugging advanced processes, see Debugging Compiled Visual Basic Components.

Note Several limitations associated with using the Visual Basic environment to debug components with MTS have been resolved for COM+. For more information, see COM+ Visual Basic Debugging Support Contrasted with MTS.

See Also

Writing Transactional Components

Writing Secure Components

Writing Poolable Components

Writing Queued Components

Writing Components for COM+ Events

Handling Errors in COM+


Debugging Components Written in Visual C++

When you are ready to debug the COM+ functionality in your Microsoft® Visual C++® components, you can configure Visual C++ project or the Component Services administrative tool to launch the debugger. If you are using Visual C++, you can debug with a remote client using OLE RPC and just-in-time (JIT) debugging. If you are unable to run your client under the debugger or if the client is running on another machine, you can use the COM+ Launch in debugger setting. You will find this in the Component Services administrative tool as a check box on the Advanced tab of the COM+ application Properties dialog box.

When you are finished debugging, you should shut down the COM+ applications you are debugging. If a server process is left running, you might get an error message the next time you try to build a DLL when the existing DLL is still loaded in memory. To shut down a COM+ application, right-click the application in the console tree and then click Shut down.

Note If you are using transactions, you might also want to increase the transaction time-out, which defaults to 60 seconds. You can also specify a value of 0, effectively specifying an infinite transaction time-out period. Using the Component Services administrative tool, change the transaction time-out setting on the Options tab of the My Computer Properties window.

Debugging Server Application Components with Visual C++

When debugging COM+ server applications, you may want to debug remote calls by loading both the client and the server application into the debugger. With Visual C++, you can debug remote calls to your components through the just-in-time (JIT) and OLE RPC settings. The JIT setting causes the compiled component to start the Visual C++ debugger when an error occurs; the OLE RPC setting enables the debugger to step from client to component as you step through your code.

When these features are enabled, you can start your client under the debugger. When the client makes a call to your component, the debugger will step into the component's code in the server process, even if the server is on a different computer on the network. A debugging session is automatically started on the server computer if necessary. Similarly, single stepping past the return statement in the component's code will return debugging to the next statement in the client's code.

Note You may be able to save a few steps by using the COM+ Launch in debugger setting. This allows you to specify the Visual C++ (or other) debugger without having to make special debug settings in the Visual C++ environment. You will find this in the Component Services administrative tool as a check box on the Advanced tab of the COM+ application Properties dialog box. For more information, see "Debugging Without Visual C++" in this topic.

When the COM+ application containing your component is a server application, you must begin by shutting down the application using the Component Services administrative tool. To do this, right-click the COM+ application in the console tree and then click Shut down.

To enable RPC debugging in Visual C++

  1. In Visual C++, on the Tools menu, click Options.
  2. In the Options dialog box, on the Debug tab, select the OLE RPC debugging and Just-in time debugging check boxes.
  3. Click OK.

To begin debugging, start your client project in the debugger.

You can also debug your component without launching your client in the debugger. In this case, your component must launch the debugger on its own. To do this, your component project must specify an executable for the debug session, along with the COM+ application ID.

To enable a server application component to launch the Visual C++ debugger

  1. On the Project menu, click Settings.
  2. In the Project Settings dialog box, in the Settings For box, select Win32 Debug.
  3. On the Debug tab, in the Category box, select General.
  4. In the Executable for debug session box, enter the fully qualified path for Dllhost.exe, followed by an argument specifying the application ID of the COM+ application containing the component.

    Note Using the Component Services administrative tool, you will find the application ID on the General tab of the COM+ application's Properties dialog box. Following is an example:

    C:\Winnt\System32\Dllhost.exe /ProcessID:{<applicationID>}

  5. Click OK.

You can now set breakpoints, start the debugger, and begin making calls to your component.

Debugging Library Application Components With Visual C++

To debug components in a library application, you must configure the client's project because the client's process will host the library application.

To enable library application debugging with Visual C++

  1. In Visual C++, on the Project menu, click Settings.
  2. In the Project Settings dialog box, in the Settings For box, click Win32 Debug.
  3. On the Debug tab, in the Category box, click Additional DLLs.
  4. In the Modules list, add the component DLLs in your library application. This allows you to set breakpoints before your DLL is actually loaded.
  5. Click OK.

Debugging Without Visual C++

Whether or not you are using Visual C++ for debugging, you can use the Launch in debugger setting to specify the debugger in which your components should run.

To specify a debugger from the Component Services administrative tool

  1. In the console tree, select the COM+ library application containing the components you wish to debug.
  2. Right-click the application, and then click Properties.
  3. In the application's Properties dialog box, click the Advanced tab.
  4. Under Debugging, select the Launch in debugger check box.
  5. In the Debugger path box, enter path to the debugger you want to use. You can also click Browse to locate the debugger. Following is an example:
    C:\Winnt\System32\Ntsd.exe
  6. Click OK.

See Also

Debugging Components Written in Visual Basic


Debugging Components Written in Visual Basic

You can use the Microsoft® Visual Basic® 6.0 development environment for debugging within certain scenarios. Using Visual Basic for debugging allows access to tools familiar to Visual Basic programmers. On the other hand, because during debugging Visual Basic components run within the Visual Basic environment's process, it may be necessary to debug your component after it has been compiled by using the Microsoft Visual C++® development environment.

For more information about debugging within the Visual Basic integrated development environment (IDE), see Debugging in the Visual Basic IDE. For more on debugging Visual Basic components after they're compiled using the Visual C++ development environment, see Debugging Compiled Visual Basic Components.

Also, several limitations associated with using the Visual Basic environment to debug components with MTS have been resolved for COM+. For more information, see COM+ Visual Basic Debugging Support Contrasted with MTS.

Note If you have already used Visual Basic on the same computer as COM+, you may have noticed the Component Services add-in available in the Visual Basic environment. Originally in MTS, this feature was designed to update the registry each time you recompiled a component in a COM+ application. However, given the nature of the interaction of the Microsoft Windows® Registry and the COM+ registration database, some settings may not be completely updated. Therefore, instead of using the commands available with this add-in, you should remove and reinstall your components to update settings after recompiling.

See Also

Debugging Components Written in Visual C++


Debugging in the Visual Basic IDE

Using the Microsoft® Visual Basic® integrated development environment (IDE) for debugging gives Visual Basic developers access to familiar tools and ease-of-use. While many components will eventually need to be more fully debugged using the Microsoft Visual C++® environment, one strategy might be to first debug as much functionality as possible with Visual Basic. For example, you might want to use the Visual Basic IDE for debugging within COM+ when you aren't yet debugging multithreading, component tracking, remote calls, or process isolation.

In general, when using the Visual Basic environment for debugging, you first compile the project and add the DLL to a COM+ application. Then you set binary compatibility for the project, referencing the DLL you made, and start the project to begin debugging.

The following offers.

General Guidelines for Debugging in the Visual Basic Environment

  • While you are debugging using Visual Basic, COM+ treats the Visual Basic components as if they belong to a library application, even if the components are registered as belonging to a server application. Because it runs as a library application, the component icons in the Component Services administrative tool do not spin as the components are debugged.
  • If you change transaction attributes on a component during debugging or make a source code change that requires Visual Basic to generate a new CLSID or ProgID, be sure to delete and reinstall the COM+ application containing the component. If you have set binary compatibility for the component, you will be warned that changes have occurred.

Notes on Debugging Within a COM+ Application

  • If you make changes in the Visual Basic IDE in your component’s interfaces, class names, project names, transactional support or other settings, there may be mismatches between the configuration data in the Component Services explorer and the actual configuration running in the Visual Basic debugger.
  • Do not export a COM+ application while you are debugging a component in the application. COM+ will treat the Visual Basic development environment as the component.
  • If you are running a component outside the debugger and then decide to begin debugging, an instance of the component may still be running in COM+ when you start it in the debugger. COM+ will detect this condition and attempt to silently shut down the instance it controls. To avoid this problem, remove the component from the Component Services administrative tool before you begin debugging.

To debug using the Visual Basic environment

  1. Open the component project in Visual Basic.
  2. Compile your component, and then set binary compatibility in your project to the compiled component.
  3. Set the MTSTransactionMode property to a value other than 0 - NotAnMTSObject. When you start the project, this setting prompts Visual Basic to activate your component within COM+.
  4. From the Project menu, click Properties, and then enter the start program on the Debugging tab. The start program is the client executable that calls this component.

    Note The start program must be local to the component you are debugging.

  5. Press F5 to begin debugging the component.

After you press F5, Visual Basic launches the client application and runs the component in debug mode. You can place breakpoints in the component's code and set watches on variables.

See Also

Debugging Compiled Visual Basic Components

COM+ Visual Basic Debugging Support Contrasted with MTS


Debugging Compiled Visual Basic Components

Given that in many cases you will be able to debug only a portion of your component's functionality within the Microsoft® Visual Basic® environment, there will be situations in which you will need to debug components built with Visual Basic after they have been compiled. Since the Visual Basic environment doesn't enable this, you must instead use the Microsoft Visual C++® environment.

To debug a Visual Basic component in the Visual C++ environment

  1. In Visual Basic 6.0, open the Visual Basic project that you want to debug.
  2. On the File menu, click Make <YourProject>.dll.
  3. In the Make Project dialog box, click Options.
  4. In the Project Properties dialog box, on the Compile tab, click Compile to Native Code and No Optimization and select the Create Symbolic Debug Info check box.
  5. Click OK, and then click OK again to compile your project.
  6. Move the compiled DLL to the location where COM+ applications are normally installed.

    Note If you don't move the DLL, you may get an error message informing you that symbolic debugging information for the DLL could not be located. If you have trouble getting the debugger to stop at breakpoints in your component, confirm that the DLL is in the standard packages directory, delete the component from its package, and re-add the component.

  7. Start Visual C++.
  8. On the File menu, click Open Workspace.
  9. In the Open Workspace dialog box, set Files of Type to All files(*.*), select your compiled component, and click Open.
  10. From the File menu, click Open (not Open Workspace) and open the Visual Basic module (.bas), form (.frm), or class (.cls) that you want to debug.
  11. On the Project menu, click Settings.
  12. In the Project Settings dialog box, on the Debug tab, select General in the Category box.
  13. In the Executable for debug session box, enter the fully qualified path for Dllhost.exe, followed by an argument specifying the process ID of the COM+ application containing the component. You will find the process ID on the General tab of the COM+ application's Properties dialog box. Following is an example:
    C:\Winnt\System32\Dllhost.exe /ProcessID:{<processID>}
  14. Click OK.

See Also

Debugging in the Visual Basic IDE

COM+ Visual Basic Debugging Support Contrasted with MTS


COM+ Visual Basic Debugging Support Contrasted with MTS

COM+ removes or reduces several limitations of debugging with Microsoft® Visual Basic® 6.0 and MTS. The following list summarizes changes you can expect with COM+:

  • Debugging multiple components—In COM+, you can debug scenarios in which a client running in one instance of the IDE makes calls to any number of DLLs running in another as a project group. The objects in the grouped DLL projects can call each other arbitrarily, flowing context as needed. Of course, this also works when the DLLs and the client are in the same project group in the same instance of the IDE.
  • Debugging Limitations on Class_Initialize and Class_Terminate Events—With COM+, you can put code in the Class_Initialize and Class_Terminate events of a COM+ application component even if that code attempts to access the object or its corresponding context object. You can set breakpoints there and use watches. You can also set breakpoints in the Class_Terminate event.

    Although it is no longer needed as a workaround, you can still implement the IObjectControl interface and use its Activate and Deactivate methods if you need to execute code during startup and shutdown of your component. You can also now put breakpoints in code for the IObjectControl::Deactivate or IObjectControl::CanBePooled methods.

  • Watching MTS Objects—With COM+, you can add watches for object variables returned by COM+, including return values from the SafeRef, GetObjectContext, and IObjectContext::CreateInstance methods.
  • Increased stability when components fail—In COM+, a component failure will no longer always stop Visual Basic (which runs in the same process as the debugged component). For example, support for just-in-time (JIT) reactivation failures now allows you to look at the object context while debugging.
  • Debugger may reactivate objects released by COM+—As with MTS, Visual Basic 6.0 may reactivate COM+ objects while you are debugging single-step through a client. Because of the way that Visual Basic 6.0 discovers information about objects, this is expected behavior. For example, consider the following code:
    Dim x as object
Set x = CreateObject("MyApp.Class")
x.Test
Set x = Nothing

    If the x.Test method calls IObjectContext::SetComplete, COM+ immediately frees x from memory, but x has not yet been set to Nothing. When x.Test returns, the Visual Basic debugger calls QueryInterface on x for the IProvideClassInfo interface. The context wrapper associated with x creates a new instance of MyApp.Class to service the QueryInterface call. As a result, you will see this uninitialized object in the debugger after x.Test has returned. This object appears only in the debugger and is removed by the subsequent instruction to set x to Nothing.

See Also

Debugging in the Visual Basic IDE

Debugging Compiled Visual Basic Components


Creating and Configuring COM+ Applications

A COM+ application is the primary unit of administration and security for COM+ (Component Services). The COM+ application is a grouping of components that, generally, perform related functions. Components consist of COM-based interfaces and methods.

After creating a COM+ application, you can configure its related attributes at the application level, component level, component-interface level, and component-method level. Attribute settings determine how your application will deliver COM+ services through its components, interfaces, and methods.

The topics in this section are described in the following table.

Topic | Description
Creating COM+ Applications | Provides procedures for creating a new application, installing new components, importing components, removing components from a COM+ application, and deleting a COM+ application.
Configuring COM+ Applications | Lists and describes application, component, interface, and method attributes.
Converting MTS Packages to COM+ Applications | Describes the process of automatically converting an MTS package to a COM+ application and explains how to perform the conversion manually.
Automating COM+ Administration | Introduces COMAdmin objects, describes how to retrieve collections from the COM+ catalog, and identifies how to use COMAdmin objects to automate all tasks in the administration of COM+ applications and services.


Creating COM+ Applications

This section describes how to create a new (empty) COM+ application and then add components to that application. It also describes how to add COM components to, and remove them from, existing COM+ applications, and how to move and copy components from one COM+ application to another.

Topic | Description
Creating a New COM+ Application | Describes how to create a new COM+ application.
Installing New Components | Describes how to install new components.
Importing Components | Describes how to import components.
Removing a Component from a COM+ Application | Describes how to delete a component from a COM+ application.
Moving Components | Describes how to move a component from one COM+ application to another.
Copying Components | Describes how to copy a component from one COM+ application to another.
Deleting a COM+ Application | Describes how to delete a COM+ application.

For conceptual information on the procedures described in this section, see COM+ Application Overview and Deployment and Registration of COM+ Applications.

For procedural information on the administrative tasks involved in exporting and installing COM+ applications, see "Installing COM+ Applications" in the Component Services Administrator's Guide.

See Also

Configuring COM+ Applications

Converting MTS Packages to COM+ Applications

Automating COM+ Administration


Creating a New COM+ Application

Creating a new COM+ application requires two basic steps, as follows:

  • Creating an empty COM+ application (described below).
  • Adding components to the application. (See Installing New Components and Importing Components.)

To create an empty COM+ application

  1. In the console tree of the Component Services administrative tool, select the computer on which you want to create an application.
  2. Select the COM+ Applications folder for that computer.
  3. On the Action menu, point to New, and then click Application. You can also right-click the COM+ Applications folder, point to New, and then click Application.
  4. On the Welcome page of the COM+ Application Install Wizard, click Next, and then in the Install or Create a New Application dialog box, click Create an empty application.
  5. In the box provided, type a name for the new application. (Note that the following special characters cannot be used in an application name: \, /, ~, !, @, #, %, ^, &, *, (, ), |, }, {, ], [, ', ", >, <, ., ?, :, and ;.) Under Activation type, click Library application or Server application. Click Next.

    Note A server application runs in its own process. Server applications can support all COM+ services. A library application runs in the process of the client that creates it. Library applications can use role-based security but do not support remote access or queued components.

  6. In the Set Application Identity dialog box, under Account, click Interactive user – the current logged on user or This user. If you select This user, type the user name and password. You must also retype the password in the Confirm password box. Click Next. (The default selection for application identity is Interactive User. The interactive user is the user logged on to the server computer at any given time. You can select a different user by selecting This user and entering a specific Microsoft® Windows® 2000 user or group.)

    Note The Set Application Identity dialog box appears only if you selected Server application for the new application's activation type in the COM Application Install Wizard's preceding dialog box. The identity property is not used for library applications.

  7. Click Finish.

The new application will now be displayed under the COM+ Applications folder in the console tree of the Component Services administrative tool.

See Also

Installing New Components

Importing Components

Removing a Component from a COM+ Application

Moving Components

Copying Components

Deleting a COM+ Application


Installing New Components

To add components to the Components folder of a COM+ application, you can either use the COM+ Component Install Wizard or drag .dll files that contain the components from the Windows 2000 Explorer and drop them in the application.

If you use the COM+ Component Install Wizard, you can either install a new component, which registers the component on the computer, or import components that have already been registered. Components can be added to empty applications or existing applications.

To add a component to a COM+ application

  1. In the console tree of the Component Services administrative tool, select the computer hosting the COM+ application.
  2. Open the COM+ Applications folder for that computer, and select the application in which you want to install the component(s).
  3. Open the application folder and select Components.
  4. On the Action menu, point to New, and then click Component. You can also right-click the Components folder, point to New, and then click Component.
  5. On the Welcome page of the COM+ Application Install Wizard, click Next, and then in the Import or Install a Component dialog box, click Install new component(s) .
  6. In the Install new components dialog box, click Add to browse for the component you want to add.
  7. In the Select files to install dialog box, type the filename of the component to install or select a filename from the displayed list. Click Open.

    After you add the files, the Install new components dialog box displays the files you have added and their associated components. If you select the Details check box, you will see more information about file contents and the components that were found.

    Note COM components must have a type library. If COM+ cannot find your component's type library, your component will not appear in the list. You can also remove a file from the Files to install list by selecting it and clicking Remove.

  8. Click Next, and then click Finish to install the component.

See Also

Creating a New COM+ Application

Importing Components

Removing a Component from a COM+ Application

Moving Components

Copying Components

Deleting a COM+ Application


Importing Components

You can use the Component Services administrative tool to import into applications specific components that have already been registered on your computer as COM components in the Windows registry. Importing a component does not install the interface or method information required to set interface properties or to configure access to the component from a remote client. Therefore, if possible, you should install rather than import components.

Note When importing a component into a COM+ application, COM+ does not populate interface and method information for the component. During the export of an application proxy, COM+ will not provide marshaling information (type libraries or proxy/stubs) for some or all of the interfaces. Exporting application proxies that contain imported components will fail or issue a warning in Microsoft® Windows® 2000.

To import a component into a COM+ application

  1. In the console tree of the Component Services administrative tool, select the computer hosting the COM+ application.
  2. Open the COM+ Applications folder for that computer, and select the application in which you want to install the component.
  3. Open the application folder and select Components.
  4. On the Action menu, point to New, and then click Component. You can also right-click the Components folder, point to New, and then click Component.
  5. On the Welcome page of the COM+ Application Install Wizard, click Next, and then in the Import or Install a Component dialog box, click Import component(s) that are already registered.
  6. In the Choose Components to Import dialog box, select the Details check box to see complete information about the components that are already registered. Select the component(s) you want to import from the displayed list, and click Next.
  7. Click Finish.

See Also

Creating a New COM+ Application

Installing New Components

Removing a Component from a COM+ Application

Moving Components

Copying Components

Deleting a COM+ Application


Removing a Component from a COM+ Application

You can use the Component Services administrative tool to remove components from a COM+ application.

Note Exercise care when deleting and reinstalling individual components from a COM+ application. This process requires detailed knowledge about the component's classes, including their attributes, security configurations on interfaces and methods, and other settings.

To remove a component from a COM+ application

  1. In the console tree of the Component Services administrative tool, select the application that contains the component you want to remove.
  2. Open the application's Components folder.
  3. Select the component you want to remove.
  4. On the Action menu, click Delete. You can also select the component, right-click, and click Delete.
  5. Click Yes when prompted to confirm your action.

See Also

Creating a New COM+ Application

Installing New Components

Importing Components

Moving Components

Copying Components

Deleting a COM+ Application


Moving Components

You can move a component from one COM+ application to another. In effect, moving a component removes the component from the original COM+ application and installs it in the target COM+ application.

To move a component from one COM+ application to another

  1. In the details pane of the Component Services administrative tool, right-click the component that you want to move and then click Move.
  2. In the Move component(s) dialog box, select the destination COM+ application to which you want the component to be moved.
  3. Click OK.

See Also

Creating a New COM+ Application

Installing New Components

Importing Components

Removing a Component from a COM+ Application

Copying Components

Deleting a COM+ Application


Copying Components

You can copy a component from one COM+ application to another. After you copy a component to another COM+ application, you can configure this component differently than the original component.

To copy a component from one COM+ application to another

  1. In the details pane of the Component Services administrative tool, right-click the component that you want to copy and then click Copy.
  2. In the Copy Component dialog box, in the Please select a Destination pane, select the COM+ application to which the component will be copied.
  3. Enter the new ProgID for the copied component.

    Note The ProgID for the original component is displayed for reference and cannot be changed.

  4. Enter the new CLSID for the copied component. COM+ displays an automatically generated CLSID. In most cases, this will be sufficient to uniquely identify the copied component. Enter a new CLSID only if you want to change the one provided by COM+.
  5. Click OK.

See Also

Creating a New COM+ Application

Installing New Components

Importing Components

Removing a Component from a COM+ Application

Moving Components

Deleting a COM+ Application


Deleting a COM+ Application

As existing applications become dated or are no longer being used, you may need to remove them.

To delete a COM+ application

  1. In the console tree of the Component Services administrative tool, select the computer for which you want to delete an application.
  2. Open the COM+ Applications folder for the specified computer to display all the applications.
  3. Select the application you want to remove.
  4. If you selected a server application, shut down the application. You can shut down an application by selecting it in the Component Services administrative tool, right-clicking, and then clicking Shut down. If you selected a library application, make sure that all processes currently using this library application are shut down.
  5. On the Action menu, click Delete. You can also right-click the application name and then click Delete. You can also delete an application by selecting it in the Component Services administrative tool and pressing the Delete key, or you can select the application, right-click, and then click Delete.
  6. Click Yes when prompted to confirm your action.

In addition, if a server application or application proxy has been installed on a computer using Windows Installer (as described in "Installing COM+ Applications" in the Component Services Administrator's Guide), you can delete it through the Add/Remove Programs utility in the Microsoft® Windows® Control Panel. Or you can delete an installed server application or application proxy by using the Windows Installer command line syntax:

msiexec -x <application_name>.msi

These methods are especially useful for deleting COM+ applications on client machines that are not running the Component Services administrative tool.

Deleting the application also deletes any components contained in the application. If these components depend on additional resources (database connections, data or text files, IIS virtual root configuration, and so on), these resources must be removed through mechanisms other than the Component Services administrative tool.

See Also

Creating a New COM+ Application

Installing New Components

Importing Components

Removing a Component from a COM+ Application

Moving Components

Copying Components


Configuring COM+ Applications

A COM+ application is essentially a declarative construct that enables you to configure any number of components in common. For example, you can configure the components in an application with a common security policy.

Configuration is an essential part of the development process for COM+ applications. How you configure an application will determine how COM+ will provide services for it and how it behaves when running.

You can configure COM+ applications using either the Component Services administration tool or the scriptable administration objects and interfaces that provide the underlying functionality of the administration tool. For details on performing scripted administration, see Automating COM+ Administration.

You can configure elements at the following levels within COM+ applications:

  • Application-level settings
  • Component-level (class-level) settings
  • Interface-level settings
  • Method-level settings

How you install components into an application can affect how you can configure them. You should always install components into COM+ applications (as opposed to importing them). Installing components will fully register them, along with interfaces and type libraries, in the COM+ class registration database (RegDB) so that you can configure them.

Application-Level Settings

Attribute | Description
Activation | Specifies application type, either server application or library application, and if a server application, enables application to run as NT Service.
Enforce access checks | Turns security checking on and off.
Security level | Specifies that access checks will be performed at the process level (access-checking levels generated from roles) or both at process and at component levels (full role-based security).
Authentication level | Sets the authentication level used on calls into the application.
Impersonation level | Sets the impersonation level used on calls to other applications.
Queuing | Specifies that application components will use queuing services.
Enable CRM | Enables use of Compensating Resource Managers.
Server Process Shutdown | Specifies that the process will shut down after a specified idle period.
Permissions | Disables changes to configuration settings, including deletion.
Security identity | Specifies the identity under which the application runs.
Launch in debugger | Specifies that the application will be launched in a debugger, with command-line settings you set.
Enable 3GB support | Enables use of extended process memory address space.

Component-Level (Class-Level) Settings

Attribute | Description
Transactions | Sets automatic transaction requirements—Disabled, Not Supported, Supported, Required, or Requires New.
Synchronization | Sets synchronization requirements—Disabled, Not Supported, Supported, Required, or Requires New.
JIT Activation | Enables Just-in-time activation.
Object Pooling | Enables object pooling. Minimum and maximum pool size and object time-out values are configurable.
Object Construction | Enables parameterized object construction with an administratively specified constructor string.
Enforce component level access checks | Turns on or off component-level role-based security checking.
Declarative role assignment | Enables explicit assignment of roles to the component.
Queuing exception class | Indicates an exception class for handling client-side failures.
Instrumentation events and statistics | Enables detailed system event and object statistics reporting.

Interface-Level Setting

Attribute | Description
Queued | Indicates a queuable interface, defined in IDL.
Declarative role assignment | Enables explicit assignment of roles to the interface as well as implicitly inherited roles from the component level.

Method-Level Setting

Attribute | Description
Auto-done | Automatically deactivates object on method return and votes in transaction.
Declarative role assignment | Enables explicit assignment of roles to the method as well as implicitly inherited roles from the interface and component levels.

See Also

Creating COM+ Applications

Conversion of MTS Packages to COM+ Applications

Automating COM+ Administration


Configuring Library Applications

Because COM+ library applications run in the client's process, the configurable elements for library applications are considerably different than for server applications. You cannot configure any aspect of the application that is determined by the hosting process.

At the application level, several settings are either limited or unavailable for library applications. These constraints are described in the following table:

Attribute | Description
Security level | You must choose component-level access checks. The library application cannot influence process-level access checks. See Setting a Security Level for Access Checks.
Enabling or disabling authentication | You can indicate whether the library application will participate in authentication performed by the host process. See Enabling Authentication for a Library Application.
Impersonation level | Unavailable. The setting of the host process is used.
Security identity | Unavailable. The application runs under the identity of the host process.
Server process shutdown | Unavailable.
Enable 3-GB support | Unavailable.
Launch in debugger | Unavailable.
Enable CRM | Unavailable.
Queuing | Unavailable.

See Also

Configuring Transactions

Configuring Synchronization

Configuring Security

Configuring Object Pooling

Configuring JIT Activation

Configuring a COM+ Server Application as an NT Service

Configuring Queued Components

Configuring COM+ Events


Configuring Transactions

The transaction attribute is a declarative property that automatically manages transactions on behalf of a component developer. By setting this attribute, you eliminate the need to use explicit transaction controls in your component.

COM+ looks at the attribute to determine the type of transaction protection it must provide as it activates each object. Depending on its requirement, an object can share its caller's transaction, require a new transaction, or operate without transaction protection.

For detailed information about valid transaction attribute values, transaction attribute dependencies, and how to set transaction attribute values, see the following topics in this section:

  • Description of Transaction Attribute Values
  • Transaction Attribute Dependencies
  • Setting the Transaction Attribute

See Also

Configuring Library Applications

Configuring Synchronization

Configuring Security

Configuring Object Pooling

Configuring JIT Activation

Configuring a COM+ Server Application as an NT Service

Configuring Queued Components

Configuring COM+ Events


Description of Transaction Attribute Values

COM+ provides the following transaction attribute values:

  • Disabled—When you disable the transaction attribute, COM+ ignores the transactional requirements of the component in determining context placement of the object. As a result, the object may or may not share its caller's context (and transaction).

    In general, you should use this attribute value when you know the component never accesses a resource manager. When migrating COM components to COM+, you must disable the transaction attribute to maintain the same transactional behavior as the unconfigured COM component.

    Note An unconfigured component is a COM component that has not been installed in a COM+ application.

  • Not Supported—An object with this value never participates in a transaction, regardless of the transactional status of its caller. By declaring this value, you ensure that an object will not vote in its caller's transaction nor begin a transaction of its own. Not Supported is the default value for all components.
  • Supported—An object with this value participates in a transaction if one exists. You declare this value when you want an object to share in its caller's transaction but not require a transaction of its own.
  • Required—When you set this attribute value, COM+ ensures that all objects created from the component will be transactional. This is the preferred setting for a component that performs resource activities because it guarantees transaction protection for those activities.

    As COM+ activates an object, it looks at the transactional status of its caller. If the caller has a transaction, COM+ flows the caller's transactional boundary to include the new object. Otherwise, COM+ begins a transaction, making the new object the root of the transaction.

  • Requires New—An object with this value must participate in a new transaction as the root of the transaction, regardless of the transactional status of the caller. COM+ automatically initiates a new transaction, which is distinct from the caller's transaction.

    COM+ does not support nested transactions. Thus, when one transactional object calls another component marked as Requires New, COM+ creates an independent transactional boundary for the newly activated object. The second transaction cannot affect the first transaction unless the first transaction explicitly notes the results of the second transaction and modifies its vote based on those results.

See Also

Transaction Attribute Dependencies

Setting the Transaction Attribute


Transaction Attribute Dependencies

The following table shows the characteristics of each COM+ transaction attribute value, including the value's effect on transaction (Tx) characteristics. COM+ enforces just-in-time (JIT) activation and synchronization for all transaction components.

Attribute Value | New Tx? | Client's Tx? | Tx Root? | JIT | Sync
Disabled | Never | Maybe | Never | Optional | Optional
Not Supported | Never | Never | Never | Optional | Optional
Supported | Never | If client has Tx | Never | Required | Required
Required | Maybe | If client has Tx | If client has no Tx | Required | Required
Requires New | Always | Never | Always | Required | Required

See Also

Description of Transaction Attribute Values

Setting the Transaction Attribute


Setting the Transaction Attribute

You can set transaction attributes manually by using the Component Services administrative tool, or you can add programmatic support for transactions when you write your component.

For more on transaction attribute values, see Description of Transaction Attribute Values.

To set the attribute using the Component Services administrative tool

  1. In the console tree, right-click the component you want to configure and then click Properties.
  2. In the component properties dialog box, click the Transactions tab.
  3. Under Transaction support, click the option for the value you want. The default value for all components is Not Supported.
  4. Click OK.

You must repeat this procedure for each component.

To add programmatic support in your component

You can add the transaction attribute value to your IDL file, which publishes the value in the component's type library. See Mtxattr.h for current attribute syntax.

Microsoft® Visual Basic® 6.0 programmers can set the transaction attribute with MTSTransactionMode, a class module property for ActiveX® DLL projects. Visual Basic maps your selection to the equivalent COM+ transaction attribute value and publishes the value in your component's type library.

The following table maps each MTSTransactionMode property value to its equivalent COM+ transaction value.

MTSTransactionMode Property | COM+ Transaction Value
NotAnMTSObject (default) | Disabled
NoTransactions | Not Supported (default)
RequiresTransaction | Required
UsesTransaction | Supported
RequiresNewTransaction | Requires New

See Also

Description of Transaction Attribute Values

Transaction Attribute Dependencies


Configuring Synchronization

The synchronization attribute is a declarative property that specifies what type of synchronization you want your components to have when they are activated. When you include the synchronization attribute, COM+ handles the details of synchronization on your behalf; you do not have to make any other calls.

Depending on its requirements, an object can share its caller's synchronization, require a new synchronization, or operate without synchronization.

The following topics in this section describe configurable aspects of synchronization:

  • Synchronization Attribute Values
  • Synchronization Dependencies
  • Setting the Synchronization Attribute

See Also

Configuring Library Applications

Configuring Transactions

Configuring Security

Configuring Object Pooling

Configuring JIT Activation

Configuring a COM+ Server Application as an NT Service

Configuring Queued Components

Configuring COM+ Events


Synchronization Attribute Values

COM+ provides the following synchronization attribute values:

  • Disabled—When you disable the synchronization attribute, COM+ ignores the synchronization requirements of the component in determining context for the object. As a result, the object may or may not share its caller's context (and synchronization).

    In general, you should use this attribute value when you know the component never accesses a resource manager. When migrating COM components to COM+, you must disable the synchronization attribute to maintain the same behavior as the unconfigured COM component. An unconfigured component is a COM component that has not been installed in a COM+ application.

  • Not Supported—An object with this value never participates in synchronization, regardless of the status of its caller. This setting is available only for components that are non-transactional and do not use just-in-time (JIT) activation.
  • Supported—An object with this value participates in synchronization if it exists. You declare this value when you want an object to share in its caller's synchronization but not require synchronization of its own.

    A good reason to set your synchronization attribute to Supported is that this setting can be less expensive in terms of system resources. However, it is more difficult to write your component because of the need to protect it from concurrent calls. The implication of setting the synchronization attribute to Supported is that, under certain circumstances, an instance of your object may be created in such a way that it's not synchronized. If the component's Threading Model is Free or Both, you will have to protect your instance data with some type of locking mechanism. If the Threading Model is Apartment (STA), you won't need to protect your instance data.

  • Required—When you set this attribute, COM+ ensures that all objects created from the component will be synchronized. In effect, whenever COM+ creates an instance of your component, it makes sure there's only one thread going through this instance at a time.

    As COM+ activates an object, it looks at the synchronization status of its caller. If the caller is synchronized, COM+ flows the caller's synchronization boundary to include the new object. Otherwise, COM+ begins the synchronization.

  • Requires New—An object with this value must participate in a new synchronization, where COM+ manages contexts and apartments on behalf of all components involved in the call. COM+ automatically initiates a new synchronization, which is distinct from the caller's synchronization.

    A good reason to set your synchronization attribute to Requires New is that this setting allows you to make outside calls to an instance of your component more efficiently. However, it also makes calls between your object and the object that created it more expensive in terms of system resources.

    For example, assume a case where your object and its creator object share the same synchronization boundary. If client A calls the creator object and client B calls your object, the second call will have to wait until the first call is completed. If you set Requires New, your object is created in a separate synchronization boundary. In this case, calls from other objects can be processed at the same time. However, calls from the creator object to your object require more system resources because they must cross synchronization boundaries.

See Also

Synchronization Dependencies

Setting the Synchronization Attribute


Synchronization Dependencies

Synchronization values can be automatically determined or constrained by the configuration of other properties, such as transactional requirements and just-in-time (JIT) activation. For example, COM+ enforces synchronization both for transactional and for JIT-activated components.

These dependencies exist because components that are JIT-activated or participating in transactions must have proper isolation and concurrency behavior. Therefore, COM+ requires that access to these components be serialized by enforcing synchronization. (For details on these dependencies, see JIT Activation.)

The following tables show the characteristics of the COM+ synchronization attribute values.

Transactional requirement

When transactions are set to | Synchronization can be set to
Disabled | Anything, depending on JIT activation
Not Supported | Anything, depending on JIT activation
Supported | Required
Required | Required
Requires New | Required or Requires New

JIT Activation

When JIT activation is set to | Synchronization can be set to
Enabled | Required or Requires New
Disabled | Anything

For more detail about how transaction, JIT activation, and synchronization attributes behave together, see Transaction Attribute Dependencies.

See Also

Synchronization Attribute Values

Setting the Synchronization Attribute


Setting the Synchronization Attribute

Set the synchronization attribute by using either the Component Services administrative tool or the COM+ Administration Library (See Automating COM+ Administration.)

To set the attribute using the Component Services administrative tool

  1. After installing your component, open the component's Properties dialog box.
  2. Click the Concurrency tab.
  3. Under Synchronization support, click the option button adjacent to the value you want to select for the component.
  4. Click OK.

See Also

Synchronization Attribute Values

Synchronization Dependencies


Configuring Security

You can configure a number of security features for an application. You can do this by using either the Component Services administrative tool or the COM+ Administrative SDK functions.

The topics in this section, described in the following table, discuss the configuration of security features by using the Component Services administrative tool.

Topic | Description
Configuring Role-Based Security | Explains how to define roles for the application, assign them to resources, and enable access checking to be performed at various levels.
Setting Authentication | Explains how to set an authentication level to administratively determine how authentication will be performed for either server or library applications.
Setting an Impersonation Level | Explains how to grant an impersonation authority on calls made out of the application.

See Also

Configuring Library Applications

Configuring Transactions

Configuring Synchronization

Configuring Object Pooling

Configuring JIT Activation

Configuring a COM+ Server Application as an NT Service

Configuring Queued Components

Configuring COM+ Events


Configuring Role-Based Security

If your COM+ application uses role-based security, there are several tasks that need to be completed. When designing the components in your application, you define the roles that are necessary to protect access to the components. You also decide which roles to assign to the application's components, interfaces, and methods. During application integration, you use the Component Services administrative tool to add the defined roles to the application and assign each role to the appropriate components, interfaces, and methods.

In configuring role-based security, you perform the following steps:

  1. Enable access checks at the application level—To turn on security checking for an application. See Enabling Access Checks for an Application for details on how to perform this step.
  2. Set security level for access checks—To set security either at process or at process and component level. See Setting a Security Level for Access Checks for details on how to perform this step.
  3. Enable access checks at the component level—To turn on security checking at the component, interface, and method levels. See Enabling Access Checks at the Component Level for details on how to perform this step.
  4. Define roles for an application—To create roles for an application. See Defining Roles for an Application for details on how to perform this step.
  5. Assign roles to components, interfaces, or methods—To assign roles to specific resources within an application. See Assigning Roles to Components, Interfaces, or Methods for details on how to perform this step.

See Also

Setting Authentication

Setting an Impersonation Level


Enabling Access Checks for an Application

Performing this step enables either process access checks or full role-based security, depending on what security level you select and whether you enable access checking for individual components.

To enable access checks for an application

  1. In the console tree of the Component Services administrative tool, right-click the COM+ application for which you want to enable access checks, and then click Properties.
  2. In the application properties dialog box, click the Security tab.
  3. Select the Enforce access checks for this application check box.
  4. Click OK.

After enabling access checks, you should select the appropriate security level. See Setting a Security Level for Access Checks. Also, you must be sure to define roles and add them to the application. If access checks are enabled but no roles have been added, all calls to the application will fail. See Defining Roles for an Application.

Note When debugging your application, it might be helpful to disable security so that you can concentrate on other aspects of your program's behavior and design.

See Also

Configuring Role-Based Security

Setting a Security Level for Access Checks

Enabling Access Checks at the Component Level

Defining Roles for an Application

Assigning Roles to Components, Interfaces, or Methods


Setting a Security Level for Access Checks

After you have enabled access checks, for your COM+ application, you must select the level at which you wish to have access checks performed:

To select a security level

  1. In the console tree of the Component Services administrative tool, right-click the COM+ application for which you want to enable access checks, and then click Properties.
  2. In the application properties dialog box, click the Security tab.
  3. Under Security level, select one of the following:
    • Perform access checks only at the process level—This setting indicates that users in roles that are assigned to the application will be added to the process security descriptor. This has the following effects and implications:

      Fine-grained role checking is turned off at the component, method, and interface levels. Security checks are performed only at the application level.

      The security property is not included on the context for any objects running within the application. This can potentially affect how objects are activated. See Security Context Property.

      The security call context will not be made available. Programmatic security that relies on security call context information will not function. See Security Call Context Information.

    • Perform access checks at the process and component level—This setting indicates that process-level security descriptor checks and full role-based security checks will be performed. This has the following effects and implications:

      To enable role checking for particular components, you must enable access checks at the component level.

      The security property is included on the context for any objects running within the application. This can potentially affect how objects are activated. See Security Context Property.

      The security call context is available. Programmatic role-based security is enabled. See Security Call Context Information.

      Note For COM+ library applications, you must choose to check both at process and at component levels for any meaningful access checking to work. Library applications rely on the host process for process-level security. You can determine how the library application interacts with authentication performed by the host process by setting authentication. For more information, see Library Application Security.

  4. Click OK.

The next time the application is started, security will automatically be checked at the specified level. Only users assigned to roles assigned to the application will be given access to the application.

See Also

Configuring Role-Based Security

Enabling Access Checks for an Application

Enabling Access Checks at the Component Level

Defining Roles for an Application

Assigning Roles to Components, Interfaces, or Methods


Enabling Access Checks at the Component Level

If your application includes a component that does not need security checks, you might decide to disable role checks for that component to improve performance. Or when debugging, it might be helpful to disable security so that you can concentrate on other aspects of program functionality.

By default, when you install a component, component-level access checks are enabled. However, this takes effect only when application-level access checks are enabled and when the security level is set to Perform access checks at the process and component level.

To enable or disable access checks at the component level

  1. In the console tree of the Component Services administrative tool, locate the COM+ application that contains the component for which you want to disable (or enable) role checks. Expand the view in the tree to view the components in the Components folder.
  2. Right-click the component for which you want to enable role checks, and then click Properties.
  3. In the component properties dialog box, click the Security tab.
  4. Select Enforce component level access checks to enforce component-level checks.
  5. Click OK.

The new setting will take effect the next time the application is started.

See Also

Configuring Role-Based Security

Enabling Access Checks for an Application

Setting a Security Level for Access Checks

Defining Roles for an Application

Assigning Roles to Components, Interfaces, or Methods


Defining Roles for an Application

You determine a security policy for an application by defining the security privileges that it requires. To do this you declare a symbolic level of privilege as a role—that is, define the role for the application—and then assign the role to specific resources within the application. This design is fulfilled when the application is deployed and system administrators populate the role with actual users and user groups. For greater detail, see Role-Based Security.

To add a role to an application

  1. In the console tree of the Component Services administrative tool, locate the COM+ application to which you want to add the role. Expand the tree to view the folders for the application.
  2. Right-click the Roles folder for the application, point to New, and then click Role.
  3. In the Role dialog box, type the name of the new role in the box provided.
  4. Click OK.

Note After adding roles to the application, you must be sure to assign the roles to the appropriate components, interfaces, and methods. Otherwise, if role-based security has been chosen and enabled and if roles have been added but not assigned, all calls to the application will fail. For more information, see Assigning Roles to Components, Interfaces, or Methods.

See Also

Configuring Role-Based Security

Enabling Access Checks for an Application

Setting a Security Level for Access Checks

Enabling Access Checks at the Component Level

Assigning Roles to Components, Interfaces, or Methods


Assigning Roles to Components, Interfaces, or Methods

You can explicitly assign a role to any item within a COM+ application that is visible through the Component Services administrative tool. Doing so ensures that any users that are members of the role will be permitted access to that item and any other items that it contains. For example, if you assign the role "Readers" to a component, any member of "Readers" is allowed access to that component and any interfaces and methods it exposes. "Readers" will show up as an Inherited role for any of those interfaces and methods.

A method is accessible to callers only if you assign a role to it, either by explicitly assigning the role directly to the method or by assigning a role to the method's interface or the method's component, in which case the role will be inherited by the method. If no role is assigned and if access checks are enabled, all calls to the method will fail.

Before you can assign a role, you must define it for the application. All roles defined for the application will appear in the Roles explicitly set for selected item(s) window on the Security tab for any components, methods, and interfaces within the application.

To assign roles to a component, method, or interface

  1. In the console tree of the Component Services administrative tool, locate the COM+ application for which the role has been defined. Expand the tree to view the application's components, interfaces, or methods, depending on what you are assigning the role to.
  2. Right-click the item to which you want to assign the role, and then click Properties.
  3. In the properties dialog box, click the Security tab.
  4. In the Roles explicitly set for selected item(s) box, select the roles that you want to assign to the item.
  5. Click OK.

Any roles that you have explicitly set for an item will be inherited by any lower-level items it contains and will show up in the Roles inherited by selected item(s) window for those items.

See Also

Configuring Role-Based Security

Enabling Access Checks for an Application

Setting a Security Level for Access Checks

Enabling Access Checks at the Component Level

Defining Roles for an Application


Setting Authentication

Setting authentication means different things depending on the type of application.

For COM+ server applications, you set an authentication level that determines how authentication will be performed when clients call into components within the application. For more information, see Setting an Authentication Level for a Server Application.

For COM+ library applications, you enable or disable authentication to determine whether or not the application will be subject to the authentication performed by the hosting process. For more information, see Enabling Authentication for a Library Application.

See Also

Configuring Role-Based Security

Setting an Impersonation Level


Setting an Authentication Level for a Server Application

  • When you set an authentication level for an application, you determine what degree of authentication is performed when clients call into the application. Higher authentication levels provide greater security and data integrity, although usually with some performance degradation. For more detail, see Client Authentication.

To select an authentication level for a server application

  1. Right-click the COM+ application for which you are setting authentication, and then click Properties.
  2. In the application properties dialog box, click the Security tab.
  3. In the Authentication level for calls box, select the appropriate level. The levels are as follows, ordered from lowest to highest security:
    • None No authentication occurs.
    • Connect Authenticates credentials only when the connection is made.
    • Call Authenticates credentials at the beginning of every call.
    • Packet Authenticates credentials and verifies that all call data is received. This is the default setting for COM+ server applications.
    • Packet Integrity Authenticates credentials and verifies that no call data has been modified in transit.
    • Packet Privacy Authenticates credentials and encrypts the packet, including the data and the sender's identity and signature.
  4. Click OK.

See Also

Enabling Authentication for a Library Application


Enabling Authentication for a Library Application

Because COM+ library applications are hosted by other processes, their security requirements may be different from those of server applications. If the library application will be hosted by a browser, it might need to receive unauthenticated callbacks.

To address this need, you can disable authentication so that the hosting process does not perform security checks for callers of the library application. When you disable authentication, calls to the library application effectively go unauthenticated—all calls to it will succeed. For more detail, see Library Application Security.

To enable (or disable) authentication for a library application

  1. Right-click the COM+ application for which you are enabling or disabling authentication, and then click Properties.
  2. In the application properties dialog box, click the Security tab.
  3. Under Authentication, select the Enable authentication check box to enable authentication; clearing the check box will disable authentication.
  4. Click OK.

See Also

Setting an Authentication Level for a Server Application


Setting an Impersonation Level

  • When you set an impersonation level for an application, you determine what degree of authority the application grants other applications to use its identity when it calls them. You can set this only for COM+ server applications—library applications run under the identity of the hosting process and use the impersonation level that it specifies. For more detail, see Impersonation Levels.

To select an impersonation level

  1. Right-click the COM+ application for which you are setting authentication, and then click Properties.
  2. In the application properties dialog box, click the Security tab.
  3. In the Impersonation level box, select the appropriate level. The levels are as follows, ordered from granting least to greatest authority:
    • Anonymous The client is anonymous to the server. The server can impersonate the client, but the impersonation token (a local credential) does not contain any information about the client.
    • Identify The server can obtain the client's identity and can impersonate the client to determine access-checking levels.
    • Impersonate The server can impersonate the client while acting on its behalf, although with restrictions. The server can access resources on the same computer as the client. If the server is on the same computer as the client, it can access network resources as the client. If the server is on a computer different from the client, it can access only resources that are on the same computer as the server. This is the default setting for COM+ server applications.
    • Delegate The server can impersonate the client while acting on its behalf, whether or not on the same computer as the client. During impersonation, the client's credentials (both those with local and those with network validity) can be passed to any number of machines.
  4. Click OK.

See Also

Configuring Role-Based Security

Setting Authentication


Configuring Object Pooling

You can configure a component to be pooled using either the Component Services administrative tool or by using the COM+ Administrative SDK functions. Before you configure it, you should be certain that the component is correctly written to support pooling. For details, see Object Pooling.

By default, a component will not be pooled. After you configure a component as pooled, you can specify several properties, including the following, that will determine how COM+ maintains the pool:

  • Minimum pool size
  • Maximum pool size
  • Creation request time-out value

For a description of how to set these values, see Configuring a Component to Be Pooled.

Monitoring Objects

You can monitor object statistics as the application runs. By doing so, you can fine-tune the object pool characteristics to achieve the performance you want. For a given component, you can monitor the following statistics:

  • Objects held by client references
  • Objects currently activated
  • Total number of objects created, both activated and deactivated
  • Objects in call
  • Average object call time

For a description of how to monitor objects using the Component Services administrative tool, see Monitoring Object Statistics.

Specifying Constructor Strings

To customize a component for a given task, you can administratively specify constructor strings for that component. You can do this whenever the component has specifically been written to recognize the string that you enter. For a description of how to enable an object constructor string, see Specifying an Object Constructor String.

See Also

Configuring Library Applications

Configuring Transactions

Configuring Synchronization

Configuring Security

Configuring JIT Activation

Configuring a COM+ Server Application as an NT Service

Configuring Queued Components

Configuring COM+ Events


Configuring a Component to Be Pooled

You can configure a component to be pooled only when it is correctly written to support being pooled. For details of these requirements, see Requirements for Poolable Objects.

When you configure a component to be pooled, you can specify the following properties to determine how COM+ maintains the pool:

  • Minimum pool size Represents the number of objects that are created when the application starts and the minimum number of objects that are maintained in the pool while the application is running. If the number of available objects in the pool drops below the specified minimum, new objects are created to meet any outstanding object requests and refill the pool. If the number of available objects in the pool is greater than the minimum number, those surplus objects are destroyed during a clean-up cycle.
  • Maximum pool size Represents the maximum number of pooled objects that the pooling manager will create, both actively used by clients and inactive in the pool. When creating objects, the pooling manager checks to verify that the maximum pool size has not been reached and, if it hasn't, the pool manager creates a new instance of the object to dispense to the client. If the maximum pool size has been reached, client requests will be queued and will receive the first available object from the pool on a first-come first-served basis. Object creation requests will time-out after a specified period.
  • Creation timeout (ms) Specifies how long a client will wait, in milliseconds, for an object to be returned from the pool after a call to CoCreateInstance. If the client call is unsuccessful, the error E_TIMEOUT is returned.

To set pooling-related properties

  1. In the details pane of the Component Services administrative tool, right-click the component that you want to configure, and then click Properties.
  2. In the component properties dialog box, click the Activation tab.
  3. To enable object pooling for the component, select the Enable object pooling check box.
  4. In the Minimum pool size box, enter the minimum number of objects of this type in the pool. The pool will be maintained to have at least this many objects.
  5. In the Maximum pool size box, enter the maximum number of objects of this type in the pool. The number of objects, both activated and deactivated, will never exceed this value.
  6. In the Creation timeout (ms) box, enter the amount of time, in milliseconds, a client will wait for a pooled object if one is not immediately available.

See Also

Monitoring Object Statistics

Specifying an Object Constructor String


Monitoring Object Statistics

You can monitor object statistics as an application runs. By doing so, you can fine-tune the object pool characteristics to achieve the balance in performance and resources that you would like to have.

You can monitor status for any objects that are configured to support object statistics and event reporting. Enabling object statistics has a very slight performance overhead.

To enable object statistics

  1. In the details pane of the Component Services administrative tool, right-click the component that you want to configure and then click Properties.
  2. In the component properties dialog box, click the Activation tab.
  3. To enable object statistics for the component, under Activation Context, select the Component supports events and statistics check box.

To monitor object status

  1. In the console tree of the Component Services administrative tool, open the folder for the application that includes the components you want to monitor.
  2. Right-click the Components folder, point to View, and then click Status View. The details pane now displays the status view for all components in the application. The following table describes the six columns in the status view.
    Column | Description
    ProgID | Identifies a specific component.
    Objects | Shows the number of objects that are currently held by client references.
    Activated | Shows the number of objects that are currently activated.
    Pooled | Shows the total number of objects created by the pool, including objects that are in use and objects that are deactivated.
    In Call | Identifies objects in call.
    Call Time (ms) | Shows the average call duration (in milliseconds) of method calls made in the last 20 seconds (up to 20 calls). Call time is measured at the object and does not include the time used to traverse the network.

See Also

Configuring a Component to Be Pooled

Specifying an Object Constructor String


Specifying an Object Constructor String

Object constructor strings are initialization strings that are administratively specified for a component. You can specify a constructor string when a component has been written specifically to recognize the string that you enter. Components can access these strings programmatically by using IObjectConstruct.

Constructor strings will be passed in at object creation time only when object construction is enabled. Empty strings can be valid entries. For more detail, see Using Object Constructor Strings.

To enter an object constructor string for a component

  1. In the details pane of the Component Services administrative tool, right-click the component that you want to configure and then click Properties.
  2. In the component properties dialog box, click the Activation tab.
  3. To enable use of the object constructor string, select the Enable object construction check box.
  4. In the Constructor string box, enter the construction string (for example, DSN=AccountingServer). You have the option of entering an empty string.

See Also

Configuring a Component to Be Pooled

Monitoring Object Statistics


Configuring JIT Activation

You can configure just-in-time (JIT) activation for a component by using either the Component Services administrative tool or the COM+ Administrative SDK functions. Before you change a component's configuration, you should be certain that it supports JIT activation and know how its behavior might be affected by a given configuration. For details, see Just-in-Time (JIT) Activation.

The following topics in this section describe configurable aspects of JIT activation:

  • Enabling JIT Activation for a Component
  • Enabling Auto-Done for a Method

See Also

Configuring Library Applications

Configuring Transactions

Configuring Synchronization

Configuring Security

Configuring Object Pooling

Configuring a COM+ Server Application as an NT Service

Configuring Queued Components

Configuring COM+ Events


Enabling JIT Activation for a Component

You should configure a component to be JIT activated only when it is correctly written to support the COM+ Just-in-Time (JIT) Activation service. If a component is deactivated between method calls, it will lose any associated state. Given the default behavior of JIT activation, this is unlikely to occur when you don't expect it to, but you should be aware of a component's requirements prior to changing its configuration and of the expectations of clients that will be calling the component.

For stateful components or for components with certain client usage patterns, you might want to disable JIT activation. For many components, however, enabling JIT activation will simplify the client-server programming model as well as use server resources more efficiently. For greater detail about this feature, see Just-in-Time (JIT) Activation.

Note If a component is configured to require transactions, JIT activation will be enabled automatically. You cannot disable it in this case. For more detail, see Transaction Attribute Dependencies.

When you enable JIT activation for a component, its synchronization attribute will be set to Required for that component. You cannot change the synchronization setting in this case. For more detail, see Synchronization Dependencies.

To enable JIT activation

  1. In the details pane of the Component Services administrative tool, right-click the component that you want to configure and then click Properties.
  2. In the component properties dialog box, click the Activation tab.
  3. To enable JIT activation for the component, select the Enable Just In Time Activation check box.
  4. Click OK.

When you have enabled JIT activation for a component, you have the option of enabling the auto-done feature for any method exposed by that component. See Enabling Auto-Done for a Method for more information.

See Also

Enabling Auto-Done for a Method


Enabling Auto-Done for a Method

You can enable the auto-done feature for any method exposed by a component for which JIT activation is enabled. If JIT activation is disabled, auto-done is unavailable.

You should enable auto-done only for a method that has intentionally been written to take advantage of it because this feature can potentially change the expected behavior of the method.

When you enable auto-done, you are changing the default behavior of both JIT activation and automatic transactions for that method. You may want to use this feature because it can remove the necessity to explicitly declare consistency and doneness—this can instead be done by simply returning an HRESULT when auto-done is enabled. Essentially, when you enable auto-done, you are instructing COM+ to do the following:

  • Set the done bit to True by default on the context in which the object runs whenever this method is called.
  • Inspect the HRESULT returned by the method; if it indicates SUCCESS or FAILURE, set the consistency bit accordingly. This can result in an automatic call to IObjectContext::SetComplete or IObjectContext::SetAbort, depending also on what the method does internally.

For more detail about the behavior of auto-done, see Setting the Done Bit.

To enable auto-done for a method

  1. In the details pane of the Component Services administrative tool, right-click the method that you want to configure and then click Properties.
  2. In the method properties dialog box, click the General tab.
  3. To enable auto-done, select the Automatically deactivate this object when this method returns check box. If the check box is unavailable, you must first enable JIT activation for the component.
  4. Click OK.

See Also

Enabling JIT Activation for a Component


Enforcing Activation in the Caller's Context

You can control whether or not an object gets activated in its own context. When you use the Component Services administrative tool to require component activation in the caller's context, the following will occur when COM+ activates an instance of the component in a context:

  • The object will be activated in the creator's context if possible.
  • Object activation will fail if it requires its own context; CO_E_ATTEMPT_TO_CREATE_OUTSIDE_CLIENT_CONTEXT will be returned.

Whether or not the object requires its own context depends on its configuration relative to the current state of the caller's context properties. For more detail, see Contexts.

You would want to control activation at that fine a level if some aspect of your object would not function properly if it has its own context. For example, if the component does not support marshaling and it has its own context, any calls to it will fail because cross-context calls are intercepted and a lightweight marshal performed.

To enforce activation in the caller's context

  1. In the details pane of the Component Services administrative tool, right-click the component (located within the Components folder of any selected COM+ application) for which you are setting activation properties and then click Properties.
  2. In the component properties dialog box, click the Activation tab.
  3. Select the Must be activated in the callers context check box.
  4. Click OK.

See Also

Enforcing Activation in the Default Context


Enforcing Activation in the Default Context

A configured COM component is usually activated in its own context; that is, COM+ references the component's catalog information to provide any configured services. However, you can choose to activate a configured component in the default context. A base COM component—a registered component that has no COM+ catalog information—is usually activated in the default context.

Activating a COM component in the default context provides three major performance benefits, as follows:

  • You save system resources by limiting the number of contexts that are created.
  • You increase performance by limiting the number of cross-context calls. Because calls across contexts require marshaling, it is much faster for a COM object activated in the default context to make calls to other objects in the default context. The performance in this case (of calls within the same context) is similar to that of calling a subroutine.
  • You can import older COM applications into COM+ and run them without a problem. For example, you may have several older COM applications implemented under the assumption that it was allowable to pass object references within an apartment without marshaling the references. These COM applications will not work when imported into COM+ because the object references will be passed across context boundaries. However, you can make this type of COM application run when imported if you use the Component Services administrative tool to mark all the classes in the application as Must be activated in the default context.

The major disadvantage to activating a configured component in the default context is that COM+ will not provide any of the component's configured services. There is a trade-off between enhanced performance and the ability to use COM+ services.

For example, assume a COM component does not require any COM+ services (such as transactions, just-in-time activation, events, queued components, synchronization, or object pooling) and this component will be making a number of calls to other COM components that may be activated in the default context. In this case, it would be a good idea to activate the calling component in the default context.

If the COM component requires COM+ services, it cannot be marked as Must be activated in the default context. In addition, there is no real performance gain if a COM object activated in the default context makes a number of calls to objects in other contexts. (For more detail, see Contexts.)

To enforce activation in the default context

  1. In the details pane of the Component Services administrative tool, right-click the component (located within the Components folder of any selected COM+ application) that you want to activate in the default context and then click Properties.
  2. In the component properties dialog box, click the Activation tab.
  3. Select the Must be activated in the default context check box.
  4. Click OK.

Note When you run a configured component in the default context, COM+ will not activate any of the configured services for that component. These services are available again when you uncheck the Must be activated in the default context check box and subsequently run the configured component in its own context.

See Also

Enforcing Activation in the Caller's Context


Configuring a COM+ Server Application as an NT Service

With the release of Microsoft® Windows® 2000, 64-bit Edition, Component Services provides developers with the ability to configure a COM+ server application as an NT service and to implement the service as a COM+ server application by using the Component Services administrative tool.

Running a COM+ server application as an NT service offers the following advantages:

  • If your application always needs to be running, Component Services can optionally have the server started automatically and can also restart the server if it times out. For example, if a computer running Queued Components listener components is rebooted, the Queued Components listeners can be started automatically if they are configured as an NT service.
  • If your application needs to perform privileged operations, the application can run as the local system account. Only NT services are allowed to run with this level of security. The application will be compatible with Windows Clustering, which will manage services during system failover.
  • If other services need to be marked as dependent, Component Services provides that option. For example, if your application makes use of functionality provided by another service, the service marked as dependent will be started before your application starts.

Starting an Application Automatically

When the COM+ server application is started automatically, it acts like an NT service, requiring the developer to manage the server via the Services administrative tool. The application can also be configured to shut down using the time-out feature of Component Services. For example, if the application is started automatically and is configured to time out in one minute in COM+, the application will start up at boot time and then promptly shut down in one minute. To avoid unanticipated conflicts, such configurations should be carefully administered.

Note NT services are managed and configured through the Services administrative tool. The NT services tool can be accessed by launching the Component Services administrative tool and then clicking Services (Local).

Starting an Application Manually

When the COM+ server application is started manually, it acts like a DLL host with the security settings of an NT service. The service will be started up manually when activated and shut down automatically when it times out.

Service Configurations

Regardless of the startup type, the application can be configured to run as a local system account or assigned to a user account. The local system and user account can be configured at the time of creating the service. To configure the security settings, the Services administrative tool will have to be used. Dependencies can also be set for the service.

The application can also be started in any particular order by selecting dependencies from a list of other system services. For example, the Windows NT® system services can be marked as dependent and will not start the application until the system services have been started in the specified order. This will properly initialize the service application before it is used.

For a step-by-step instruction on how to configure a COM+ application to run as an NT service, see Creating an NT Service in this section.

See Also

Configuring Library Applications

Configuring Transactions

Configuring Synchronization

Configuring Security

Configuring Object Pooling

Configuring JIT Activation

Configuring Queued Components

Configuring COM+ Events


Creating an NT Service

A COM+ server application can be created as an NT service to start either automatically during the system startup or manually by activations. If the service fails to start, the option for error handling specifies the severity of the error and determines the action to be taken. The option to configure a service to run as the local system account is also available, as well as the option to assign a specific user account for which the COM+ server application will run. Dependencies can also be selected from a list of services registered on the computer using Component Services. This will determine which services must be executed before this service is started.

To configure a COM+ application to run as an NT service

  1. On the Start menu, point to Programs, point to Administrative Tools, and then click Component Services.
  2. In the console tree of the Component Services administrative tool, click the COM+ server application.
  3. Right-click the COM+ server application, and then click Properties.
  4. In the Properties dialog box, click the Activation tab. In the Activation type box, check the Run application as NT Service check box.
  5. Click the Setup New Service button.
  6. In the Startup type box in the Service Name dialog box, select Automatic or Manual.
  7. (Optional) To specify the action to be taken for a particular error, select Ignore, Normal, Severe, or Critical in the Error Handling box. The behavior associated with each option is as follows:
    • Ignore The startup program logs the error but continues the startup operation.
    • Normal The error is logged, a message box is displayed, and the startup program continues the startup operation.
    • Severe The error is logged, and the system is restarted with the last known good configuration. If it is the last known good configuration that is being started when the error is logged, the startup operation continues.
    • Critical The error is logged, and the system is restarted with the last known good configuration. If it is the last known good configuration that is being started when the error is logged, the startup operation fails.
  8. (Optional) To run the service as a local system account, select the Local System radio button in the Account box. To indicate that the service should be allowed to interact with the desktop, check the Allow service to interact with desktop check box.
  9. (Optional) To assign the service to a user account:
    1. In the Account box, select This Account radio button.
    2. To select the user, enter the user name in the User box or click the Browse button.
    3. Enter the password for the user account in the Password box.
    4. Enter the same password in the Confirm Password box.
  10. (Optional) To set other services as dependent, select the dependent services from the list in the Dependencies box.
  11. Click Create.

See Also

Configuring a COM+ Server Application as an NT Service


Configuring Queued Components

To enable queuing for a component that has been developed to support it, use the Component Services administrative tool to specify a COM+ application as queued. Selecting an application to be queued creates an MSMQ queue and associates it with this application. Add components to this queued application, and start the Queued Components listener to make the application eligible to receive messages. The check boxes that enable the queued application and start the Queued Components listener are located on the Queuing tab of an application's application properties dialog box in the Component Services administrative tool.

After creating a queued application, you may add components with queuable and non-queuable interfaces to the application. However, only the queuable interfaces, which contain no out parameters and return values, will support queuing.

Note If you prefer, you can add the components to a COM+ application first and then declare the application to be queued. The sequence of when an application is specified as queued does not matter. A component can be specified as queuable, whether or not the application is queued. However, only queuable components in a queued application can be invoked asynchronously.

After creating the queued application and adding the necessary components, you must enable the Queued Components listener. While specifying an application as queued allows it to receive messages, the application does not actively listen to or receive messages from the input queue until the Queued Components listener is started.

Any queuable components that are contained in the queued application can be executed asynchronously. Asynchronous execution means that processing can occur even though resources may not currently be available to handle the request. Typically, one component calls another component and must wait for the results of that call before handling another task. In the case of a queuable component, the call returns immediately—whether or not the processing has occurred. The component is free to move on to other tasks. Later, after the request has been processed, the requesting component receives notification of the result.

For more information on developing queued components, see Writing Queued Components.

For details on how to configure the Queued Components service using the Component Services administrative tool, see the following topics in this section:

  • Specifying an Application as Queued
  • Starting the Queued Components Listener

See Also

Configuring Library Applications

Configuring Transactions

Configuring Synchronization

Configuring Security

Configuring Object Pooling

Configuring JIT Activation

Configuring a COM+ Server Application as an NT Service

Configuring COM+ Events


Specifying an Application as Queued

A queued application requires an associated MSMQ queue. When you specify an application as queued, the Component Services administrative tool creates this queue.

To specify an application as queued

  1. In the console tree of the Component Services administrative tool, right-click the COM+ application that you want to be queued and then click Properties.
  2. On the Queuing tab, select the Queued check box.

    Note If the Queued check box is unavailable, it means that there are no components with queuable interfaces, and therefore the application cannot be queued. Use a tool such as OLEVIEW to examine the component's interfaces and review them so that all methods contain only [in] parameters. All component interfaces that have only [in] parameters are assumed to be queuable interfaces.

  3. Click OK.

See Also

Configuring Queued Components

Starting the Queued Components Listener


Starting the Queued Components Listener

After establishing a queued application and its queued components, you can begin to invoke those components, causing request messages to be sent to the application’s queue. To begin processing these queued requests, you must use the Component Services administrative tool to start a Queued Components listener.

Note The application must not be running when you start the Queued Components listener. If the application is running, it will not recognize the changed status of the Queued Components listener and must be shut down and restarted before it will process the queued messages properly.

To start the Queued Components Listener

  1. In the console tree of the Component Services administrative tool, right-click the queued application and then click Properties.
  2. On the Queuing tab, select the Listen check box and click Start Application.
  3. Click OK.

See Also

Configuring Queued Components

Specifying an Application as Queued


Configuring COM+ Events

To configure a COM+ application to receive notification of an event, the COM+ application must have a registered event class and a registered subscription.

For more information on registering event classes and subscriptions, see the following topics in this section:

  • Registering an Event Class
  • Registering a Subscription

See Also

Configuring Transactions

Configuring Synchronization

Configuring Security

Configuring Object Pooling

Configuring JIT Activation

Configuring Queued Components


Registering an Event Class

So that subscribers can find an event class and subscribe to it, event classes must be registered in the COM+ catalog. COM+ requires a type library that describes the event interfaces and methods so that it can properly match and connect subscribers and publishers. The type library must reside in or be accompanied by a self-registering DLL.

You can use the Component Services administrative tool or the COM+ Administrative SDK functions to register an event class in the COM+ catalog.

To register an event class with the Component Services administrative tool

  1. Create a new COM+ application.
  2. Open the application folder and select Components.
  3. On the Action menu, click New. (You can also select the Components folder, right-click, point to New, and then click Component.)
  4. Click Install new event class(es).
  5. Enter the path to the event class component DLL.
  6. Click OK.

The event class is registered in the COM+ catalog and can be located by subscribers interested in obtaining the information provided by the event class. For information on how to register the event class by using the COM+ administrative interfaces, see ICOMAdminCatalog::InstallEventClass.

See Also

Registering a Subscription


Registering a Subscription

After you have registered an event class in the COM+ catalog, you can add subscribers to the event class and subscriptions to the subscribers. Subscriptions can subscribe to a single method or to all the methods of an interface. To receive calls on more than one method—but not to every method—of an interface, you must add a subscription for each method to which you want to receive a call. The Component Services administration tool will search the COM+ catalog for registered event classes that support the interfaces implemented by the subscriber and will offer you the choice to subscribe. Choose the publisher that offers you the desired events.

To add subscribers to the subscriber component

  1. After creating a new COM+ application and installing the subscriber component, right-click the Subscriptions folder to enable the COM+ New Subscription Wizard.
  2. Choose the event class from which you want to receive events.
  3. Enter a name for the subscription.
  4. Enable the subscription.
  5. Click OK.

When a publisher application wants to fire an event, the publisher instantiates the event class object and calls a method on it. COM+ searches the COM+ catalog to find all the subscribers. It creates the subscriber object (directly, queued, or with a moniker) and passes on the method call originally made by the publisher.

See Also

Registering an Event Class


Conversion of MTS Packages to COM+ Applications

COM+ can be viewed as a merging of Microsoft Transaction Server (MTS) and COM, along with the introduction of a host of new features. If you are currently using MTS, Microsoft® Windows® 2000 makes the conversion to COM+ completely automatic.

For the most part, your MTS packages are converted to COM+ applications during the Windows 2000 setup procedure. Without doing anything beyond the typical setup, you can take advantage of all the new COM+ features. For a list and brief explanation of the most significant COM+ improvements, see COM+ Programming Overview.

If you would like to learn more about the automatic conversion of MTS packages to COM+ applications during the Windows 2000 setup process, as well as how to troubleshoot any errors that might occur during this process, see Automatic Conversion from MTS in this section.

If you would like to learn how to manually convert MTS packages to COM+ applications, see Manual Conversion from MTS in this section.

You should also be aware that installing COM+ introduces several new capabilities that your MTS packages may be able to use as COM+ applications. These are explained in COM+ Conversion Results and Issues in this section.


Automatic Conversion from MTS

When a computer running the Microsoft® Windows® Option Pack with Microsoft Windows NT® 4.0, Microsoft Windows 95, or Microsoft Windows 98 is upgraded to Microsoft Windows 2000, the setup process will automatically convert all existing MTS packages to COM+ applications (except for the MTS SDK sample applications). If this conversion fails or encounters a problem that is not fatal, an error message is displayed and an event log entry is generated indicating the reason for the failure.

How Automatic Conversion Works

Automatic conversion occurs in two steps, as follows:

  1. During Windows 2000 setup. The conversion is handled by the Windows 2000 setup process through the MTSTOCOM utility.

    Note If step 1 fails, some or all of the MTS packages may actually have been converted but may be missing certain properties. In this case, use the Component Services administrative tool to verify all attributes. The MTS attributes will still be present on the computer (in the system registry at HKEY_LOCAL_MACHINE\Microsoft\Transaction Server) but will be accessible only via the regedit.exe utility.

  2. After the last reboot before the Windows logon dialog box is displayed. Step 2 handles those conversion actions that require network access (primarily role member creation).

    Note If step 2 fails (due to temporary network or domain controller failures), it is possible to rerun the MTSTOCOM conversion utility any number of times. To do this, type the following at the command prompt, or after selecting Run from the Start menu:

    %windir%\system32\mtstocom.exe

MTSTOCOM Log File

The MTSTOCOM utility generates a log file (Mtstocom.log) in the Windows directory. This log file keeps a record of the conversion from MTS packages to COM+ applications. If there were any errors during the conversion process, it is always a good idea to check the log file for further information. The log file catches common problems, such as invalid user or password.

See Also

Manual Conversion from MTS

COM+ Conversion Results and Issues


Manual Conversion from MTS

You might want to isolate conversion of MTS packages to COM+ applications so that it is outside the Microsoft® Windows® 2000 setup process. The following procedure offers an alternate approach:

  1. Export the MTS packages on the Microsoft Windows NT® 4.0, Microsoft Windows 95, or Microsoft Windows 98 computer using the MTS 2.0 Package Export feature (resulting in an MTS package file and a collection of other files).
  2. Delete the MTS packages and upgrade to Windows 2000, or perform a clean installation of Windows 2000.
  3. Install the MTS package (.pak) files on a Windows 2000 computer by using the Component Services administrative tool's Application Install wizard. You will also need to reset the application "Run As" identity.

Note Only the automatic conversion procedure (through Windows 2000 setup or running the MTSTOCOM utility) generates the MTSTOCOM log file. This file is not generated when following the manual conversion procedure.

See Also

Automatic Conversion from MTS

Manual Conversion from MTS

COM+ Conversion Results and Issues


COM+ Conversion Results and Issues

Whether you choose to convert your MTS packages to COM+ applications manually or let the Microsoft® Windows® 2000 setup process do it for you automatically, you should be aware of the results of conversion as well as the issues.

What Is Converted

During conversion, the MTSTOCOM utility converts roles, role assignments, interfaces, methods, users, the computer list, and most computer settings. The MTSTOCOM utility also converts the identity and password for an MTS package.

The new COM+ attributes that were not available in MTS are automatically set to the following defaults for all converted MTS components. These defaults can be changed using either the Component Services administrative tool or the COM+ administrative interfaces.

  • JIT Activation enabled.
  • Object Pooling disabled.
  • Concurrency same as Transaction setting.
  • Tracker enabled.

Conversion Issues

COM+ is automatically installed when you install Windows 2000. It is not possible to uninstall COM+. Issues related to upgrades of existing MTS and COM+ installations include the following:

  • If you are currently using MTS 1.0, MTS is automatically upgraded to COM+. However, user-defined packages will be lost and you must re-create them.
  • If you are currently using MTS 2.0 (shipped as part of the Microsoft Windows NT® Option Pack), MTS is automatically upgraded to COM+. All user-defined packages will be upgraded to COM+ applications. All components should work as they did under MTS 2.0.
  • If you installed the Windows 2000 Beta 2 COM+ preview release, you must reinstall any user-defined applications that have been created using that release. All other aspects of the upgrade should work as expected.
  • If you are using MTS 1.0 and MTS 2.0 and have installed the SDK option, the SDK files will be removed. You can install the latest COM+ SDK, which is available through the Windows 2000 Platform SDK.
  • You cannot manage a remote MTS machine from a COM+ computer.

See Also

Automatic Conversion from MTS

Manual Conversion from MTS


Automating COM+ Administration

COM+ provides an administration object model that exposes all of the functionality of the Component Services administrative tool, itself a graphical front end written on top of them. You can use these objects, supplied by the Component Services Administration (COMAdmin) Library, to automate all tasks in the administration of COM+ applications and services.

The COMAdmin objects enable you to read and write information that is stored on the COM+ catalog, the underlying data store that holds all COM+ configuration data.

You can use these objects to do the following:

  • Create and configure COM+ applications.
  • Install and export existing COM+ applications.
  • Manage installed COM+ applications.
  • Manage and configure services.
  • Remotely administer Component Services on a different machine.

You can use the scriptable COMAdmin objects with any Automation-compatible language. Develop either lightweight scripts or general-purpose administration tools. For example, you can do the following:

  • Write scripts to perform routine administrative tasks.
  • Write scripts to automate processes in the development of COM+ applications.
  • Develop general-purpose tools for administering and monitoring Component Services.
  • Develop setup executables to install and deploy your COM+ application.

The COMAdmin Library provides backward compatibility with the MTS 2.0 Administration Library. Most existing MTS 2.0 administration code will still work, although with some exceptions. (See MTS Administration Library.)

To automate administration effectively, you should be familiar with administration tasks as performed with the Component Services administrative tool.

The following topics in this section provide an overview for automating administration using the COMAdmin objects:

  • Overview of the COMAdmin Objects
  • Retrieving Collections on the COM+ Catalog
  • Setting Properties and Saving Changes to the COM+ Catalog
  • Handling Administration Errors
  • Administration Operations Within Transactions
  • MTS Administration Library

For full descriptions of the COMAdmin objects and the corresponding interfaces, see the COM+ Reference documentation for the following objects: COMAdminCatalog, COMAdminCatalogCollection, COMAdminCatalogObject, ICOMAdminCatalog, ICatalogCollection, and ICatalogObject.


Overview of the COMAdmin Objects

The COMAdmin objects offer a simple object model that provides you with access to the COM+ catalog. In doing so, they serve to model all the functionality provided by the Component Services administrative tool. Whenever you do any kind of COM+ administration, you are interacting with the COM+ catalog. For a description of the catalog, see Accessing the COM+ Catalog in this section.

The information you obtain from either the Component Services administrative tool or by using the COMAdmin objects is structured similarly, and the actions you perform in either context are analogous. The basic correlation between using the Component Services snap-in and programmatic administration is that folders in the console tree of the snap-in correspond to collections in the COM+ catalog. That is, just as each folder in the snap-in contains items all of a kind—for example, COM+ Applications holds installed COM+ applications—each collection in the COM+ catalog holds items of a uniform kind. Further, just as each item in a folder has properties that you can set on a property sheet, each item in a collection exposes properties that you can set.

To enable you to configure objects within this structure, the COMAdmin objects provide you with the means to do the following:

  • Access the COM+ catalog
  • Access collections in the catalog
  • Access items in collections
  • Access properties on the items in the collections

To support these actions, the COMAdmin Library provides the following three objects:

  • COMAdminCatalog, which you use to represent the catalog itself
  • COMAdminCatalogCollection, which you use to represent any collection
  • COMAdminCatalogObject, which you use to represent any item in a collection

For fuller descriptions of these objects, see Summary Description of the COMAdmin Objects in this section.

To get a quick idea of typical actions you perform in programmatic administration, see Introductory Example in this section.

See Also

Retrieving Collections on the COM+ Catalog

Setting Properties and Saving Changes to the COM+ Catalog

Handling Administration Errors

Administration Operations Within Transactions

MTS Administration Library


Accessing the COM+ Catalog

The COM+ catalog is the underlying data store that holds all COM+ configuration data. Whenever you do any kind of COM+ administration, you are reading and writing data stored in the catalog. The only way that you can access the catalog is through the Component Services administrative tool or through the COMAdmin library.

The COM+ catalog provides a layer of abstraction over the actual details of where and how COM+ configuration data is stored. Much of the data is stored in the COM+ class registration database (or RegDB), which holds data for all configured components installed in COM+ applications. This database is used at application run time to provide configuration data to COM+ to properly activate objects in an appropriate context, enabling services to be provided for objects per their configuration. The RegDB itself is a transacted resource manager that uses Microsoft DTC transactions via the Compensating Resource Manager—when you make persisted configuration changes, they are committed transactionally. The only way that you can access RegDB is through the COM+ catalog, using the COMAdmin objects or the Component Services administrative tool.

On each machine running Microsoft® Windows® 2000, there is a COM+ catalog server running as a component in the system application. The catalog server controls access to the catalog data stored on its machine; in effect, the catalog server is a query engine that allows you to read and write data in the catalog on that machine. When you initiate programmatic administration by instantiating COMAdminCatalog, this object opens a session with the local catalog server. Requests for collections or collection items on the local catalog are handled by the local catalog server. When you connect to a remote machine, you are communicating with the catalog server on that machine.

Security Considerations in Administration

To change data on the COM+ catalog, you need to have authority as an administrator. To use the Component Services administrative tool to change any configuration data, you need to be a member of the Administrators role assigned to the system application on the machine you are trying to administer. Likewise, to change any data by using the COMAdmin objects, your code needs to be running with Administrator authority. That is, an application or script using the COMAdmin objects must be running under a user account that is assigned to the Administrators role on the system application on the machine that it is trying to administer. The application can access and change information on the catalog only to the extent that the account under which it is running has that authority.

See Also

Overview of the COMAdmin Objects

Summary Description of the COMAdmin Objects

Introductory Example


Summary Description of the COMAdmin Objects

There are three generic objects supplied by the COMAdmin library (Comadmin.dll). You use these objects, respectively, to gain access to the catalog, to represent collections in the catalog, and to represent the items contained within collections. Each object implements a COM dual interface. The objects and their corresponding interfaces have identical functionality; you can use either the objects or the corresponding interfaces, depending on the development tools you are using.

COMAdminCatalog

This is a generic object that you use to represent the catalog itself. COMAdminCatalog is the fundamental object you use in programmatic administration. Besides establishing the basic connection with the catalog server when you instantiate it, COMAdminCatalog provides methods that perform a broad range of actions. This object enables you to do the following:

  • Get collections on the catalog.
  • Connect to the catalog server on a remote machine.
  • Install, export, start, shut down, and obtain information regarding COM+ applications.
  • Install components into COM+ applications and obtain information regarding components.
  • Start, stop, or refresh services running on the machine.
  • Refresh, restore, or back up catalog information.

COMAdminCatalog implements the ICOMAdminCatalog interface.

COMAdminCatalogCollection

This is a generic object that you use to represent any collection in the catalog, supplying a string naming the particular collection at object instantiation time. Use this object when retrieving a collection with the ICOMAdminCatalog::GetCollection method (exposed by both COMAdminCatalog and COMAdminCatalogCollection). This object enables you to do the following:

  • Enumerate through the items contained within the collection.
  • Retrieve an item from the collection.
  • Add or remove items to or from the collection.
  • Save or discard any pending changes made to the collection or to the items it contains.
  • Get a different collection in the catalog.

COMAdminCatalogCollection implements the ICatalogCollection interface.

COMAdminCatalogObject

This is a generic object that you use to represent any item that is contained within a collection. Use this object when retrieving an item with the Item property on COMAdminCatalogCollection. This object enables you to do the following:

  • Get or set properties supported by the item that the object is being used to represent.
  • Obtain information about the item and its properties.

COMAdminCatalogObject implements the ICatalogObject interface.

See Also

Overview of the COMAdmin Objects

Accessing the COM+ Catalog

Introductory Example


Introductory Example

When using the COMAdmin objects, you typically carry out the following general steps (not given in a strict order here):

  • Open a session with the COM+ catalog on the local machine.
  • Optionally, connect to the COM+ catalog on a remote machine.
  • Perform actions such as starting or stopping services—actions that don't pertain to a particular COM+ application.
  • Perform actions such as install or export COM+ applications, or install components into applications—actions that pertain to reading from or writing to files.
  • Create a new COM+ application by adding a new item to the "Applications" collection.
  • Configure COM+ applications or elements, such as components, within them. To do this, you set properties on objects stored on the catalog, which means that first you must locate the object (by navigating through the collection tree) in the correct collection and retrieve it.
  • When you find the right collection, you can iterate through its items and retrieve the appropriate one or you can add a new item to the collection.
  • Set or get properties on the item.
  • Save or discard pending changes to the catalog.
  • Handle any errors that might occur. (You do this throughout the process.)

To show what these steps look like when you use the COMAdmin objects, a Microsoft® Visual Basic® example is provided below. It briefly illustrates some of the typical steps described above, such as locating collections in the collection tree, enumerating through a collection to retrieve an item, and setting properties on that item. This example does not do any error handling.

The example below will perform the following actions:

  1. Create a new COM+ application, "Hello World."
  2. Install some components, Foo and Bar, into it, which are both housed within a single DLL, HelloWorld.dll.
  3. Configure role-based security for the application, first defining two roles: Administrators and Readers.
  4. The Administrators role is assigned access to the entire application.
  5. The Readers role is assigned access to only the Foo component.
  6. Security properties are turned on so that role checking will be enforced for the application.
  7. Finally, the Hello World application is exported to a file.
'  Open a session with the catalog.
'  Instantiate a COMAdminCatalog object.
Dim Catalog As COMAdminCatalog
Set Catalog = New COMAdminCatalog

'  Create a new COM+ application.
'  First get the "Applications" collection from the catalog,
'  representing it with the generic COMAdminCatalogCollection.
Dim Applications As COMAdminCatalogCollection
Set Applications = Catalog.GetCollection("Applications")

'  Add a new item to this collection, representing the item
'  with the generic object, COMAdminCatalogObject.
Dim HelloWorldObject As COMAdminCatalogObject
Set HelloWorldObject = Applications.Add

'  Set the "Name" of the new item, using the Value property
'  on COMAdminCatalogObject. Value is a generic property taking a
'  name/value (string/variant) pair to set a named property.
HelloWorldObject.Value("Name") = "Hello World"

'  Save changes made to the "Applications" collection.
Applications.SaveChanges

'  Install components into the application.
'  Use the InstallComponent method on COMAdminCatalog.
'  In this case, the last two parameters are passed as empty strings.
Catalog.InstallComponent("Hello World","HelloWorld.DLL","","")

'  Define the roles Administrators and Readers
'  by adding them to the "Roles" collection related to Hello World.
'  First get the "Roles" collection related to Hello World.
'  Use the GetCollection method on COMAdminCatalogCollection,
'  passing in the name of the desired collection, "Roles",
'  and the Key property value of HelloWorldObject.
'  The Key property uniquely identifies the object, serving
'  here to distinguish the "Roles" collection related
'  to Hello World from that of any other application.
Dim Roles As COMAdminCatalogCollection
Set Roles = Applications.GetCollection("Roles",HelloWorldObject.Key)

'  Add new items to this "Roles" collection.
Dim AdministratorsObject As COMAdminCatalogObject
Dim ReadersObject As COMAdminCatalogObject
Set AdministratorsObject = Roles.Add
Set ReadersObject = Roles.Add

'  Set the "Name" for the new items.
AdministratorsObject.Value("Name") = "Administrators"
ReadersObject.Value("Name") = "Readers"

'  Save changes made to any items in this "Roles" collection.
Roles.SaveChanges

'  Assign the Readers role to the Foo component to
'  restrict its scope of access. (The Administrators role, if assigned
'  only at the application level, can access the whole application.)
'  First get the "Components" collection related to Hello World.
'  Use the GetCollection method on COMAdminCatalogCollection,
'  passing in the name of the desired collection, "Components", and
'  the Key property value of HelloWorldObject.
Dim Components As COMAdminCatalogCollection
Set Components = Applications.GetCollection("Components",HelloWorldObject.Key )

'  Locate the item for Foo component in this "Components" collection.
'  First Populate the collection to read in data for all its items.
Components.Populate

'  Enumerate through the "Components" collection
'  until the Foo component item is located.
Dim FooObject As COMAdminCatalogObject
For Each FooObject in Components
If FooObject.Name = "Foo" Then Exit For
Next

'  Get the "RolesForComponent" collection related to the
'  Foo component, using the Key property of FooObject.
Dim RolesForFoo As COMAdminCatalogCollection
Set RolesForFoo = Components.GetCollection("RolesForComponent",FooObject.Key)

'  Add a new item to this "RolesForComponent" collection.
Dim FooReadersObject As COMAdminCatalogObject
Set FooReadersObject = RolesForFoo.Add

'  Set the "Name" of the new item to be "Readers".
FooReadersObject.Value("Name") = "Readers"

'  Save changes made to this "RolesForComponent" collection.
RolesForFoo.SaveChanges

'  Now set properties to enforce role-based security.
'  First set role-based security at the application level.
HelloWorldObject.Value("ApplicationAccessChecksEnabled") = True
HelloWorldObject.Value("AccessLevel") = 1

'  Save these changes.
Applications.SaveChanges

'  Set the role checking property at the component level for Foo.
FooObject.Value("ComponentAccessChecksEnabled") = True

'  Save these changes.
Components.SaveChanges

'  Finally, export the new configured Hello World application to an
'  MSI file, used to install the application on other machines.
'  Use the ExportApplication method on COMAdminCatalogObject.
Catalog.ExportApplication("Hello World","c:\Program Files\Com applications\HelloWorld.MSI")

See Also

Overview of the COMAdmin Objects

Accessing the COM+ Catalog

Summary Description of the COMAdmin Objects


Retrieving Collections on the COM+ Catalog

Data on the catalog is stored within a hierarchy of collections. In the Component Services administrative tool, these collections appear as folders in the console tree. Collections serve as containers for items. The items in a given collection will all be of a consistent type—that is, they will all represent the same kind of element—and there can be an arbitrary number of items in a collection. For example, the Applications collection will contain an item for each COM+ application that is installed on the machine. This collection appears in the administrative tool as the COM+ Applications folder.

The collections occur in a hierarchical structure because the elements they contain follow an innate order of inclusion. For example, because components are installed into a COM+ application, the Components collection is logically subsumed under the Applications collection. More particularly, to hold the components installed into that particular application, there is a distinct Components collection for each item in the Applications collection.

You get a collection on the catalog whenever you want to retrieve an item and set properties on it. In the general case, you need to step through several collections to get to the element you want. For the procedure for doing this, see Navigating the Collection Hierarchy in this section.

After you have retrieved a collection and before you can work directly with the items it contains, you must populate the collection, which fetches data for the collection's contents from the COM+ catalog. For details, see Populating Collections in this section.

Additionally, there is a facility you can use that enables you to dynamically query to see what related collections are available from a given collection you are holding. For details, see Querying for Available Related Collections in this section.

See Also

Overview of the COMAdmin Objects

Setting Properties and Saving Changes to the COM+ Catalog

Handling Administration Errors

Administration Operations Within Transactions

MTS Administration Library


Navigating the Collection Hierarchy

Some collections you can retrieve easily by using the GetCollection method on the COMAdminCatalog object. This method will retrieve a "top-level" collection; that is, a collection such as Applications, which stands on its own and which is unique and not logically subsumed under another collection.

Most collections, however, are logically subsumed under another collection because they contain elements that are part of some larger structure. For example, the Components collection is subsumed, or related, to the Applications collection because it contains the components installed in a particular COM+ application, which itself corresponds to an item in the Applications collection. Related collections such as this are not unique; there is a Components collection for each distinct application.

Therefore, collections are arranged in a hierarchical structure that corresponds naturally to the logical relationships between the items they contain. For most of the elements you will want to configure using the COMAdmin objects, you will need to navigate through some portion of the collection hierarchy to retrieve the appropriate item.

What this means in practice is that if you wish to get an item in a related collection, you need to go through all the necessary higher level, subsuming collections first. And to retrieve a related collection, you need to retrieve the specific item in the parent collection to which the child collection is related. For example, if you wish to configure an item corresponding to a component in a particular COM+ application, you must perform the following steps:

  1. Get the Applications collection.
  2. Enumerate through the contents of the Applications collection until you get to the item corresponding to the correct COM+ application.
  3. Get the Components collection for that particular COM+ application.
  4. Enumerate through the contents of the Components collection until you get to the item corresponding to the correct component.

The following Microsoft® Visual Basic® example (omitting extraneous steps) shows how to perform the preceding steps:

Dim Catalog As COMAdminCatalog
Dim Applications As COMAdminCatalogCollection
Dim Components As COMAdminCatalogCollection
Dim AppObject As COMAdminCatalogObject

' Get the Applications collection and populate it
Set Applications = Catalog.GetCollection("Applications")
Applications.Populate

' Get the correct application, My Application
For Each AppObject in Applicationss
If AppObject.Name = "My Application" Then Exit For
Next

' Get the Components collection for My Application
Set Components = Applications.GetCollection("Components" , AppObject.Key)

Two distinct GetCollection methods are used in the preceding example. The first is exposed by COMAdminCatalog and is used to get a top level collection—in this case, "Applications." The second is exposed by COMAdminCatalogCollection and is used to get a collection related to the present collection; you indicate precisely which collection you want by passing in the name "Components" and the Key value of the parent object, a GUID that uniquely identifies it.

In the most general case, you may need to fully expand the tree, getting related collections iteratively down the collection hierarchy until you retrieve the one you want. The steps you would take follow the same general model, repetitively. For a complete list of collections, see Administration Collections.

In some cases, you might want to use a shortcut method the second time you follow a path through the collection hierarchy. You can use this method only after you have already cached all the intervening Key values. For details, see ICOMAdminCatalog::GetCollectionByQuery.

See Also

Retrieving Collections on the COM+ Catalog

Populating Collections

Querying for Available Related Collections


Populating Collections

After you have retrieved a collection and before you can work directly with the items it contains, you must populate the collection by using the ICatalogCollection::Populate method. This fetches data for the collection's contents from the COM+ catalog.

It is important to understand that whenever you use the COMAdmin objects to manipulate items or data in collections, you are really working on transiently cached data; you are not working directly with the persisted catalog. Nothing that you do with a collection or any of its items is reflected on the catalog until you call ICatalogCollection::SaveChanges on the collection. For more detail, see Saving or Discarding Changes.

Any subsequent calls to ICatalogCollection::Populate, prior to calling ICatalogCollection::SaveChanges, will have the effect of discarding pending changes to all items in the collection. Populate will always populate the cache you're working in with whatever data is persisted on the underlying catalog data store.

See Also

Retrieving Collections on the COM+ Catalog

Navigating the Collection Hierarchy

Querying for Available Related Collections


Querying for Available Related Collections

If you are writing a general-purpose administration tool, it is likely that you will need to write routines for navigating the entire collection hierarchy. To support this, COM+ has a facility that enables you to dynamically query for the related collections that are available from any given collection.

The RelatedCollectionInfo collection is available from any collection that you might be holding and contains an item for each available related collection. You can enumerate through these items to determine whether a given collection is available.

You can get the RelatedCollectionInfo collection from any collection you are holding by using the GetCollection method on the COMAdminCatalogCollection object, leaving the second parameter blank where you would normally specify a parent item's Key property.

See Also

Retrieving Collections on the COM+ Catalog

Navigating the Collection Hierarchy

Populating Collections


Setting Properties and Saving Changes to the COM+ Catalog

Each item in a collection exposes properties. These properties serve to hold configuration data for whatever element the item represents. In the Component Services administrative tool, these properties appear on a property page that you access by right-clicking on an item in a folder.

Since the items in a given collection will all represent the same kind of thing, those items will expose a set of properties that is consistent across the collection. For example, every item in the Applications collection will expose a Name property, an AppID property, and so forth. This is analogous to how each application in the Component Services administrative tool has a consistently structured property page available for it.

For a complete list of properties exposed by items in each collection, see Administration Collections.

You represent an item in a collection by using the COMAdminCatalogObject object. This object enables you to set and get any of the properties exposed by the item. When setting properties, it is also possible that you might be contending with another writer to the COM+ catalog. For more information, see Getting and Setting Properties in this section.

After you have set properties, no changes are actually committed until you explicitly save changes. For more information, see Saving or Discarding Changes in this section.

When you save changes, the COM+ catalog will enforce some configuration logic to ensure that you don't set things to incompatible configurations. It will also change some properties for you when you explicitly change certain other properties. For more information, see Interdependencies Between Properties in this section.

Additionally, COM+ has a facility that enables you to dynamically query to see what properties are available for the items in a given collection. For details, see Querying for Available Properties in this section.

See Also

Overview of the COMAdmin Objects

Retrieving Collections on the COM+ Catalog

Handling Administration Errors

Administration Operations Within Transactions

MTS Administration Library


Getting and Setting Properties

Before you can read or write particular properties exposed by an item in a collection, you must take the following steps:

  1. Retrieve the collection.
  2. Populate the collection to read in data for it from the COM+ catalog.
  3. Retrieve the specific item in the collection, representing it with the COMAdminCatalogObject object.

Because the particular properties exposed will vary from item to item depending on what the item represents—that is, an item representing a component will have different properties than one representing a COM+ application—you set any of these properties using a single generic property, the Value property, on COMAdminCatalogObject.

Value enables you to set or get any specific named property exposed by an item, taking a name-value pair when setting, and returning a value for a named property when getting.

No changes are actually recorded to the COM+ catalog, until you explicitly save changes, using the SaveChanges method on the COMAdminCatalogCollection object. That is, you save pending changes for all properties on all items in a given collection at once. For details, see Saving or Discarding Changes.

Not all changes that you make will be accepted. To a certain extent, the COM+ catalog enforces some coherency logic to ensure that you configure things in a reasonable way. Additionally, when you change some properties, others might change automatically by the same coherency logic. These effects will show up when you attempt to save changes.

Note It is possible for you to be in contention with another writer to the COM+ catalog. Between calls to Populate and SaveChanges for a given collection, you do not have a lock on any of that data in the catalog. Multiple parties may simultaneously be configuring items in a given collection and will be contending when they save changes. This means that someone else may change settings on an object before or after you do, either running some kind of program using the COMAdmin objects or using the Component Services administrative tool, either locally or remotely. The general rule with writing objects on the catalog is that all properties on an object are written at once. That is, the last writer wins—the object is saved in the catalog precisely as the last writer configured it.

See Also

Saving or Discarding Changes

Interdependencies Between Properties

Querying for Available Properties


Saving or Discarding Changes

When you set properties on an item, no changes are actually recorded to the COM+ catalog until you explicitly save changes. You do this using the SaveChanges method on the COMAdminCatalogCollection object for the collection containing the item. That is, you save pending changes for all properties on all items in a given collection at once.

If you wish to discard changes that have not yet been committed, you can call the Populate method on the COMAdminCatalogCollection object. This will read in all persistent data from the COM+ catalog for all items in the collection, effectively deleting any pending changes.

When you use SaveChanges, any inconsistencies in property settings that you have chosen will result in an error, and SaveChanges will fail to write the object that returned the error. All properties on a given item are written or will fail to be written as a whole.

However, when write errors occur, they may not be due to incompatible settings; some other failure may have occurred. You will need to inspect the details of the failure to be certain. For more information, see Handling Administration Errors and Interdependencies Between Properties.

As a general rule, the more changes you attempt to save at once, particularly changes to multiple objects, the more likely you are to get an error and the more difficult it will be to track down.

Additionally, between calls to Populate and SaveChanges, you do not have a lock on the items in the collection—contention is possible. For more details, see Getting and Setting Properties.

See Also

Getting and Setting Properties

Interdependencies Between Properties

Querying for Available Properties


Interdependencies Between Properties

When you set properties, the COM+ catalog enforces some coherency logic to ensure that you configure elements in a reasonable way. This logic can be implemented in two ways, as follows:

  • Dependencies—You might be blocked from making some changes because another property depends on a particular setting for a property you attempt to set. For example, if a component is set with the attribute Transactions Required and if you then attempt to change the Synchronization setting to None, an error is generated when you attempt to call SaveChanges. Transactions depend on Synchronization.
  • Side effects—Some properties might be changed for you without your explicitly setting them. For example, if you set a component with the attribute Transactions Required, Synchronization will be set to Required as well. This is really the flip side of dependencies—one property takes precedence over another, and its dependency is expressed through first setting the secondary property and then blocking changes to it.

In the list of properties exposed by items in a collection, all listed in the Administration Collections section, the dependencies and side effects are stated for each property. When you configure COM+ applications and components, you should be aware of what constraints are imposed on configurations.

See Also

Getting and Setting Properties

Saving or Discarding Changes

Querying for Available Properties


Querying for Available Properties

If you are writing a general-purpose administration tool, it is likely that you will need to write routines for setting properties in full generality. To support this, there is a facility that enables you to dynamically query for which properties are available for the items in any given collection.

The PropertyInfo collection is available from any collection that you might be holding. The PropertyInfo collection contains an item for each available property. You can enumerate through these items to determine whether a given property is available.

You can get the PropertyInfo collection from any collection you are holding by using the GetCollection method on the COMAdminCatalogCollection object, leaving the second parameter blank where you would normally specify a parent item's Key property.

See Also

Getting and Setting Properties

Saving or Discarding Changes

Interdependencies Between Properties


Handling Administration Errors

Errors generated when using the COMAdmin objects are reported in two ways, as follows:

  • Using error codes specific to the COMAdmin library.
  • Using extended error information available in special ErrorInfo collections.

Error Codes

You handle administration error codes as you would any COM error message. In Microsoft® Visual C++®, these codes are returned as HRESULTs. In Microsoft Visual Basic® and in Java, they are thrown as exceptions that you can catch. For C++ programmers, the COM+ administration error codes are defined in Winerror.h. For Visual Basic programmers, they are available through the Visual Basic IDE.

ErrorInfo Collection

When an error occurs, signaled by some kind of failure code, more detailed information may be available, depending on the nature of the error. The COMAdmin objects provide extended information in circumstances where the precise cause of the failure is difficult to determine without a detailed report, such as with multiple read and write operations.

For example, when you use methods such as Populate and SaveChanges on the COMAdminCatalogCollection object, you can be reading or writing data for every item in the collection. Complicated errors can occur, and they can be difficult to diagnose based on a single numeric error code. Therefore, the COMAdmin Library makes extended error information through a special collection.

When extended error information is available, it is placed in the ErrorInfo collection that is related to the original collection that had the error. To retrieve the error report, you get that related collection and examine the items it contains. You can retrieve the ErrorInfo collection by using GetCollection on COMAdminCatalogCollection, leaving the second parameter blank where you would normally specify a parent item's Key property.

When you get an error, you must immediately get and populate the ErrorInfo collection for the collection that failed, without performing any other operations on that collection. Otherwise, the ErrorInfo collection will be reset and will not detail that failure.

The items in the ErrorInfo collection expose the special error-reporting properties MajorRef and MinorRef, which detail the particular cause of the error. For more information, see ErrorInfo Collection.

See Also

Overview of the COMAdmin Objects

Retrieving Collections on the COM+ Catalog

Setting Properties and Saving Changes to the COM+ Catalog

Administration Operations Within Transactions

MTS Administration Library


Administration Operations Within Transactions

The COM+ registration database (RegDB) is a transacted resource manager that can participate in COM+ transactions. This enables you to perform administration operations within a transaction and have all configuration changes committed or aborted as an atomic operation, even across multiple machines. In some circumstances, it can be very beneficial to do this, although there is isolation and blocking behavior that you should take into account, and performing administration tasks within transactions does involve slight changes to the normal administration programming model.

Benefits of Doing Administration Operations Within Transactions

  • Consistency of data—Administration operations performed within a transaction are committed or aborted as a whole, although there are some non-transactional COM+ catalog resources for which this may not be the case.
  • Consistent deployment across multiple machines—If you are deploying COM+ applications across multiple servers, you can guarantee that all servers are left with identical configurations.
  • Scaling and performance—When you do multiple operations within a transaction, all writes to RegDB are performed at once. Persisted writes to RegDB are a relatively expensive operation; if you are making many writes to RegDB, you can get a big performance benefit from doing them all at once instead of every time you call SaveChanges.

Isolation Behavior of RegDB

To ensure proper data consistency and serializable transactions, RegDB enforces particular blocking and isolation behavior when administration operations are being performed within transactions.

Whenever a component that is doing work within a transaction calls any method that will cause a write to the COM+ catalog—such as SaveChanges, InstallApplication, or InstallComponent—a writer lock is taken on COM+ catalog server code that will block any other writers from coming in until the current transaction commits or aborts. That is, writers can come in only if they have the correct transaction affinity and are participating in the current transaction.

Readers are not blocked. However, the data that readers will see will not reflect any interim changes made within the transaction until that transaction actually commits. Any components participating in that transaction will see interim data states when they read data, but all components outside the transaction will see those changes only after the transaction has completed.

SaveChanges Behavior

To achieve the isolation behavior described above, RegDB effectively provides a cache that components within the transaction act on. This changes the behavior of the SaveChanges method.

Normally, without the presence of a transaction, any pending changes are written to the catalog when you call SaveChanges, and SaveChanges doesn't return until all writes are physically completed. This guarantees that if a call to SaveChanges returns successfully, you can call StartApplication and it will activate the application with fresh data.

However, within a transaction, SaveChanges will affect only the cache, not RegDB itself, and SaveChanges will return immediately whether or not all changes have been transactionally committed to RegDB. There is no guarantee that StartApplication will be using fresh data subsequent to SaveChanges returning. If you need to call StartApplication in this context, it's advisable to sleep for some period of time before doing so.

Transaction Time-Out Period

If you are doing numerous administration operations within a transaction, it may be a long running transaction. In this case, the transaction time-out value can be an issue. This is determined either by the transaction time-out value set for the component initiating the transaction or by the machine-wide time-out setting for the machine where that component is running. If you are doing numerous operations within a transaction, it's advisable to set the appropriate transaction time-out period to a sufficiently long value and, if necessary, to restore the original setting when you're done.

Non-Transactional COM+ Catalog Resources

The registry, the file system, and Windows Installer (MSI) are COM+ catalog resources that are not transactional. If there is an error that aborts a transaction, changes to these resources may not be rolled back. If there is an error while installing an existing COM+ application from an .msi file, the application won't appear in the Component Services snap-in but it might appear in Add/Remove programs, in which case you'll need to manually remove it.

Recovering in the Event of System Hangs

If a component doing administration operations within a transaction were to hang while it holds a writer lock on the catalog server code, it would block everyone else from making any changes to the catalog. Should this happen, you can clear the lock on the catalog by shutting down and restarting the System Application.

Scripting with the TransactionContext Object

Probably the simplest way to do administration operations within transactions is to script it using the TransactionContext object to control the transaction. For example, the following script demonstrates how to transactionally add two new applications so that either both applications or neither application will be created:

Dim txctx
Dim cat
Dim apps
Dim app1
Dim app2

WScript.Echo "Starting"
Set txctx = CreateObject("TxCtx.TransactionContext")
Set cat = txctx.CreateInstance("COMAdmin.COMAdminCatalog")
Set apps = cat.GetCollection("Applications")
Set app1 = apps.Add
app1.Value("Name") = "Test App #1"
apps.SaveChanges
Set app2 = apps.Add
app2.Value("Name") = "Test App #2"
apps.SaveChanges

WScript.Echo "Ending"
txctx.Commit

See Also

Overview of the COMAdmin Objects

Retrieving Collections on the COM+ Catalog

Setting Properties and Saving Changes to the COM+ Catalog

Handling Administration Errors

MTS Administration Library


MTS Administration Library

The MTS Administration Library shipped with the COM+ Administration interfaces provides backward compatibility with the MTS 2.0 Administration Library. Most existing MTS 2.0 administration code will still work with the MTSAdmin Library that is provided; however, some functionality has changed.

To take advantage of new functionality or if you are writing administration code for the first time, you should use the COMAdmin Library.

The following elements in the current MTS Administration Library are changed from the MTS 2.0 Administration Library:

  • The IRemoteComponentUtil interface is no longer available.
  • The RemoteComponents collection is no longer available.
  • The RoleID property is no longer available, the Role Name is now used as the key for this.
  • The ExportPackage method no longer exports a client.exe.
  • The RemoteComponentInstallPath property is no longer exposed on the LocalComputer collection.
  • The ApplicationInstallPath property will no longer be exposed on the LocalComputer collection.
  • The System package is now named System Application.
  • The Utilities package is now named COM+ Utilities.
  • The IsSystem property exists in the Components collection in MTSAdmin but will return "NotImpl" when checked and will not be saved if set.
  • The PackageName property is no longer supported by the Components collection. To figure out the package's name, you will now need to get the PackageID and then find the matching package in the Packages collection.
  • The following properties no longer exist on the InterfacesForComponent collection:
    • ProxyCLSID
    • ProxyDLL
    • ProxyThreadingModel
    • TypeLibFile
    • TypeLibID
    • TypeLibLangID
    • TypeLibPlatform
    • TypeLibVersion

See Also

Overview of the COMAdmin Objects

Retrieving Collections on the COM+ Catalog

Setting Properties and Saving Changes to the COM+ Catalog

Handling Administration Errors

Administration Operations Within Transactions


Creating and Configuring COM+ Application Partitions

Administrators can use COM+ to programmatically create and configure COM+ application partitions. In fact, all creation and configuration tasks that an administrator can do from the Component Services or the Active Directory Users and Computers administrative tools can be done by using COM+ collections, objects, and interfaces or through Active Directory System Interface (ADSI).

The tasks that an administrator would most likely want to execute programmatically are described in the following topics in this section:

  • Managing Local Partitions
  • Managing Partitions Within Active Directory
  • Setting Administrative Rights for a Partition
  • Setting Partition Scope
  • Grouping Applications into Partitions
  • Collecting Partition Metrics
  • Configuring the Partition Cache

To accomplish these tasks, COM+ provides the following programming elements:

  • A set of partitions-related collections: ApplicationPartitions, LocalPartitions, LocalPartitionSets, and LocalUsers.
  • A set of COM+ objects for creating and managing partitions in Active Directory.
  • The ICOMAdminCatalog2 interface on the COMAdminCatalog object. This interface includes the following methods:
    • GetAppPartitionId
    • GetAppPartitionName
    • GetBaseApplicationPartitionId
    • GetCurrentApplicationPartitionId
    • GetCurrentApplicationPartitionName
  • Partition properties, such as the partition ID. The partition ID can be included in the COM+ instrumentation header file for collecting partitions-related metrics.
  • Two additional properties on the SubscriptionsforComponent collection: EventClassApplicationID and EventClassPartitionID.
  • A COM+ registry key, PartitionCache, for changing the partition cache size.


Managing Local Partitions

As an alternative to creating and configuring local partitions through the Component Services administrative tool, you can manage partitions programmatically by using partition-specific collections. The COM+ application partitions feature includes four collections that hold partitions-related configuration data. These collections and their descriptions are as follows:

  • ApplicationPartitions—A collection used to specify the applications contained within each partition.
  • LocalPartitions—A collection used to specify the partition sets to which partitions are mapped. This collection is used only when partition sets are mapped to local users and not to remote users in the domain.
  • LocalPartitionSets—A collection used to specify partition sets and their properties. This collection is used only when partition sets are mapped to local users and not to remote users in the domain.
  • LocalUsers—A collection used to specify the partition sets to which user identities are mapped. This collection is used only when partition sets are mapped to local users and not to remote users in the domain.

As with any type of COM+ collection, you access these collections by calling the ICatalogCollection interface on the COMAdminCatalogCollection object and using the standard ICatalogCollection methods.

In addition, the SubscriptionsforComponent collection includes two partition-related properties: an event class application ID (EventClassApplicationID) and an event class partition ID (EventClassPartitionID). This allows a subscriber to subscribe to a publisher whose application resides within a partition, thus fully integrating the COM+ Events service into partitions.

Note For information about creating and managing local partitions through the use of the Component Services administrative tool, see the online help available from within that tool.

See Also

Managing Partitions Within Active Directory

Setting Administrative Rights for a Partition

Setting Partition Scope

Grouping Applications into Partitions

Collecting Partition Metrics

Configuring the Partition Cache


Managing Partitions Within Active Directory

As an alternative to managing Active Directory partitions through the Active Directory Users and Computers administrative tool, you can manage COM+ partitions programmatically through the use of a set of COM+ objects within Active Directory System Interface (ADSI).

Regardless of the administrative technique you choose for managing COM+ partitions, there is a general sequence of steps that administrators must follow:

  1. Create the new COM+ partitions within Active Directory for your domain.
  2. Create COM+ partition sets within Active Directory, and map them to your newly created COM+ partitions.
  3. Configure your Active Directory partitions on your local machine, using the appropriate COM+ object. When you configure an Active Directory partition on a local machine, a COM+ Applications folder is automatically created in that partition folder.
  4. Install your COM+ applications in the appropriate COM+ partitions.

All of the preceding steps can be done programmatically, using a set of Active Directory interfaces called ADSI. The objects available for managing partitions that are available within ADSI are as follows:

  • DS_USERPARTITIONSETLINK_NAME
  • DS_PARTITIONLINK_NAME
  • DS_OBJECTID_NAME
  • DS_DEFAULTPARTITIONLINK_NAME
  • DS_USERLINK_NAME
  • DS_PARTITIONSET_NAME
  • DS_PARTITION_NAME

For information on using these objects, see ADSI Reference.

For information on creating and managing COM+ partitions through the use of the Active Directory Users and Computers and Component Services administrative tools, see the online help available from within each tool.

See Also

Managing Local Partitions

Setting Administrative Rights for a Partition

Setting Partition Scope

Grouping Applications into Partitions

Collecting Partition Metrics

Configuring the Partition Cache


Setting Administrative Rights for a Partition

To control who can create, delete, modify, or view partitions, administrative rights can be defined for each partition. These rights are defined for each administrative role. Within the Component Services administrative tool, under the COM+ Applications folder, administrative roles are assigned to users by accessing the Roles folder within the System Application folder. Within the Roles folder are two roles to which you can assign users: Administrator and Reader.

Users assigned the Administrator role are allowed to create, modify, and delete COM+ application partitions. Within the Administrator folder, you can grant a user rights either to a specific partition, by adding the user name to the appropriate partition folder, or to all partitions, by adding the user name to the Global folder.

Note Any user name being added to the COM+ Administrator role within the System Application must be member of the Administrators or Power Users group. If an administrator attempts to add a user that is not a member of the Administrators or Power Users group, the following error message appears:

One or more users do not exist or lack security privileges for this operation

See Also

Managing Local Partitions

Managing Partitions Within Active Directory

Setting Partition Scope

Grouping Applications into Partitions

Collecting Partition Metrics

Configuring the Partition Cache


Setting Partition Scope

As described in the topic Activating Components Within Partitions, the COM+ partition from which to activate a component is determined by a number of factors, including the default partition of the user identity. When a component of a COM+ application is activated within a certain partition, all subsequent component activations within that same application will be within that same partition. This is because the partition ID flows from the context of the first instantiated object to any other object contexts within the same process. This flowing of the partition ID from one object context to another is referred to as partition scope.

In some cases, administrators might want to change the partition scope. Administrators can do so programmatically by calling the ICOMAdminCatalog2::SetApplicationPartition method. One of the parameters for this method is a partition ID or partition name.

For example, if an administrator wants to install an application in a partition named Test, the administrator can first call the ICOMAdminCatalog2::SetApplicationPartition method to set the partition ID or name to the Test partition and then call the ICOMAdminCatalog::InstallApplication method.

See Also

Managing Local Partitions

Managing Partitions Within Active Directory

Setting Administrative Rights

Grouping Applications into Partitions

Collecting Partition Metrics

Configuring the Partition Cache


Grouping Applications into Partitions

When deciding how to group applications into partitions, administrators need to be aware of certain rules and restrictions., including the following:

  • An application can be installed into one or more partitions.
  • Only one instance of a given component can exist in an application.

Public vs. Private Components

Other restrictions exist when deciding how to group COM+ applications. These restrictions pertain to public versus private components within an application. Application components can generally be either public or private. However, when grouping applications into partitions, administrators should be aware of some restrictions around public and private components. The following table lists these restrictions.

If an application is: | Then components in a partition can be:
A server application | Public and private.
A library application | Public only. Otherwise, the caller’s application could have the same components, which would create ambiguity.
In the Base Application Partition | Public only. This ensures backward compatibility.

Application IDs

Every COM+ application installed on a machine has a unique application ID. However, application names need only be unique within a single partition and do not have to be unique on a machine.

The following table shows what happens to the application ID when an application is imported into a partition or exported from a partition.

If an application is: | Then the application ID:
Imported to the Base Application Partition | Remains the same
Imported to a partition other than the Base Application Partition | Is changed
Exported | Is included in the exported file

See Also

Managing Local Partitions

Managing Partitions Within Active Directory

Setting Administrative Rights

Setting Partition Scope

Collecting Partition Metrics

Configuring the Partition Cache


Collecting Partition Metrics

In some cases, an organization might want to collect information on COM+ application use for the purposes of monitoring, capacity planning, and resource accounting.

For example, an application service provider (ASP) might want to charge a customer for its resource usage. To do this, COM+ allows you to collect event and metrics information on a per-partition basis.

The way to collect this information for a specific partition is by specifying, for each COM+ instrumentation interface, the partition ID member within the standard event structure. The event structure is the first value of a COM+ instrumentation interface . For more information, see the reference material for the Event Structure interfaces.

See Also

Managing Local Partitions

Managing Partitions Within Active Directory

Setting Administrative Rights

Setting Partition Scope

Grouping Applications into Partitions

Configuring the Partition Cache


Configuring the Partition Cache

The COM+ application partitions feature includes a partition cache. This cache stores user-to-partition mappings and is designed to minimize lookups over the network to the Active Directory.

Changing Cache Size

The partition cache consists of three tables, whose size can be modified to enhance performance. These tables consist of the number of SID entries in the cache, the number of OU entries in the cache, and the number of partition entries in the cache.

To change these table sizes, administrators can modify the values of a registry key. The registry key and its values are as follows:

Registry key:

HKLM\SOFTWARE\Microsoft\COM3\PartitionCache

Key Values | Description
NumSidEntries | Contains the DWORD value for the number of SID entries in the cache (default=512). This value should be set to a value greater than the number of unique identities that a machine will be servicing in the cache invalidation time window.
NumNameEntries | Contains the DWORD value for the number of OU name entries in the cache (default=64). This value should be set to a value greater than the number of unique OU names that a machine will be servicing in the cache invalidation time window.
NumPartitionEntries | Contains the DWORD value for the number of partition entries in the cache (default=1024). In the cache invalidation time window, the DWORD value should be set to a number greater than the number of unique partitions that a machine will be servicing. This is because a component's context can include a partition ID for a partition that does not reside on that machine.
EntryExpiration | Contains the DWORD value for the tick count (each tick = ~7 minutes) until a cache entry becomes invalid (default=4 (~28 minutes)).

Flushing the Cache

In some cases, an administrator might need to flush the partition cache. Administrators can do this programmatically by calling the ICOMAdminCatalog2::FlushPartitionCache method, as in the following example:

HRESULT ICOMAdminCatalog2::FlushPartitionCache();

See Also

Managing Local Partitions

Managing Partitions Within Active Directory

Setting Administrative Rights

Setting Partition Scope

Grouping Applications into Partitions

Collecting Partition Metrics


Deployment and Registration of COM+ Applications

This section introduces the features in COM+ that facilitate deployment of COM+ applications. The section also describes how COM+ applications are registered in the COM+ catalog. For more information, see the topics described in the following table.

Note For detailed procedures on deploying COM+ applications, see "Installing COM+ Applications," in the Component Services Administrator's Guide.

Topic | Description
Deploying COM+ Applications | Describes how to create installation packages for COM+ applications and application proxies through the Component Services administrative tool or the COM+ 1.0 Administration Library.
Deploying Application Proxies | Describes how to export a COM+ server application as an application proxy through the Component Services administrative tool.
The COM+ Catalog | Describes how the COM+ catalog stores COM+ application attributes, class attributes, and computer-level attributes.
The COMREPL Replication Utility | Describes the COMREPL utility, which is used to replicate the COM+ 1.0 catalog from a given source computer to one or more target computers.


Deploying COM+ Applications

You can use the Component Services administrative tool or the COM+ Administration Library to create installation packages for COM+ applications and application proxies.

COM+ generates Windows Installer-compatible installation packages, which in a single file contain all the necessary pieces to install a COM+ application on another machine.

When exporting a COM+ application, the Component Services administrative tool determines the application's set of classes, components, and their attributes, as well as application-level attributes. From this information, the Component Services administrative tool generates a single .msi file, which contains the following:

  • Windows Installer tables with COM registration information (see the Windows Installer documentation for details).
  • An .apl file containing the application's attributes. (This is an internal file; the format of this file is not documented.)
  • DLLs and type libraries that describe the interfaces implemented by the COM+ application's classes.

In addition to the .msi file, the Component Services administrative tool generates a cabinet (.cab) file. This file wraps the .msi file, allowing the developer to deploy the COM+ application through Microsoft® Internet Explorer.

Note When exporting a COM+ application, the Component Services administrative tool packages only the standard COM+ parts of the application. It does not package, for example, any dependent DLL or data files. The dependent DLL files must first be installed on a computer prior to installing the COM+ application. Alternatively, you can use the Windows Installer authoring tool to add these dependent files to the .msi file generated by the Component Services administrative tool. (See the Windows Installer documentation for details.)

Installing COM+ Applications on Other Computers

The Windows Installer (.msi) file generated by the Component Services administrative tool can be used to install the COM+ application on another computer. The .msi file containing a COM+ application can be installed only on computers that support COM+ 1.0 Services (currently only Microsoft Windows® 2000). For detailed procedures on deploying COM+ applications, see "Installing COM+ Applications," in the Component Services Administrator's Guide.

Unless the .msi file is modified using a Windows Installer authoring tool, COM+ applications installed by using the Windows Installer appear in the Add/Remove Programs control panel.

See Also

Deploying Application Proxies

The COM+ Catalog

The COMREPL Replication Utility


Deploying Application Proxies

To access a COM+ server application remotely from another (client) computer, the client computer must have a subset of the attributes of the server application installed, including proxy/stub DLLs and type libraries for DCOM/QC interface remoting. This subset is called an application proxy.

Through the Component Services administrative tool, you can easily export a COM+ server application as an application proxy. For COM+ to generate an application proxy, it is important that all components in the server application were installed and not imported. (For more information on this distinction, see Importing Components.) This ensures that the application includes all the necessary registration information.

Note It is recommended that you separate the interface definitions from the class implementations. Otherwise, the set of DLLs or type libraries included in the COM+ application proxy will include actual server code.

Application proxies generated by COM+ are Windows Installer installation packages. After installation, the application proxies appear in the client computer's Add/Remove Programs control panel (unless the .msi file is modified using a Windows Installer authoring tool).

Remote Access via Application Proxies

When generating an application proxy, COM+ automatically provides the following information, required for the application proxy to remotely access a COM+ server application:

  • Class identity information (CLSIDs and ProgIDs)—an application proxy supports up to two ProgIDs.
  • Application identity and relation of classes to applications (AppID).
  • Location information per application (Remote Server Name).
  • Marshaling information for all the interfaces exposed by the application (for example, type libraries and proxy/stubs).
  • MSMQ queue names and identifiers (if the Queued Components service is enabled for the application).
  • Class, interface, and method attributes, excluding role information.
  • Application attributes.

Installing Application Proxies on Other Operating Systems

Unlike COM+ server applications, application proxies can be installed on any operating system that supports DCOM (and Windows Installer). On computers that aren't running Microsoft® Windows® 2000 (and therefore lack COM+), only the subset of information required for DCOM remoting is installed. This information is installed into the Windows registry (using the HKEY_CLASSES_ROOT, APPID/CLSID keys).

Note When installing an application proxy (.msi file) on computers that aren't running Windows 2000, it is necessary to have Windows Installer running on those machines. Windows Installer is available in redistributable form as part of the Platform SDK. It is recommended that developers ship the Windows Installer redistributable file (instmsi.exe) along with their application's .msi file. This will ensure that system administrators have Windows Installer available when deploying application proxies on non-Windows 2000 clients.

On Windows 2000 computers, the application proxy information is installed into the COM+ Registration Database and is visible in the Component Services administrative tool.

See Also

Deploying COM+ Applications

The COM+ Catalog

The COMREPL Replication Utility


The COM+ Catalog

The COM+ catalog stores COM+ application attributes, class attributes, and computer-level attributes. It guarantees consistency among these attributes and provides common operations on top of these attributes.

The COM+ catalog uses two different stores, as follows:

  • COM+ Registration Database
  • The Microsoft® Windows® registry (HKEY_CLASSES_ROOT)

The catalog presents a unified, logical view of these two stores and exposes them through the COM+ 1.0 Administration Library. This library provides, through a scripting language, all the functionality of the Component Services administrative tool.

For existing COM components that do not require any new COM+ services, lookup occurs in the existing Windows registry. The COM+ catalog also uses the Windows registry for type library and interface proxy/stub registration.

Split Registration

For new components that are actually already existing COM components that are used in the services environment (for example, MTS components), the basic COM aspect of the registration is stored in the Windows registry and new services and attributes (for example, Queued Components) are stored in the COM+ Registration Database. This is known as a split registration.

Each attribute is stored in only one location: either the Windows registry or the COM+ Registration Database. New COM components are registered exclusively in the COM+ Registration Database, with some duplication in the Windows registry so that existing tools can use them.

Transactional Updates to the Catalog

Some operations on the catalog are performed in a transactional manner. When you invoke the COM+ 1.0 Administration Library from a transactional component, the updates to the COM+ Registration Database will take place within the calling component's transaction boundary.

However, updates that involve changes to other stores (such as the file system and Windows registry) are not guaranteed to be fully transactional. An aborted transaction can leave these stores in a state that is inconsistent with any changes made to one another or to the COM+ Registration Database.

See Also

Deploying COM+ Applications

Deploying Application Proxies

The COMREPL Replication Utility


The COMREPL Replication Utility

COMREPL is a utility that will replicate the COM+ 1.0 catalog from a given source computer to one or more target computers. Think of the source computer representing a "master configuration." COMREPL is used to replicate this master configuration to maintain a set of identically configured computers.

The unit of replication is the entire COM+ configuration on the master computer. All COM+ applications on the master are replicated to the target computers—it's all or nothing. In addition, all COM+ applications previously installed on the target computers, with the exception of the COM+ preinstalled applications, will be deleted as part of the replication process.

COMREPL replicates only COM+ configuration data. This includes COM+ applications and COM+ specific computer settings. Microsoft® Internet Information Services (IIS) has a similar utility (IISSync), which makes use of COMREPL to replicate IIS and COM+ configuration.

For detailed information on launching and using COMREPL, see the following topics in this section:

  • Using COMREPL
  • What Gets Replicated
  • Replication Phases
  • File Management
  • Logging and Error Reporting

See Also

Deploying COM+ Applications

Deploying Application Proxies

The COM+ Catalog


Using COMREPL

To launch the COMREPL command line utility

  1. Add %windir%\system32\Com to the default environment path by typing the following in the command prompt:
    set path = %PATH%;%windir%\system32\Com
  2. Enter the following COMREPL command:
    COMREPL <sourceComputer> <targetComputerList> [/n [/v]]

    Where:

    <sourceComputer>: the computer name of the source

    <targetComputerList>: the computer names of the targets separated by spaces

    /n: option to suppress confirmation prompt before starting replication

    /v: echo log file output to the console

Notes

  • Because COM+ is not replicated (only configuration data and applications), all target machines must already have COM+ installed.
  • The user must pass role checks for the system application on both the source and the target computers.
  • No local machine accounts that may be used by roles are replicated.
  • The target machine(s) must be online.
  • The user is responsible for replicating all non-COM+ data (for example, database tables, data files, and so forth) to the target machine(s).
  • Microsoft® Windows NT® Clusters can participate in replication, but because COMREPL replicates only to named machines, if a failed machine is replaced by a backup, the then named machine would be the one being replicated to.

See Also

What Gets Replicated

Replication Phases

File Management

Logging and Error Reporting


What Gets Replicated

Applications

All applications installed on the source computer are replicated except for the following:

Non-COM+ application elements and dependencies

The administrator is responsible for replicating anything that a COM+ application depends on but which is not properly part of the application itself, such as data files and DLLs. COMREPL will not replicate anything outside of COM+ application elements.

COM+ preinstalled applications

Applications that are used internally by COM+ and are installed via the COM+ setup program are not replicated. These include the following:

  • System application
  • COM+ utilities
  • COM+ QC Dead Letter Queue Listener

Applications created by IIS

These applications are not replicated and include the following:

  • IIS in-process applications
  • IIS utilities
  • All applications created for isolated or pooled virtual roots

Computer List

The remote computers named in the Computers folder in the Component Services administration tool will not be replicated from source to target computer.

Properties

The following LocalComputer properties are replicated:

  • TransactionTimeout
  • ResourcePoolingEnabled
  • DCOMEnabled
  • DefaultAuthenticationLevel
  • DefaultImpersonationLevel
  • SecurityTrackingEnabled
  • CISEnabled
  • SecureReferencesEnabled
  • InternetPortsListed
  • DeafultToInternetPorts
  • Ports
  • RpcProxyEnabled

The following LocalComputer properties are not replicated:

  • Description
  • ApplicationProxyRSN
  • IsRouter

For descriptions of the LocalComputer properties, see LocalComputer Collection.

See Also

Using COMREPL

Replication Phases

File Management

Logging and Error Reporting


Replication Phases

COMREPL does its work in three phases. The replication process is divided into distinct phases for the following two reasons:

  • To separate work done to prepare the source from work that is done on each target
  • To delay modification of the target until all data has been acquired from the source

The replication phases are as follows:

  1. Prepare phase—Exports all the installed applications locally on the source computer. This phase does not touch the configuration of any targets.
  2. Copy phase—Copies data to a target computer. All applications exported on the source are copied to the target. This is a file copy operation. (See File Management.) This step also acquires some data from the source computer that is not encapsulated within exported application files (for example, application identities). This data is held in memory within COMREPL. This phase does not touch the configuration of any target computers.
  3. Install phase—Installs source catalog on a target computer. When this step is initiated, all data required to reconfigure the target is within application files in the target's file system or is held as instance data within COMREPL. This phase will delete all the installed applications on the target (except the applications described in What Gets Replicated) prior to installing the applications copied from the source. COMREPL installs on multiple targets concurrently by using an install thread per target.

See Also

Using COMREPL

What Gets Replicated

File Management

Logging and Error Reporting


File Management

To enable the transfer of application files, COMREPL automatically manages sets of file system folders on the source and target. These COMREPL folders are all rooted in %systemdir%\com\replication.

Source folders:

  • ..\ReplicaSource

    Applications exported during the prepare phase are stored here.

    This folder is overwritten each time the prepare phase is executed against a given source computer.

    This folder is never explicitly deleted, so replication to targets can take place at any time after the source is prepared.

    Each application is stored in its own subfolder named <appName>+<appID>.

Target folders:

  • ..\ReplicaNew

    The copy phase copies all files and subfolders from ReplicaSource on the source to ReplicaNew on the target.

    Any previous contents of ReplicaNew are deleted each time the copy phase is run against a given target.

    This folder exists only while the replication process is running. (See ReplicaCurrent below.)

  • ..\ReplicaCurrent

    The replicated applications currently installed on the target are stored here.

    When the install phase is started, the ReplicaNew folder is renamed to ReplicaCurrent.

    If there is an existing ReplicaCurrent folder, it is renamed to ReplicaOld.

    If there is an existing ReplicaOld folder, its contents are deleted.

  • ..\ReplicaOld

    Saves the application files installed during the next to last replication.

    These files are saved for backup purposes only.

See Also

Using COMREPL

What Gets Replicated

Replication Phases

Logging and Error Reporting


Logging and Error Reporting

Log file

COMREPL generates a log file containing status and error messages. This file is stored on the computer where COMREPL was launched in %systemdir%\com\replication\comrepl.log.

This log file is cleared when a copy phase is started. Subsequent installation on targets will append to the file.

Error handling

Errors are noted in the log file described above. Detailed error information may also be found in the event log on source or target computers.

See Also

Using COMREPL

What Gets Replicated

Replication Phases

File Management


COM+ Glossary

A

access token
An object that describes the security context of a process or thread. The information in a token includes the identity and privileges of the user account associated with the process or thread. When a user logs on, the system verifies the user's password by comparing it with information stored in a security database. If the password is authenticated, the system produces an access token. Every process executed on behalf of this user has a copy of this access token. See also context, primary access token.
ACID properties
Acronym coined by transaction processing pioneers for atomic, consistent, isolated, and durable. These properties ensure predictable behavior, reinforcing the role of transactions as all-or-none propositions designed to reduce the management load when there are many variables.
activation
The chain of events that results in the creation of a COM object and the return of a valid pointer to an interface on that object. In COM+, an object gets activated either in its own context or in that of its creator (an object that has requested the object being activated). COM+ services rely on appropriate activation of an object based on the object's configuration. In the course of activation, the system determines the context in which the object runs, initializes the context properties, checks access permissions, and establishes a security identity. See also activation security, activation type, context, just-in-time (JIT) activation.
activation security
A form of security protection that determines who can launch a server. Activation security is automatically applied by the Service Control Manager (SCM) of a particular machine. Upon receipt of a request from a client to activate an object, the SCM checks the request against activation-security information stored within its registry. Activation security is also checked for same-machine activations. Also called launch security. See also activation, activation type, call security, Service Control Manager (SCM).
activation type
Activation category for a COM+ application that indicates whether the application runs in or out of its client's process space (depending on whether it's a library or server application, respectively) as well as whether the application runs as an NT service. See also COM+ library application, COM+ server application.
activity
In COM+, a logical thread comprising one or more transactions and containing a collection of components that are grouped into a COM+ application. Every COM+ object belongs to one activity. The association between an object and an activity cannot be changed.
apartment model process
A process that has two or more single-threaded apartments and no multithreaded apartments. See also free-threaded process, mixed model process, multithreaded apartment model, neutral apartment model, single-threaded process.
application proxy
A set of files containing registration information that allows a client to remotely access a COM+ server application. When run on a client computer, an application proxy file writes information about the server application to the client computer; the client can then remotely access the server application.
application partitions See COM+ application partition.
application partition sets See COM+ application partition sets.
authentication
The security process of determining that a caller of an application is actually who it says it is—verifying the authenticity of an identity claim. For COM+ applications, authentication can be turned on and configured administratively, after which it works transparently to the application.
authorization
The security process of determining whether a caller of an application is authorized to do what it is asking to do.

C

call security
A form of security protection that controls access to a server's objects after a server has been launched. See also activation security.
class (COM)
A named, concrete implementation of one or more interfaces. A COM class is identified by a CLSID and, sometimes, a ProgID. See also interface, method.
cloaking
A server's ability to mask its own identity when making calls on a client's behalf. When cloaking is enabled, calls made by the server impersonating the client can be made under the client's identity. When cloaking is disabled, calls by the server will be made under the server's identity. See also dynamic cloaking, impersonation, static cloaking.
COM+ application
The primary unit of administration and security for Component Services. A COM+ application is a group of COM components that, generally, perform related functions. These components further consist of COM interfaces and methods. See also interface, method.
COM+ application partitions
A COM+ feature that enables, on a single machine, the creation of a separate execution space for an application. Within its own execution space, an application's execution is isolated from versions of the same application that are installed in other partitions, thus allowing multiple versions of the application to be executed simultaneously on a single machine. Each version of the application can be separately configured and managed, according to the specific needs of its users.
COM+ application partition sets
A group of application partitions that is mapped to a particular user ID.
COM+ catalog
The underlying data store that holds all COM+ configuration data. Performance of COM+ administration tasks requires reading and writing data stored in the catalog. The catalog can be accessed only through the Component Services administrative tool or through the COMAdmin library.
COM+ Events
A COM+ service that extends the COM+ programming model to support late-bound events or method calls between the publisher or subscriber and the event system. COM+ Events matches and connects publishers and subscribers. A publisher makes the method call to initiate an event, and a subscriber receives these calls from the publisher. COM+ Events maintains the list of interested subscribers who will receive the calls and directs those calls without requiring the knowledge of the publisher. See also publisher, subscriber.
COM+ library application
A COM+ application that runs in the process of the client that creates it. Library applications can use role-based security but do not support remote access or queued components. See also COM+ server application, role-based security.
COM+ Queued Components
A COM+ service, based on Microsoft® Message Queuing Services (MSMQ), that provides an easy way to invoke and execute components asynchronously. Message processing can occur without regard to the availability or accessibility of either the sender or the receiver.
COM+ server application
A COM+ application that runs in its own process. Server applications can support all COM+ services. See also COM+ library application.
COM component
A binary unit of code that includes packaging and registration code and that creates COM objects. All COM+ applications consist of one or more COM components.
commit tree
In a distributed transaction system, the conceptual representation of a transaction as based on the hierarchical relationships between individual transaction managers participating in a distributed transaction. Included in that hierarchy are the enlisted resource managers associated with the transaction managers. See also distributed transaction, Distributed Transaction Coordinator (DTC), global commit coordinator, resource manager, transaction, transaction manager.
COM object
In the COM programming model, a programming structure encapsulating both data and functionality, which 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. See also interface, method, pseudo-object.
Compensating Resource Manager (CRM)
A COM+ feature that enables non-transactional resources to participate in a two-phase commit transaction with the Microsoft® Distributed Transaction Coordinator (DTC). Typically, CRMs do not provide the isolation capabilities of full resource managers, but they do provide transactional atomicity and durability by writing to a log. See also Distributed Transaction Coordinator (DTC), resource manager, two-phase commit protocol.
Component Services administrative tool
Introduced in the release of the Microsoft Windows® 2000 operating system, a user-interface snap-in through which administrators and developers can create, configure, and maintain COM+ applications, as well as administer distributed transactions and memory-resident databases. The Component Services administrative tool can also be used to view system events and manage system services local to the computer on which the tool is installed.
conceptual model
The first step in the COM+ application design phase, where the developer defines the business problems to be solved and decides what components and services are required. See also logical model, physical model, three-tier architectural model.
concurrency
The ability of more than one transaction or process to access the same data at the same time.
configured component
A COM component that has been installed into a COM+ application. After it is installed, the component is configured within the COM+ catalog to make use of the available COM+ services. See also COM component, unconfigured component.
context
A set of run-time properties associated with one or more COM objects that are used to provide services for those objects. Every COM object runs in a single context from activation to deactivation (always within the same apartment). Initialized when an object is activated, context properties, such as security context properties, represent the run-time needs of an object. See also activation.

D

data tier
In the three-tier architecture model for business applications, the DBMS access layer, which can be accessed through the middle tier, or business services layer, and on occasion through the presentation tier, or user services layer. The data tier consists of data access components (rather than raw DBMS connections) to aid in resource sharing and to allow clients to be configured without installing the DBMS libraries and ODBC drivers on each client. Also called data services layer. See also middle tier, presentation tier, three-tier architectural model.
deadlock
In multithreaded applications, a threading problem that occurs when each thread is waiting for another thread to do something. See also multithreaded apartment model, race condition.
delegation
A form of impersonation that authorizes a server to act on a client's behalf, giving the server the ability to impersonate clients over the network. See also impersonation.
distributed transaction
A transaction that updates data on more than one networked computer. See also transaction.
Distributed Transaction Coordinator (DTC)
Introduced in the Microsoft Windows 2000 operating system and tightly integrated with COM+, a system service that manages transactions and transaction-related communications that are distributed across two or more systems to ensure successful and complete transactions. See also distributed transaction, transaction, transaction manager.
dynamic cloaking
A form of cloaking where the original client identity is discovered as the server thread access token on each method call to the downstream server. Although the identity that is presented can be determined dynamically, the overhead required to do this can be considerably more expensive. For COM+ applications, the default configuration is for dynamic cloaking capability because it provides the flexibility that is usually required by circumstances that necessitate using impersonation in the first place. See also cloaking, impersonation, static cloaking.

E

enumerator object
Enables enumeration of items in a collection. See also COM object.
event
An action recognized by an object, such as clicking the mouse or pressing a key, and for which you can write code to respond. See also COM+ Events.
EventClass object
EventClass objects are configured components that provide a persistent record in the event system to describe the publishers and the firing interfaces associated with those publishers.
event method
A method in a COM+ interface that identifies a COM+ event. Event methods must be uniquely named and can contain only input parameters. The return value must be an HRESULT. See also interface, method.
event object
A COM object that can signal one or more threads that an event has occurred, essentially acting as a traffic cop. Any thread within a process can create an event object. See also COM object.
exception
An abnormal condition or error that occurs during the execution of a program and that requires the execution of software outside the normal flow of control.

F

failback
In a cluster network system, the process of restoring resources and services to their primary server after they have been temporarily relocated to a backup system while repairs were implemented on the original host. See also failover.
failover
In a cluster network system, the process of relocating an overloaded or failed resource—such as a server, a disk drive, or a network—to its backup component. See also failback.
free-threaded process
A process that has a multithreaded apartment and no single-threaded apartments. See also apartment model process, mixed model process, multithreaded apartment model, neutral apartment model, single-threaded process.

G

global commit coordinator
In a distributed transaction system, the root transaction manager of the commit tree. This coordinator makes the decision to either commit or abort a given transaction and is never in doubt. See also commit tree, distributed transaction, Distributed Transaction Coordinator (DTC), transaction, transaction manager.

I

impersonation
The ability of a thread to execute in a security context different from that of the process owning the thread. The server thread uses an access token representing the client's credentials, and with this, it can access resources that the client can access. See also access token, context, impersonation level.
impersonation level
The degree of authority an application grants other applications to use its identity when it calls them. This can be set only for COM+ server applications.
interception
For an object activated in a given context, the process of handling calls to that object from across the context boundary. Calls across context are handled with lightweight interface proxies that will handle whatever mediation is required to adjust the run-time environment from one that accommodates the caller to one that accommodates the callee. See also activation, context, interface proxy.
interface
In COM-based programming, a collection of related public functions that provide access to a COM object. The set of interfaces on a COM object composes a contract that specifies how programs and other objects can interact with the COM object. See also class (COM), COM object, method.
interface proxy
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. See also interface stub.
interface stub
An interface-specific object that unpackages marshaled parameters and calls the required method. The stub runs in the receiver's address space and communicates with a corresponding interface proxy in the sender's address space. See also interface proxy.
interior object
In a transactional hierarchy, any object under the root object. See also COM object, root object.

J

Just-in-Time (JIT) activation
An automatic service provided by COM+ that allows idle server resources to be used more productively. When a component is configured as JIT activated, COM+ can deactivate an instance of it while a client still holds an active reference to the object. The next time the client calls a method on the object, COM+ will reactivate the object transparently to the client, just in time. See also activation.

L

launch security See activation security.
listener
An architectural element of the COM+ Queued Components service. The listener is a COM object that opens the message queue associated with its host application and waits for messages to arrive. As messages arrive, the listener dispatches threads that process messages. See also COM+ Queued Components, message mover, player, recorder.
logical model
The second step in a COM+ application design process, where the conceptual model is broken out into the logical tiers of the three-tier architecture, as follows: the presentation tier, or user services; the middle tier, or business services; and the data tier, or data services. See also conceptual model, data tier, middle tier, physical model, presentation tier, three-tier architectural model.
loosely coupled event (LCE)
A loosely coupled event means that the event’s sender (publisher) and receiver (subscriber) are not closely bound. In a LCE system, such as COM+ Events, event information from different publishers is persisted in an event store. Subscribers query this store and select the events that they want to receive. Selecting event information from the event store creates a subscription. When an event occurs, the event system looks in this database and finds the interested subscribers, creates a new object of each interested class, and calls a method on that object. See also tightly coupled event (TCE).

M

marshaling
The process of packaging, sending, and unpackaging interface method parameters across thread or process boundaries so that a remote procedure call can take place.
message mover
The architectural element of the COM+ Queued Components service that moves failed messages back to their input queue so that they can be retried. To ensure that messages are not lost or duplicated in the event of failure during the move, the message mover tool preserves all the message properties that can be preserved when moving messages from one queue to another. See also COM+ Queued Components, listener, player, recorder.
meta-event
Meta-events are used by the COM+ Events system to notify interested subscribers whenever EventClass objects or subscriptions are created, modified, or removed.
method
In COM-based programming, a process performed by a COM object when it receives a message. See also COM object, interface.
middle tier
In the three-tier architecture model for business applications, the layer comprising the business logic and data rules. The components that make up the middle tier can be used to enforce business rules, such as business algorithms, legal or governmental regulations, and data rules, which are designed to keep the data structures consistent within either specific or multiple databases. Because these middle-tier components are not tied to a specific client, they can be used by all applications and can be moved to different locations as response time and other rules require. Also called business services layer or business logic tier. See also data tier, presentation tier, three-tier architectural model.
mixed model process
A process that has a multithreaded apartment and one or more single-threaded apartments. See also apartment model process, free-threaded process, multithreaded apartment model, neutral apartment model, single-threaded process.
moniker
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. See also COM object.
.msi file
A file created by the Component Services administrative tool when you export a COM+ application or application proxy for installation on another computer. The .msi file can be installed on any Windows-based client using Windows Installer. See also application proxy, COM+ application, Component Services administrative tool.
multithreaded apartment model
An apartment model in which 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. See also apartment model process, free-threaded process, mixed model process, neutral apartment model, single-threaded process.

N

nested transaction
A secondary transaction initiated from within an existing, primary, or parent, transaction boundary. The primary transaction does not commit until all of its subordinate, or nested, transactions commit. See also transaction.
neutral apartment model
A threading model in which objects follow the guidelines for multithreaded apartments but can execute on any kind of thread. The neutral apartment model is the recommended threading model for COM components and COM+ applications. See also apartment model process, free-threaded process, mixed model process, multithreaded apartment model, single-threaded process.

O

object See COM object.
object pooling
An automatic service provided by COM+ that enables you to configure a component to have instances of itself kept active in a pool, ready to be used by any client that requests the component. You can administratively configure and monitor the pool maintained for a given component, specifying characteristics such as pool size and creation request time-out values. When the application is running, COM+ manages the pool for you, handling the details of object activation and reuse according to the criteria you have specified. Object pooling can greatly increase performance of your application when a given object is expensive to create, such as objects that require connections to databases.

P

partitions See COM+ application partitions.
partition sets See COM+ application partition sets.
persistent object
A COM object that can save its internal state when asked to do so by a client and that conforms to COM-defined 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. See also COM object, persistent object interface.
persistent object interface
A COM interface implemented by a persistent object. Clients use persistent object interfaces to tell those persistent objects when and where to store their state. See also interface, persistent object.
Phase Zero notification interface
COM+ interface that allows applications to detect when a transaction is ready to proceed with a two-phase commit protocol so that it can perform the necessary notification operations and communicate to the transaction manager when the operations have been completed. See also interface, two-phase commit protocol.
physical model
The third and final step in the COM+ application design process, where the developer determines where the components reside physically and how they are to be coded. See also conceptual model, logical model, presentation tier, three-tier architectural model.
player
The architectural element of the COM+ Queued Components service that retrieves the message from a queue and then loads the server object and the standard interface stubs to unmarshal data and invoke server methods. The player unmarshals the client's security context at the server side and then invokes the server component and makes the same method calls. The method calls are not played back by the player until the client component completes and the transaction that recorded the method calls commits. See also COM+ Queued Components, listener, message mover, recorder.
presentation tier
In the three-tier architecture model for business applications, the layer that presents data to the user and optionally permits data manipulation and data entry. The two main types of user interface for the presentation tier are the traditional application and the Web-based application. Also called user services layer. See also data tier, middle tier, three-tier architectural model.
primary access token
Describes the security context of the user account associated with a process. See also access token, context.
proxy manager
In standard marshaling, a proxy that manages all the interface proxies for a single object. See also interface proxy, marshaling.
pseudo-object
A type of contained object, such as a user selection in a document, a range of cells in a spreadsheet, or a range of characters in a text document. This type of object is called a pseudo-object because it isn't treated as a distinct object until a user marks the selection. See also COM object.
publisher
The sender of an event. In the COM+ Events architecture, the publisher makes the method call to initiate an event. See also COM+ Events, subscriber.

Q

queued components See COM+ Queued Components.
queue moniker
The moniker used to activate a queued component. The queue moniker requires that it receive the class ID (CLSID) of the object to be invoked from the new moniker directly to the right of it. See also COM+ Queued Components, moniker.

R

race condition
In a multithreaded application, a condition that occurs when one thread finishes before another on which it depends, causing the former to use a false 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 also deadlock, multithreaded apartment model.
recorder
The architectural element of the COM+ Queued Components service that marshals the client's security context into a message and records all of the method calls for an object. In its role as proxy for the server component, the recorder is a system-provided DLL that selects interfaces from the queuable interfaces in the COM+ catalog. See also COM+ Queued Components, COM+ catalog, listener, message mover, player.
resource dispenser
In the COM+ programming model, a component that manages nondurable shared state on behalf of the application components within a process. Resource dispensers are similar to resource managers but without the guarantee of durability. See also Shared Property Manager (SPM).
resource manager
A COM+ system service that manages persistent or durable data in databases, durable message queues, or transactional file systems. It is the resource manager that knows how to store data and perform disaster recovery. COM+ server applications use resource managers to maintain the durable state of an application, such as the record of inventory on hand, pending orders, and accounts receivable. Resource managers work in cooperation with the Microsoft Distributed Transaction Coordinator (DTC) to guarantee atomicity and isolation to an application. See also Distributed Transaction Manager (DTC).
role-based security
A COM+ security service provided for COM+ applications. A role represents a category of users defined for a COM+ application for the purpose of determining access permissions to the application's resources. Roles are assigned by a developer to components, interfaces, and methods. Users are assigned by an administrator to appropriate roles, enabling a user within a given role to access any resources to which that role is assigned.
root object
The first object of a transaction, called the root of the transaction, and always placed in a new transactional boundary. There can be only one root object in a transaction. All other objects in the transactional hierarchy under the root object are called interior objects. See also COM object, interior object.

S

semaphore
In the COM programming model, a kernel object used to maintain a reference count on some available resource.
Service Control Manager (SCM)
A Microsoft Windows NT Server process that manages all the services in the Windows NT registry.
Shared Property Manager (SPM)
In Com+, a resource dispenser that you can use to share state among multiple objects within a server process. See also resource dispenser.
single-threaded process
A process that consists of just one single-threaded apartment, which in turn consists of exactly one thread. All COM objects that live in a single-threaded apartment can receive method calls from only the one thread that belongs to that apartment. See also apartment model process, free-threaded process, mixed model process, multithreaded apartment model, neutral apartment model.
split registration
For components that are already existing COM components and are used in the COM+ services environment, the registration arrangement in which the basic COM aspect of the registration is stored in the Windows registry and new COM+ services and attributes (for example, Queued Components) are stored in the COM+ Registration Database. Each component attribute is stored in either the Windows registry or the COM+ Registration Database. New COM components are registered exclusively in the COM+ Registration Database, with some duplication in the Windows registry so that existing tools can use them.
stateful
Of or pertaining to a system or process that monitors all details of the state of an activity in which it participates. See also stateless.
stateless
Of or pertaining to a system or process that participates in activity without monitoring all details of its state. See also stateful.
static cloaking
A form of cloaking where the original client identity can be presented once to a downstream server, setting the original client identity once on the proxy. This client identity is presented as a server thread token that will be used on subsequent method calls. See also cloaking, dynamic cloaking, impersonation.
subscriber
The receiver of an event. In the COM+ Events architecture, the subscriber receives the calls made by the publisher. See also COM+ Events, publisher.
subscription object
In the COM+ Events system, an object created by a subscriber to request and manage the delivery of events. See also COM+ Events, subscriber.

T

three-tier architectural model
The fundamental framework for the logical design model, segments an application's components into three tiers of services as follows: the presentation tier, or user services; the middle tier, or business services; and the data tier, or data services. These tiers do not necessarily correspond to physical locations on various computers on a network, but rather to logical layers of the application. See also conceptual model, data tier, logical model, middle tier, physical model, presentation tier.
tightly coupled event (TCE)
A tightly coupled event means that the event’s sender (publisher) and receiver (subscriber) are closely bound. In a TCE system, the publisher is provided with an interface on which to call a method when a change occurs. The subscriber knows which publisher to request notification from and the interfaces that are exposed. A TCE system requires that both the publisher and the subscriber are running at all times. See also loosely coupled event (LCE).
trace log
A log file automatically generated by DTC that shows data related to one or more distributed transactions. Examples of data in a trace log are transaction ID, transaction time, and messages indicating the transaction outcome.
transaction
A unit of work in which a series of related operations occur during an application process. A transaction executes exactly once and is atomic—either all of the work is done or none of it is. See also distributed transaction.
transaction commit tree See commit tree.
Transaction Internet Protocol (TIP)
Transaction Internet Protocol is a standard two-phase commit protocol that enables heterogeneous transaction managers to coordinate distributed transactions, especially over the Internet. The TIP two-phase commit protocol is simple to implement and is independent of the application-to-application communications protocol, such that it may be used with any application protocol but especially HTTP. See also two-phase commit protocol.
transaction manager
The part of the Microsoft Distributed Transaction Coordinator (DTC) that executes on each machine participating in a distributed transaction and manages the activities related to committing or aborting that part of the transaction. See also Distributed Transaction Coordinator (DTC).
transaction processing application
A collection of transaction operations that automate a given business task. See also distributed transaction, transaction, transaction processing system.
transaction processing system
A complete system, comprising both computer hardware and software, that hosts a transaction processing application to perform routine transactions necessary to conduct business. See also distributed transaction, transaction, transaction processing application.
two-phase commit protocol
A protocol used only in distributed transactions, ensures that the outcome of a transaction is consistent across all transaction managers participating in the transaction. The protocol operates in two distinct phases to ultimately commit or abort a transaction: Phase one evaluates the condition of each resource manager, and phase two completes the transaction. See also distributed transaction, resource manager, transaction, Transaction Internet Protocol (TIP), transaction manager.

U

unconfigured component
A COM component that has not been installed into a COM+ application. See also COM component, configured component.

X

XA interfaces
A standard set of programming interfaces that allow COM+ application developers to access XA-compliant databases and create resource managers that operate with relational databases, message queuing, transactional files, and object-oriented databases. Although Microsoft does not directly support the XA protocol, Microsoft does support translation facilities between OLE transactions and XA.


Reference

This section contains reference documentation for COM+ application developers and developers automating COM+ administration. Topics include:

COM+ Administration Reference

COM+ Programmer's Reference

Additional reference information that may be relevant to COM+ application developers can be found in the Tools Developer Reference.


COM+ Administration Reference

This topic contains reference material for the COM+ 1.0 Administration Library. The objects and interfaces made available by this library enable you to perform programmatically all the actions you can perform using the Component Services administration tool.

Topic | Description
Administration Objects | Describes the objects that you can use to manage your COM+ applications programmatically.
Administration Collections | Describes the collections that contain objects and resources you can manage.
Administration Interfaces | Describes the interfaces that you can use to manage your COM+ applications programmatically.


Administration Objects

The administration objects provide a way to access and manipulate all of the COM+ configuration data accessible through the Component Services administration tool. You can use these objects to automate all tasks in COM+ administration.

The administration objects enable you to read and write information that is stored on the COM+ catalog, the underlying data store that holds all COM+ configuration data. Information on the catalog is structured as collections holding items which expose properties. These correspond to folders, items in folders, and property sheets for those items, in the Component Services administration tool.

You initiate programmatic administration using the COMAdminCatalog object. You manipulate collections on the catalog using the COMAdminCatalogCollection object. And you can manipulate items in collections using the COMAdminCatalogObject object.

For information regarding the collections on the catalog and their properties see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

Interface | Description
COMAdminCatalog | Use this interface to initiate a session over the COM+ catalog. Retrieve collections, install applications and components, start and stop services, and connect to remote servers.
COMAdminCatalogCollection | Use this interface to manipulate any collection on the catalog. Add, remove, enumerate through, and retrieve items in the collection, and access related collections.
COMAdminCatalogObject | Use this interface to manipulate an item in a collection. Get and put properties exposed by the item.

Note These objects are provided by the COM+ Admin Type Library DLL (Comadmin.dll).


COMAdminCatalog Object

The COMAdminCatalog object provides access to the COM+ catalog data store. You use it to initiate a session to do automated administration of COM+. It enables you to access collections on the catalog, install COM+ applications and components, start and stop services, and connect to and administer remote servers. This object implements the ICOMAdminCatalog interface.

Remarks

You use the COMAdminCatalog object to begin programmatic access to COM+ configuration data stored on the COM+ catalog. This information underlies the folders and items seen in the Component Services administration tool.

Folders correspond to collections on the catalog, which you can represent using the COMAdminCatalogCollection object. Items in folders correspond to items in collections, which you can represent using the COMAdminCatalogObject object.

For information regarding specific collections and their properties, see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

For information on the properties exposed by the COMAdminCatalog object, see ICOMAdminCatalog Properties.

The COMAdminCatalog object implements the ICOMAdminCatalog interface, which provides the following methods.

Methods | Description
BackupREGDB | Backs up the COM+ class registration database (RegDB) to a specified file.
Connect | Connects to a remote computer for programmatic administration on that computer.
ExportApplication | Exports a COM+ application or application proxy to a file for installation on other machines.
GetCollection | Returns a COMAdminCatalogCollection object representing a specified collection.
GetCollectionByQuery | Gets a collection on the catalog given the key values for all parent items. Returns a COMAdminCatalogCollection object.
GetEventClassesForIID | Gets a list of event classes that implement a specified interface.
GetMultipleComponentsInfo | Returns information about components found in specified .dll files.
ImportComponent | Imports a registered in-process component to a COM+ application. Should not be used: Use InstallComponent instead.
InstallApplication | Installs a COM+ application or application proxy from a file.
InstallComponent | Installs a component into a COM+ application, and provides default configuration in the COM+ class registration database (RegDB).
InstallEventClass | Installs an event class into an application.
InstallMultipleComponents | Installs components from multiple files into a COM+ application.
InstallMultipleEventClasses | Installs event classes from multiple files into an application.
QueryApplicationFile | Returns information about a COM+ application from an application file.
RefreshComponents | Refreshes component registration information from the Registry.
RefreshRouter | Refreshes the data being used by the component load balancing service on a CLB server, if the CLB service is installed.
RestoreREGDB | Restores the COM+ class registration database (RegDB) from a specified file. Requires a reboot to take effect.
ServiceCheck | Checks the status of a COM+ service.
ShutdownApplication | Initiates shutdown of a COM+ application server process.
StartApplication | Launches a COM+ server application in a dedicated process.
StartRouter | Starts the component load balancing service on a CLB server, if the CLB service is installed.
StopRouter | Stops the component load balancing service on a CLB server, if the CLB service is installed.


COMAdminCatalogCollection Object

The COMAdminCatalogCollection object is a generic object used to represent any collection on the COM+ catalog. Use it to enumerate, add, remove, and retrieve items in a collection, and to access related collections. This object implements the ICatalogCollection interface.

Remarks

You use the COMAdminCatalogCollection object when you want to programmatically manipulate a collection on the COM+ catalog. These collections correspond to folders seen in the Component Services administration tool.

Items inside the folders correspond to items in collections, which you can represent using the COMAdminCatalogObject object.

For information regarding the collections on the catalog and their properties see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

For information on the properties exposed by the COMAdminCatalogCollection object, see ICatalogCollection Properties.

The COMAdminCatalogCollection object implements the ICatalogCollection interface, and provides the following methods.

Methods | Description
Add | Adds an item to the collection, and returns it as a COMAdminCatalogObject object.
GetCollection | Retrieves a related collection, and returns it as a COMAdminCatalogCollection object.
Populate | Reads in data from the catalog data store for all objects in the collection.
Remove | Removes an item from the collection given its index, and reindexes all items with higher indices.
SaveChanges | Saves pending changes made to the collection and any of its items to the catalog data store.


COMAdminCatalogObject Object

The COMAdminCatalogObject object is used to represent items in collections on the COM+ catalog. Use this object to get and put properties exposed by the item it is being used to represent. This object implements the ICatalogObject interface.

Remarks

You use the COMAdminCatalogObject object to programmatically manipulate items contained in collections on the COM+ catalog. These items correspond to items shown inside folders in the Component Services administration tool.

Collections, and folders, themselves are represented using the COMAdminCatalogCollection object.

For information regarding specific collection objects and their properties see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

For information on the properties exposed by the COMAdminCatalogObject object, see ICatalogObject Properties.

Methods | Description
IsPropertyReadOnly | Returns a Boolean indicating whether the specified property can only be read.
IsPropertyWriteOnly | Returns a Boolean indicating whether the specified property can only be set.


Administration Collections

The administration collections serve to hold and organize configuration data stored on the COM+ catalog. They correspond to folders appearing in the Component Services administration tool. You can access these collections using the COM+ administration objects and interfaces.

You initiate programmatic administration using the COMAdminCatalog object. You represent any collections on the catalog using the COMAdminCatalogCollection object. And you represent items in collections using the COMAdminCatalogObject object.

The items within a given collection will expose a consistent set of properties, corresponding to the fact that all items in a collection represent the same kind of thing; for instance every item in the Components collection represents a component, and all expose the same properties used to configure a component. These properties can be accessed using the COMAdminCatalogObject object.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

The COMAdmin Catalog data store supports the collections described in the following table.

Collections | Description
ApplicationCluster Collection | Holds a list of the server machines in the application cluster.
ApplicationPartitions Collection | Used to specify the applications contained within each partition.
Applications Collection | Contains an object for each COM+ application installed on the local machine.
Components Collection | Holds an object for each component in the related application.
ComputerList Collection | Holds a list of the machines exposed by the Component Services administration tool.
DCOMProtocols Collection | Holds a list of the protocols to be used by DCOM. It contains an object for each protocol.
ErrorInfo Collection | Retrieves extended error information regarding methods that deal with multiple objects.
InprocServers Collection | Holds a list of the in-process servers registered with the system. It contains an object for each component.
GetCollection Collection | Gets a collection related to a specific object.
InterfacesForComponent Collection | Holds an object for each interface exposed by the component to which the collection is related.
LegacyComponents Collection | Holds an object for each component in the Applications collection drawn from the 32-bit registry on 64-bit machines.
LegacyServers Collection | Identical to the InprocServers collection except that the LegacyServers collection also includes local servers.
LocalComputer Collection | Contains an object that holds computer level settings information.
LocalPartitions Collection | Used to specify the partition sets to which partitions are mapped.
LocalPartitionSets Collection | Used to specify partition sets and their properties.
LocalUsers Collection | Used to specify the partition sets to which user identities are mapped.
MethodsForInterface Collection | Holds an object for each method on the interface to which the collection is related.
PropertyInfo Collection | Retrieves information about the properties that a specified collection supports.
PublisherProperties Collection | Holds an object for each publisher property for the parent Subscription.
RelatedCollectionInfo Collection | Retrieves information about other collections related to the collection from which it is called.
Roles Collection | Holds an object for each role assigned to the application to which it is related.
RolesForComponent Collection | Holds an object for each role assigned to the component to which the collection is related.
RolesForInterface Collection | Holds an object for each role assigned to the interface to which the collection is related.
RolesForMethod Collection | Holds an object for each role assigned to the method to which the collection is related.
Root Collection | Serves as a container for the top-level collections on the catalog.
SubscriberProperties Collection | Holds an object for each subscriber property for the parent Subscription or TransientSubscription.
SubscriptionsForComponent Collection | Holds an object for each subscription for the parent Component.
TransientSubscriptions Collection | Holds an object for each transient subscription.
UsersInRole Collection | Holds an object for each user in the role to which the collection is related.
WOWInprocServers Collection | A top-level collection that holds a list of the in-process servers registered with the system for 32-bit components on 64-bit computers.
WOWLegacyServers Collection | Identical to the LegacyServers collection except that this collection is drawn from the 32-bit registry on 64-bit machines.


ApplicationCluster Collection

The ApplicationCluster collection is a top-level collection. It holds a list of the server machines in the application cluster. It contains an object for each server.

The application cluster is defined for purposes of the component load balancing (CLB) service. The CLB service must be installed on the machine for the application cluster collection to be used.

Note that you designate a router in the application cluster with the IsRouter property on the LocalComputer collection object, and designate that a given component should be load balanced with the LoadBalancingSupported property on a Components collection object.

The ApplicationCluster collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to the following collections from the ApplicationCluster collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the ApplicationCluster collection supports the following property:

Name

The name of the server. Extra spaces at the beginning and end of the string will be stripped out.

Access: | WriteOnce
Type: | String
Default: | "New Computer"

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


ApplicationPartitions Collection

The ApplicationPartitions collection is used to specify the applications contained within each partition.

Related collections

You can navigate to any of the following collections from the ApplicationPartitions collection:

Applications

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The following properties are supported by the COMAdminCatalogObject object within the ApplicationPartitions collection:

ID

Name

Description

Changeable

Deleteable

ID

A GUID representing the partition. This is used for the COMAdminCatalogObject.Key property on the object being used to represent the partition.

Access: | WriteOnce
Type: | String
Default: | <Generated>

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.

Name

This property represents the partition name. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadWrite
Type: | String
Default: | "New Partition"

Description

This property represents the description identifying the partition.

Access: | ReadWrite
Type: | String
Default: | ""

Changeable

Determines if this partition is changeable.

Access: | ReadWrite
Type: | Bool
Default: | True

Deleteable

Determines if this partition can be deleted.

Access: | ReadWrite
Type: | Bool
Default: | True


Applications Collection

The Applications collection is a top-level collection. It contains an object for each COM+ application installed on the local machine. The properties exposed by these objects hold all settings made at the application level.

You set properties for components within an application using the related Components collection. You assign roles to an application using the related Roles collection. To install components into an application use methods on the COMAdminCatalog object. To install an application from a file, or to shut down or export an application, use methods on the COMAdminCatalog object. Otherwise to create a new application you can add an object to the Applications collection.

The Applications collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the Applications collection:

Components

Roles

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the Applications collection supports the following properties:

AccessChecksLevel

Activation

ApplicationAccessChecksEnabled

ApplicationProxy

AppPartitionID

ApplicationProxy

ApplicationProxyServerName

Authentication

AuthenticationCapability

Changeable

CommandLine

ConcurrentApps

CreatedBy

CRMEnabled

CRMLogFile

Deleteable

Description

DumpEnabled

DumpOnException

DumpOnFailfast

DumpPath

EventsEnabled

ID

ImpersonationLevel

Identity

IsEnabled

IsSystem

MaxDumpCount

Name

Password

ProcessFlags

QueuingEnabled

QCAuthenticateMsgs

QCListenerMaxThreads

QueueListenerEnabled

RecycleActivationLimit

RecycleCallLimit

RecycleExpirationTimeout

RecycleLifetimeLimit

RecycleMemoryLimit

RunForever

ServiceName

ShutdownAfter

ThreadMax

3GigSupportEnabled

AccessChecksLevel

Indicates whether access checks will be performed at the only the process level, or at both the process and component level. It is advised that you use the constants in the enumeration, and not the numeric values.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminAccessChecksApplicationLevel = 0 COMAdminAccessChecksApplicationComponentLevel = 1
Default: | COMAdminAccessChecksApplicationComponentLevel

Activation

Local activation indicates that objects within the application will run within a dedicated local server process (server application). Inproc activation indicates that objects run in their creator's process (library application). It is advised that you use the constants in the enumeration, and not the numeric values.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminActivationInproc = 0 COMAdminActivationLocal = 1
Default: | COMAdminActivationLocal

ApplicationAccessChecksEnabled

Indicates whether access checks will be performed for the application when clients make calls into it.

Access: | ReadWrite
Type: | Bool
Default: | False

AppPartitionID

A GUID representing the application partition ID.

Access: | WriteOnce
Type: | String
Default: | <Generated>

ApplicationProxy

Indicates whether the application is an application proxy.

Access: | ReadOnly
Type: | Bool
Default: | False

ApplicationProxyServerName

A remote server name used when exporting the application proxy. It is this server name that the application proxy will point to when it is installed on a client machine.

Access: | ReadWrite
Type: | String
Default: | ""

Authentication

Sets authentication level for calls, with values corresponding to the Remote Procedure Call (RPC) authentication settings. When Default authentication is chosen, the setting in the DefaultAuthenticationLevel property on the LocalComputercollection object is used. Note that for library (Inproc) applications, the only valid settings here are Default and None. It is advised that you use the constants in the enumeration, and not the numeric values.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminAuthenticationDefault = 0 COMAdminAuthenticationNone = 1 COMAdminAuthenticationConnect = 2 COMAdminAuthenticationCall = 3 COMAdminAuthenticationPacket = 4 COMAdminAuthenticationIntegrity = 5 COMAdminAuthenticationPrivacy = 6
Default: | COMAdminAuthenticationPacket

AuthenticationCapability

Determines what identity will be presented when calls are impersonated.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminAuthenticationCapabilitiesNone = 0x0 COMAdminAuthenticationCapabilitiesStaticCloaking = 0x20 COMAdminAuthenticationCapabilitiesDynamicCloaking = 0x40 COMAdminAuthenticationCapabilitiesSecureReference = 0x2
Default: | COMAdminAuthenticationCapabilitiesDynamicCloaking

Changeable

Determines whether changes to the application settings or those of its components are allowed, either programmatically or through the Component Services administration tool.

Access: | ReadWrite
Type: | Bool
Default: | True

CommandLine

A command line string for use in debugging. The application can be launched in a debugger with the specified command line.

Access: | ReadWrite
Type: | String
Default: | ""

ConcurrentApps

Specifies the maximum number of poolable applications that can run concurrently.

Access: | ReadWrite
Type: | Long
Value: | 1 - 1048576
Default: | 1

CreatedBy

Informational string to describe who created the application.

Access: | ReadWrite
Type: | String
Default: | “”

CRMEnabled

Determines whether the Compensating Resource Manager is enabled.

Access: | ReadWrite
Type: | Bool
Default: | False

CRMLogFile

Name and path of file for keeping the log for the compensating resource manager.

Access: | ReadWrite
Type: | String
Default: | “”

Deleteable

Sets whether the application can be deleted, either programmatically or through the Component Services administration tool.

Access: | ReadWrite
Type: | Bool
Default: | True

Description

Describes the Application.

Access: | ReadWrite
Type: | String
Default: | “”

DumpEnabled

Reserved for future use.

Access: | ReadWrite
Type: | Bool
Default: | False

DumpOnException

Reserved for future use.

Access: | ReadWrite
Type: | Bool
Default: | False

DumpOnFailfast

Enables the dump of the state of a COM+ application when the application fails.

Access: | ReadWrite
Type: | Bool
Default: | False

DumpPath

The path of the directory in which the dump files will be saved.

Access: | ReadWrite
Type: | String
Default: | “%systemroot%\system32\com\dmp”

EventsEnabled

Indicates whether events are enabled for the application.

Access: | ReadWrite
Type: | Bool
Default: | True

ID

A GUID representing the application. This is used for the COMAdminCatalogObject.Key property on the object being used to represent the application.

Access: | WriteOnce
Type: | String
Default: | <Generated>

Identity

Sets the server process identity for the application. Specify a valid Windows 2000 user account or “Interactive User” to have the application assume the identity of the current logged-on user. This is not enabled for library applications, which run in the client process. Note that the Password property below should be set at the same time as Identity, prior to using SaveChanges, as the password and identity will be validated prior to being saved. If the password and identity get out of sync the application cannot be launched until they are reset by an administrator.

Access: | ReadWrite
Type: | String
Default: | “InteractiveUser”

IsEnabled

If a COM+ application or component is disabled, the disable property is enabled and IsEnabled is True. If the application or component is not disabled, IsEnabled is False.

Access: | ReadWrite
Type: | Bool
Default: | True

ImpersonationLevel

Sets impersonation level used for calls made to other applications.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminImpersonationAnonymous = 1 COMAdminImpersonationIdentify = 2 COMAdminImpersonationImpersonate = 3 COMAdminImpersonationDelegate = 4
Default: | COMAdminImpersonationImpersonate

IsSystem

Identifies COM+ system applications.

Access: | ReadOnly
Type: | Bool
Default: | False

MaxDumpCount

Indicates the maximum number of files to be generated before overwriting occurs.

Access: | ReadWrite
Type: | String
Default: | “5”

Name

The name of the application. This is used for the COMAdminCatalogObject.Name property on the object being used to represent the application. Extra spaces at the beginning and end of the string will be stripped out.

Unique names should be chosen for applications. If multiple applications are created with the same name, it can interfere with referencing the applications by name, potentially resulting in unpredictable behavior.

Access: | ReadWrite
Type: | String
Default: | “New Application”

Password

Sets the password used by the server process to log on under the identity above. Note that Password should be set at the same time as Identity, prior to using SaveChanges. (See the information under Identity regarding keeping these in sync.)

Access: | WriteOnly
Type: | String
Default: | “”

ProcessFlags

Access: | ReadWrite
Type: | Long
Value: | 0 – 65000
Default: | 0

QCAuthenticateMsgs

Indicates whether to disassociate QC message authentication from role-based security.

Access: | ReadWrite
Type: | Bool
Default: | True

QCListenerMaxThreads

Indicates the maximum number of concurrent threads. The valid range for this property is 0 to 1000. For a newly created application, the setting is derived from the algorithm currently used for determining the default number of listener threads: 16 times the number of CPUs in the server.

Note COM+ no longer reads the following registry key: HKLM\Software\Microsoft\COM3\Debug\QCListenerMaxThread.

Access: | ReadWrite
Type: | Integer
Value: | 0 - 1000
Default: | 0

This property is also available with read/write capability from the Queuing tab of the Component Services administrative tool's property pages.

For more information about QCListernerMaxThreads, see Setting the Maximum Number of Threads in the Component Services Administrator's Guide.

QueuingEnabled

Indicates whether queued components is enabled for the application.

Access: | ReadWrite
Type: | Bool
Default: | False

QueueListenerEnabled

Indicates whether the queued components listener is enabled for the application. If it is enabled, it will be launched when the application starts. This property only takes effect if QueuingEnabled is set to True.

Access: | ReadWrite
Type: | Bool
Default: | False

RecycleActivationLimit

Indicates the maximum number of activations of configured objects in the application to accept before recycling the process. The default number of activations is 0.

Access: | ReadWrite
Type: | Long
Value: | 0 - 1048576
Default: | 0

RecycleCallLimit

Indicates the maximum number of calls to allow configured objects in the application to accept before recycling the process. The default number of calls is 0.

Access: | ReadWrite
Type: | Long
Value: | 0 - 1048576
Default: | 0

RecycleExpirationTimeout

Indicates the amount of time (in minutes) to allow a recycled process to run before shutting it down. The countdown begins immediately after the process is recycled. The default expiration time-out is 15 minutes.

Access: | ReadWrite
Type: | Long
Value: | 0 - 1048576
Default: | 15

RecycleLifetimeLimit

Indicates the maximum number of minutes to allow a process to run before recycling it. The default number of minutes is 0.

Access: | ReadWrite
Type: | Long
Value: | 0 - 1048576
Default: | 0

RecycleMemoryLimit

Indicates the maximum amount of memory usage (in kilobytes) allowed a process before it's recycled. If the process's memory usage exceeds the specified number for a period longer than one minute, the process is recycled. The default amount of memory usage is 0 KB.

Access: | ReadWrite
Type: | Long
Value: | 0 - 1048576
Default: | 0

RunForever

Enables a server process to continue if an application is idle. If set to True, the server process will not shut down when left idle. If set to False the process will shut down according the value set by the ShutDownAfter property. RunForever is not enabled for library (Inproc) applications.

Access: | ReadWrite
Type: | Bool
Default: | False

ServiceName

The service name corresponding to the application configured to run as an NT service. If this value is NULL, the application is not configured to run as an NT service. Otherwise, the configuration information for the service can be found by using the service name.

Access: | ReadOnly
Type: | String
Default: | ""

ShutdownAfter

Sets the delay before shutting down a server process after it becomes idle. Shutdown latency ranges from 0 to 1440 minutes. If RunForever is set to True, this property will be ignored. ShutdownAfter is not enabled for library (Inproc) applications.

Access: | ReadWrite
Type: | Long
Values: | 0-1440
Default: | 3

ThreadMax

Indicates the maximum number of threads running on a single process. ThreadMax takes advantage of object pooling's number range. The default value is 0.

Access: | ReadWrite
Type: | Long
Value: | 0 - 1048576
Default: | 0

3GigSupportEnabled

Indicates whether the application can use 3GB of memory in its process. If this is not enabled, the application will only be able to use 2GB of memory.

Access: | ReadWrite
Type: | Bool
Default: | False

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


Components Collection

The Components collection is always related to an object in the Applications collection. It holds an object for each component in the related application. The properties exposed by these objects hold settings made at the component level.

Note that you assign roles to a component using the related RolesForComponent collection, and can examine the interfaces exposed by a component using the related InterfacesForComponent collection.

The Components collection supports the Remove method but not the Add method on the COMAdminCatalogCollection object. To install or import components into an application, use methods on the COMAdminCatalog object.

Related collections

You can navigate to any of the following collections from the Components collection:

InterfacesForComponent

RolesForComponent

SubscriptionsForComponent

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the Components collection supports the following properties:

AllowInprocSubscribers

ApplicationID

CLSID

ComponentAccessChecksEnabled

ComponentTransactionTimeout

ComponentTransactionTimeoutEnabled

COMTIIntrinsics

ConstructionEnabled

ConstructorString

CreationTimeout

Description

DLL

EventTrackingEnabled

ExceptionClass

FireInParallel

IISIntrinsics

IsEnabled

IsEventClass

IsPrivateComponent

JustInTimeActivation

LoadBalancingSupported

MaxPoolSize

MinPoolSize

MultiInterfacePublisherFilterCLSID

MustRunInClientContext

MustRunInDefaultContext

ObjectPoolingEnabled

ProgID

PublisherID

Synchronization

ThreadingModel

Transaction

TxIsolationLevel

VersionBuild

VersionMajor

VersionMinor

VersionSubBuild

AllowInprocSubscribers

Enables in process subscribers, if the component is an event class.

Access: | ReadWrite
Type: | Bool
Default: | True

ApplicationID

The GUID for the application containing the component. Must be a valid application's GUID; this will be verified prior to being saved when SaveChanges is called. If this value is changed to be a GUID for a different application, the component will move to that application.

Access: | ReadWrite
Type: | String
Default: | N/A

CLSID

A GUID for the component. This is used for the COMAdminCatalogObject.Key property on the object being used to represent the component.

Access: | ReadOnly
Type: | String
Default: | N/A

ComponentAccessChecksEnabled

Indicates whether role-based access checks will be performed on calls into the component. Works in conjunction with the AccessChecksLevel and ApplicationAccessChecksEnabled properties on the application.

Access: | ReadWrite
Type: | Bool
Default: | True

ComponentTransactionTimeout

When using transactions, the time period in which a transaction times out can be specified. The default is 60 seconds and cannot be longer than 3600 seconds. The time-out value can be set to 0, specifying an infinite transaction time-out period.

Access: | ReadWrite
Type: | Long
Values: | 0-3600
Default: | 60

ComponentTransactionTimeoutEnabled

Specifies if the transaction time-out period is enabled. By default the transaction time-out feature is disabled.

Access: | ReadWrite
Type: | Bool
Default: | False

COMTIIntrinsics

Enables passing of IIS context properties, such as the application and user session object, into the context for this class.

Access: | ReadWrite
Type: | Bool
Default: | False

ConstructionEnabled

Determines whether the ConstructorString will be passed to the object when it is constructed.

Access: | ReadWrite
Type: | Bool
Default: | False

ConstructorString

Initialization string for component construction. You can create different objects from the same generic component using object constructor strings. If ConstructionEnabled is False this will be ignored.

Access: | ReadWrite
Type: | String
Default: | ""

CreationTimeout

Number of seconds before time-out when creating the object.

Access: | ReadWrite
Type: | Long
Values: | 0 – 2147483647
Default: | 0

Description

Describes the component.

Access: | ReadWrite
Type: | String
Default: | ""

DLL

The name and path of the file containing the component.

Access: | ReadOnly
Type: | String
Default: | N/A

EventTrackingEnabled

Determines whether Events will be tracked. Events include actions such as application shutdown; object creation and release; object references, consistency, activation, and deactivation; method calls, returns, and exceptions; transaction startup, preparing to commit, and abort; resource dispenser connection, allocation, and recycling; thread allocation and recycling.

Access: | ReadWrite
Type: | Bool
Default: | True

ExceptionClass

The CLSID, which can be a GUID or a moniker string, to activate an alternative program during the process of dealing with a repeatedly failing QC program.

Access: | ReadWrite
Type: | String
Default: | ""

FireInParallel

Enables events to be fired in parallel, if the component is an event class.

Access: | ReadWrite
Type: | Bool
Default: | False

IISIntrinsics

Enables passing of IIS context properties, such as an application session object or user session object, into the context for this class.

Access: | ReadWrite
Type: | Bool
Default: | False

IsEnabled

If a COM+ application or component is disabled, the disable property, IsEnabled, is enabled and set to True. If the application or component is not disabled, the IsEnabled property is set to False.

Access: | ReadWrite
Type: | Bool
Default: | True

IsEventClass

Indicates whether the component is an event class.

Access: | ReadOnly
Type: | Bool
Default: | False

IsPrivateComponent

Determines whether a server application is a private component. A private component in a server application can be activated only from within the application. For example, if you call CoCreateInstance() on a private component, it will fail from out-of-process but succeed in-process. In contrast, if you call CoCreateInstance() on a public component, it will succeed both in-process and out-of-process.

Access: | ReadWrite
Type: | Bool
Default: | False

JustInTimeActivation

Determines whether JIT Activation is enabled for the component. This property will be set to True when the Transaction support is set to Required, Requires New or Supported. When JustInTimeActivation is set to True, Synchronization must be set to Required or Requires New (it will default to Required).

Access: | ReadWrite
Type: | Bool
Default: | False

LoadBalancingSupported

Determines whether the component will participate in load balancing if the component load balancing service is installed and enabled on the server.

Access: | ReadWrite
Type: | Bool
Default: | False

MaxPoolSize

Maximum number of objects pooled.

Access: | ReadWrite
Type: | Long
Values: | 0 - 1048576
Default: | 1048576

MinPoolSize

Minimum number of objects pooled.

Access: | ReadWrite
Type: | Long
Values: | 0 – 1048576
Default: | 0

MultiInterfacePublisherFilterCLSID

CLSID for the publisher filter used, if the component is an event class.

Access: | ReadWrite
Type: | String
Default: | N/A

MustRunInClientContext

Indicates that component must be activated in its original caller's context, otherwise activation fails.

Access: | ReadWrite
Type: | Bool
Default: | False

MustRunInDefaultContext

Indicates that the component must be activated in the default caller's context; otherwise, activation fails.

Access: | ReadWrite
Type: | Bool
Default: | False

ObjectPoolingEnabled

Determines whether object pooling is enabled for the component.

Access: | ReadWrite
Type: | Bool
Default: | False

ProgID

A friendly name used for identifying the component.

Access: | ReadOnly
Type: | String
Default: | N/A

PublisherID

Identifier for the event publisher, if the component is an event class.

Access: | ReadOnly
Type: | String
Default: | ""

Synchronization

Determines call synchronization for the component.

Access: | ReadWrite
Type: | Long
Values: | COMAdminSynchronizationIgnored = 0 COMAdminSynchronizationNone = 1 COMAdminSynchronizationSupported = 2 COMAdminSynchronizationRequired = 3 COMAdminSynchronizationRequiresNew = 4
Default: | COMAdminSynchronizationIgnored

ThreadingModel

Determines how instances of the component are assigned to threads for method execution. Values correspond to COM threading models. It is advised that you use the constants in the enumeration, and not the numeric values. Note that you must change the threading model of a configured component with this property, and not directly in the registry. Threading model changes made directly in the registry will not be picked up dynamically in the RegDB, and the component will not work as expected.

Access: | ReadOnly
Type: | Long
Enum: | COMAdminThreadingModelApartment = 0 COMAdminThreadingModelFree = 1 COMAdminThreadingModelMain = 2 COMAdminThreadingModelBoth = 3 COMAdminThreadingModelNeutral = 4
Default: | N/A

Transaction

Determines how a component supports transactions. It is advised that you use the constants in the enumeration, and not the numeric values.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminTransactionIgnored = 0 COMAdminTransactionNone = 1 COMAdminTransactionSupported = 2 COMAdminTransactionRequired = 3 COMAdminTransactionRequiresNew = 4
Default: | COMAdminTransactionIgnored

TxIsolationLevel

Indicates the transaction isolation levels. There are five isolation levels: none, read uncommitted, read committed, repeatable read, and serialized. The default isolation level is serialized.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminTxIsolationLevelNone = 0 COMAdminTxIsolationLevelReadUnCommitted = 1 COMAdminTxIsolationLevelReadCommitted = 2 COMAdminTxIsolationLevelRepeatableRead = 3 COMAdminTxIsolationLevelSerializable = 4
Default: | COMAdminTxIsolationLevelSerializable

VersionBuild

Version build identifier.

Access: | ReadOnly
Type: | DWORD
Default: | ""

VersionMajor

Version identifier.

Access: | ReadOnly
Type: | DWORD
Default: | ""

VersionMinor

Version sub-identifier.

Access: | ReadOnly
Type: | DWORD
Default: | ""

VersionSubBuild

Version sub-build identifier.

Access: | ReadOnly
Type: | DWORD
Default: | ""


ComputerList Collection

The ComputerList collection is a top-level collection. It holds a list of the machines exposed by the Component Services administration tool. It contains an object for each machine.

The ComputerList collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

However, you cannot remove "My Computer."

Related collections

You can navigate to any of the following collections from the ComputerList collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the ComputerList collection supports the following property:

Name

The name of the computer. Extra spaces at the beginning and end of the string will be stripped out.

Access: | WriteOnce
Type: | String
Default: | "New Computer"

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


DCOMProtocols Collection

The DCOMProtocols collection is a top-level collection. It holds a list of the protocols to be used by DCOM. It contains an object for each protocol.

The DCOMProtocols collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the DCOMProtocols collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the DCOMProtocols collection supports the following properties:

Name

Order

ProtocolCode

Name

The name of the protocol.

Access: | WriteOnce
Type: | String
Default: | "New Protocol"

Order

The order in which to try the protocol.

Access: | ReadWrite
Type: | Long
Values: | 0 – 65000
Default: | 0

ProtocolCode

The lettercode for the protocol. Must be a valid lettercode.

Access: | ReadWrite
Type: | String
Default: | ""

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


ErrorInfo Collection

The ErrorInfo collection is used to retrieve extended error information regarding methods that deal with multiple objects, such as Populate and SaveChanges on the COMAdminCatalogCollection object, and methods to install, import or export applications or components on the COMAdminCatalog object.

Use the GetCollection method on a COMAdminCatalogCollection to access the ErrorInfo collection associated with the original collection. The ErrorInfo collection is accessible from any collection except ErrorInfo, RelatedCollectionInfo, PropertyInfo, and InprocServers.

The ErrorInfo collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Note that you must call GetCollection on ErrorInfo immediately after an error occurs, otherwise error information will be lost.

Related collections

You can navigate to any of the following collections from the ErrorInfo collection:

RelatedCollectionInfo

PropertyInfo

Properties

The COMAdminCatalogObject object within the ErrorInfo collection supports the following properties:

MajorRef

MinorRef

Name

ErrorCode

MajorRef

The key value for the object which had an error, if applicable. For instance, if a SaveChanges for a collection failed on a particular object in the collection, the key value for that object will be the MajorRef. In contexts where the key value doesn't apply, MajorRef will be the same as Name. Use this to look at the item that failed update, or to find the component or dll that failed to install.

Access: | ReadOnly
Type: | String
Default: | None

MinorRef

A precise specification of the item which had an error, such as a property name. If multiple errors occurred, or in contexts in which this doesn't apply, MinorRef will be <Invalid>.

Access: | ReadOnly
Type: | String
Default: | None

Name

The name of the object or file which had an error.

Access: | ReadOnly
Type: | String
Default: | None

ErrorCode

The error code for the object or file.

Access: | ReadOnly
Type: | String
Default: | None


InprocServers Collection

The InprocServers collection is a top-level collection. It holds a list of the in-process servers registered with the system. It contains an object for each component.

The InprocServers collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the InprocServers collection:

RelatedCollectionInfo

PropertyInfo

Properties

The COMAdminCatalogObject objects within the InprocServers collection support the following properties:

CLSID

InprocServer32

ProgID

CLSID

A GUID for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

InprocServer32

The file path for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

ProgID

A name identifying the component.

Access: | ReadOnly
Type: | String
Default: | N/A


InterfacesForComponent Collection

The InterfacesForComponent collection holds an object for each interface exposed by the component to which the collection is related.

The InterfacesForComponent collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the InterfacesForComponent collection:

MethodsForInterface

RolesForInterface

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the InterfacesForComponent collection supports the following properties:

CLSID

Description

IID

Name

QueuingEnable

QueuingSupported

CLSID

A GUID for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

Description

A description for the interface.

Access: | ReadWrite
Type: | String
Default: | ""

IID

A GUID for the interface.

Access: | ReadOnly
Type: | String
Default: | N/A

Name

A name for the interface.

Access: | ReadOnly
Type: | String
Default: | N/A

QueuingEnabled

Queuing Enabled marks the interface as "queuable", and can be set by the Admin SDK or Component Services administrative tool. However, only an interface that has the Queuing Supported flag set can have the Queuing Enabled flag set.

Access: | ReadWrite
Type: | Bool
Default: | False

QueuingSupported

The interface supports queuing. For an interface to support queuing all methods should only have in parameters. Queuing Supported is exposed through the SDK as a read only property.

Access: | ReadOnly
Type: | Bool
Default: | False


LegacyComponents Collection

The LegacyComponents collection holds an object for each component in the Applications collection drawn from the 32-bit registry on 64-bit machines. The properties exposed by these objects hold settings made at the component level.

The LegacyComponents collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the LegacyComponents collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The following properties are supported by the COMAdminCatalogObject object within the LegacyComponents collection:

AccessPermissions

ActivateAtStorage

AppID

AppName

AuthenticationLevel

CLSID

ClassName

DllSurrogate

InprocHandler32

InprocServer32

IsEnabled

LaunchPermissions

LocalServer32

LocalService

Password

ProgID

RemoteServer

RunAs

ServiceParameters

ThreadingModel

AccessPermissions

Access: | ReadOnly
Type: | String
Default: | N/A

ActivateAtStorage

Access: | ReadOnly
Type: | String
Default: | N/A

AppID

The application ID.

Access: | ReadOnly
Type: | String
Default: | N/A

AppName

The name of the application.

Access: | ReadOnly
Type: | String
Default: | N/A

AuthenticationLevel

Authentication level used by applications that have Authentication set to Default. Values correspond to the Remote Procedure Call (RPC) authentication settings.

Note Default is not a valid setting here; a nonzero value must be set. It is advised that you use the constants in the enumeration, and not the numeric values.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminAuthenticationNone = 1 COMAdminAuthenticationConnect = 2 COMAdminAuthenticationCall = 3 COMAdminAuthenticationPacket = 4 COMAdminAuthenticationIntegrity = 5 COMAdminAuthenticationPrivacy = 6
Default: | COMAdminAuthenticationConnect

CLSID

A GUID for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

ClassName

The name of the class.

Access: | ReadOnly
Type: | String
Default: | N/A

DllSurrogate

Access: | ReadOnly
Type: | String
Default: | N/A

InprocHandler32

Access: | ReadOnly
Type: | String
Default: | N/A

InprocServer32

The file path for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

IsEnabled

If the COM+ application or component is disabled, IsEnabled is False. If the COM+ application or component is enabled, IsEnabled is True.

Access: | ReadWrite
Type: | Bool
Default: | True

LaunchPermissions

Access: | ReadOnly
Type: | String
Default: | N/A

LocalServer32

Specifies the full path to a 32-bit local server application.

Access: | ReadOnly
Type: | String
Default: | N/A

LocalService

Access: | ReadOnly
Type: | String
Default: | N/A

Password

Sets the password used by the server process to log on under the specified identity. Password should be set at the same time as Identity, prior to using SaveChanges.

Access: | WriteOnly
Type: | String
Default: | ""

ProgID

A name identifying the component.

Access: | ReadOnly
Type: | String
Default: | N/A

RemoteServer

Access: | ReadOnly
Type: | String
Default: | N/A

RunAs

Access: | ReadOnly
Type: | String
Default: | N/A

ServiceParameters

Access: | ReadOnly
Type: | String
Default: | N/A

ThreadingModel

Determines how instances of the component are assigned to threads for method execution. Values correspond to COM threading models. It is advised that you use the constants in the enumeration, and not the numeric values.

Note You must change the threading model of a configured component with this property, and not directly in the registry. Threading model changes made directly in the registry will not be picked up dynamically in the RegDB, and the component will not work as expected.

Access: | ReadOnly
Type: | Long
Enum: | COMAdminThreadingModelApartment = 0 COMAdminThreadingModelFree = 1 COMAdminThreadingModelMain = 2 COMAdminThreadingModelBoth = 3 COMAdminThreadingModelNeutral = 4
Default: | N/A


LegacyServers Collection

Exposed properties for the LegacyServers collection are intended to be identical to the InprocServers collection except that the LegacyServers collection also includes local servers.

Related collections

You can navigate to any of the following collections from the LegacyServers collection:

RelatedCollectionInfo

PropertyInfo

Properties

The following properties are supported by the COMAdminCatalogObject objects within the LegacyServers collection:

ClassName

CLSID

InprocServer32

LocalServer32

ProgID

ClassName

The name of the class.

Access: | ReadOnly
Type: | String
Default: | N/A

CLSID

A GUID for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

InprocServer32

The file path for the component.

Access: | ReadOnly
Type: | None
Default: | N/A

LocalServer32

Specifies the full path to a 32-bit local server application.

Access: | ReadOnly
Type: | None
Default: | N/A

ProgID

A name identifying the component.

Access: | ReadOnly
Type: | String
Default: | N/A


LocalComputer Collection

The LocalComputer collection is a top-level collection. It contains a single object that corresponds to the computer whose catalog you are accessing. This object holds computer level settings information. If you call the Connect method on the COMAdminCatalog object, the object in the LocalComputer collection will contain information about the remote computer whose catalog you are accessing.

The LocalComputer collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Example

The following Visual Basic example demonstrates how to get the computer name of a remote computer by using the LocalComputer collection. To use this example, add the COM + 1.0 Admin Type Library as a reference to your Visual Basic project:

Private Sub Command1_Click()
       Dim oCat As New COMAdminCatalog
       Dim oLocalComputerCol As COMAdminCatalogCollection
       Dim oLocalComputerItem As COMAdminCatalogObject

       oCat.Connect "Windows2000ComputerName"
       Set oLocalComputerCol = oCat.GetCollection("LocalComputer")
       oLocalComputerCol.Populate
       Set oLocalComputerItem = oLocalComputerCol.Item(0)
       MsgBox oLocalComputerItem.Value("Name")

       Set oLocalComputerItem = Nothing
       Set oLocalComputerCol = Nothing
       Set oCat = Nothing
End Sub

Related collections

You can navigate to any of the following collections from the LocalComputer collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the LocalComputer collection supports the following properties:

ApplicationProxyRSN

CISEnabled

DCOMEnabled

DefaultAuthenticationLevel

DefaultImpersonationLevel

DefaultToInternetPorts

Description

InternetPortsListed

IsRouter

LoadBalancingCLSID

LocalPartitionLookupEnabled

Name

OperatingSystem

Ports

ResourcePoolingEnabled

RPCProxyEnabled

SecureReferencesEnabled

SecurityTrackingEnabled

TransactionTimeout

ApplicationProxyRSN

Remote server name used by application proxies by default.

Access: | ReadWrite
Type: | String
Default: | ""

CISEnabled

Indicates that COM Internet Services are enabled.

Access: | ReadWrite
Type: | Bool
Default: | True

DCOMEnabled

Set to true to enable DCOM on the machine.

Access: | ReadWrite
Type: | Bool
Default: | True

DefaultAuthenticationLevel

Authentication level used by applications that have Authentication set to Default. Values correspond to the Remote Procedure Call (RPC) authentication settings. Note that Default is not a valid setting here; a non-zero value must be set. It is advised that you use the constants in the enumeration, and not the numeric values.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminAuthenticationNone = 1 COMAdminAuthenticationConnect = 2 COMAdminAuthenticationCall = 3 COMAdminAuthenticationPacket = 4 COMAdminAuthenticationIntegrity = 5 COMAdminAuthenticationPrivacy = 6
Default: | COMAdminAuthenticationConnect

DefaultImpersonationLevel

Imersonation level to allow if one is not set. Note that Default is not a valid setting here; a non-zero value must be set. It is advised that you use the constants in the enumeration, and not the numeric values.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminImpersonationAnonymous = 1 COMAdminImpersonationIdentify = 2 COMAdminImpersonationImpersonate = 3 COMAdminImpersonationDelegate = 4
Default: | COMAdminImpersonationIdentify

DefaultToInternetPorts

Determines whether the default type of port provided should be Internet (True) or Intranet (False).

Access: | ReadWrite
Type: | Bool
Default: | True

Description

Description of the computer.

Access: | ReadWrite
Type: | String
Default: | ""

InternetPortsListed

Determines whether the ports listed in the Ports property are to be used for Internet (True) or for Intranet (False).

Access: | ReadWrite
Type: | Bool
Default: | True

IsRouter

Set to true if the machine is a router for the component load balancing (CLB) service. This property can only be set to true if the component load balancing service is currently installed on the machine, otherwise it will error with COMADMIN_E_REQUIRES_DIFFERENT_PLATFORM.

If this property is set to true, the CLB server will be configured and will start at startup. The server will be added to the ApplicationCluster if it is not already present.

Access: | ReadWrite
Type: | Bool
Default: | False

LoadBalancingCLSID

Represents the CLSID of the object to balance.

Access: | ReadWrite
Type: | String
Default: | NULL

LocalPartitionLookupEnabled

Indicates whether the user of the partition mappings is checked into the local store.

Access: | ReadWrite
Type: | Bool
Default: | False

Name

The name of the computer. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadOnly
Type: | String
Default: | "My Computer"

OperatingSystem

The operating system installed on the server.

Access: | ReadWrite
Type: | Long
Enum: | COMAdminOSWindows3_1 = 1 COMAdminOSWindows9x = 2 COMAdminOSWindowsNT = 3 COMAdminOSWindowsNTEnterprise = 4
Default: |

Ports

A string describing ports that are for either internet or intranet use, depending on the InternetPortsListed property. For example: "500-599: 600-800".

Access: | ReadWrite
Type: | String
Default: | ""

ResourcePoolingEnabled

Enables use of resource dispensers.

Access: | ReadWrite
Type: | Bool
Default: | True

RPCProxyEnabled

Controls whether the RPC IIS proxy is enabled. The RPC IIS proxy is used in conjunction with IIS to forward calls to the RPC mechanism from IIS and is one of the core pieces of COM Internet Services, which is related to CISEnabled. For more information on RPCProxyEnabled, see HTTP RPC Security.

Access: | ReadWrite
Type: | Bool
Default: | False

SecureReferencesEnabled

Enforces in DCOM machines that cross-process calls to IUnknown::AddRef and IUnknown::Release methods are secured.

Access: | ReadWrite
Type: | Bool
Default: | False

SecurityTrackingEnabled

Set to true if security tracking is enabled on objects.

Access: | ReadWrite
Type: | Bool
Default: | True

TransactionTimeout

If you are doing numerous operations within a transaction, it's advisable to set the appropriate transaction time-out period to a sufficient value in seconds.

Access: | ReadWrite
Type: | Long
Values: | 0-3600
Default: | 60


LocalPartitions Collection

The LocalPartitions collection is used to specify the partition sets to which partitions are mapped. This collection is used only when partition sets are mapped to local users and not to remote users in the domain.

Related collections

You can navigate to any of the following collections from the LocalPartitions collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The following properties are supported by the COMAdminCatalogObject object within the LocalPartitions collection:

ID

PartitionSetID

Name

Description

ID

This property represents the partition GUID.

Access: | WriteOnce
Type: | String
Default: | "{00000000-0000-0000-0000-000000000000}"

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.

PartitionSetID

A GUID representing the partition set.

Access: | WriteOnce
Type: | String
Default: | NULL

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.

Name

This property represents the partition set name. Extra spaces at the beginning and end of the string will be stripped out.

Access: | WriteOnce
Type: | String
Default: | ""

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.

Description

Not yet implemented.

Access: | ReadOnly
Type: | None
Default: | ""


LocalPartitionSets Collection

The LocalPartitionSets collection is used to specify partition sets and their properties. This collection is used only when partition sets are mapped to local users and not to remote users in the domain.

Related collections

You can navigate to any of the following collections from the LocalPartitionSets collection:

LocalPartitions

LocalUsers

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the LocalPartitionSets collection supports the following properties:

ID

Name

Description

DefaultPartition

ID

A GUID representing the partition set.

Access: | WriteOnce
Type: | String
Default: | <Generated>

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.

Name

This property represents the partition set name. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadWrite
Type: | String
Default: | "New Partition Set"

Description

Not yet implemented.

Access: | ReadWrite
Type: | None
Default: | ""

DefaultPartition

The GUID representing the default partition.

Access: | ReadWrite
Type: | String
Default: | "{41E90F3E-56C1-4633-81C3-6E8BAC8BDD70}"


LocalUsers Collection

The LocalUsers collection is used to specify the partition sets to which user identities are mapped. This collection is used only when partition sets are mapped to local users and not to remote users in the domain.

Related collections

You can navigate to any of the following collections from the LocalUsers collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The following properties are supported by the COMAdminCatalogObject object within the LocalUsers collection:

UserID

UserName

PartitionSetID

UserID

The GUID representing the user.

Access: | WriteOnce
Type: | String
Default: | <Generated>

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.

UserName

This property represents the user name. Extra spaces at the beginning and end of the string will be stripped out.

Access: | WriteOnce
Type: | String
Default: | "New User"

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.

PartitionSetID

A GUID representing the partition set.

Access: | ReadWrite
Type: | String
Default: | <Generated>


MethodsForInterface Collection

The MethodsForInterface collection holds an object for each method on the interface to which the collection is related.

The MethodsForInterface collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the MethodsForInterface collection:

RolesForMethod

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the MethodsForInterface collection supports the following properties:

AutoComplete

CLSID

Description

IID

Index

Name

AutoComplete

Determines whether the object will automatically be deactivated when the method completes, without SetComplete or SetAbort necessarily having been called. This only affects the default setting of the JIT Activation "Done" bit at method start; this bit can be reset (as with SetComplete or SetAbort) within the method to override the default.

Access: | ReadWrite
Type: | Bool
Default: | False

CLSID

A GUID for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

Description

A description of the method.

Access: | ReadWrite
Type: | String
Default: | None

IID

A GUID for the interface.

Access: | ReadOnly
Type: | String
Default: | N/A

Index

The method dispatch identifier.

Access: | ReadOnly
Type: | DWORD
Default: | None

Name

The method name.

Access: | ReadOnly
Type: | String
Default: | N/A


PropertyInfo Collection

The PropertyInfo collection is used to retrieve information about the properties that a specified collection supports. The PropertyInfo collection is accessible from any COMAdminCatalogCollection object by using the GetCollection method. The PropertyInfo collection will contain one object for each property that is supported by the original collection.

The PropertyInfo collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the PropertyInfo collection:

RelatedCollectionInfo

PropertyInfo

Properties

The COMAdminCatalogObject object within the PropertyInfo collection supports the following property:

Name

The name of the property.

Access: | ReadOnly
Type: | String
Default: | None


PublisherProperties Collection

The PublisherProperties collection holds an object for each publisher property for the parent Subscription.

The PublisherProperties collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the PublisherProperties collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the PublisherProperties collection supports the following properties.

Name

Value

Name

Name of the property. Extra spaces at the beginning and end of the string will be stripped out.

Access: | WriteOnce
Type: | String
Default: | "New Property"

Value

A value for the property.

Access: | ReadWrite
Type: | Variant
Default: | N/A

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


RelatedCollectionInfo Collection

The RelatedCollectionInfo collection is used to retrieve information about other collections related to the collection from which it is called. The RelatedCollectionInfo collection is accessible from any COMAdminCatalogCollection object by using the GetCollection method. The RelatedCollectionInfo collection will contain one object for each collection that is accessible from the original collection. Related collections follow the Component Services administration tool collection hierarchy.

The RelatedCollectionInfo collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the RelatedCollectionInfo collection:

RelatedCollectionInfo

PropertyInfo

Properties

The COMAdminCatalogObject object within the RelatedCollectionInfo collection supports the following property:

Name

The name of the related collection.

Access: | ReadOnly
Type: | String
Default: | None


Roles Collection

The Roles collection is always related to an object in the Applications collection. It holds an object for each role assigned to the application to which it is related.

The Roles collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the Roles collection:

UsersInRole

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the Roles collection supports the following properties:

Description

Name

Description

A description of the role.

Access: | ReadWrite
Type: | String
Default: | None

Name

The role name. This is used for the COMAdminCatalogObject.Name and COMAdminCatalogObject.Key properties on the object being used to represent the role. Extra spaces at the beginning and end of the string will be stripped out.

Access: | WriteOnce
Type: | String
Default: | "New Role"

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


RolesForComponent Collection

The RolesForComponent collection holds an object for each role assigned to the component to which the collection is related. The roles must already be assigned at the application level.

The RolesForComponent collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the RolesForComponent collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the RolesForComponent collection supports the following property:

Name

The role name. Must already be a role assigned to the application (appearing the Roles collection). This is used for the COMAdminCatalogObject.Name and COMAdminCatalogObject.Key properties on the object being used to represent the role. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadWrite
Type: | String
Default: | "New Role"


RolesForInterface Collection

The RolesForInterface collection holds an object for each role assigned to the interface to which the collection is related. The roles must already be assigned at the application level.

The RolesForInterface collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the RolesForInterface collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The following property is supported by the COMAdminCatalogObject object within the RolesForInterface collection:

Name

The role name. Must already be a role assigned to the application (appearing the Roles collection). This is used for the COMAdminCatalogObject.Name and COMAdminCatalogObject.Key properties on the object being used to represent the role. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadWrite
Type: | String
Default: | "New Role"


RolesForMethod Collection

The RolesForMethod collection holds an object for each role assigned to the method to which the collection is related. The roles must already be assigned at the application level.

The RolesForMethod collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the RolesForMethod collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject objects within the RolesForMethod collection support the following property:

Name

The role name. Must already be a role assigned to the application (appearing the Roles collection). This is used for the COMAdminCatalogObject.Name and COMAdminCatalogObject.Key properties on the object being used to represent the role. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadWrite
Type: | String
Default: | "New Role"


Root Collection

The Root collection serves as a container for the top-level collections on the catalog. It does not contain any COMAdminCatalogObject objects or support any properties.

The Root collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

The following are the top-level collections on the catalog accessible from the Root collection:

Applications

ComputerList

ApplicationCluster

LocalComputer

InprocServers

DCOMProtocols

TransientSubscriptions

RelatedCollectionInfo

PropertyInfo

WOWInprocServers

ApplicationPartitions

LocalPartitionSets

LegacyServers

WOWLegacyServers


SubscriberProperties Collection

The SubscriberProperties collection holds an object for each subscriber property for the parent SubscriptionsForComponent or TransientSubscriptions.

The SubscriberProperties collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the SubscriberProperties collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the SubscriberProperties collection supports the following properties:

Name

Value

Name

Name of the property. Extra spaces at the beginning and end of the string will be stripped out.

Access: | WriteOnce
Type: | String
Default: | "New Property"

Value

A value for the property.

Access: | ReadWrite
Type: | Variant
Default: | N/A

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


SubscriptionsForComponent Collection

The SubscriptionsForComponent collection holds an object for each subscription for the parent Component.

The SubscriptionsForComponent collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the SubscriptionsForComponent collection:

PublisherProperties

SubscriberProperties

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the SubscriptionsForComponent collection supports the following properties:

Description

Enabled

EventClassPartitionID

EventClassApplicationID

EventCLSID

FilterCriteria

ID

InterfaceID

MachineName

MethodName

Name

PerUser

PublisherID

Queued

SubscriberApplicationID

SubscriberCLSID

SubscriberMoniker

SubscriberPartitionID

UserName

Description

Description for the subscription.

Access: | ReadWrite
Type: | String
Default: | ""

Enabled

Indicates whether the subscription is presently enabled.

Access: | ReadWrite
Type: | Bool
Default: | True

EventClassPartitionID

When subscribing to event classes, the subscriber has the option to subscribe to an event class in the same or different partition. When subscribing to an event class the EventClassPartitionID property is used to represent the GUID of the partition ID containing the event class.

Access: | WriteOnce
Type: | String
Default: | N/A

EventClassApplicationID

When subscribing to event classes, the subscriber has the option to subscribe to an event class in the same or different application. When subscribing to an event class the EventClassApplicationID property is used to represent the GUID of the application ID containing the event class.

Access: | WriteOnce
Type: | String
Default: | N/A

EventCLSID

CLSID for the event class. You can indicate an EventCLSID or a PublisherID but not both.

Access: | WriteOnce
Type: | String
Default: | N/A

FilterCriteria

A string indicating the filter criteria. Can be a CLSID for a PublisherFilter class.

Access: | ReadWrite
Type: | String
Default: | N/A

ID

Identifier for the subscription.

Access: | WriteOnce
Type: | String
Default: | <Generated>

InterfaceID

IID for interface subscribed to.

Access: | WriteOnce
Type: | String
Default: | N/A

MachineName

A remote machine name for subscriptions to event classes on a remote machine.

Access: | ReadWrite
Type: | String
Default: | ""

MethodName

Method on the interface being subscribed to.

Access: | ReadWrite
Type: | String
Default: | N/A

Name

Name for the subscription. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadWrite
Type: | String
Default: | "New Subscription"

PerUser

Indicates whether the subscription applies only for a given user, UserName.

Access: | ReadWrite
Type: | Bool
Default: | False

PublisherID

ID for the publisher. You can indicate an EventCLSID or a PublisherID but not both.

Access: | WriteOnce
Type: | String
Default: | ""

Queued

Indicates whether the subscription is queued.

Access: | ReadWrite
Type: | Bool
Default: | False

SubscriberApplicationID

The GUID for the application containing the subscriber component.

Access: | ReadWrite
Type: | String
Default: | NULL

SubscriberCLSID

The CLSID of the subscriber component. If the CLSID is NULL, the subscription is transient. Otherwise, the subscription is persistent and the SubscriberInterface property must be NULL. This property works in conjunction with the MachineName property in a persistent subscription.

Access: | ReadWrite
Type: | String
Default: | NULL

SubscriberMoniker

A moniker for a subscriber marked as Queued. A default value is generated when Queued is initially set to True.

Access: | ReadWrite
Type: | String
Default: | N/A

SubscriberPartitionID

When subscribing to event classes, the subscriber has the option to subscribe to an event class in the same or different partition. When subscribing to an event class in the same partition, this property is used to represent the GUID of the partition ID of the subscriber.

Access: | WriteOnce
Type: | String
Default: | <Generated>

UserName

Name of user that the subscription applies to, when PerUser is True.

Access: | ReadWrite
Type: | String
Default: | N/A

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


TransientSubscriptions Collection

The TransientSubscriptions collection holds an object for each transient subscription. Transient subscriptions can be created on the fly for running object instances, and vanish when the object is destroyed.

The TransientSubscriptions collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the TransientSubscriptions collection:

PublisherProperties

SubscriberProperties

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the TransientSubscriptions collection supports the following properties:

Description

Enabled

EventCLSID

FilterCriteria

ID

InterfaceID

MethodName

Name

PerUser

PublisherID

SubscriberInterface

UserName

Description

Description for the subscription.

Access: | ReadWrite
Type: | String
Default: | ""

Enabled

Indicates whether the subscription is presently enabled.

Access: | ReadWrite
Type: | Bool
Default: | True

EventCLSID

CLSID for the event class. You can indicate an EventCLSID or a PublisherID but not both.

Access: | WriteOnce
Type: | String
Default: | N/A

FilterCriteria

A string indicating the filter criteria. Can be a CLSID for a PublisherFilter class.

Access: | ReadWrite
Type: | String
Default: | N/A

ID

Identifier for the subscription.

Access: | WriteOnce
Type: | String
Default: | <Generated>

InterfaceID

IID for interface subscribed to.

Access: | WriteOnce
Type: | String
Default: | N/A

MethodName

Method on the interface being subscribed to.

Access: | ReadWrite
Type: | String
Default: | N/A

Name

Name for the subscription. Extra spaces at the beginning and end of the string will be stripped out.

Access: | ReadWrite
Type: | String
Default: | "New Subscription"

PerUser

Indicates whether the subscription applies only for a given user, UserName.

Access: | ReadWrite
Type: | Bool
Default: | False

PublisherID

ID for the publisher. You can indicate an EventCLSID or a PublisherID but not both.

Access: | WriteOnce
Type: | String
Default: | ""

SubscriberInterface

Pointer to the subscriber's interface.

Access: | ReadWrite
Type: | Variant
Default: | N/A

UserName

Name of user that the subscription applies to, when PerUser is True.

Access: | ReadWrite
Type: | String
Default: | N/A

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


UsersInRole Collection

The UsersInRole collection holds an object for each user in the role to which the collection is related.

The UsersInRole collection supports the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the UsersInRole collection:

RelatedCollectionInfo

PropertyInfo

ErrorInfo

Properties

The COMAdminCatalogObject object within the UsersInRole collection supports the following property:

User

The user name.

Access: | WriteOnce
Type: | String
Default: | "New User"

Note Properties with WriteOnce access are ReadWrite while using the Add method prior to using SaveChanges, and are ReadOnly afterwards.


WOWInprocServers Collection

The WOWInprocServers collection is a top-level collection. It holds a list of the in-process servers registered with the system for 32-bit components on 64-bit computers. It contains an object for each component.

The WOWInprocServers collection does not support the Add and Remove methods on the COMAdminCatalogCollection object.

Related collections

You can navigate to any of the following collections from the WOWInprocServers collection:

RelatedCollectionInfo

PropertyInfo

Properties

The following properties are supported by the COMAdminCatalogObject objects within the WOWInprocServers collection:

CLSID

InprocServer32

ProgID

CLSID

A GUID for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

InprocServer32

The file path for the component.

Access: | ReadOnly
Type: | None
Default: | N/A

ProgID

A name identifying the component.

Access: | ReadOnly
Type: | String
Default: | N/A


WOWLegacyServers

Exposed properties for the WOWLegacyServers collection are intended to be identical to the LegacyServers collection except that this collection is drawn from the 32-bit registry on 64-bit machines.

Related collections

You can navigate to any of the following collections from the LegacyServers collection:

RelatedCollectionInfo

PropertyInfo

Properties

The COMAdminCatalogObject objects within the LegacyServers collection support the following properties:

ClassName

CLSID

InprocServer32

LocalServer32

ProgID

ClassName

The name of the class.

Access: | ReadOnly
Type: | String
Default: | N/A

CLSID

A GUID for the component.

Access: | ReadOnly
Type: | String
Default: | N/A

InprocServer32

The file path for the component.

Access: | ReadOnly
Type: | None
Default: | N/A

LocalServer32

Specifies the full path to a 32-bit local server application.

Access: | ReadOnly
Type: | None
Default: | N/A

ProgID

A name identifying the component.

Access: | ReadOnly
Type: | String
Default: | N/A


Administration Interfaces

The administration interfaces provide a way to access and manipulate all of the COM+ configuration data accessible through the Component Services administration tool. You can use these objects to automate all tasks in COM+ administration.

The administration interfaces enable you to read and write information that is stored on the COM+ catalog, the underlying data store that holds all COM+ configuration data. Information on the catalog is structured as collections holding items which expose properties. These correspond to folders, items in folders, and property sheets for those items, in the Component Services administration tool.

You initiate programmatic administration using the ICOMAdminCatalog interface. You manipulate collections on the catalog using the ICatalogCollection interface. And you can manipulate items in collections using the ICatalogObject interface.

For information regarding the collections on the catalog and their properties see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

Interface | Description
ICOMAdminCatalog | Use this interface to initiate a session over the COM+ catalog. Retrieve collections, install applications and components, start and stop services, and connect to remote servers.
ICatalogCollection | Use this interface to manipulate any collection on the catalog. Add, remove, enumerate through, and retrieve items in the collection, and access related collections.
ICatalogObject | Use this interface to manipulate an item in a collection. Get and put properties exposed by the item.

Note These interfaces are provided by the COM+ Admin Type Library DLL (Comadmin.dll).


ICOMAdminCatalog Interface

Provides access to the COM+ catalog data store. Use this interface to initiate a session to do programmatic COM+ administration, access collections on the catalog, install COM+ applications and components, start and stop services, and connect to remote servers.

When to Implement

You do not need to implement the ICOMAdminCatalog interface. A system-supplied class object, COMAdminCatalog, implements ICOMAdminCatalog.

When to Use

You use ICOMAdminCatalog whenever you are doing automated administration of COM+ applications and services. Use ICOMAdminCatalog to initiate navigation of the COM+ catalog collections. Use Connect to connect to the catalog on other computers to do remote administration. Use GetCollection to retrieve top-level collections on the currently active catalog. These collections can be represented and navigated using ICatalogCollection. The items within a given collection can be represented and examined or modified using ICatalogObject.

For information regarding the collections on the COM+ catalog see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

Methods in Vtable Order

This table is presented for when you use interfaces directly as in C++.

If you are using Visual Basic, the ICOMAdminCatalog methods are implemented on the COMAdminCatalog object.

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
ICOMAdminCatalog Methods | Description
GetCollection | Gets a top-level collection on the COM+ catalog.
Connect | Connects to the COM+ catalog on a remote computer, and retrieves a root collection bound to that computer.
get_MajorVersion | Gets the major version number of the COMAdmin Library.
get_MinorVersion | Gets the minor version number of the COMAdmin Library.
GetCollectionByQuery | Gets any collection on the COM+ catalog given the key values for all parent items.
ImportComponent | Imports a component registered as an inproc server. Should not be used: Use InstallComponent instead.
InstallComponent | Installs a component into a COM+ application, and provides default configuration in the COM+ class registration database (RegDB).
ShutdownApplication | Initiates shutdown of a COM+ server application process.
ExportApplication | Exports a COM+ application or application proxy to a file for installation on different machines.
InstallApplication | Installs a COM+ application or application proxy from a file.
StopRouter | Stops the component load balancing service, if the service is installed.
RefreshRouter | Deprecated.
StartRouter | Starts the component load balancing service, if the service is installed.
Reserved1 | Reserved for future use.
Reserved2 | Reserved for future use.
InstallMultipleComponents | Installs components from multiple files into a COM+ application.
GetMultipleComponentsInfo | Retrieves information about components found in specified files.
RefreshComponents | Refreshes component registration information from the Registry.
BackupREGDB | Backs up the COM+ class registration database (RegDB) to a specified file.
RestoreREGDB | Restores the COM+ class registration database (RegDB) from a specified file. Requires a reboot to take effect.
QueryApplicationFile | Returns information about a COM+ application from an application file.
StartApplication | Launches a COM+ server application in a dedicated process.
ServiceCheck | Checks the status of a COM+ service.
InstallMultipleEventClasses | Installs multiple event classes into an application.
InstallEventClass | Installs an event class into an application.
GetEventClassesForIID | Gets a list of event classes that implement a specified interface.


ICOMAdminCatalog Properties

The ICOMAdminCatalog interface and COMAdminCatalog object provide the properties described in this topic.

[C/C++]

In C++, programs call methods of the ICOMAdminCatalog interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters [C/C++]

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the MajorVersion property is a long variable. The method that gets this property has the following prototype:

HRESULT get_MajorVersion(long * retval);

Properties [C/C++]

The following table lists the properties that are managed by the ICOMAdminCatalog interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
MajorVersion | G | long | Returns a Long as the major version number of COMAdmin Library.
MinorVersion | G | long | Returns a Long as the minor version number of COMAdmin Library.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.

[Visual Basic]

Property | Description
MajorVersion | Returns a Long as the major version number of COMAdmin Library.
MinorVersion | Returns a Long as the minor version number of COMAdmin Library.


ICOMAdminCatalog::BackupREGDB

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::BackupREGDB [C/C++]

COMAdminCatalog.BackupREGDB Method [Visual Basic]

Backs up the COM+ class registration database (RegDB) to a specified file.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::BackupREGDB(
  BSTR  bstrBackupFilePath
);

[Visual Basic]
object.BackupREGDB(bstrBackupFilePath)

Parameters [C/C++]

bstrBackupFilePath [in]
File to which RegDB will be backed up.

Parts[Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrBackupFilePath
Required String indicating the file to which RegDB will be backed up.

Return Values[C/C++]

S_OK
Method completed successfully.


ICOMAdminCatalog::Connect

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::Connect [C/C++]

COMAdminCatalog.Connect Method [Visual Basic]

Connects to the COM+ catalog on a specified remote computer.

[C/C++] Passes back a pointer to a ICatalogCollection interface.

[Visual Basic] Returns a reference to a COMAdminCatalogCollection object.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::Connect(
  BSTR bstrConnectString,
  IDispatch ** ppCatalogCollection
);

[Visual Basic]
set collectionobject = object.Connect(bstrConnectString)

Parameters [C/C++]

bstrConnectString [in]
The name of the remote computer.
ppCatalogCollection [out]
A reference to the ICatalogCollection interface for the root collection on the remote computer.

Parts [Visual Basic]

collectionobject
Required object variable that evaluates to a COMAdminCatalogCollection object.
object
Required object variable that evaluates to a COMAdminCatalog object.
bstrConnectString
Required String as the name of a remote computer. To connect to a local computer, supply an empty string as this argument.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.
E_OUTOFMEMORY
Insufficient memory to complete the operation.

Remarks

[C/C++] When you use the Connect method, the ICOMAdminCatalog interface you are holding will then work over the machine to which you have connected.

[Visual Basic] When you use the Connect method, the COMAdminCatalog object you are holding will then work over the machine to which you have connected.

The Connect method also retrieves a root collection which is bound to the remote computer. A root collection serves as a starting point to locate top-level collections, and does not contain any objects or properties.

You can use the GetCollection method to get a top-level collection on the local machine without first using the Connect method.


ICOMAdminCatalog::ExportApplication

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::ExportApplication [C/C++]

COMAdminCatalog.ExportApplication Method [Visual Basic]

Exports a COM+ application or application proxy to a file, ready for installation on different machines.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::ExportApplication(
  BSTR bstrApplIdOrName,
  BSTR bstrApplicationFile,
  long lOptions
);

[Visual Basic]
object.ExportApplication(bstrApplIdOrName, bstrApplicationFile, lOptions)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application to be exported, or the name of the application.
bstrApplicationFile [in]
Name of the file to export the application to, including the file path. If this is not set the default directory will be used and the application file named after the application.
lOptions [in]
See Remarks below for option flags.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application to be exported, or the name of the application.
bstrApplicationFile
Required String as the name of the file to export the application to, including the file path. If this is not set the default directory will be used and the application file named after the application.
lOptions
Optional Long. See Remarks below for option flags.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.
COMADMIN_E_OBJECT_DOES_NOT_EXIST
The application does not exist.

Remarks

If no option flags are provided, ExportApplication will export the specified COM+ application to an MSI file, without the users assigned to application roles.

Multiple export option flags can be used in conjunction. The option flags that can be used with ExportApplication are:

Option | Value | Description
COMAdminExportNoUsers | 0 | Don't export users with roles (default).
COMAdminExportUsers | 1 | Do export users with roles.
COMAdminExportApplicationProxy | 2 | Exports an application as an application proxy.
COMAdminExportForceOverwriteOfFiles | 4 | Overwrite files.


ICOMAdminCatalog::GetCollection

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::GetCollection [C/C++]

COMAdminCatalog.GetCollection Method [Visual Basic]

Retrieves a top-level collection on the COM+ catalog.

[C/C++] Passes back a pointier to a ICatalogCollection interface.

[Visual Basic] Returns a reference to a COMAdminCatalogCollection object.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::GetCollection(
  BSTR bstrCollName,
  IDispatch ** ppCatalogCollection
);

[Visual Basic]
Set collectionbject = object.GetCollection(bstrCollName)

Parameters [C/C++]

bstrCollName [in]
The name of the collection to retrieve from the catalog.
ppCatalogCollection [out]
A reference to the ICatalogCollection interface for the collection.

Parts [Visual Basic]

collectionobject
Required object variable that evaluates to a COMAdminCatalogCollection object.
object
Required object variable that evaluates to a COMAdminCatalog object.
bstrCollName
Required String as the name of the collection to be retrieved.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.
E_OUTOFMEMORY
Insufficient memory to complete the operation.

Remarks

This method will retrieve a top-level collection from the COM+ catalog, such as Applications. For related collections that are not top-level collections, such as Components, use the GetCollection method available from the parent collection.

For a complete list of collections on the catalog, see Administration Collections.

The object instance retrieved by GetCollection doesn't contain data from the catalog for items contained within the collection. Use the Populate method to read in data for items in the collection.


ICOMAdminCatalog::GetCollectionByQuery

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::GetCollectionByQuery [C/C++]

COMAdminCatalog.GetCollectionByQuery Method [Visual Basic]

Retrieves a collection on the COM+ catalog given the Key property values for all of its parent items.

[C/C++] Passes back a pointer to a ICatalogCollection interface.

[Visual Basic] Returns a reference to a COMAdminCatalogCollection object.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::GetCollectionByQuery(
  BSTR bstrCollName,
  SAFEARRAY ** aQuery,
  IDispatch ** ppCatalogCollection
);

[Visual Basic]
set collectionobject = object.GetCollectionByQuery(bstrCollName, bstrQuery)

Parameters [C/C++]

bstrCollName [in]
The name of the collection to retrieve from the catalog.
aQuery [in]
A safearray consisting of Key property values for all parent items of the collection to be retrieved.
ppCatalogCollection [out]
A reference to the ICatalogCollection interface for the collection.

Parts [Visual Basic]

collectionobject
Required object variable that evaluates to a COMAdminCatalogCollection object.
object
Required object variable that evaluates to a COMAdminCatalog object.
bstrCollName
Required String as the name of the collection to retrieve from the catalog.
bstrQuery
Required String consisting of Key property values for all parent items of the collection to be retrieved. Key values are separated by semicolons, and with no spaces, i.e. "key1;key2;key3".

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.
E_UNEXPECTED
The collection name is invalid.
E_OUTOFMEMORY
Insufficient memory to complete the operation.

Remarks

The Key property for an item is a GUID that serves to uniquely identify it on the COM+ catalog.

The GetCollectionByQuery will get any collection on the catalog given the Key values for all of its parent items. With three of the collections, however, it will behave differently: ErrorInfo, RelatedCollectionInfo, and PropertyInfo. If you specify any of these collections, GetCollectionByQuery will always return that named collection immediately relative to the Root collection.

To get the ErrorInfo, RelatedCollectionInfo, or PropertyInfo collections that are relative to an arbitrary collection on the catalog, and not relative to the Root collection, use the GetCollection method from the parent collection.

For a complete list of available collections, see Administration Collections.


ICOMAdminCatalog::GetEventClassesForIID

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::GetEventClassesForIID [C/C++]

COMAdminCatalog.GetEventClassesForIID Method [Visual Basic]

Gets a list of the event classes registered on the machine that implement a specified interface.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::GetEventClassesForIID(
  BSTR bstrIID,
  SAFEARRAY( VARIANT ) * varCLSIDs,
  SAFEARRAY( VARIANT ) * varProgIDs,
  SAFEARRAY( VARIANT ) * varDescriptions
);

[Visual Basic]
object.GetEventClassesForIID(bstrIID, varCLSIDs, varProgIDs, varDescriptions)

Parameters [C/C++]

bstrIID [in]
GUID representing the interface for which event classes should be found. If NULL, all event classes registered on the machine will be returned.
varCLSIDs [out]
Reference to an array of CLSIDs for the event classes implementing the interface specified in bstrIID.
varProgIDs [out]
Reference to an array of ProgIDs for the event classes implementing the interface specified in bstrIID.
varDescriptions [out]
Reference to an array of descriptions for the event classes implementing the interface specified in bstrIID.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrIID
Required String as a GUID representing the interface for which event classes should be found. If NULL, all event classes registered on the machine will be returned.
varCLSIDs
Required reference to an array of Variants holding the CLSIDs for the event classes implementing the interface specified in bstrIID.
varProgIDs
Required reference to an array of Variants holding the ProgIDs for the event classes implementing the interface specified in bstrIID.
varDescriptions
Required reference to an array of Variants holding descriptions for the event classes implementing the interface specified in bstrIID.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.


ICOMAdminCatalog::GetMultipleComponentsInfo

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::GetMultipleComponentsInfo [C/C++]

COMAdminCatalog.GetMultipleComponentsInfo Method [Visual Basic]

Returns information about components found in the specified files.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::GetMultipleComponentsInfo(
  BSTR  bstrApplIdOrName,
  SAFEARRAY( VARIANT ) * varFileNames,
  SAFEARRAY( VARIANT ) * varCLSIDs,
  SAFEARRAY( VARIANT ) * varClassNames,
  SAFEARRAY( VARIANT ) * varFileFlags,
  SAFEARRAY( VARIANT ) * varComponentFlags
);

[Visual Basic]
object.GetMultipleComponentsInfo(bstrApplIdOrName, varFileNames, varCLSIDs, varClassNames, varFileFlags, varComponentFlags)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application, or the name of the application.
varFileNames [in]
Reference to an array of names of files containing the components.
varCLSIDs [out]
Reference to an array for passing back component CLSIDs.
varClassNames [out]
Reference to an array for passing back component class names.
varFileFlags [out]
Reference to an array for passing back file flags, used to return information about files. See Remarks below for option flags.
varComponentFlags [out]
Reference to an array for passing back component flags, used to return information about components in files. See Remarks below for option flags.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String with a GUID representing the application, or the name of the application.
varFileNames
Required reference to an array of Variants holding the names of the files containing the components.
varCLSIDs
Required reference to an array of Variants hold the component CLSIDs.
varClassNames
Required reference to an array of Variants to hold the component class names.
varFileFlags
Required reference to an array of Variants to hold file flags, used to return information about files. See Remarks below for option flags.
varComponentFlags
Required reference to an array of Variants to hold component flags, used to return information about components in files. See Remarks below for option flags.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks

The file option flags are used to return information about the files indicated. The file option flags returned by GetMultipleComponentsInfo are:

Option | Value
COMAdminFileFlagLoadable | 0x00000001
COMAdminFileFlagCOM | 0x00000002
COMAdminFileFlagContainsRS | 0x00000004
COMAdminFileFlagContainsComp | 0x00000008
COMAdminFileFlagContainsTLB | 0x00000010
COMAdminFileFlagSelfReg | 0x00000020
COMAdminFileFlagSelfUnReg | 0x00000040
COMAdminFileFlagUnloadableDLL | 0x00000080
COMAdminFileFlagDoesNotExist | 0x00000100
COMAdminFileFlagAlreadyInstalled | 0x00000200
COMAdminFileFlagBadTLB | 0x00000400
COMAdminFileFlagGetClassObjFailed | 0x00000800
COMAdminFileFlagClassNotAvailable | 0x00001000
COMAdminFileFlagRegistrar | 0x00002000
COMAdminFileFlagNoRegistrar | 0x00004000
COMAdminFileFlagDLLRegsvrFailed | 0x00008000
COMAdminFileFlagRegTLBFailed | 0x00010000
COMAdminFileFlagRegistrarFailed | 0x00020000
COMAdminFileFlagError | 0x00040000

The component option flags are used to return information about the components indicated. The component option flags returned by GetMultipleComponentsInfo are:

Option | Value
COMAdminComponentFlagTypeInfoFound | 0x00000001
COMAdminComponentCOMPlusPropertiesFound | 0x00000002
COMAdminComponentProxyFound | 0x00000004
COMAdminComponentInterfacesFound | 0x00000008
COMAdminComponentAlreadyInstalled | 0x00000010
COMAdminComponentNotInApplication | 0x00000020


ICOMAdminCatalog::ImportComponent

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::ImportComponent [C/C++]

COMAdminCatalog.ImportComponent Method [Visual Basic]

Imports a component already registered as an in-process server into a COM+ application. Generally should not be used: Use InstallComponent instead.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::ImportComponent(
  BSTR bstrApplIdOrName,
  BSTR bstrCLSIDOrProgID
);

[Visual Basic]
object.ImportComponent(bstrApplIdOrName, bstrCLSIDOrProgID)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application into which to import the component, or the name of the application.
bstrCLSIDOrProgID [in]
The CLSID or ProgID for the component to import.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application into which to import the component, or the name of the application.
bstrCLSIDOrProgID
Required String as the CLSID or ProgID for the component to import.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.

Remarks

Use the InstallComponent method instead of ImportComponent. InstallComponent fully registers the component in the COM+ class registration database (RegDB), whereas ImportComponent does not, resulting in an application with limited functionality.

ImportComponent will import a component that is registered as an in-process server in the Registry. It does not bring any interface, method, or type library information for the component into the COM+ class registration database. This will restrict how the component can be configured. When you attempt to export a COM+ application that has an imported component to an application proxy, the proxy will contain no interface or type library information for the component, and marshalling for that component will fail.


ICOMAdminCatalog::InstallApplication

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::InstallApplication [C/C++]

COMAdminCatalog.InstallApplication Method [Visual Basic]

Installs a COM+ application or application proxy from a file.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::InstallApplication(
  BSTR  bstrApplicationFile,
  BSTR  bstrDestinationDirectory,
  long  lOptions,
  BSTR  bstrUserID,
  BSTR  bstrPassword,
  BSTR  bstrRSN
);

[Visual Basic]
object.InstallApplication(bstrApplicationFile, bstrDestinationDirectory, lOptions, bstrUserID, bstrPassword, bstrRSN)

Parameters [C/C++]

bstrApplicationFile [in]
The name of the file containing the application to install.
bstrDestinationDirectory [in]
Optional. Where to install the components. If left blank the default directory will be used.
lOptions [in]
Optional. See Remarks below for option flags.
bstrUserID [in]
Optional. The User ID under which to run the application.
bstrPassword [in]
Optional. The password under which to run the application.
bstrRSN [in]
Optional. A remote server name to use for an application proxy.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplicationFile
Required String as the name of the file containing the applicaiton to install.
bstrDestinationDirectory
Optional String with the path indicating where to install the components. If left blank the default directory will be used.
lOptions
Optional Long. See Remarks below for option flags.
bstrUserId
Optional String with the User ID under which to run the application.
bstrPassword
Optional String with the password under which to run the application.
bstrRSN
Optional String with a remote server name to use for an application proxy.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.
E_OUTOFMEMORY
Insufficient memory to complete the operation.
E_UNEXPECTED
A catastrophic failure has occurred.
ERROR_INSTALL_FAILURE
A fatal error occurred during installation.
COMADMIN_E_OBJECT_DOES_NOT_EXIST
The application does not exist.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks

The option flags that can be used with InstallApplication are:

Option | Value | Description
COMAdminInstallNoUsers | 0 | Don't install users saved in application file (default).
COMAdminInstallUsers | 1 | Do install users saved in application file.
COMAdminInstallForceOverwriteOfFiles | 2 | Overwrite files.


ICOMAdminCatalog::InstallComponent

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::InstallComponent [C/C++]

COMAdminCatalog.InstallComponent Method [Visual Basic]

Installs all components (COM classes) from a DLL file into a COM+ application, and registers the components in the COM+ class registration database (RegDB) as configured components, providing a default configuration.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::InstallComponent(
  BSTR bstrApplIdOrName,
  BSTR bstrDLL,
  BSTR bstrTLB,
  BSTR bstrPSDLL
);

[Visual Basic]
object.InstallComponent(bstrApplIdOrName, bstrDLL, bstrTLB, bstrPSDLL)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application into which to install the component, or the application name.
bstrDLL [in]
The name of the DLL file containing the component to install.
bstrTLB [in]
The name of the external type library file. If the type library file is embedded in the DLL, pass in an empty string for this parameter.
bstrPSDLL [in]
The name of the proxy-stub DLL file. If there is no proxy-stub DLL associated with the component, pass in an empty string for this parameter.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application into which to install the component, or the application name.
bstrDLL
Required String as the name of the .dll file containing the component to install.
bstrTLB
Required String as the name of the external type library file. If the type library file is embedded in the DLL, pass in an empty string for this parameter.
bstrPSDLL
Required String as the name of the proxy-stub DLL file. If there is no proxy-stub DLL associated with the component, pass in an empty string for this parameter.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.

Remarks

InstallComponent is the recommended way to install all components into COM+ applications (as opposed to ImportComponent).

InstallComponent provides full registration of components in the COM+ class registration database (RegDB) as configured components, including interface, method, type library and proxy-stub information necessary for marshalling.


ICOMAdminCatalog::InstallEventClass

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::InstallEventClass [C/C++]

COMAdminCatalog.InstallEventClass Method [Visual Basic]

Installs an event class from a file into a COM+ application.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::InstallEventClass(
  BSTR bstrApplIdOrName,
  BSTR bstrDLL,
  BSTR bstrTLB,
  BSTR bstrPSDLL
);

[Visual Basic]
object.InstallEventClass(bstrApplIdOrName, bstrDLL, bstrTLB, bstrPSDLL)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application into which to install the event class, or the application name.
bstrDLL [in]
The name of the DLL file containing the event classes to install.
bstrTLB [in]
The name of an external type library file. If the type library file is embedded in the DLL, pass in an empty string for this parameter.
bstrPSDLL [in]
The name of the proxy-stub DLL file. If there is no proxy-stub DLL associated with the event class, pass in an empty string for this parameter.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application into which to install the component, or the application name.
bstrDLL
Required String as the name of the DLL file containing the event classes to install.
bstrTLB
Required String as the name of the external type library file. If the type library file is embedded in the DLL, pass in an empty string for this parameter.
bstrPSDLL
Required String as the name of the proxy-stub DLL file. If there is no proxy-stub DLL associated with the event class, pass in an empty string for this parameter.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.

Remarks

Use InstallEventClass to install event classes from a DLL holding dummy implementations of the event classes. The requirements are: a self-registering DLL; a typelib describing the interfaces implemented by the event classes; and each event class must have a CLSID and a ProgID.

The dummy implementation of the interface exposed by an event class will never actually run, it exists only to register the event class. Instead, when the event class is created by the publisher, an implementation is provided by the Events system to send the event to subscribers.


ICOMAdminCatalog::InstallMultipleComponents

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::InstallMultipleComponents [C/C++]

COMAdminCatalog.InstallMultipleComponents Method [Visual Basic]

Installs components from multiple files into a COM+ application.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::InstallMultipleComponents(
  BSTR bstrApplIdOrName,
  SAFEARRAY( VARIANT ) * varFileNames,
  SAFEARRAY( VARIANT ) * varCLSIDS
);

[Visual Basic]
object.InstallMultipleComponents(bstrApplIdOrName, varFileNames, varCLSIDS)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application into which to install the components, or the name of the application.
varFileNames [in]
Reference to an array of names of the DLL files containing the components to install.
varCLSIDS [in]
Reference to an array of CLSIDs for the components to install.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application into which to install the components, or the name of the application.
varFileNames
Required reference to an array of Variants holding the names of the DLL files containing the components to install.
varCLSIDS
Required reference to an array of Variants holding CLSIDs for the components to install.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.


ICOMAdminCatalog::InstallMultipleEventClasses

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::InstallMultipleEventClasses [C/C++]

COMAdminCatalog.InstallMultipleEventClasses Method [Visual Basic]

Installs event classes from multiple files into a COM+ application.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::InstallMultipleEventClasses(
  BSTR bstrApplIdOrName,
  SAFEARRAY( VARIANT ) * varFileNames,
  SAFEARRAY( VARIANT ) * varCLSIDS
);

[Visual Basic]
object.InstallMultipleEventClasses(bstrApplIdOrName, varFileNames, varCLSIDS)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application into which to install the event classes, or the name of the application.
varFileNames [in]
Reference to an array of names of the DLL files containing the event classes to install.
varCLSIDS [in]
Reference to an array of CLSIDs for event classes to install.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application into which to install the event classes, or the name of the application.
varFileNames
Required reference to an array of Variants holding the names of the DLL files containing the event classes to install.
varCLSIDS
Required reference to an array of Variants holding CLSIDs for event classes to install.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter.

Remarks

Use InstallMultipleEventClasses to install event classes from DLLs holding dummy implementations of the event classes. The requirements are: a self-registering DLL; a typelib describing the interfaces implemented by the event classes; and each event class must have a CLSID and a ProgID.

The dummy implementation of the interface exposed by an event class will never actually run, it exists only to register the event class. Instead, when the event class is created by the publisher, an implementation is provided by the Events system to send the event to subscribers.


ICOMAdminCatalog::QueryApplicationFile

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::QueryApplicationFile [C/C++]

COMAdminCatalog.QueryApplicationFile Method [Visual Basic]

Retrieves information about a COM+ application from an application file.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::QueryApplicationFile(
  BSTR  bstrApplicationFile,
  BSTR * bstrApplicationName,
  BSTR * bstrApplicationDescription,
  VARIANT_BOOL * bHasUsers,
  VARIANT_BOOL * bIsProxy,
  SAFEARRAY( VARIANT ) * varFileNames
);

[Visual Basic]
object.QueryApplicationFile(bstrApplicationFile, bstrApplicationName, bstrApplicationDescription, bHasUsers, bIsProxy, varFileNames)

Parameters [C/C++]

bstrApplicationFile [in]
Application file from which information will be retrieved.
bstrApplicationName [out]
Reference to string containing name of the application in the specified file.
bstrApplicationDescription [out]
Reference to string containing description of the application.
bHasUsers [out]
Reference to boolean value indicating whether the application has user information associated with its roles.
bIsProxy [out]
Reference to boolean value indicating whether the file contains an application proxy.
varFileNames [out]
Reference to array containing names of DLL files for components installed in the application.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplicationFile
Required String indicating the application file from which information will be retrieved.
bstrApplicationName
Required reference to String containing name of the application in the specified file.
bstrApplicationDescription
Required reference to String containing description of the application.
bHasUsers
Required reference to Boolean value indicating whether the application has user information associated with its roles.
bIsProxy
Required reference to Boolean value indicating whether the file contains an application proxy.
varFileNames
Required reference to array of Variants containing names of DLL files for components installed in the application.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.
E_FAIL
Unspecified error.
E_OUTOFMEMORY
Insufficient memory to complete the operation.


ICOMAdminCatalog::RefreshComponents

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::RefreshComponents [C/C++]

COMAdminCatalog.RefreshComponents Method [Visual Basic]

Updates component registration information from the Registry.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::RefreshComponents(void);

[Visual Basic]
object.RefreshComponents

Parts[Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.

Return Values[C/C++]

S_OK
Method completed successfully.

Remarks

The RefreshComponents method is called from within the Microsoft Visual Basic development environment when you use the Auto-refresh or Refresh all component information features on the Component Services add-in menu.

RefreshComponents will compare CLSIDs and ProgIDs between the COM+ class registration database (RegDB) and the Registry for mismatches. It will update RegDB– refreshing components– only when there is a mismatch between CLSIDs and a match between corresponding ProgIDs.

Only CLSID information is updated to RegDB. No interface or method information is updated. Components that are refreshed using RefreshComponents cannot be configured or secured at the interface or method levels within COM+ applications.

You generally should not use RefreshComponents. The recommended way to update components in COM+ applications is to remove and reinstall the components using InstallComponent, so that complete registration information is updated in RegDB.


ICOMAdminCatalog::RefreshRouter

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::RefreshRouter [C/C++]

COMAdminCatalog.RefreshRouter Method [Visual Basic]

This function is deprecated.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::RefreshRouter(void);

[Visual Basic]
object.RefreshRouter

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.

Return Values [C/C++]

S_OK
Method completed successfully.


ICOMAdminCatalog::RestoreREGDB

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::RestoreREGDB [C/C++]

COMAdminCatalog.RestoreREGDB Method [Visual Basic]

Restores the COM+ class registration database (RegDB) from a specified file. This requires a system reboot in order to take effect.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::RestoreREGDB(
  BSTR  bstrBackupFilePath
);

[Visual Basic]
object.RestoreREGDB(bstrBackupFilePath)

Parameters [C/C++]

bstrBackupFilePath [in]
File from which RegDB will be backed up.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrBackupFilePath
Required String indicating the file from which RegDB will be backed up.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.
E_OUTOFMEMORY
Insufficient memory to complete the operation.
E_NOTIMPL
This function is not implemented.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.


ICOMAdminCatalog::ServiceCheck

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::ServiceCheck [C/C++]

COMAdminCatalog.ServiceCheck Method [Visual Basic]

Returns the current status of a COM+ service.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::ServiceCheck(
  long  lService,
  long * pulStatus
);

[Visual Basic]
set x = object.ServiceCheck(lService)

Parameters [C/C++]

lService [in]
Long representing the service for which status will be checked. See Remarks for service flags.
pulStatus [out]
Reference to Long holding the status for the indicated service. See Remarks for service status flags.

Parts [Visual Basic]

x
Required Long holding the status for the indicated service. See Remarks for service status flags.
object
Required object variable that evaluates to a COMAdminCatalog object.
lService
Required Long representing the service for which status will be checked. See Remarks for service flags.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.

Remarks

The Service option flags that can be used with ServiceCheck are listed in the following table.

Option | Value | Description
COMAdminServiceLoadBalanceRouter | 1 | Component Load Balancing service.

The Status option flags that can be used with ServiceCheck are listed in the following table.

Option | Value | Description
COMAdminServiceStopped | 0 | Service is currently stopped.
COMAdminServiceStartPending | 1 | Service is due to start up.
COMAdminServiceStopPending | 2 | Service is due to stop.
COMAdminServiceRunning | 3 | Service is running normally.
COMAdminServiceContinuePending | 4 | Service is due to continue.
COMAdminServicePausePending | 5 | Service is due to pause.
COMAdminServicePaused | 6 | Service is currently paused.
COMAdminServiceUnknownState | 7 | Service status is unknown.


ICOMAdminCatalog::ShutdownApplication

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::ShutdownApplication [C/C++]

COMAdminCatalog.ShutdownApplication Method [Visual Basic]

Initiates shutdown of a COM+ server application process.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::ShutdownApplication(
  BSTR bstrApplIdOrName
);

[Visual Basic]
object.ShutdownApplication(bstrApplIdOrName)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application to shut down, or the application name.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application to shut down, or the application name.

Return Values [C/C++]

S_OK
Method completed successfully.
COMADMIN_E_OBJECT_DOES_NOT_EXIST
The application does not exist.


ICOMAdminCatalog::StartApplication

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::StartApplication [C/C++]

COMAdminCatalog.StartApplication Method [Visual Basic]

Starts up a specified COM+ server application. The application components will be launched in a dedicated server process.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::StartApplication(
  BSTR  bstrApplIdOrName
);

[Visual Basic]
object.StartApplication(bstrApplIdOrName)

Parameters [C/C++]

bstrApplIdOrName [in]
GUID representing the application to start up, or the name of the application.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.
bstrApplIdOrName
Required String as a GUID representing the application to start up, or the name of the application.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.


ICOMAdminCatalog::StartRouter

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::StartRouter [C/C++]

COMAdminCatalog.StartRouter Method [Visual Basic]

Starts the component load balancing service, if the service is currently installed.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::StartRouter(void);

[Visual Basic]
object.StartRouter

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.

Return Values [C/C++]

S_OK
Method completed successfully.
COMADMIN_E_SERVICENOTINSTALLED
The component load balancing service is not currently installed on the machine.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks

When called on a machine acting as the component load balancing (CLB) server, the StartRouter method will start up the service, and subsequent component activation requests will be routed across the application cluster that is defined on the router.


ICOMAdminCatalog::StopRouter

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog::StopRouter [C/C++]

COMAdminCatalog.StopRouter Method [Visual Basic]

Stops the component load balancing service, if the service is currently installed.

Syntax

[C/C++]
HRESULT ICOMAdminCatalog::StopRouter(void);

[Visual Basic]
object.StopRouter

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalog object.

Return Values [C/C++]

S_OK
Method completed successfully.
COMADMIN_E_SERVICENOTINSTALLED
The component load balancing service is not currently installed on the machine.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks

When called on a machine acting as the component load balancing (CLB) server, the StopRouter method will stop the server from routing component activation requests to other servers in the application cluster.


ICOMAdminCatalog2 Interface

The ICOMAdminCatalog2 interface is an extension of the ICOMAdminCatalog. This interface is used to pause or resume a server, disable or enable a COM+ application, dump the process state to a file, configure an application to run as an NT service, check whether the process dump is supported, and set the partitioning of an application.

When to Implement

You do not need to implement the ICOMAdminCatalog2 interface. If you are using Microsoft® Visual Basic®, the ICOMAdminCatalog2 methods are implemented on the COMAdminCatalog object. The system-supplied class object, COMAdminCatalog, implements ICOMAdminCatalog2.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of an object's programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object's methods, or gets or sets one of its properties.
IComAdminCatalog2 Methods | Description
ShutdownProcess | Initiates shutdown of the specified process.
PauseProcess | Pauses an application server process.
ResumeProcess | Resumes an application server process.
IsProcessPaused | Returns TRUE if process is paused.
DumpProcess | Dumps an image of this process to the disk.
IsProcessDumpSupported | Tells the caller whether the process dump feature is supported on this server.
SetApplicationPartition | Sets the application partition scope.
GetCurrentApplicationPartitionId | Gets the current application partition ID.
GetCurrentApplicationPartitionName | Gets the current application partition name.
GetRunningApps | Gets the running applications for the specified application.
CreateServiceForApplication | Configures an application to run as an NT service.
DeleteServiceForApplication | Reconfigure an application running as an NT service.
GetBaseApplicationPartitionId | Gets the application partition ID for the base application partition.
CopyApplications | Copies the application from the source partition to the current application partition.
CopyComponent | Copies the component configuration while retaining the implementation.
ImportComponentAsLegacy | Imports the specified class as a nonconfigured component.
PromoteLegacyComponent | Promotes the specified class to a configured COM+ component.
GetAppPartitionId | Gets partition ID for the specified application ID.
GetAppPartitionName | Gets the name of the partition in which the specified application ID is located.
ImportComponentByType | Imports a component that is already registered as an inproc server in the 32-bit or 64-bit registry.
Is64BitCatalogServer | Determines whether the target catalog server is 64 bit.
MoveComponent | Moves the component configuration while retaining the implementation.
GetInstanceIDFromPID | Gets an instance ID for the specified process ID.
RecycleProcess | Recycles an application server process.
GetInstanceIDFromApplID | Converts an application ID or name to an instance ID. This method can be used only with nonpooled applications.

See Also

ICOMAdminCatalog Interface

Requirements

To use the methods of this interface, you must include comadmin.idl in your project.


IComAdminCatalog2::CopyApplications

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::CopyApplications C/C++]

COMAdminCatalog.CopyApplications Method [Visual Basic]

Copies the application from the source partition to the current application partition.

[C/C++]
HRESULT CopyApplications(
BSTR bstrSourcePartitionId,
SAFEARRAY(VARIANT) * varApplIds
) = 0;
[Visual Basic]
object.CopyApplications(bstrSourcePartitionId, varApplIds)

Parameters [C/C++]

bstrSourcePartitionId
[in] The partition ID containing the application to be copied.
varApplIds
[in] Points to an array of variants containing the application ID to be copied.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrSourcePartitionId
The partition ID containing the application to be copied.
varApplIds
Points to an array of variants containing the application ID to be copied.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
The source partition is not different from the target partition.

Comments

Applications in the base partition that contain one or more legacy components may not be copied to any other partition.


IComAdminCatalog2::CopyComponent

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::CopyComponent C/C++]

COMAdminCatalog.CopyComponent Method [Visual Basic]

Copies the component configuration while retaining the implementation.

[C/C++]
HRESULT CopyComponent(
BSTR bstrSourcePartitionId,
BSTR bstrClsid,
BSTR bstrNewApplId,
BSTR bstrNewClsid,
BSTR bstrNewProgId
) = 0;
[Visual Basic]
object.CopyComponent(bstrSourcePartitionId, bstrClsid, bstrNewApplId, bstrNewClsid, bstrNewProgId)

Parameters [C/C++]

bstrSourcePartitionId
[in] The partition ID containing the component to be copied.
bstrClsid
[in] The class identifier for the class object.
bstrNewApplId
[in] The application ID for the duplicated application.
bstrNewClsid
[in] The class identifier for the duplicated class object.
bstrNewProgId
[in] The ProgID for the duplicated class object.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrSourcePartitionId
The partition ID for the application to be copied.
bstrClsid
The class identifier for the class object.
bstrNewApplId
The application ID for the duplicated application.
bstrNewClsid
The class identifier for the duplicated class object.

bstrNewProgId

The ProgID for the duplicated class object.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid arguments.


IComAdminCatalog2::CreateServiceForApplication

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::CreateServiceForApplication[C/C++]

COMAdminCatalog.CreateServiceForApplication Method [Visual Basic]

Creates an NT service for the specified COM+ application.

[C/C++]
HRESULT CreateServiceForApplication(
BSTR bstrApplIdOrName,
BSTR bstrServiceName,
BSTR bstrStartType,
BSTR bstrErrorControl,
BSTR bstrDependencies,
BSTR bstrRunAs,
BSTR bstrPassword,
VARIANT_BOOL bDesktopOk
) = 0;
[Visual Basic]
object.CreateServiceForApplication(bstrApplIdOrName, bstrServiceName, bstrStartType, bstrErrorControl, bstrDependencies, bstrRunAs, bstrPassword, bDesktopOk)

Parameters [C/C++]

bstrApplIdOrName
[in] The application ID or the name of the application.
bstrServiceName
[in] The service name of the application. This name is the internal name used by the NT SCM, not the display name.
bstrStartType
[in] Specifies when to start the service. The valid arguments are the options of the dwStartType parameter of the CreateService function. The arguments must be in quotes. The following are the valid arguments: SERVICE_BOOT_START, SERVICE_SYSTEM_START, SERVICE_AUTO_START, SERVICE_DEMAND_START and SERVICE_DISABLED.
bstrErrorControl
[in] Specifies the severity of the error if this service fails to start during startup. The error determines the action taken by the startup program if failure occurs. The valid arguments are the options of the dwErrorControl parameter of the CreateService function. The following are the valid arguments: SERVICE_ERROR_IGNORE, SERVICE_ERROR_NORMAL, SERVICE_ERROR_SEVERE and SERVICE_ERROR_CRITICAL.
bstrDependencies
[in] A list of dependencies for the service. There are two possible formats for the string: a standard null-delimited, double-null-terminated string (exactly as documented for CreateService); or a script-friendly list of service names separated by "\" (an invalid character to have in a service name). The rpcss service is implicit in this parameter and does not need to be specified.
bstrRunAs
[in] The user name to run this service as. This must be NULL to indicate that it should run as Local System.
bstrPassword
[in] The password for the system user account. This must be NULL if the service is configured to run as Local System.
bDesktopOk
[in] Indicates whether or not the service should be allowed to interact with the desktop. This parameter is valid only when the service is marked as Local System and must be VARIANT_FALSE otherwise.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrServiceName
The service name of the application. This name is the internal name used by the NT SCM, not the display name.
bstrStartType
Specifies when to start the service. The valid arguments are the options of the dwStartType parameter of the CreateService function. The arguments must be in quotes. The following are the valid arguments: SERVICE_BOOT_START, SERVICE_SYSTEM_START, SERVICE_AUTO_START, SERVICE_DEMAND_START and SERVICE_DISABLED.
bstrErrorControl
Specifies the severity of the error if this service fails to start during startup. The error determines the action taken by the startup program if failure occurs. The valid arguments are the options of the dwErrorControl parameter of the CreateService function. The following are the valid arguments: SERVICE_ERROR_IGNORE, SERVICE_ERROR_NORMAL, SERVICE_ERROR_SEVERE and SERVICE_ERROR_CRITICAL.
bstrDependencies
A list of services that must be started before the application is started a service. The service names are in one of two possible string formats: a standard null-delimited, double-null terminated string as documented for CreateService; or a script-friendly list of service names separated by "\" (an invalid character to have in a service name). The rpcss service is implicit in this parameter and does not need to be specified.
bstrRunAs
The user name to run this service as. This must be NULL to indicate that it should run as Local System.
bstrPassword
The password for the system user account. This must be NULL if the service is configured to run as Local System.
bDesktopOk
Indicates whether or not the service should be allowed to interact with the desktop. This parameter is valid only when the service is marked as Local System and must be VARIANT_FALSE otherwise.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid parameters for bstrStartType or bstrErrorControl.


IComAdminCatalog2::DeleteServiceForApplication

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::DeleteServiceForApplication[C/C++]

COMAdminCatalog.DeleteServiceForApplication Method [Visual Basic]

Deletes the NT service associated with a COM+ application.

[C/C++]
HRESULT DeleteServiceForApplication(
BSTR bstrAppIdOrName
) = 0;
[Visual Basic]
object.DeleteServiceForApplication(bstrAppIdOrName)

Parameters [C/C++]

bstrAppIdOrName
[in] The Application ID or the name of a COM+ application currently configured to run as an NT service.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrApplIdorName
The Application ID or the name of a COM+ application currently configured to run as an NT service.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid parameters for bstrStartType or bstrErrorControl.


IComAdminCatalog2::DumpProcess

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::DumpProcess [C/C++]

COMAdminCatalog.DumpProcess Method [Visual Basic]

Dumps an image of this process to the disk for debugging purposes.

[C/C++];
HRESULT DumpProcess(
BSTR bstrApplInstanceId,
BSTR bstrDirectory,
DWORD dwMaxImages,
BSTR *pbstrDumpFile
) = 0;
[Visual Basic]
object.DumpProcess(bstrApplInstanceId, bstrDirectory, dwMaxImages, pbstrDumpFile)

Parameters [C/C++]

bstrApplInstanceId
[in] The instance ID. An instance ID is a GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to check if a process is paused. For information on how to obtain the GUID, see GetRunningApps.
bstrDirectory
[in] The complete path to the image dump directory containing the dump file. Do not include the filename. The default path is %SystemRoot%\system32\com\dmp. If this value is NULL the default value will be used.
dwMaxImages
[in] The maximum number of images to be generated in the image dump directory.
pbstrDumpFile
[in,out] Returns the file name of the dump image.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrApplInstanceId
The instance ID. An instance ID is a GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to check if a process is paused. For information on how to obtain the GUID, see GetRunningApps.
bstrDirectory
The complete path to the image dump directory containing the dump file. Do not include the filename. The default path is %SystemRoot%\system32\com\dmp. If this value is NULL the default value will be used.
dwMaxImages
The maximum number of images to be generated in the image dump directory.
pbstrDumpFile
Returns the file name of the dump image.

Return Value [C/C++]

S_OK
Method completed successfully
E_INVALIDARG
The bstrApplInstanceId, bPaused, or pbstrDumpFile parameter is NULL.
HRESULT_FROM_WIN32(GetLastError())
The method failed.
COMADMIN_E_APP_NOT_RUNNING
The specified process is not running.

See Also

"Tool For Debugging COM+ Applications" in the Component Services administrative guide


IComAdminCatalog2::GetAppPartitionId

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetAppPartitionId [C/C++]

COMAdminCatalog.GetAppPartitionId Method [Visual Basic]

Gets the partition ID for the partition in which a specified application resides.

[C/C++]
HRESULT GetAppPartitionId(
BSTR bstrAppId,
BSTR * pbstrPartitionId
) = 0;
[Visual Basic]
object.GetAppPartitionId(bstrAppIdOrName, pbstrPartitionId)

Parameters [C/C++]

bstrAppId
[in] The application ID.
pbstrPartitionId
[out, retval] Points to the partition ID.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrAppIdOrName
The application ID.
pbstrPartitionId
The partition ID.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid arguments.
E_OUTOFMEMORY
Insufficient memory to complete the operation.


IComAdminCatalog2::GetAppPartitionName

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetAppPartitionName [C/C++]

COMAdminCatalog.GetAppPartitionName Method [Visual Basic]

Gets the name of the partition in which the specified application ID is located.

[C/C++]
HRESULT GetAppPartitionName(
BSTR bstrAppId,
BSTR * pbstrPartitionName
) = 0;
[Visual Basic]
object.GetAppPartitionName(bstrAppIdOrName, pbstrPartitionName)

Parameters [C/C++]

bstrAppId
[in] The application ID.
pbstrPartitionName
[out, retval] Points to the partition name.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrAppIdOrName
The application ID.
pbstrPartitionName
The partition name.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid arguments.
E_OUTOFMEMORY
Insufficient memory to complete the operation.


IComAdminCatalog2::GetBaseApplicationPartitionId

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetBaseApplicationPartitionId C/C++]

COMAdminCatalog.GetBaseApplicationPartitionId Method [Visual Basic]

Gets the application partition ID for the Base Application Partition.

[C/C++]
HRESULT GetBaseApplicationPartitionId(
BSTR * pbstrBasePartitionId
) = 0;
[Visual Basic]
object.GetBaseApplicationPartitionId(pbstrBasePartitionId)

Parameters [C/C++]

pbstrPartitionId
[out,retval] Points to the partition ID.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
pbstrPartitionId
The string defined as the partition ID.

Return Value

Returns the application partition ID as a string-form braced GUID—for example, {41E90F3E-56C1-4633-81C3-6E8BAC8BDD70}.


IComAdminCatalog2::GetCurrentApplicationPartitionId

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetCurrentApplicationPartitionId [C/C++]

COMAdminCatalog.GetCurrentApplicationPartitionId Method [Visual Basic]

Gets the application partition ID to which administrative calls are currently scoped. This method is useful if you plan to set the application partition scope by calling GetBaseApplicationPartitionId, which requires the application partition ID or name.

[C/C++]
HRESULT GetCurrentApplicationPartitionId(
BSTR* pbstrApplPartitionId
) = 0;
[Visual Basic]
object.GetCurrentApplicationPartitionId(pbstrApplPartitionId)

Parameters [C/C++]

pbstrApplPartitionId
[out, retval] Points to the string containing the application partition ID.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
pbstrApplPartitionId
The string containing the application partition ID.

Return Value [C/C++]

S_OK
The method completed successfully.


IComAdminCatalog2::GetCurrentApplicationPartitionName

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetCurrentApplicationPartitionName [C/C++]

COMAdminCatalog.GetCurrentApplicationPartitionName Method [Visual Basic]

Gets the application partition name to which administrative calls are currently scoped. This method is useful if you plan to set the application partition scope by calling GetBaseApplicationPartitionId, which requires the application partition name or ID.

[C/C++]
HRESULT GetCurrentApplicationPartitionName(
BSTR* pbstrApplPartitionName
) = 0;
[Visual Basic]
object.GetCurrentApplicationPartitionName(pbstrApplPartitionName)

Parameters [C/C++]

pbstrApplPartitionName
[out, retval] Points to the string containing the application partition name.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
pbstrApplPartitionName
The string containing the application partition name.

Return Value [C/C++]

S_OK
The method completed successfully.


IComAdminCatalog2::GetInstanceIDFromApplID

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetInstanceIDFromApplID[C/C++]

COMAdminCatalog.GetInstanceIDFromApplID Method [Visual Basic]

Converts an application ID or name to an instance ID. The instance ID is a GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to pause, resume, or recycle that process. For information on how to obtain the GUID, see GetRunningApps.

GetInstanceIDFromApplID can be used only with nonpooled applications.

[C/C++]
HRESULT GetInstanceIDFromApplID(
BSTR bstrAppIdOrName,
BSTR *pbstrInstanceID
) = 0;
[Visual Basic]
object. GetInstanceIDFromApplID(bstrAppIdOrName, pbstrInstanceID)

Parameters [C/C++]

bstrAppIdOrName
[in] The application ID or name for the nonpooled application.
pbstrInstanceID
[out, retval] Points to the string containing the instance ID.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrAppIdOrName
The application ID or name for the nonpooled application.
pbstrInstanceID
Points to the string containing the instance ID.

Return Value [C/C++]

S_OK
The method completed successfully.


IComAdminCatalog2::GetInstanceIDFromPID

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetInstanceIDFromPID[C/C++]

COMAdminCatalog.GetInstanceIDFromPID Method [Visual Basic]

Gets an instance ID for the specified process ID. The instance ID is a GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to pause, resume, or recycle that process. For information on how to obtain the GUID, see GetRunningApps.

[C/C++]
HRESULT GetInstanceIDFromPID(
DWORD dwPID,
BSTR *pbstrInstanceID
) = 0;
[Visual Basic]
object. GetInstanceIDFromPID(dwPID, pbstrInstanceID)

Parameters [C/C++]

dwPID
[in] The specified process ID.
pbstrInstanceID
[out, retval] Points to the string containing the instance ID.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
dwPID
The specified process ID.
pbstrInstanceID
Points to the string containing the instance ID.

Return Value [C/C++]

S_OK
The method completed successfully.


IComAdminCatalog2::GetRunningApps

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::GetRunningApps [C/C++]

COMAdminCatalog.GetRunningApps Method [Visual Basic]

Gets the running application for the specified application. This is useful for discovering and enumerating individual running processes for the same or a different application, which then enables you to pause, resume, or query these processes.

[C/C++]
HRESULT GetRunningApps(
BSTR bstrApplIdOrName,
IDispatch** ppRunningAppCollection
) = 0;
[Visual Basic]
GetRunningApps(bstrApplIdOrName)

Parameters [C/C++]

bstrApplIdOrName
[in] The application ID or the COM+ application name. This is required.
ppRunningAppCollection
[out,retval] Points to the IDispatch interface containing the running application.

Parameters [Visual Basic]

bstrApplIdorName
Required String as a GUID representing the server process.

Return Value [Visual Basic]

GetRunningApps returns an object that supports the IRunningAppCollection interface.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
The ppRunningAppCollection parameter does not point to an IDispatch interface containing the running application.

Comments

Using the IRunningAppCollection object, you can retrieve objects that support the IRunningAppInfo interface.

The following Visual Basic example demonstrates how to call GetRunningApps:

Dim rapps As IRunningAppCollection

Dim cat as New COMAdmin.COMAdminCatalog

'Set the rapps object here by calling GetRunningApps.

Set rapps = cat.GetRunningApps("My Application")


IComAdminCatalog2::ImportComponentAsLegacy

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::ImportComponentAsLegacy [C/C++]

COMAdminCatalog.ImportComponentAsLegacy Method [Visual Basic]

Imports the specified class as a nonconfigured component.

[C/C++]
HRESULT ImportComponentAsLegacy(
BSTR bstrAppIdOrName,
BSTR bstrCLSIDOrProgId,
long lComponentType
) = 0;
[Visual Basic]
object.ImportComponentAsLegacy (bstrAppIdOrName, bstrCLSIDOrProgId, lComponentType)

Parameters [C/C++]

bstrAppIdOrName
[in] The application ID or the name of a COM+ application containing the component to be imported.
bstrCLSIDOrProgId
[in] The class ID or ProgID for the class object to be imported.
lComponentType
[in] One of the values from the COMAdminComponentType enumerations described in the following table.
Enumeration | Description
COMAdminUseAnyComponent | On a 64-bit computer, use either the 64-bit or the 32-bit implementation of the specified component. The 64-bit version is preferred. On a 32-bit computer, use the native 32-bit format.
COMAdminWOWComponent | On a 64-bit computer, use the 32-bit version of a component. On a 32-bit computer, use the native 32-bit format.
COMAdminNativeComponent | Use the format that is native to the computer.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrAppIdOrName
The application ID or the name of a COM+ application containing the component to be imported.
bstrCLSIDOrProgId
The class ID or ProgID for the class object to be imported.
lComponentType
One of the values from the COMAdminComponentType enumerations described in the following table.
Enumeration | Description
COMAdminUseAnyComponent | On a 64-bit computer, use either the 64-bit or the 32-bit implementation of the specified component. The 64-bit version is preferred. On a 32-bit computer, use the native 32-bit format.
COMAdminWOWComponent | On a 64-bit computer, use the 32-bit version of a component. On a 32-bit computer, use the native 32-bit format.
COMAdminNativeComponent | Use the format that is native to the computer.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
The attempt to import a component as-legacy into an application failed because the application does not live in the base partition.


IComAdminCatalog2::ImportComponentByType

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::ImportComponentByType [C/C++]

COMAdminCatalog.ImportComponentByType Method [Visual Basic]

Imports a component that is already registered as an inproc server in the 32-bit or 64-bit registry.

[C/C++]
HRESULT ImportComponentByType(
BSTR bstrApplIdOrName,
BSTR bstrCLSIDOrProgId,
long lComponentType
) = 0;
[Visual Basic]
object.ImportComponentByType(bstrApplIdOrName, bstrCLSIDOrProgId, lComponentType)

Parameters [C/C++]

bstrApplIdOrName
[in] The application ID or name.
bstrCLSIDOrProgId
[in] The CLSID of the application.
lComponentType
[in] One of the values from the COMAdminComponentType enumerations described in the following table.
Enumeration | Description
COMAdminUseAnyComponent | On a 64-bit computer, use either the 64-bit or the 32-bit implementation of the specified component. The 64-bit version is preferred. On a 32-bit computer, use the native 32-bit format.
COMAdminWOWComponent | On a 64-bit computer, use the 32-bit version of a component. On a 32-bit computer, use the native 32-bit format.
COMAdminNativeComponent | Use the format that is native to the computer.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrApplIdOrName
The application ID or name.
bstrCLSIDOrProgId
The CLSID of the application.
lComponentType
One of the values from the COMAdminComponentType enumerations described in the following table.
Enumeration | Description
COMAdminUseAnyComponent | On a 64-bit computer, use either the 64-bit or the 32-bit implementation of the specified component. The 64-bit version is preferred. On a 32-bit computer, use the native 32-bit format.
COMAdminWOWComponent | On a 64-bit computer, use the 32-bit version of a component. On a 32-bit computer, use the native 32-bit format.
COMAdminNativeComponent | Use the format that is native to the computer.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid lComponentType parameter.


IComAdminCatalog2::Is64BitCatalogServer

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::Is64BitCatalogServer [C/C++]

COMAdminCatalog.Is64BitCatalogServer Method [Visual Basic]

Determines whether the target catalog server is 64-bit.

[C/C++]
HRESULT Is64BitCatalogServer(
VARIANT_BOOL* pbIs64Bit
) = 0;
[Visual Basic]
object.Is64BitCatalogServer(pbIs64Bit)

Parameters [C/C++]

pbIs64Bit
[in] If the catalog server is 64-bit, this Boolean is VARIANT_TRUE; else VARIANT_FALSE.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
pbIs64Bit
If the catalog server is 64-bit, this Boolean is VARIANT_TRUE; else VARIANT_FALSE.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
The pbIs64Bit parameter is NULL.


IComAdminCatalog2::IsProcessDumpSupported

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::IsProcessDumpSupported [C/C++]

COMAdminCatalog.IsProcessDumpSupported Method [Visual Basic]

Tells the caller whether the process dump feature is supported on this server. The process dump feature provides a technique to debug COM+ application at the time of failure, by dumping the state of the application to a designated directory.

[C/C++]
HRESULT IsProcessDumpSupported(
VARIANT_BOOL *pbDumpSupported
) = 0;
[Visual Basic]
object.IsProcessDumpSupported(pbDumpSupported)

Parameters [C/C++]

pbDumpSupported
[out, retval] TRUE if process dump is supported else FALSE.

Return Value [C/C++]

VARIANT_TRUE
Process dump feature is supported.
VARIANT_FALSE
Process dump feature is not supported.

See Also

"Tool For Debugging COM+ Applications" in the Component Services administrative guide


IComAdminCatalog2::IsProcessPaused

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::IsProcessPaused [C/C++]

COMAdminCatalog.IsProcessPaused Method [Visual Basic]

Determines whether the server process is paused.

[C/C++]
HRESULT IsProcessPaused(
BSTR bstrApplInstanceId,
VARIANT_BOOL * bPaused
) = 0;
[Visual Basic]
IsProcessPaused(bstrApplInstanceId)

Parameters [C/C++]

bstrApplInstanceId
[in] The instance ID. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to check if a process is paused. For information on how to obtain the GUID, see GetRunningApps.
bPaused
[out,retval] Points to the VARIANT_BOOL variable that receives the paused state.

Parameters [Visual Basic]

bstrApplInstanceId
Required string as a GUID representing the server process.

Return Value [C/C++]

S_OK
Method completed successfully
E_INVALIDARG
The bstrApplInstanceId or bPaused parameter is NULL.
COMADMIN_E_APP_NOT_RUNNING
The specified process is not running.

Return Value [Visual Basic]

TRUE
The server process is paused.
FALSE
The server process is not paused.


IComAdminCatalog2::MoveComponent

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::MoveComponent [C/C++]

COMAdminCatalog.MoveComponent Method [Visual Basic]

Moves the component configuration while retaining the implementation.

[C/C++]
HRESULT MoveComponent(
BSTR bstrSourcePartitionId,
BSTR bstrDestinationPartitionId,
BSTR bstrClsid,
BSTR bstrDestinationApplId
);
[Visual Basic]
object.MoveComponent(bstrSourcePartitionId, bstrDestinationPartitionId, bstrClsid, bstrSourceApplId, bstrDestinationApplId)

Parameters [C/C++]

bstrSourcePartitionId
[in] The partition ID of the partition containing the component to be moved.
bstrDestinationPartitionId
[in] The partition ID of the partition to which the component will be moved.
bstrClsid
[in] The class ID of the component to be moved.
bstrDestinationApplId
[in] The application ID of the application to which the component will be moved.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrSourcePartitionId
The partition ID of the partition containing the component to be moved.
bstrDestinationPartitionId
The partition ID of the partition to which the component will be moved.
bstrClsid
The class ID of the component to be moved.
bstrDestinationApplId
The application ID of the application to which the component will be moved.

Return Value [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid arguments.


IComAdminCatalog2::PauseProcess

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::PauseProcess [C/C++]

COMAdminCatalog.PauseProcess Method [Visual Basic]

Pauses an application server process.

[C/C++]
HRESULT PauseProcess(
BSTR bstrApplInstanceId
) = 0;
[Visual Basic]
object.PauseProcess(bstrApplInstanceId)

Parameters [C/C++]

bstrApplInstanceId
[in] The instance ID. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to pause that process. For information on how to obtain the GUID, see GetRunningApps.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrApplInstanceId
The instance ID. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to pause that process. For information on how to obtain the GUID, see GetRunningApps.

Return Values [C/C++]

S_OK
The process is paused successfully.
E_INVALIDARG
The bstrAppInstancelId parameter is NULL.
COMADMIN_E_APP_NOT_RUNNING
The specified process is not running.
COMADMIN_S_SOMEALREADYPAUSED
Some of the running processes for the application are already paused. This is a status code, not an error code.


IComAdminCatalog2::PromoteLegacyComponent

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::PromoteLegacyComponent [C/C++]

COMAdminCatalog.PromoteLegacyComponent Method [Visual Basic]

Promotes the specified class to a configured COM+ component.

[C/C++]
HRESULT PromoteLegacyComponent(
BSTR bstrAppIdOrName,
BSTR bstrCLSIDOrProgId
) = 0;
[Visual Basic]
object.PromoteLegacyComponent(bstrAppIdOrName, bstrCLSIDOrProgId)

Parameters [C/C++]

bstrAppIdOrName
[in] The Application ID or the name of a COM+ application containing the component to be promoted.
bstrCLSIDOrProgId
[in] The class ID or ProgID for the class object to be promoted.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrAppIdOrName
The Application ID or the name of a COM+ application containing the component to be promoted.
bstrCLSIDOrProgId
The class ID or ProgID for the class object to be promoted.

Return Values [C/C++]

If the component being promoted does not have a DLL implementation, an error is returned. If the component being promoted is of incompatible bitness type with the COM+ application, an error is returned.
S_OK
Method completed successfully.
E_INVALIDARG
The bstrAppIdOrName or bstrCLSIDOrProgId parameter is NULL.


IComAdminCatalog2::RecycleProcess

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::RecycleProcess [C/C++]

COMAdminCatalog.RecycleProcess Method [Visual Basic]

Recycles an application server process.

[C/C++]
HRESULT RecycleProcess(
BSTR strInstanceId,
long * lReasonCode
) = 0;
[Visual Basic]
object.RecycleProcess(strInstanceId, lReasonCode)

Parameters [C/C++]

strInstanceId
[in] The instance ID. An instance ID is a GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to recycle that process. For information on how to obtain the instance ID, see GetRunningApps.
lReasonCode
[in] Points to the reason code for the recycled process. COM+ can recycle processes based on several criteria, including the number of minutes that an application runs before recycling, the amount of memory usage that a process cannot exceed, the number of calls to configured objects in the application, and the number of activations. You can select more than one criterion for recycling a process. COM+ recycles the process after the first of the set of criteria is satisfied.

Parameters [Visual Basic]

strInstanceId
The instance ID. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to recycle that process. For information on how to obtain the instance ID, see GetRunningApps.
lReasonCode
The reason code for the recycled process. COM+ can recycle processes based on several criteria, including the number of minutes that an application runs before recycling, the amount of memory usage that a process cannot exceed, the number of calls to configured objects in the application, and the number of activations. You can select more than one criterion for recycling a process. COM+ recycles the process after the first of the set of criteria is satisfied.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid arguments.
E_OUTOFMEMORY
Insufficient memory to complete the operation.


IComAdminCatalog2::ResumeProcess

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::ResumeProcess [C/C++]

COMAdminCatalog.ResumeProcess Method [Visual Basic]

Resumes an application server process.

[C/C++]
HRESULT ResumeProcess(
BSTR bstrApplInstanceId
) = 0;
[Visual Basic]
object.ResumeProcess(bstrApplInstanceId)

Parameters [C/C++]

bstrApplInstanceId
[in] The instance ID. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to resume that process. For information on how to obtain the instance ID, see GetRunningApps.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrApplInstanceId
The instance ID. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to resume that process. For information on how to obtain the instance ID, see GetRunningApps.

Return Values [C/C++]

S_OK
The process is resumed successfully.
E_INVALIDARG
The bstrApplInstanceId parameter is NULL.
COMADMIN_E_APP_NOT_RUNNING
The specified process is not running.
COMADMIN_S_ SOMEALREADYRUNNING
Some of the running processes for the application are already running. This is a status code, not an error code.


IComAdminCatalog2::SetApplicationPartition

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IComAdminCatalog2::SetApplicationPartition [C/C++]

COMAdminCatalog.SetApplicationPartition Method [Visual Basic]

Sets the partition scope for all subsequent COM+ administrative calls. This is useful for scoping COMAdminCatalog calls.

For example, prior to installing an application into a partition named Test, the user can set the partition to Test, and then install the application into that partition.

Without a call to this method, COM+ by default scopes administrative calls to the user's default partition.

[C/C++]
HRESULT SetApplicationPartition(
BSTR bstrApplPartitionIdOrName
) = 0;
[Visual Basic]
object.SetApplicationPartition(bstrApplPartitionIdOrName)

Parameters [C/C++]

bstrApplPartitionIdOrName
[in] The string containing the partition ID or name of the application.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrApplPartitionIdOrName
The string containing the partition ID or name of the application.

Return Value [C/C++]

S_OK
The method completed successfully.
E_INVALIDARG
The bstrApplPartitionIdOrName parameter is GUID_NULL.
COMADMIN_E_OBJECT_DOES_NOT_EXIST
The partition is GUID_NULL and does not exist on this computer.

Comments

If there is no context or the partition ID in the context is unknown (GUID_NULL), the partition scope will be set to the base partition.


ICOMAdminCatalog2::ShutdownProcess

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICOMAdminCatalog2::ShutdownProcess [C/C++]

COMAdminCatalog.ShutdownProcess Method [Visual Basic]

Initiates the shutdown of the specified server process.

[C/C++]
HRESULT ShutdownProcess(
BSTR bstrApplInstanceId
) = 0;

[Visual Basic]
object.ShutdownProcess(bstrApplInstanceId)

Parameters [C/C++]

bstrApplInstanceId
[in] The instance ID. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to shutdown that process. For information on how to obtain the instance ID, see GetRunningApps.

Parameters [Visual Basic]

object
Required object that references a COMAdminCatalog object.
bstrApplInstanceId
Required string as the GUID of the server process to shut down.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
The bstrApplInstanceId parameter is NULL.


ICatalogCollection Interface

Use this interface to represent any collection on the COM+ catalog. Enables you to enumerate, add, remove, and retrieve items in a collection, and to access related collections.

When to Implement

You do not need to implement the ICatalogCollection interface. A system-supplied class object, COMAdminCatalogCollection, implements ICatalogCollection.

When to Use

You use ICatalogCollection to represent any collection on the COM+ catalog. The GetCollection methods on both the ICOMAdminCatalog and ICatalogCollection interfaces return pointers to ICatalogCollection when you retrieve a given collection.

Use the methods and properties on ICatalogCollection to add, remove, enumerate through, and retrieve items in the collection it is being used to represent. The items within a collection can be represented and modified with the ICatalogObject interface.

For information regarding the collections on the COM+ catalog see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

Methods in Vtable Order

This table is presented for when you use interfaces directly as in C++.

If you are using Visual Basic, the ICatalogCollection methods are implemented on the COMAdminCatalogCollection object.

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
ICatalogCollection Methods | Description
get__NewEnum | Gets a pointer to the IEnumVariant enumerator interface.
get_Item | Gets a pointer to the ICatalogObject interface for an object in the collection given its index.
get_Count | Gets the number of objects in the collection.
Remove | Removes an object from the collection given its index.
Add | Adds a default object to the collection and passes back a pointer to its ICatalogObject interface.
Populate | Reads in data from the catalog data store for all objects in the collection.
SaveChanges | Saves any changes made to the collection and its objects into the catalog data store.
GetCollection | Gets a collection related to a specific object.
get_Name | Gets the name of the collection.
get_AddEnabled | Gets true if Add is enabled.
get_RemoveEnabled | Gets true if Remove is enabled.
GetUtilInterface | Gets a utility interface for the collection. Note: Not used with COM+ Administration objects; for legacy software only.
get_DataStoreMajorVersion | Gets the major version number of the catalog data store.
get_DataStoreMinorVersion | Gets the minor version number of the catalog data store.
PopulateByKey | Reads in data from the catalog data store only for objects specified by key.
PopulateByQuery | Reserved for future use.


ICatalogCollection Properties

The ICatalogCollection interface and COMAdminCatalogCollection object expose the properties described in this topic.

[C/C++]

In C++, programs call methods of the ICatalogCollection interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters [C/C++]

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the AddEnabled property is a VARIANT_BOOL variable. The method that gets this property has the prototype:

HRESULT get_AddEnabled( VARIANT_BOOL * retval );

Properties [C/C++]

The following table lists the properties that are managed by the ICatalogCollection interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
Item | G | COMAdminCatalogObject | Returns a reference to an object from the collection given its index. See Remarks below.
Count | G | long | The number of objects in the collection.
Name | G | VARIANT | The name of the collection.
AddEnabled | G | VARIANT_BOOL | True if Add is enabled for the collection.
RemoveEnabled | G | VARIANT_BOOL | True if Remove is enabled for the collection.
DataStoreMajorVersion | G | long | The major version number of the catalog data store.
DataStoreMinorVersion | G | long | The minor version number of the catalog data store.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.

[Visual Basic]

Property | Description
AddEnabled | Returns a Boolean indicating whether the Add method is enabled for the collection.
Count | Returns a Long indicating the number of items in the collection.
DataStoreMajorVersion | Returns a Long indicating the major version number of the catalog data store.
DataStoreMinorVersion | Returns a Long indicating the minor version number of the catalog data store.
Item | Returns a COMAdminCatalogObject object as an indexed item of the collection.
Name | Returns a Variant as the name of the collection.
RemoveEnabled | Returns a Boolean indicating whether the Remove method is enabled for the collection.

Remarks [C/C++]

The get_Item method is anomolous as a property. It gets an interface pointer for an object in the collection. It has the prototype:

HRESULT  get_Item(
  long lIndex,  IDispatch * ppCatalogObject
);

Remarks [Visual Basic]

The Item property is used to retrieve an object in the collection, based on its index within the collection. The syntax is:

set object = collectionobject.Item(lIndex As Long)

where x evaluates to a COMAdminCatalogObject object, object evaluates to a COMAdminCatalogCollection object, and lIndex specifies the object's index.


ICatalogCollection::Add

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::Add [C/C++]

COMAdminCatalogCollection.Add Method [Visual Basic]

Adds an item to the collection, giving it the high index value. This change will not be reflected on the persisted COM+ catalog data store until you use SaveChanges.

[C/C++]Passes back a pointer to an ICatalogObject interface for the new item.

[Visual Basic]Returns a reference to the new item as a COMAdminCatalogObject object.

Syntax

[C/C++]
HRESULT ICatalogCollection::Add(
  IDispatch **ppCatalogObject
);

[Visual Basic]
set object = CollectionObject.Add

Parameters [C/C++]

ppCatalogObject [out]
A reference to the ICatalogObject interface for the new object.

Parts of Syntax [Visual Basic]

x
Required object variable that evaluates to the COMAdminCatalogObject object being added to the collection.
object
Required object variable that evaluates to the COMAdminCatalogCollection object to which you are adding.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Can indicate that an Out parameter is NULL.
E_NOTIMPL
This function is not implemented.

Remarks

The AddEnabled property indicates whether the collection supports this method.

When an object has been added the Count property is updated to reflect the change.

Call the SaveChanges method to write the new object to the persisted COM+ catalog data store. Until you call SaveChanges you are only affecting transient cached data, not the catalog itself.


ICatalogCollection::get__NewEnum

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::get__NewEnum [C/C++]

[C/C++] Gets the IEnumVariant enumerator interface which can be used to iterate through the collection objects.

[Visual Basic] Not available in Visual Basic.

Syntax[C/C++]

HRESULT ICatalogCollection::get__NewEnum(
  IUnknown **ppEnumVariant
);

Parameters [C/C++]

ppEnumVariant [out]
A reference to the EnumVariant interface for an enumerator object for the collection.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Can indicate that an Out parameter is NULL.
E_OUTOFMEMORY
Insufficient memory to complete the operation.


ICatalogCollection::GetCollection

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::GetCollection [C/C++]

COMAdminCatalogCollection.GetCollection Method [Visual Basic]

Retrieves a collection from the COM+ catalog that is related to the present collection. Takes a Key value indicating the parent item for the collection to be retrieved.

[C/C++] Passes back a pointier to an ICatalogCollection interface.

[Visual Basic] Returns a reference to a COMAdminCatalogCollection object.

Syntax

[C/C++]
HRESULT ICatalogCollection::GetCollection(
  BSTR bstrCollName,
  VARIANT varObjectKey,
  IDispatch **ppCatalogCollection
);

[Visual Basic]
set x = object.GetCollection(bstrCollName, varObjectKey)

Parameters [C/C++]

bstrCollName [in]
The name of the collection to retrieve from the catalog.
varObjectKey [in]
The key value for the object to which the collection is related.
ppCatalogCollection [out]
A reference to the ICatalogCollection interface for the collection.

Parts [Visual Basic]

x
Required object. Collection returned as a COMAdminCatalogCollection object.
object
Required object variable that evaluates to a COMAdminCatalogCollection object.
bstrCollName
Required String specifying the type of collection to return.
varObjectKey
Required Variant. Unique key value indicating the item to which the returned collection corresponds.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid name passed as a parameter. Can also indicate that an Out parameter is NULL.
E_OUTOFMEMORY
Insufficient memory to complete the operation.

Remarks

The Key property value uniquely identifies an item in a collection on the catalog.

GetCollection does not read in data for items in the collection from the catalog data store. Use the Populate or method to read in data for items in the collection.


ICatalogCollection::GetUtilInterface

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::GetUtilInterface [C/C++]

COMAdminCatalogCollection.GetUtilInterface Method [Visual Basic]

Gets the utility interface for the collection.

This method is for use with MTS 2.0 Administration interfaces and objects and should not be used with COM+ Administration interfaces and objects.

Syntax

[C/C++]
HRESULT ICatalogCollection::GetUtilInterface(
  IDispatch **ppUtil
);

[Visual Basic]
set x = object.GetUtilInterface

Parameters [C/C++]

ppUtil
[out] A reference to the interface on a utility object for the collection.

Parts [Visual Basic]

x
Required object. Catalog utility returned as a COMAdminCatalog object.
object
Required object variable that evaluates to a COMAdminCatalogCollection object.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Can indicate that an Out parameter is NULL.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks

The GetUtilInterface method will work as before with MTS 2.0 Administration interfaces and objects, with the exception of IRemoteComponentUtil which is no longer supported. This method should not be used with COM+ Administration interfaces and objects.


ICatalogCollection::Populate

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::Populate [C/C++]

COMAdminCatalogCollection.Populate Method [Visual Basic]

Populates the collection with data for all items contained in the collection.

Syntax

[C/C++]
HRESULT ICatalogCollection::Populate(void);

[Visual Basic]
object.Populate

Parts [Visual Basic]

object
Required object variable that evaluates to the COMAdminCatalogCollection object to populate.

Return Values [C/C++]

S_OK
Method completed successfully.
S_FALSE
There are no items in the collection.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks

Call the SaveChanges method prior to the Populate method if you wish to save pending changes. Unsaved changes made to the collection will be lost when you call the Populate method.


ICatalogCollection::PopulateByKey

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::PopulateByKey [C/C++]

COMAdminCatalogCollection.PopulateByKey Method [Visual Basic]

[C/C++]Populates a selected list of items in the collection from the COM+ catalog, based on the specified keys.

[Visual Basic]The PopulateByKey method is not available from Visual Basic.

Syntax [C/C++]

HRESULT ICatalogCollection::PopulateByKey(
  SAFEARRAY *saKeys
);

Parameters [C/C++]

saKeys [in]
Reference to an array containing the key values for the objects for which data should be read from the catalog.

Return Values [C/C++]

S_OK
Method completed successfully.
S_FALSE
The selected items are not in the collection.
E_INVALIDARG
Invalid value passed as a parameter. Can also indicate that an Out parameter is NULL.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks[C/C++]

Item keys are determined by their Key property value.

Call the SaveChanges method prior to PopulateByKey if you wish to save pending changes. Unsaved changes made to the collection will be lost when you call PopulateByKey.


ICatalogCollection::PopulateByQuery

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

CatalogCollection::PopulateByQuery [C/C++]

COMAdminCatalogCollection.PopulateByQuery Method [Visual Basic]

Reserved for future use.

Syntax

[C/C++]
HRESULT ICatalogCollection::PopulateByQuery(
  BSTR bstrQueryString,
  long lQueryType
);

[Visual Basic]
object.PopulateByQuery(bstrQueryString, lQueryType)

Parameters [C/C++]

bstrQueryString [in]
lQueryType [in]

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalogCollection object.
bstrQueryString
Required.
lQueryType
Required.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid value passed as a parameter. Can also indicate that an Out parameter is NULL.
E_NOTIMPL
This function is not implemented.


ICatalogCollection::Remove

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::Remove [C/C++]

COMAdminCatalogCollection.Remove Method [Visual Basic]

Removes an item from the collection given its index, and re-indexes the items with higher indices. These changes are not reflected on the COM+ catalog data store until you use SaveChanges.

Syntax

[C/C++]
HRESULT ICatalogCollection::Remove(
  long lIndex
);

[Visual Basic]
object.Remove(lIndex)

Parameters [C/C++]

lIndex [in]
The index of the item to be removed.

Parts [Visual Basic]

object
Required object variable that evaluates to a COMAdminCatalogCollection object.
lIndex
Required zero-based index of the object to be removed.

Return Values [C/C++]

S_OK
Method completed successfully.
E_INVALIDARG
Invalid value passed as a parameter.
E_NOTIMPL
This function is not implemented.

Remarks

The RemoveEnabled property indicates whether the collection supports this method.

When an object has been removed, objects with higher indices reindexed downward to fill its place; that is, if you remove item n, items n+1...m will slide down to become items n...m-1. The Count property will be decremented to reflect the change.

Call the SaveChanges method to save changes to the collection made using Remove to the persisted COM+ catalog data store. Until you call SaveChanges, you are only affecting transient cached data, not the catalog itself.


ICatalogCollection::SaveChanges

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogCollection::SaveChanges [C/C++]

COMAdminCatalogCollection.SaveChanges Method [Visual Basic]

Saves all pending changes made to the collection and the items it contains to the COM+ catalog data store.

Syntax

[C/C++]
HRESULT ICatalogCollection::SaveChanges(
  long *retval
);

[Visual Basic]
set x = object.SaveChanges

Parameters [C/C++]

retval [out]
The number of changes applied to the collection.

Parts [Visual Basic]

x
Optional Long to store the number of changes saved.
object
Required object variable that evaluates to the COMAdminCatalogCollection object for which to save changes.

Return Values [C/C++]

S_OK
Method completed successfully.
S_FALSE
The collection has not changed.
E_INVALIDARG
Can indicate that an Out parameter is NULL.
COMADMIN_E_OBJECTERRORS
Errors occurred accessing one or more objects.

Remarks

The SaveChanges method works exclusively on the collection on which you call it, and applies all pending changes to the COM+ catalog data store.

It will write all properties for a given item at a time to the catalog. That is, if the write succeeds for that item, then all properties as they were set in the item you held will be reflected on the catalog. The rule with multiple parties writing the same item in a collection is: last writer wins entirely. There are no partial updates.

SaveChanges passes back a Long value indicating the number of changes it is attempting to apply to the catalog; if no changes are pending the value will be zero. If some changes fail, the returned value will not reflect the failure, it will still be the number of changes attempted.


ICatalogObject Interface

Use this interface to represent items in collections on the COM+ catalog. Enables you to get and put properties exposed by objects on the catalog.

When to Implement

You do not need to implement the ICatalogObject interface. A system-supplied class object, COMAdminCatalogObject, implements ICatalogObject.

When to Use

You use ICatalogObject to represent any item in a collection on the COM+ catalog. The get_Item method on the ICatalogCollection interface returns a pointer to ICatalogObject when it retrieves an item in the collection.

Use the methods and properties of ICatalogObject to set and get properties on the item it is being used to represent. Any changes you make to the item using ICatalogObject are not reflected on the catalog data store until you call SaveChanges for the collection containing the item.

For information regarding collections and properties exposed by items in collections see Administration Collections.

For an introduction to programmatic administration of COM+, see Automating COM+ Administration.

Methods in Vtable Order

This table is presented for when you use interfaces directly as in C++.

If you are using Visual Basic, the ICatalogCollection methods are implemented on the COMAdminCatalogCollection object.

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
ICatalogObject Methods | Description
get_Value | Gets a property value.
put_Value | Sets a property value.
get_Key | Gets the value of the key property.
get_Name | Gets the name of the object.
IsPropertyReadOnly | True if the property cannot be set.
get_Valid | True if all properties were successfully read from the catalog data store.
IsPropertyWriteOnly | True if the property can only be set.


ICatalogObject Properties

The ICatalogObject interface and COMAdminCatalogObject object expose the properties described in this topic.

[C/C++]

In C++, programs call methods of the ICatalogObject interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters [C/C++]

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the Valid property is a VARIANT_BOOL variable. The method that gets this property has the prototype:

HRESULT get_Valid( VARIANT_BOOL * retval );

Properties [C/C++]

The following table lists the properties that are managed by the ICatalogObject interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
Value | GP | VARIANT | The value for any named property of the object. See Remarks below.
Key | G | VARIANT | The key identifying the object.
Name | G | VARIANT | Name of the object.
Valid | G | VARIANT_BOOL | True if all properties of the object were successfully read.

Properties [Visual Basic]

Property | Description
Key | Returns a Variant as the key identifying the item the object represents.
Name | Returns a Variant as the name of the item the object represents.
Valid | Returns a Boolean indicating whether or not all properties of the object were successfully read from the catalog data store.
Value | Returns/sets a Variant as the value for the specified property. See Remarks below.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.

Remarks [C/C++]

The Key property serves as the primary identifier for an object. In some cases it will be a GUID, such as CLSID for a component; in some cases it will be the item name, as with roles. Key properties are identified in the documentation for each specific collection. Note that if you add a new object and save it with the Key property of an existing object, you will overwrite the existing object.

The Value property is used to get or put a specific named property exposed by an item being represented by an ICatalogObject interface.

To get a named property, you provide a string naming the property, and a Variant containing the property value is passed back. The syntax is:

HRESULT  get_Value(
  BSTR  bstrPropName,
  VARIANT  * retval
);

To set a named property, you provide a string naming the property, and a Variant containing the property value. The syntax is:

HRESULT  put_Value(
  BSTR  bstrPropName,
  VARIANT  * val
);

For information regarding properties exposed by items in each collection see Administration Collections.

Remarks [Visual Basic]

The Value property is used to get or put a specific named property exposed by an item being represented by a COMAdminCatalogObject object.

To get a named property, you provide a string naming the property, and a variant containing the property value is returned.

x = object.Value("PropertyName")

where x is a Variant.

To set a named property, you provide a string naming the property, and a variant containing the property value.

object.Value("PropertyName") = x

where x is a Variant.

For information regarding properties exposed by items in each collection see Administration Collections.


ICatalogObject::IsPropertyReadOnly

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogObject::IsPropertyReadOnly [C/C++]

COMAdminCatalogObject.IsPropertyReadOnly Method [Visual Basic]

True if the specified property cannot be set.

Syntax

[C/C++]
HRESULT ICatalogObject::IsPropertyReadOnly(
  BSTR bstrPropName,
  VARIANT_BOOL *retval
);

[Visual Basic]
x = object.IsPropertyReadOnly(bstrPropName)

Parameters [C/C++]

bstrPropName [in]
Name of the property to be checked.
retval [out]
True if the specified property cannot be set.

Parts [Visual Basic]

x
Optional Variant to hold the Boolean value indicating whether the property is read only.
object
Required object variable that evaluates to a COMAdminCatalogObject object.
PropertyName
Required String containing the name of the property to be checked.

Return Values [C/C++]

S_OK
The property was successfully obtained or written.
E_INVALIDARG
Invalid property name passed as a parameter. Can also indicate that an out parameter is NULL.

Remarks

If the value returned by the IsPropertyReadOnly method is True, then you cannot modify the property. If the value returned is False, you can modify the property using Value.


ICatalogObject::IsPropertyWriteOnly

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ICatalogObject::IsPropertyWriteOnly [C/C++]

COMAdminCatalogObject.IsPropertyWriteOnly Method [Visual Basic]

True if the specified property cannot be read.

Syntax

[C/C++]
HRESULT ICatalogObject::IsPropertyWriteOnly(
  BSTR bstrPropName,
  VARIANT_BOOL *retval
);

[Visual Basic]
x = object.IsPropertyWriteOnly(bstrPropName)

Parameters [C/C++]

bstrPropName [in]
Name of the property to be checked.
retval [out]
True if the specified property cannot be read.

Parts [Visual Basic]

x
Optional Variant to hold the Boolean value indicating whether the property is write only.
object
Required object variable that evaluates to a COMAdminCatalogObject object.
bstrPropName
Required String containing the name of the property to be checked.

Return Values [C/C++]

S_OK
The property was successfully obtained or written.
E_INVALIDARG
Invalid property name passed as a parameter. Can also indicate that an out parameter is NULL.

Remarks

If the value returned by the IsPropertyWriteOnly method is True, then you cannot read the property. If the value returned is False, you can read the property using the Value property.


IRunningAppCollection

The IRunningAppCollection interface gives the user the capability to find and enumerate individual processes for an application and then initiate pause, resume or query operations on these individual processes.

When to Implement

You do not normally implement IRunningAppCollection. To use this interface in Microsoft Visual Basic you call GetRunningApps on the COMAdminCatalog object and the object that is returned implements the IRunningAppCollection interface.

When to Use

You use IRunningAppCollection when you want to navigate to and retrieve objects that support the IRunningAppInfo interface. The objects returned by calling the Item property implement IRunningAppInfo.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IRunningAppCollection Methods | Description
get_NewEnum | Gets the enumeration of objects in the collection.
get_Item | Gets the count of the applications in the collection.
get_Count | Returns the application instance by the specified index.

Requirements

To use the methods of this interface, you must include Comadmin.h in your project.


IRunningAppCollection Properties

The IRunningAppCollection interface exposes the properties described in this topic.

[C/C++]

In C++, programs call methods of the IRunningAppCollection interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters [C/C++]

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the NewEnum property is a IUnknown** variable. The method that gets this property has the following prototype:

HRESULT get_NewEnum(
   IUnknown ** pUnkEnum
);

Properties [C/C++]

The following table lists the properties that are managed by the IRunningAppCollection interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
get_NewEnum | G | IUnknown ** | Gets the enumeration of objects in the collection. Returns an object that implements the IEnumVariant interface.
get_Count | G | long* | Gets the count of the applications in the collection.
get_Item | G | long IDispatch** | Returns the application instance by the specified index.

Properties [Visual Basic]

Property | Description
_NewEnum | Gets the enumeration of objects in the collection.
Count | Gets the count of the applications in the collection.
Item | Returns the application instance by the specified index.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.

Remarks [C/C++]

The get_Item method is anomalous as a property. It gets an interface pointer for an object in the IRunningAppInfo collection. It has the prototype:

HRESULT  get_Item(
  long lIndex,
  IDispatch * ppAppObject
);

Remarks [Visual Basic]

The following example demonstrates how to call the Count property implemented by IRunningAppCollection.

COMAdminCatalog.GetRunningApps.Count

The Item property is used to retrieve the IRunningAppInfo object in the collection, based on its index within the collection. The syntax is:

dim x as IRunningAppInfo

The following example demonstrates how to iterate through an IRunningAppCollection and how to call GetRunningApps.

Dim rappinfo as IRunningAppInfo

Dim rapps As IRunningAppCollection

Dim strAppInfo As String

Dim cat as New COMAdmin.COMAdminCatalog

‘Set the rapps object here by calling GetRunningApps.

Set rapps = cat.GetRunningApps(“My Application”)

For Each rappinfo In rapps

MsgBox “ApplicationID: “ + rappinfo.ApplicationID + vbCrLF + _

“InstanceID: “ + rappinfo.InstanceID + vbCrLF + _

“ProcessID: “ + CStr(rappinfo.ProcessID + vbCrLF + _

“Paused: “ + CStr(rappinfo.Paused)

Next


IRunningAppInfo

The IRunningAppInfo interface gives the user the capability to find and enumerate individual processes for the same or different applications and then initiate pause, resume or query operations on these individual processes.

When to Implement

You do not normally implement IRunningAppInfo. To use this interface in Microsoft Visual Basic you call GetRunningApps on the COMAdminCatalog object and then call the Item property on the IRunningAppCollection interface. The object that is returned implements the IRunningAppInfo interface.

When to Use

You use IRunningAppInfo to discover the application ID, instance ID, process ID or partition ID and the paused status for running processes of a specific application.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IRunningAppInfo Methods | Description
get_PartitionID | Gets the partition ID for this process.
get_ApplicationID | Gets the application ID for this process.
get_InstanceID | Gets the instance ID of this process.
get_ProcessID | Gets the process ID for this process.
get_Paused | Returns TRUE if the process is paused; else returns FALSE.
get_Recycled | Returns TRUE if the process is being recycled; else returns FALSE.

Requirements

To use the methods of this interface, you must include Comadmin.h in your project.


IRunningAppInfo Properties

The IRunningAppInfo interface exposes the properties described in this topic.

[C/C++]

In C++, programs call methods of the IRunningAppInfo interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters [C/C++]

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the get_Application property is a BSTR* variable. The method that gets this property has the following prototype:

HRESULT get_ApplicationID(
   BSTR* pbstrAppID
);

Properties [C/C++]

The following table lists the properties that are managed by the IRunningAppInfo interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
get_ApplicationID | G | BSTR* | Gets the application ID for this process.
get_InstanceID | G | BSTR* | Gets the instance ID of this process. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to pause, resume, or recycle that process.
get_ProcessID | G | long * | Gets the process ID for this process.
get_Paused | G | VARIANT_BOOL* | Returns TRUE if the process is paused; else returns FALSE.
get_PartitionID | G | BSTR | Gets the partition ID for this process.
get_Recycled | G | VARIANT_BOOL | Returns TRUE if the process is being recycled; else returns FALSE.

Properties [Visual Basic]

Property | Description
ApplicationID | Gets the application ID for this process.
InstanceID | Gets the instance ID of this process. An instance ID is GUID, which identifies one running instance of a particular application. The instance ID is needed if you want to pause, resume, or recycle that process.
ProcessID | Gets the process ID for this process.
Paused | Returns True if the process is paused; else returns False.
PartitionID | Gets the partition ID for this process.
Recycled | Returns TRUE if the process is being recycled; else returns FALSE.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.

Remarks [Visual Basic]

The following example demonstrates how to call the ProcessID property implemented by IRunningAppInfo.

COMAdminCatalog.GetRunningApps.Item.ProcessID

The following example demonstrates how to iterate through an IRunningAppCollection and how to call GetRunningApps.

Dim rappinfo as IRunningAppInfo

Dim rapps As IRunningAppCollection

Dim strAppInfo As String

Dim cat as New COMAdmin.COMAdminCatalog

‘Set the rapps object here by calling GetRunningApps.

Set rapps = cat.GetRunningApps(“My Application”)

For Each rappinfo In rapps

MsgBox “ApplicationID: “ + rappinfo.ApplicationID + vbCrLF + _

“InstanceID: “ + rappinfo.InstanceID + vbCrLF + _

“ProcessID: “ + CStr(rappinfo.ProcessID + vbCrLF + _

“Paused: “ + CStr(rappinfo.Paused)

Next


COM+ Programmer's Reference

Reference topics include:

Topic | Description
Objects | Describes the objects that you can use to manage your COM+ applications programmatically.
Interfaces | Describes the interfaces that you can use to manage your COM+ applications programmatically.
Functions | Describes the functions that you can use to get object and call context information.
Enumerations | Describes the enumerations that you can use to define a list of integer constants in COM+.

For more reference information for COM+ developers see the Tools Developer’s Guide.


Objects

Object | Description
SecurityIdentity Object | Provides access to items that describe a particular caller's identity, such as the SID, the account name, the authentication service used, the authentication level used, and the impersonation level used.
SecurityProperty Object | Enables you to obtain information about the object's original caller and direct caller.
SecurityCallContext Object | Provides access to the current call's security context, which contains information about an object's callers, provided in the form of a collection.
SecurityCallers Object | Represents a chain of callers exposed as the "Callers" item in the SecurityCallContext collection.

Note These objects are provided by the COM+ Services Type Library DLL (Comsvcs.dll).


ContextInfo

The IObjectContextInfo object returns transaction, activity, and context information on the current context object. Using the methods of this object, you can retrieve information contained within an object context.

When To Implement

You should not implement this interface. The standard implementation provides complete functionality.

When To Use

You use this interface to track object context information based on a specific transaction, activity, or context.

Method | Description
IsInTransaction | Indicates whether the current object is executing in a transaction.
GetTransaction | Returns a pointer to the ITransaction interface of the current transaction.
GetTransactionId | Returns the identifier of the current transaction.
GetActivityId | Returns the identifier of the current activity.
GetContextId | Returns the identifier of the current context.

Requirements

To use the methods of this interface, you must include comsvcs.h in your file or set a reference to the comsvcs.dll in your project.

See Also

Contexts


SharedProperty

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

SharedProperty Object

The SharedProperty object implements ISharedProperty Interface and is used to set or retrieve the value of a shared property. A shared property can contain any data type that can be represented by a variant.

Remarks

To use the SharedProperty object, you must set a reference to the Shared Property Manager Type Library (mtxspm.dll).

You can create a SharedProperty object with the CreateProperty method or the CreatePropertyByPosition method of the SharedPropertyGroup Object.

A SharedProperty object can be created or accessed only from within a SharedPropertyGroup.

As with any COM object, you must release a SharedProperty object when you're finished using it, unless it's a local variable. For example:

Set myProperty = Nothing

The SharedProperty object provides the following property.

Property | Description
Value | Sets or retrieves the value of a shared property.


SharedPropertyGroup Object

The SharedPropertyGroup object implements ISharedPropertyGroup. You can use this object to create and access the shared properties in a shared property group.

Remarks

To use the SharedPropertyGroup object, you must set a reference to the Shared Property Manager Type Library (mtxspm.dll).

You can create a SharedPropertyGroup object with the CreatePropertyGroup method of the SharedPropertyGroupManager object.

As with any COM object, you must release a SharedPropertyGroup object when you're finished using it, unless it's a local variable. For example:

Set myPropertyGroup = Nothing

The SharedPropertyGroup object provides the following methods and properties.

Method | Description
CreateProperty | Creates a new shared property identified by a string expression that's unique within its property group.
CreatePropertyByPosition | Creates a new shared property identified by a numeric index within its property group.
Property Methods | Description
Property | Returns a reference to a shared property, given the string name by which the property is identified.
PropertyByPosition | Returns a reference to a shared property, given its numeric index in the shared property group.


SharedPropertyGroupManager Object

The SharedPropertyGroupManager object implements ISharedPropertyGroupManager that you can use to create shared property groups and to obtain access to existing shared property groups.

Remarks

To use the SharedPropertyGroupManager object, you must set a reference to the Shared Property Manager Type Library (mtxspm.dll).

You can access the SharedPropertyGroupManager object by using either the CreateObject function or the CreateInstance method of the ObjectContext object. It makes no difference which you use.

The Shared Property Manager is a resource dispenser that you can use to share state among multiple objects within a server process. You can't use global variables in a distributed environment because of concurrency and name collision issues. The Shared Property Manager eliminates name collisions by providing shared property groups, which establish unique name spaces for the shared properties they contain. The Shared Property Manager also implements locks and semaphores to protect shared properties from simultaneous access, which could result in lost updates and could leave the properties in an unpredictable state.

Shared properties can be shared only by objects running in the same process. If you want instances of different components to share properties, you have to install the components in the same COM+ application. Because there is a risk that administrators will move components from one package to another, it's safest to limit the use of a shared property group to instances of components that are defined in the same DLL.

It's also important for components sharing properties to have the same activation attribute. If two components in the same package have different activation attributes, they generally won't be able to share properties. For example, if one component is configured to run in a client's process and the other is configured to run in a server process, their objects will usually run in different processes, even though they're in the same package.

You should always instantiate the SharedPropertyGroupManager, SharedPropertyGroup, and SharedProperty objects from COM+ objects rather than from a base client. If a base client creates shared property groups and properties, the shared properties are inside the base client's process, not in a server process. This means COM+ objects can't share the properties unless the objects, too, are running in the client's process (which is generally not a good idea).

Note When you set the isolation mode to LockMethod, the Shared Property Manager requires access to the calling object's ObjectContext. You can't use this isolation mode to create a shared property group from within an object's constructor or from a non-MTS object because ObjectContext isn't available during object construction and a non-MTS object doesn't have an ObjectContext.

The SharedPropertyGroupManager object provides the following methods and properties.

Method | Description
CreatePropertyGroup | Creates a new SharedPropertyGroup with a string name as an identifier. If a group with the specified name already exists, CreatePropertyGroup returns a reference to the existing group.
Group | Returns a reference to an existing shared property group, given a string name by which it can be identified.


ObjectContext Object

The ObjectContext object implements the IObjectContext automation interface, which provides access to the current object's context.

Methods | Description
CreateInstance | Creates an object using current object's context.
DisableCommit | Declares that the object hasn't finished its work and that its transactional updates are in an inconsistent state. The object retains its state across method calls, and any attempts to commit the transaction before the object calls EnableCommit or SetComplete will result in the transaction being aborted.
EnableCommit | Declares that the object's work isn't necessarily finished, but its transactional updates are in a consistent state. This method allows the transaction to be committed, but the object retains its state across method calls until it calls SetComplete or SetAbort, or until the transaction is completed.
IsCallerInRole | Indicates whether the object's direct caller is in a specified role (either directly or as part of a group).
IsInTransaction | Indicates whether the object is executing within a transaction.
IsSecurityEnabled | Indicates whether security is enabled. COM+ security is enabled unless the object is running in the client's process.
SetAbort | Declares that the object has completed its work and can be deactivated on returning from the currently executing method, but that its transactional updates are in an inconsistent state or that an unrecoverable error occurred. This means that the transaction in which the object was executing must be aborted. If any object executing within a transaction returns to its client after calling SetAbort, the entire transaction is doomed to abort.
SetComplete | Declares that the object has completed its work and can be deactivated on returning from the currently executing method. For objects that are executing within the scope of a transaction, it also indicates that the object's transactional updates can be committed. When an object that is the root of a transaction calls SetComplete, COM+ attempts to commit the transaction on return from the current method.
Properties | Description
ContextInfo | Returns the context information object.
Count | Returns the number of named context object properties.
Item | Retrieves a named property.
Security | Returns the security object.


ObjectControl Object

The ObjectControl object implements the IObjectControl interface, which you use to define context-specific initialization and cleanup procedures for your COM+ objects and specify whether or not the objects can be recycled.

For more information on managing object state and just-in-time activation, see Object State, Activation, and Deactivation.

Methods | Description
Activate | Allows an object to perform context-specific initialization whenever it's activated. This method is called by COM+ before any other methods are called on the object.
CanBePooled | Allows an object to notify COM+ of whether it can be pooled for reuse.
Deactivate | Allows an object to perform whatever cleanup is necessary before it's recycled or destroyed.


SecurityIdentity Object

The SecurityIdentity object is a collection that provides access to information that describes a particular caller's identity, such as the SID, the account name, the authentication service, the authentication level, and the impersonation level. The SecurityIdentity object implements ISecurityIdentityColl.

The DirectCaller and OriginalCaller items of the SecurityCallContext collection are SecurityIdentity objects. The Item property allows you to retrieve items in the SecurityIdentity collection. For more information about how to obtain these items, see ISecurityIdentityColl properties.

Only COM+ applications that use role-based security can access this object. For more information on roles and how they are used, see Role-Based Security and Programming Component Security.

To use the SecurityIdentity object, you must set a reference to the COM+ Services Type Library (comsvcs.dll).

You obtain a reference to a SecurityIdentity object by calling the GetSecurityCallContext function and then using the Item method to retrieve the "DirectCaller" or the OriginalCaller property of the security context object. As with any COM object, you should release a SecurityIdentity object when you are finished using it, unless it's a local variable.

The SecurityIdentity object provides the following properties.

Property | Description
Count | The number of items in the security identity collection.
Item | An indexed property that allows you to obtain a specified item in the security identity collection.

Note If a legacy COM application or a COM+ application that does not use role-based security calls GetSecurityCallContext to obtain a reference to the SecurityCallContext object, E_NOINTERFACE is returned. Because this object is required, these applications do not have access to SecurityIdentity objects.

Collection Items

This collection represents a security identity, which provides information about a particular caller in the chain of calls ending with the current call. To obtain an item in this collection, use the Item property of the SecurityIdentity object, specifying the string name of the item. All items in this collection are read-only.

For each item in the security identity collection, the following table provides a description, the data type, and the string index used to retrieve it.

Item | Description | Data Type | Index
SID | The security identifier of the caller. | V_ARRAY | "SID"
Account Name | The account name that the caller is using. | V_BSTR | "AccountName"
Authentication Service | The authentication service used by the caller, such as NTLMSSP, Kerberos, or SSL. | V_I4 | "AuthenticationService"
Impersonation Level | The impersonation level, which indicates how much authority the caller has been given to act on a client's behalf. | V_I4 | "ImpersonationLevel"
Authentication Level | The authentication level used by the caller, which indicates the amount of protection given during the call. | V_I4 | "AuthenticationLevel"

See Also

Programming Component Security, Role-Based Security, GetSecurityCallContext, SecurityCallContext, SecurityCallers.


SecurityProperty Object

The SecurityProperty object enables you to obtain information about the object's original caller and direct caller. You can obtain a reference to the current object's SecurityProperty object by retrieving the Security property from the current object's ObjectContext.

The preferred way to obtain information about an object's callers is to use the SecurityCallContext object instead of the SecurityProperty object.

For C++ programmers, ISecurityProperty provides the functionality that the SecurityProperty object exposes.

The SecurityProperty object provides the following methods:

Methods | Description
GetDirectCallerName | Retrieves the user name associated with the external process that called the currently executing method.
GetDirectCreatorName | In MTS 2.0, this method retrieves the user name associated with the external process that directly created the current object. In COM+ 1.0, do not use this method because its behavior is unpredictable.
GetOriginalCallerName | Retrieves the user name associated with the base process that initiated the call sequence from which the current method was called.
GetOriginalCreatorName | In MTS 2.0, this method retrieves the user name associated with the base process that initiated the activity in which the current object is executing. In COM+ 1.0, do not use this method because its behavior is unpredictable.

See Also

ObjectContext Object, Programming Component Security, SecurityCallContext Object.


GetDirectCallerName Method

Retrieves the user name associated with the external process that called the currently executing method.

Visual Basic Syntax

username = object.GetDirectCallerName( )

Parts of Syntax

username
The user name associated with the process from which the current method was invoked.
object
An object with a reference to a SecurityProperty object.

Remarks

You use the GetDirectCallerName method to determine the user name associated with the process that called the object's currently executing method.

The following scenarios illustrate the functionality of the GetDirectCallerName method:

  • A base process, running on server A as user A, calls into object X on server B, running as user B. Then object X calls into object Y, running on server C. If object Y calls GetDirectCallerName, the name of user B is returned.
  • A base process, running on server A as user A, calls into object X on server B, running as user B. Then object X calls into object Y, running in the same process as object X, also on server B. When object Y calls GetDirectCallerName, the name of user A is returned, not the name of user B.

Example

See Also

Programming Component Security, ObjectContext Object


GetDirectCreatorName Method

In MTS 2.0, this method retrieves the user name associated with the current object's immediate (out-of-process) creator. However, you should not use this method in COM+ applications because its behavior is unpredictable.

Visual Basic Syntax

username = object.GetDirectCreatorName( )

Parts of Syntax

username
The user name associated with the process that directly created the current object.
object
An object with a reference to a SecurityProperty object.

See Also

Programming Component Security, ObjectContext Object


GetOriginalCallerName Method

Retrieves the user name associated with the base process that initiated the sequence of calls from which the call into the current object originated.

Visual Basic Syntax

username = object.GetOriginalCallerName( )

Parts of Syntax

username
The user name associated with the base process that initiated the call sequence from which the current method was called.
object
An object with a reference to a SecurityProperty object.

Remarks

You use the GetOriginalCallerName method to determine the user name associated with the original process that initiated the call sequence from which the current method was called. The following scenario illustrates the functionality of the GetOriginalCallerName method.

Base process 1, running on server A as user A, creates object X on server B, running as user B. Then base process 1 passes its reference on object X to base process 2, running on server D as user D. Base process 2 uses that reference to call into object X. Object X then calls into object Y, running on server C. If object Y then calls GetOriginalCallerName, the name of user D is returned.

Note Usually, an object's original caller is the same process as its original creator. The only situation in which the original caller and the original creator would be different is one in which the original creator passes a reference to another process, and the other process initiates the call sequence (as in the preceding example).

The path to the original caller is broken if any object along the chain was created by some other means than IObjectContext::CreateInstance or ITransactionContext::CreateInstance. For example, if base process 1 uses CoCreateInstance to create X, when Y calls GetOriginalCallerName, the name it gets back will be the name of user B, not user D. This is because the call sequence is traced back through the objects' context and COM+ can only create a context for an object that is created with either IObjectContext::CreateInstance or ITransactionContext::CreateInstance.

Example

See Also

Programming Component Security, ObjectContext Object


GetOriginalCreatorName Method

In MTS 2.0, this method retrieves the user name associated with the original base process that initiated the activity in which the current object is executing. However, you should not use this method in COM+ applications because its behavior is unpredictable.

Visual Basic Syntax

username = object.GetOriginalCreatorName( )

Parts of Syntax

username
The user name associated with the base process that initiated the activity in which the current object is executing.
object
An object with a reference to a SecurityProperty object.

See Also

Programming Component Security, ObjectContext Object


SecurityCallContext Object

The SecurityCallContext object is a collection that provides access to the current call's security context, which contains information about an object's callers. Using this object, you can also find out whether an object's direct caller is a member of a particular role and whether security is enabled for the object. It implements ISecurityCallContext.

Only COM+ applications that use role-based security can access the SecurityCallContext object. For more information on roles, see Role-Based Security.

To use the SecurityCallContext object, you must set a reference to the COM+ Services Type Library (comsvcs.dll).

You obtain a reference to the SecurityCallContext object by calling the GetSecurityCallContext function. If a legacy COM application or a COM+ application that does not use role-based security tries to obtain a reference to the SecurityCallContext object, E_NOINTERFACE is returned.

As with any COM object, you should release a SecurityCallContext object when you're finished using it, unless it's a local variable. The following table describes the methods for the SecurityCallContext object.

Method | Description
IsCallerInRole | Indicates whether the object's direct caller is a member of the specified role (either directly or as part of a group).
IsSecurityEnabled | Indicates whether role-based security is enabled.
Property | Description
Count | Returns the number of security call context object properties.
Item | Returns a specified item in the security call context collection.

Example

Collection Items

This collection represents a security call context, which provides information about the callers in the chain of calls ending with the current call. To obtain an item in this collection, use the Item property of the SecurityCallContext object, specifying the string name of the item. All items in this collection are read-only.

For each item in the security call context collection, the following table provides a description, the data type, and the string index used to retrieve it.

Item | Description | Data Type | Index
Direct Caller | The immediate caller of the object. | A SecurityIdentity Object | "DirectCaller"
Original Caller | The caller that originated the chain of calls to the object. | A SecurityIdentity Object | "OriginalCaller"
Minimum Authentication Level | The lowest authentication level used in the chain of calls. | Long | "MinAuthenticationLevel"
Number of Callers | The number of callers in the chain of calls to the object. | Long | "NumCallers"
Callers | The callers in the chain of calls that ends with the current call. | A SecurityCallers Object | "Callers"

See Also

Programming Component Security, Role-Based Security, GetSecurityCallContext, SecurityCallers Object, SecurityIdentity Object.


SecurityCallers Object

The SecurityCallers object represents a chain of callers. Using this object, you can access individual callers in the chain. Each caller is represented by a SecurityIdentity object. The "Callers" item available from the SecurityCallContext object is a SecurityCallers object. The SecurityCallers object implements ISecurityCallersColl.

Only COM+ applications that use role-based security can access this object. For more information on roles and how they are used, see Role-Based Security.

To use the SecurityCallers object, you must set a reference to the COM+ Services Type Library (comsvcs.dll).

You obtain a reference to a SecurityCallers object by calling the GetSecurityCallContext function and then using the Item property to retrieve the "Callers" item of the security call context collection. Then, you can retrieve information about a specific caller using the Item property with a numerical index to identify which caller you want. Using the SecurityIdentity object that represents that caller, you can access properties describing the caller's identity. For more information, see ISecurityCallersColl properties.

As with any COM object, you must release a SecurityCallers object when you're finished using it, unless it's a local variable.

The SecurityCallers object provides the following properties.

Properties | Description
Count | The number of items in the security callers collection.
Item | An indexed property that allows you to obtain a specified item in the security callers collection.

Note Only COM+ applications that use role-based security can access the SecurityCallers object. The reason for this is that a legacy COM application or a COM+ application that does not use role-based security cannot obtain a reference to the SecurityCallContext object from GetSecurityCallContext.

Collection Items

The security callers collection represents a chain of callers that cross security boundaries. These callers are also known as upstream callers. You can obtain information about particular callers in the collection, but you cannot set values in the collection.

Each item in this collection is a SecurityIdentity object. To obtain an item in this collection, use the Item property of the SecurityCallers collection object, specifying an integer index between 0 and one less than the number of callers in the collection. To retrieve the direct caller, this index should be 0, and to retrieve the original caller, the index can be either -1 or the number of callers - 1.

See Also

Programming Component Security, Role-Based Security, GetSecurityCallContext, SecurityCallContext Object, SecurityIdentity Object


TransactionContext Object

The TransactionContext object is a generic transactional that begins a transaction. By calling the methods of this object you can compose the work of multiple COM objects in a single transaction and explicitly commit or abort the transaction.

When to Implement

You should not implement this object. The standard implementation provides complete transaction functionality.

When to Use

A non-transactional client uses this object to begin a transaction. Using the methods of this object, the client can call additional COM objects that, if configured to participate in a transaction, execute within the transaction boundary of the transaction context object. Based on its business logic, the client can explicitly commit or abort the transaction. The following table describes the methods of the TransactionContext object.

Method | Description
Abort | Aborts the work of all COM objects participating in the current transaction. The transaction ends on return from this method.
Commit | Attempts to commit the work of all COM objects participating in the current transaction. The transaction ends on return from this method.
CreateInstance | Creates another COM object. If the component that provides the object is configured to support or require a transaction, then the new object runs under the transaction of the TransactionContext object.

Requirements

To use this object, set a reference to the Transaction Context Type Library (txctx.dll).

Remarks

The TransactionContext object limits reuse of the business logic driving the transaction. For this reason, it is recommended that the TransactionContext object be used sparingly.

You obtain a reference to the TransactionContext object by using the CreateObject function. For example:

Set objTransactionContext = _
    CreateObject("TxCtx.TransactionContext")

See Also

Configuring Transactions


Interfaces

Interface | Description
IContextState | Controls object deactivation and transaction voting by manipulating context state bits.
IEnumEventObject | Enumerates the event objects that are registered in the COM+ event store.
IEventClass | Associates a class of event objects with the event interface those objects implement.
IEventControl | Controls the behavior of an event object, the object that fires an event to its subscribers.
IEventObjectChange | Notifies subscribers of changes to the event store.
IEventObjectCollection | Manages objects in an event objects collection.
IEventSubscription | Specifies information about the relationship between an event subscriber and an event to which it is subscribing.
IEventSystem | Provides access to the event data store.
IFiringControl | Fires an event to a single subscription.
IMessageMover | Moves messages from one queue to another queue.
IMultiInterfaceEventControl | Controls the behavior of an event object, the object that fires an event to its subscribers.
IMultiInterfacePublisherFilter | Manages a filtered subscription cache for an event method.
IObjectContext | Provides access to the current object's context.
IObjectContextActivity | Retrieves a unique identifier associated with the current activity.
IObjectContextInfo | Returns transaction, activity, and context information on the current context object.
IObjectControl | Implement when you want to define context-specific initialization and cleanup procedures for your COM+ objects and specify whether or not the objects can be recycled.
IObjectConstruct | Performs parameterized object construction.
IObjectConstructString | Provides access to a constructor string.
IPlaybackControl | Used in Queued Components to participate in the abnormal handling of server-side playback errors and client-side failures of the MSMQ delivery mechanism.
IPublisherFilter | Manages a filtered subscription cache for an event method.
ISecurityCallContext | Provides access to security methods and information about the security call context of the current call.
ISecurityCallersColl | Provides access to information about individual callers in a collection of callers exposed by ISecurityCallContext.
ISecurityIdentityColl | Provides access to a collection of security information representing a caller's identity.
ISecurityProperty | Allows you to determine the security ID of the current object's original caller or direct caller.
ISharedProperty | Used to set or retrieve the value of a shared property.
ISharedPropertyGroup | Used to create and access the shared properties in a shared property group.
ISharedPropertyGroupManager | Used to create shared property groups and to obtain access to existing shared property groups.
ITransactionContextEx | Provides a generic transactional object that begins a transaction.
ITxProperty | Provides methods that you can use to set or retrieve the value assigned to a transacted property.
ITxPropertyGroup | Used to create and access transacted properties contained in a transacted property group.
ITxPropertyGroupManager | Used to create a container for property groups.

Note These interfaces are provided by the COM+ Services Type Library DLL (Comsvcs.dll).


ICOMLBArguments

The ICOMLBArguments interface is used to activate the COM+ component load balancing service.

When to Implement

This interface is used to activate the COM+ component load balancing service. Implement ICOMLBArguments in conjunction with the ISelectCOMLBServer interface. The LocalMachine object in the COM+ catalog contains a property for the CLSID of the load balancing module. The methods on the ICOMLBArguments interface allow you to obtain and set this CLSID, as well as to obtain and set the machine name for the load balancing server.

When to Use

You do not call the methods of ICOMLBArguments. These methods are called by applications that activate the COM+ component load balancing services.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICOMLBArguments Methods | Description
GetCLSID | Obtains the object's CLSID.
SetCLSID | Sets the object's CLSID.
GetMachineName | Obtains the object's machine name.
SetMachineName | Sets the object's machine name.

See Also

ISelectCOMLBServer


ICOMLBArguments::GetCLSID

Obtains the object's CLSID.

HRESULT GetCLSID(
  CLSID **ppCLSID  //The object's CLSID
);

Parameters

ppCLSID
[out] Indirect pointer to the object's CLSID.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The CLSID has been set successfully.

See Also

ISelectCOMLBServer


ICOMLBArguments::SetCLSID

Sets the object's CLSID.

HRESULT SetCLSID(
  CLSID *pCLSID  //The object's CLSID
);

Parameters

pCLSID
[in] Points to the object's CLSID.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The CLSID has not been set.

See Also

ISelectCOMLBServer


ICOMLBArguments::GetMachineName

Obtains the object's machine name.

HRESULT GetMachineName(
  ULONG cchSvr,         //The object's machine name
  WCHAR szServerName[]  //The object's server name
);

Parameters

cchSvr
[in] The object's machine name.
szServerName[]
[out, max_is (cchSvr)] The object's server name.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The machine name has been set successfully.

See Also

ISelectCOMLBServer


ICOMLBArguments::SetMachineName

Sets the object's machine name.

HRESULT SetMachineName(
  ULONG cchSvr,         //The object's machine name
  WCHAR szServerName[]  //The object's server name
);

Parameters

cchSvr
[in] The object's machine name.
szServerName[]
[in, size_is (cchSvr)] The object's server name.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The machine name has not been set.

See Also

ISelectCOMLBServer


IContextState

The IContextState interface controls object deactivation and transaction voting by manipulating context state bits. By calling the methods of this interface, you can set consistency and done bits independently of each other and get the current status of each bit.

When to Implement

You should not implement this interface. The standard implementation provides complete functionality.

When to Use

Although you can already set the consistency and done bits using methods exposed by the IObjectContext interface, you can only manipulate both bits at the same time. The IContextState interface provides finer control, allowing you to set each bit independently of the other.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
Method | Description
SetDeactivateOnReturn | Sets the done bit.
GetDeactivateOnReturn | Returns the Boolean value stored in the done bit.
SetMyTransactionVote | Sets the consistency bit.
GetMyTransactionVote | Returns the value associated with the consistency bit.

Requirements

To use the methods of this interface, you must include comsvcs.h in your file or set a reference to the comsvcs.dll in your project.

Remarks

The IContextState interface provides methods to check the current state of an object's consistency and done bits. Also, the methods of IContextState return errors that indicate the absence of just-in-time (JIT) activation or the absence of a transaction.

See Also

Consistency and Doneness


IContextState::GetDeactivateOnReturn

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ContextState::GetDeactivateOnReturn [C/C++]

IContextState.GetDeactivateOnReturn [Visual Basic]

This method retrieves the Boolean value stored in the done bit of a context. COM+ returns an error if just-in-time (JIT) activation is not available for the object.

[C/C++]
HRESULT IContextState::GetDeactivateOnReturn(
  [out] VARIANT_BOOL *pbDeactivate
);

[Visual Basic]
contextstateobject.GetDeactivateOnReturn pbDeactivate

Parameters

pbDeactivate
[out] A reference to the Boolean value TRUE or FALSE.

Return Values

CONTEXT_E_NOJIT
Just-in-time (JIT) activation is not available to this context.

Remarks

When this method returns FALSE on the root object of a transaction, the object will not deactivate and the transaction will not terminate unless the client releases its reference to the object or until the done bit is set to TRUE.

See Also

Consistency and Doneness


IContextState::GetMyTransactionVote

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IContextState::GetMyTransactionVote [C/C++]

IContextState.GetMyTransactionVote [Visual Basic]

This method retrieves the value stored in the consistency bit of a context. If the method fails, you may be able to determine that a transaction is not present, based on the HRESULT.

If the method succeeds, it returns a Boolean value from the consistency bit. From this value, you can determine whether the object can be committed or must be aborted. Regardless of the object's state, the object must be participating in a transaction.

[C/C++]
HRESULT IContextState::GetMyTransactionVote(
  [out] TransactionVote *pTxVote
);

[Visual Basic]
contextstateobject.GetMyTransactionVote pTxVote

Parameters

pTxVote
[out] A reference to the enumerated value of the type specified.

Return Values

CONTEXT_E_NOTRANSACTION
The object is not running in a transaction.

Remarks

Retrieving this value before deactivating the object allows the object to confirm its vote.

See Also

Consistency and Doneness


IContextState::SetDeactivateOnReturn

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IContextState::SetDeactivateOnReturn [C/C++]

IContextState.SetDeactivateOnReturn [Visual Basic]

This method sets the done bit to TRUE or FALSE. The done bit controls whether the object deactivates on method return. When set to TRUE, the done bit causes the object to deactivate when the method call returns. When set to FALSE, the object remains active after the method call returns.

[C/C++]
HRESULT IContextState::SetDeactivateOnReturn(
  VARIANT_BOOL bDeactivate
);

[Visual Basic]
contextstateobject.SetDeactivate bDeactivate

Parameters

bDeactivate
[in] A reference to the Boolean value TRUE or FALSE.

Return Values

CONTEXT_E_NOJIT
Just-in-time (JIT) activation is not available in this context.

Remarks

The done bit default is FALSE.

See Also

Consistency and Doneness


IContextState::SetMyTransactionVote

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IContextState::SetMyTransactionVote [C/C++]

IContextState.SetMyTransactionVote [Visual Basic]

Sets the Consistent bit to TRUE or FALSE. This method accepts the values txCommit and txAbort, which set the consistency bit to TRUE and FALSE, respectively. COM+ inspects this bit only when deactivating the object and can be set multiple times within a method call.

[C/C++]
HRESULT IContextState::SetMyTransactionVote(
  TransactionVote txVote
);

[Visual Basic]
contextstateobject.SetMyTransactionVote txVote

Parameters

txVote
[in] A reference to the enumeration of the type specified.

Return Values

CONTEXT_E_NOTRANSACTION
The object is not running in a transaction.

Remarks

The consistency bit default is TRUE.

See Also

Consistency and Doneness


IEnumEventObject

The IEnumEventObject interface enumerates the event objects that are registered in the COM+ events store.

This interface provides a view of an event object collection. Visual Basic programmers can obtain similar functionality through the IEventObjectCollection interface.

When to Implement

You do not generally need to implement IEnumEventObject. This interface is implemented on objects that are created by calls to IEventObjectCollection::get_NewEnum.

When to Use

Use the IEnumEventObject interface to enumerate all the event objects obtained by a query.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IEnumEventObject Methods | Description
Clone | Creates another enumerator that contains the same enumeration state as the current one.
Next | Retrieves a specified number of items in the enumeration sequence.
Reset | Resets the enumeration sequence to the beginning.
Skip | Skips over a specified number of items in the enumeration sequence.

See Also

IEventObjectCollection


IEnumEventObject::Clone

Creates another enumerator that contains the same enumeration state as the current one. The new enumerator supports the same interface as the original one.

HRESULT Clone(
  IEnumEventObject ** ppInterface  //Pointer to enumeration object
);

Parameters

ppInterface
[out] Address of a pointer to the IEnumEventObject interface on the enumeration object. Cannot be NULL. If the method is unsuccessful, the value of this output variable is undefined.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The enumeration object was successfully created.

Remarks

When the pointer to the IEnumEventObject is returned, it is positioned at the first object in the collection not at the place of the enumeration object being cloned.


IEnumEventObject::Next

Obtains the next cReqElem items in the enumeration sequence. If there are fewer than the requested number of elements left in the sequence, this method obtains the remaining elements. The number of elements actually obtained is returned through pcRetElem.

HRESULT Next(
  ULONG cReqElem,           //Number of elements requested
  IUnknown **ppInterface,   //Elements obtained
  ULONG *pcRetElem          //Number of elements obtained
);

Parameters

cReqElem
[in] Number of elements being requested.
ppInterface
[out] Address to a pointer to the IUnknown interface on the first object obtained. Cannot be NULL.
pcRetElem
[out] Pointer to the number of elements actually obtained. Cannot be NULL.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
All elements requested were obtained.
S_FALSE
Not all elements requested were obtained. The number of elements obtained was written to pcRetElem.


IEnumEventObject::Reset

Resets the enumeration sequence to the beginning.

HRESULT Reset(void);

Return Value

S_OK
The enumeration sequence was reset.
S_FALSE
The enumeration sequence was reset, but there are no items in the enumerator.

Remarks

You can use the S_FALSE return value as an optimization to detect an empty enumeration.

A call to this method, resetting the sequence, does not guarantee that the same set of objects will be enumerated after the reset, because the collection may have changed.


IEnumEventObject::Skip

Skips over the next specified number of elements in the enumeration sequence.

HRESULT Skip(
  ULONG cSkipElem  //Number of elements to be skipped
);

Parameter

cSkipElem
[in] Number of elements to be skipped.

Return Values

S_OK
The requested number of elements was skipped.
S_FALSE
The number of elements skipped was not the same as the number requested.

Remarks

Skip may return S_FALSE if cSkipElem is greater than the remaining number of elements. In this case, Skip moves to the last element in the enumeration sequence.


IEventClass

The IEventClass interface associates a class of event objects with the event interface those objects implement. IEventClass is the interface that is implemented by the CLSID_CEventClass objects, which are different than event class objects that are CoCreated by a publisher for the purpose of firing events.

An event object implements the IMultiInterfaceEventControl event interface. While this object can be used to configure event classes in the event store, the preferred method is to use the Admin interfaces. However, not all of the properties exposed by the IEventClass interface are available through the Admin interfaces.

When to Implement

You do not need to implement the IEventClass interface. IEventClass is implemented by the CLSID_CEventClass objects.

When to Use

Event publishers and objects that add event classes to the event store call the methods of IEventClass to specify the object class that implements a particular event interface. Once the information is written to an event class object, the creator can store the event class object in the event store by calling IEventSystem::Store.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IEventClass Methods | Description
get_EventClassID | Obtains the CLSID for the event class object.
put_EventClassID | Writes the CLSID for the event class object.
get_EventClassName | Obtains the ProgID for the event class object.
put_EventClassName | Writes the ProgID for the event class object.
get_OwnerSID | Obtains the security ID of the event class object's creator. Supported only for backward compatibility.
put_OwnerSID | Writes the security ID of the event class object's creator. Supported only for backward compatibility.
get_FiringInterfaceID | Obtains the ID of the event interface on the event class object. Supported only for backward compatibility.
put_FiringInterfaceID | Writes the ID of the event interface on the event class object. Supported only for backward compatibility.
get_Description | Obtains a displayable text description of the event class object.
put_Description | Writes a displayable text description of the event class object.
get_CustomConfigCLSID | Obtains the CLSID of a component that can assist in adding properties into the property bag of a subscription object. Supported only for backward compatibility and returns E_NOTIMPL.
put_CustomConfigCLSID | Writes the CLSID of a component that can assist in adding properties into the property bag of a subscription object. Supported only for backward compatibility and returns E_NOTIMPL.
get_TypeLib | Obtains the path of the type library that contains the description of the event interface.
put_TypeLib | Writes the path of the type library that contains the description of the event interface.


IEventClass Properties

The methods of the IEventClass interface get and put the properties described in this topic.

In Visual Basic and Java, programs get and set these properties directly. In C++, programs call methods of the IEventClass interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the EventClassID property is a BSTR variable. The methods that get and put this property have the following prototypes;

get_EventClassID(BSTR * EventClassID);

put_EventClassID(BSTR EventClassID);

Properties

The following table lists the properties that are managed by the IEventClass interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
EventClassID | GP | BSTR | GUID identifying the event object.
EventClassName | GP | BSTR | ProgID of the event object.
OwnerSID | GP | BSTR | Security ID of the creator of the event object. Supported only for backward compatibility.
FiringInterfaceID | GP | BSTR | ID of the event interface on the event object. Supported only for backward compatibility.
Description | GP | BSTR | Displayable text that describes the event class object.
CustomConfigCLSID | GP | BSTR | CLSID of a component that can assist in adding properties into the property bag of a subscription object. Supported only for backward compatibility. Both get_ and put_ methods return E_NOTIMPL.
TypeLib | GP | BSTR | Path of the type library containing the description of the event interface.

Return Values

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL.


IEventControl

The IEventControl interface controls the behavior of an event object, the object that fires an event to its subscribers. The IEventControl interface differs from the IMultiInterfaceEventControl interface in that it supports only one interface for the event object. For event classes that support more than one interface, see IMultiInterfaceEventControl.

When to Implement

You do not need to implement the IEventControl interface. When you register an event publisher, COM Events creates an event object class that implements the defined event interface and IEventControl.

When to Use

Call the methods of IEventControl to specify the way an event object fires its events.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IEventControl Methods | Description
SetPublisherFilter | Assigns a publisher filter to an event method.
get_AllowInprocActivation | Determines whether subscribers can be activated in the publisher's process.
put_AllowInprocActivation | Specifies whether subscribers can be activated in the publisher's process.
GetSubscriptions | Obtains the collection of subscriptions associated with an event method.
SetDefaultQuery | Establishes a default query to determine subscribers.


IEventControl Properties

The methods of the IEventControl interface get and put the properties described in this topic.

In Visual Basic and Java, programs get and set these properties directly. In C++, programs call methods of the IEventControl interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the AllowInProcActivation property is a BOOL variable. The methods that get and put this property have the following prototypes;

get_AllowInProcActivation(BOOL * pAllowInProcActivation);

put_AllowInProcActivation(BOOL AllowInProcActivation);

Properties

The following table lists the properties that are managed by the IEventControl interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
AllowInProcActivation | GP | BOOL | If TRUE, components created by the COM event system do not have to support being called as LocalServer. Default is FALSE.

Return Values

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.
EVENT_S_SOME_SUBSCRIBERS_FAILED
An event was able to invoke some, but not all, of the subscribers.
EVENT_E_ALL_SUBSCRIBERS_FAILED
An event was unable to invoke any of the subscribers.
EVENT_S_NOSUBSCRIBERS
An event was published but there were no subscribers.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.
EVENT_E_INVALID_PER_USER_SID
The owner SID on a per-user subscription does not exist.
EVENT_E_USER_EXCEPTION
A user-supplied component or subscriber raised an exception.
EVENT_E_TOO_MANY_METHODS
An interface has too many methods from which to fire events.
EVENT_E_MISSING_EVENTCLASS
A subscription cannot be stored unless the event class for the subscription already exists.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.
EVENT_E_COMPLUS_NOT_INSTALLED
COM+ is required for this operation, but it is not installed.


IEventControl::GetSubscriptions

Obtains a collection of subscription objects associated with an event method.

HRESULT GetSubscriptions(
  BSTR MethodName,                   //Event method
  BSTR OptionalCriteria,
  int *pErrorIndex,
  IEventObjectCollection **ppCollection  //Subscription collection
);

Parameters

MethodName
[in] Event method associated with the subscription collection.
OptionalCriteria
[in, unique] String specifying the query criteria. If NULL, the default query specified by the SetDefaultQuery method is used. For details on forming a valid expression for this parameter, see the Remarks section below.
pErrorIndex
[in, unique] The location, expressed as an offset, of an error in the OptionalCriteria parameter. Cannot be NULL.
ppCollection
[out] Address of a pointer to IEventObjectCollection interface on a collection object that enumerates the subscriptions associated with the event object.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The subscription collection was successfully obtained.
EVENT_S_SOME_SUBSCRIBERS_FAILED
An event was able to invoke some, but not all, of the subscribers.
EVENT_E_ALL_SUBSCRIBERS_FAILED
An event was unable to invoke any of the subscribers.
EVENT_S_NOSUBSCRIBERS
An event was published but there were no subscribers.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.
EVENT_E_INVALID_PER_USER_SID
The owner SID on a per-user subscription does not exist.
EVENT_E_USER_EXCEPTION
A user-supplied component or subscriber raised an exception.
EVENT_E_TOO_MANY_METHODS
An interface has too many methods from which to fire events.
EVENT_E_MISSING_EVENTCLASS
A subscription cannot be stored unless the event class for the subscription already exists.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.
EVENT_E_COMPLUS_NOT_INSTALLED
COM+ is required for this operation, but it is not installed.

Remarks

This method is a more specialized form of the IEventSystem::Query method. In addition to obtaining only subscription objects, a collection obtained by calling GetSubscriptions is automatically updated whenever the subscription collection changes.

The query criteria specified by the OptionalCriteria parameter can be "ALL", to specify a request for all subscription objects, or a Boolean expression denoting one or more conditions a subscription object must meet to be included in the query result. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"

See Also

IEventControl::SetDefaultQuery, IEventSystem::Query


IEventControl::SetDefaultQuery

Establishes the default query to be used when a publisher filter is not associated with an event method.

HRESULT SetDefaultQuery(
  BSTR MethodName,
  BSTR Criteria,
  int *pErrorIndex
);

Parameters

MethodName
[in] Name of the method to which the default query is assigned.
Criteria
[in] String specifying the query criteria. Cannot be NULL. For details on forming a valid expression for this parameter, see the Remarks section below.
pErrorIndex
[out] The location, expressed as an offset, of an error in the Criteria parameter.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The default query was successfully assigned.
EVENT_S_SOME_SUBSCRIBERS_FAILED
An event was able to invoke some, but not all, of the subscribers.
EVENT_E_ALL_SUBSCRIBERS_FAILED
An event was unable to invoke any of the subscribers.
EVENT_S_NOSUBSCRIBERS
An event was published but there were no subscribers.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.
EVENT_E_INVALID_PER_USER_SID
The owner SID on a per-user subscription does not exist.
EVENT_E_USER_EXCEPTION
A user-supplied component or subscriber raised an exception.
EVENT_E_TOO_MANY_METHODS
An interface has too many methods from which to fire events.
EVENT_E_MISSING_EVENTCLASS
A subscription cannot be stored unless the event class for the subscription already exists.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.
EVENT_E_COMPLUS_NOT_INSTALLED
COM+ is required for this operation, but it is not installed.

Remarks

The query criteria specified by the OptionalCriteria parameter can be "ALL", to specify a request for all subscription objects, or a Boolean expression denoting one or more conditions a subscription object must meet to be included in the query result. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"

See Also

IEventControl::GetSubscriptions, IEventSystem::Query


IEventControl::SetPublisherFilter

Assigns a publisher filter to an event method.

HRESULT SetPublisherFilter(
  BSTR MethodName,            //Name of event method
  IPublisherFilter *pFilter   //Publisher filter
);

Parameters

MethodName
[in] Name of the event method associated with the publisher filter to be assigned.
pFilter
[in, unique] Pointer to the IPublisherFilter interface on the publisher filter associated with the specified method.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The publisher filter was successfully assigned.
EVENT_S_SOME_SUBSCRIBERS_FAILED
An event was able to invoke some, but not all, of the subscribers.
EVENT_E_ALL_SUBSCRIBERS_FAILED
An event was unable to invoke any of the subscribers.
EVENT_S_NOSUBSCRIBERS
An event was published but there were no subscribers.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.
EVENT_E_INVALID_PER_USER_SID
The owner SID on a per-user subscription does not exist.
EVENT_E_USER_EXCEPTION
A user-supplied component or subscriber raised an exception.
EVENT_E_TOO_MANY_METHODS
An interface has too many methods from which to fire events.
EVENT_E_MISSING_EVENTCLASS
A subscription cannot be stored unless the event class for the subscription already exists.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.
EVENT_E_COMPLUS_NOT_INSTALLED
COM+ is required for this operation, but it is not installed.

Remarks

An event publisher can install a publisher filter at run time to fire an event only to subscribers that meet the criteria specified in the filter.


IEventObjectChange

The IEventObjectChange interface notifies subscribers of changes to the event store.

When to Implement

This interface fires events that reflect changes to the COM Events event store. Implement IEventObjectChange on objects that need to be informed of changes to the subscriptions, and event classes in the event store. For example, a graphical user interface (GUI) that displays information about objects in the event store would need to be updated when there is a change in the data it displays.

In addition to implementing this interface, the client must be a registered subscriber for these events. To obtain the CLSID of an event class object that will fire these events, the subscription object can get the value of the IEventSystem::EventObjectChangeClassID property.

When to Use

You do not call the methods of IEventObjectChange. COM+ Events calls these methods to fire an event when there is a change to the event store.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IEventObjectChange Methods | Description
ChangedSubscription | Indicates that a subscription object has been added, modified, or deleted.
ChangedEventClass | Indicates that an event class object has been added, modified, or deleted.
ChangedPublisher | Indicates a publisher object has been added, modified, or deleted.

See Also

IEventSystem Properties


IEventObjectChange::ChangedEventClass

Indicates that an event class object has been added, modified, or deleted.

HRESULT ChangedEventClass(
  EOC_ChangeType ChangeType,     //Description of change
  BSTR bstrEventClassID          //ID of changed event class
);

Parameters

ChangeType
[in] Type of change to the event class object. Values are taken from the EOC_ChangeType enumeration.
bstrEventClassID
[in] EventClassID property of the event class object that is changed.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event was successfully fired to the subscriber.


IEventObjectChange::ChangedPublisher

Indicates that a publisher object has been added, modified, or deleted.

HRESULT ChangedSubscription(
  EOC_ChangeType ChangeType,   //Description of change
  BSTR bstrPublisherID        //ID of changed publisher
);

Parameters

ChangeType
[in] Type of change to the subscription object. Values are taken from the EOC_ChangeType enumeration.
bstrPublisherID
[in] PublisherID property of the publisher object that is changed.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK

The event was successfully fired to the subscriber.


IEventObjectChange::ChangedSubscription

Indicates that a subscription object has been added, modified, or deleted.

HRESULT ChangedSubscription(
  EOC_ChangeType ChangeType,   //Description of change
  BSTR bstrSubscriptionID        //ID of changed subscription
);

Parameters

ChangeType
[in] Type of change to the subscription object. Values are taken from the EOC_ChangeType enumeration.
bstrSubscriptionID
[in] SubscriptionID property of the subscription object that is changed.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event was successfully fired to the subscriber.


IEventObjectChange2

The IEventObjectChange2 interface notifies subscribers of changes to the event store while including partition and application ID information. The IEventObjectChange2 interface has the same firing characteristics as IEventObjectChange.

Previously, subscribers to the EventObjectChange event class were fired only if the object being changed was in the same partition as the subscriber. This causes problems with subscribers, such as the COMSVCS event publisher, that want to hear about subscriptions to any event class they care about. Therefore, EventObjectChange subscribers will now fire whether the object being changed is in the same partition as the subscriber or the object is a subscription and its EventClassPartitionID property specifies the partition of the subscriber. The EventObjectChange subscriber will then hear about changes to objects in its partition as well as changes to subscriptions in other partitions that have created a "cross partition" subscription to the subscriber's partition. If the object being changed is in the "base" partition or is an unconfigured object, all subscribers to EventObjectChange will hear about the change—no partitioning filter is performed.

When to Implement

This interface fires events that reflect changes to the COM+ Events event store. Implement IEventObjectChange2 on objects that need to be informed of changes to the subscriptions and event classes in the event store. For example, a graphical user interface that displays information about objects in the event store would need to be updated when there is a change in the data it displays.

In addition to implementing this interface, the client must be a registered subscriber for these events. To obtain the CLSID of an event class object that will fire these events, the subscription object can get the value of the IEventSystem::EventObjectChangeClassID property.

When to Use

You do not call the methods of IEventObjectChange2. COM+ Events calls these methods to fire an event when there is a change to the event store.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IEventObjectChange2 Methods | Description
ChangedSubscription | Indicates that a subscription object has been added, modified, or deleted.
ChangedEventClass | Indicates that an event class object has been added, modified, or deleted.

See Also

IEventSystem Properties


IEventObjectChange2::ChangedEventClass

Indicates that an event class object has been added, modified, or deleted.

HRESULT ChangedEventClass(
COMEVENTSYSCHANGEINFO* pInfo
);

Parameters

pInfo
[in] Points to the system event structure.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event was successfully fired to the subscriber.


IEventObjectChange2::ChangedSubscription

Indicates that a subscription object has been added, modified, or deleted.

HRESULT ChangedSubscription(
COMEVENTSYSCHANGEINFO* pInfo
);

Parameters

pInfo
[in] Points to the system event structure.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event was successfully fired to the subscriber.


System Event Structure

The IEventObjectChange2 has a system event structure as its only parameter value, which contains the partition and application ID from which an event originated.

typedef [hidden] struct{
   DWORD cbSize;
   EOC_ChangeType   changeType;
   BSTR objectId;
   BSTR partitionId;
   BSTR applicationId;
   GUID reserved [10];
}COMEVENTSYSCHANGEINFO;

Parameters

cbSize
The size of this structure.
changeType
The type of change that has been made to the subscription.
objectId
The EventClass ID or subscription ID from which the change impacts.
partitionId
The EventClass partition ID or the subscriber partition ID affected.
applicationId
The EventClass application ID or subscriber application ID affected.
reserved
Reserved.


IEventObjectCollection

The IEventObjectCollection interface manages objects in an event objects collection.

When to Implement

You do not normally implement IEventObjectCollection. This interface is implemented on collection objects that are created by calls to IEventSystem::Query or IEventControl::GetSubscriptions.

When to Use

This interface exposes the methods that are normally exposed on Visual Basic collection objects. Implementers using C++ can call the methods of IEventObjectCollection, or they can call the get_NewEnum method to obtain an enumeration object that implements the IEnumEventObject interface.

Implementers using Visual Basic can use an event object collection in a for-each statement.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IEventObjectCollection Methods | Description
get__NewEnum | Not normally called by the user. Exposed for use by the Visual Basic run-time environment.
get_Item | Obtains a specific item in the collection. For details on syntax, see Remarks section below.
get_NewEnum | Obtains an enumeration object that implements IEnumEventObject.
get_Count | Obtains the number of objects in the collection.
Add | Adds an event object to the collection.
Remove | Removes an event object from the collection.

See Also

IEnumEventObject


IEventObjectCollection Properties

The property methods of the IEventObjectCollection interface get and put the properties described in this topic.

In Visual Basic and Java, programs get and set these properties directly. In C++, programs call methods of the IEventObjectCollection interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the Count property is a long variable. The method that gets this property has the following prototype;

get_Count(long * plCount);

Properties

The following table lists the properties that are managed by the IEventObjectCollection interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
_NewEnum | G |  | See Remarks below.
NewEnum | G | IUnknown* | Enumeration of objects in the collection.
Count | G | long | Number of objects in the collection.

Remarks

The _NewEnum property is used primarily by the Visual Basic run-time environment in processing a for-each statement.

Return Values

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.

See Also

IEnumEventObject


IEventObjectCollection::Add

Adds an event object to the collection.

HRESULT Add(
  VARIANT *varItem,   //Event object to be added
  BSTR bstrObjectID   //ID property of event object
);

Parameters

varItem
[in] Pointer to the event object to be added to the collection. Cannot be NULL.
bstrObjectID
[in] ID property of the event object to be added. For example, if the collection consists of subscription objects, this parameter would contain the SubscriptionID property of the event subscription object to be added to the collection.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event object was successfully added to the collection.


IEventObjectCollection::Remove

Removes an event object from the collection.

HRESULT Remove(
  BSTR bstrObjectID   //ID property of event object
);

Parameters

bstrObjectID
[in] ID property of the event object to be added. For example, if the collection consists of subscription objects, this parameter would contain the SubscriptionID property of the event subscription object to be added to the collection.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event object was successfully removed from the collection.


IEventSubscription

The IEventSubscription interface is used by publisher filters. The IEventSubscription interface, in conjunction with IEventSystem, specifies information about the relationship between an event subscriber and an event to which it is subscribing.

When to Implement

You do not need to implement the IEventSubscription interface. A system-supplied event object class (CLSID_CEventSubscription) implements IEventSubscription.

When to Use

After calling IMultiInterfaceEventControl::GetSubscriptions to obtain a collection of CEventSubscription objects, a filter uses this interface to obtain information about the individual subscriptions. It is particularly important to specify one of these properties: PublisherID or EventClassID. Specifying an InterfaceID restricts the events you receive to one interface. If InterfaceID is NULL, you receive events from all the interfaces on the EventClass. Specifying a MethodName restricts the events you will receive to one method. If MethodName is NULL, you receive methods from all the interfaces.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IEventSubscription Methods | Description
get_SubscriptionID | Obtains the unique ID for the subscription object.
put_SubscriptionID | Writes the unique ID for the subscription object.
get_SubscriptionName | Obtains a displayable name for the subscription object.
put_SubscriptionName | Writes a displayable name for the subscription object.
get_PublisherID | Obtains the unique ID of the event publisher.
put_PublisherID | Writes the unique ID of the event publisher.
get_EventClassID | Obtains the unique ID of the event class associated with the subscription.
put_EventClassID | Writes the unique ID of the event class associated with the subscription.
get_MethodName | Obtains the name of the event method.
put_MethodName | Writes the name of the event method.
get_SubscriberCLSID | For a persistent subscription, obtains the CLSID of the subscriber component.
put_SubscriberCLSID | For a persistent subscription, writes the CLSID of the subscriber component.
get_SubscriberInterface | For a transient subscription, obtains a marshaled pointer to the event interface on the subscriber.
put_SubscriberInterface | For a transient subscription, writes a marshaled pointer to the event interface on the subscriber.
get_PerUser | Determines if the subscription will receive the event only if the owner of the subscription is logged on to the same computer as the publisher. Contrast with get_MachineName.
put_PerUser | Specifies that the subscription will receive the event only if the owner of the subscription is logged on to the same machine as the publisher. Contrast with put_MachineName.
get_OwnerSID | Obtains the security ID of the subscription's creator.
put_OwnerSID | Writes the security ID of the subscription's creator. If PerUser is TRUE, this specifies the user that must be logged on to receive the event.
get_Enabled | Determines if the subscription is enabled.
put_Enabled | Specifies if the subscription is enabled.
get_Description | Obtains a displayable text description of the subscription.
put_Description | Writes a displayable text description of the subscription.
get_MachineName | For a persistent subscription, obtains the name of the computer on which the subscriber should be activated. Contrast with get_PerUser.
put_MachineName | For a persistent subscription, writes the name of the computer on which the subscriber should be activated. Contrast with put_PerUser.
GetPublisherProperty | Obtains the value of a property stored in the property bag to define publisher context.
PutPublisherProperty | Writes a property and its value to the property bag to define publisher context.
RemovePublisherProperty | Removes a property and its value from the property bag that defines publisher context.
GetPublisherPropertyCollection | Obtains a collection of properties and values stored in the publisher property bag.
GetSubscriberProperty | Obtains the value of a property stored in the property bag to define subscriber context.
PutSubscriberProperty | Writes a property and its value to the property bag to define subscriber context.
RemoveSubscriberProperty | Removes a property and its value from the property bag that defines subscriber context.
GetSubscriberPropertyCollection | Obtains a collection of properties and values stored in the subscriber property bag
get_InterfaceID | Obtains the ID for a particular interface for which the subscriber wants to receive events.
put_InterfaceID | Writes the ID for a particular interface for which the subscriber wants to receive events.


IEventSubscription Properties

The methods of the IEventSubscription interface get and put the properties described in this topic.

In Visual Basic, programs get and set these properties directly. In C++, programs call methods of the IEventSubscription interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the SubscriptionID property is a BSTR variable. The methods that get and put this property have the following prototypes;

get_SubscriptionID(BSTR * SubscriptionID);

put_SubscriptionID(BSTR SubscriptionID);

Properties

The following table lists the properties that are managed by the IEventSubscription interface and their data types and indicates for each property whether the interface supports getting (G), putting(P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
SubscriptionID | GP | BSTR | Unique identifier of the subscription object.
SubscriptionName | GP | BSTR | Displayable name of the subscription object.
PublisherID | GP | BSTR | Identifier of an event publisher object.
EventClassID | GP | BSTR | Unique identifier of an event class object.
MethodName | GP | BSTR | Name of the event method to be called on the subscriber.
SubscriberCLSID | GP | BSTR | CLSID of the subscriber component. If not empty, the subscription is persistent and the SubscriberInterface property must be NULL. This property works in conjunction with the MachineName property in a persistent subscription.
SubscriberInterface | GP | IUnknown* | Marshaled pointer to the event interface on the subscriber component. If not NULL, the subscription is transient and the SubscriberCLSID property must be empty.
PerUser | GP | BOOL | If TRUE, the subscription is enabled only if the user specified by the OwnerSID property is logged on to the computer on which the subscription is defined. Default is FALSE.
OwnerSID | GP | BSTR | Security ID of the subscription object's creator.
Enabled | GP | BOOL | If TRUE, the subscription is enabled and events fired by the publisher will reach the subscriber. If FALSE, events fired by the publisher will not reach the subscriber. The subscription will still appear in collections and can be queried.
Description | GP | BSTR | Displayable text that describes the subscription object.
MachineName | GP | BSTR | The computer on which the subscriber should be activated. Only meaningful if the SubscriberCLSID property is not empty. This property has no effect on transient subscriptions.
InterfaceID | GP | BSTR | Identifier of a particular interface for which the subscriber wants to receive events.

Return Values

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.

Remarks

Specifying a PublisherID property does not guarantee that a subscriber will not receive events fired by other publishers.


IEventSubscription::GetPublisherProperty

Obtains the value of a specified property in the property bag of the publisher specified by the PublisherID property.

HRESULT GetPublisherProperty(
  BSTR bstrPropertyName,      //Name of requested property
  VARIANT *pvarPropertyValue  //Value of requested property
);

Parameters

bstrPropertyName
[in] Name of the requested property.
pvarPropertyValue
[out] Pointer to the value of the requested property.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained.

Remarks

Publisher filters should call this method to obtain filter properties stored by the subscription builder.


IEventSubscription::GetPublisherPropertyCollection

Obtains a collection of the properties contained in the publisher property bag.

HRESULT GetPublisherPropertyCollection(
  IEventObjectCollection **ppCollection  //Collection of properties
);

Parameters

ppCollection
[out] Address of a pointer to the IEventObjectCollection interface on an event object collection. Cannot be NULL.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The enumerator object was successfully created.

Remarks

A property bag is used to store information about the events the subscriber needs to be notified about. For example, if a subscriber to a sports ticker is to obtain only baseball scores, it could use the property bag in the subscription object to specify this restriction.


IEventSubscription::GetSubscriberProperty

Obtains the value of a specified property in the property bag of the subscriber specified by the SubscriberID property.

HRESULT GetSubscriberProperty(
  BSTR bstrPropertyName,      //Name of requested property
  VARIANT *pvarPropertyValue  //Value of requested property
);

Parameters

bstrPropertyName
[in] Name of the requested property.
pvarPropertyValue
[out] Pointer to the value of the requested property.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained.


IEventSubscription::GetSubscriberPropertyCollection

Obtains a collection of the properties contained in the subscriber property bag.

HRESULT GetSubscriberPropertyCollection(
  IEventObjectCollection **ppCollection  //Collection of properties
);

Parameters

ppCollection
[out] Address of a pointer to the IEventObjectCollection interface on an event object collection. Cannot be NULL.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The enumerator object was successfully created.

Remarks

A property bag is used to store information about the events the subscriber needs to be notified about. For example, if a subscriber to a sports ticker is to obtain only baseball scores, it could use the property bag in the subscription object to specify this restriction.


IEventSubscription::PutPublisherProperty

Writes a named property and its value to the property bag of the publisher specified by the PublisherID property.

HRESULT PutPublisherProperty(
  BSTR bstrPropertyName,     //Name of the property
  VARIANT varPropertyValue   //Value of the property
);

Parameters

bstrPropertyName
[in] Name of the property whose value is to be written to the property bag. If the property is not in the property bag, this method adds it.
varPropertyValue
[in] Value of the property to be written to the property bag. If the property is already in the property bag, this method overwrites the current value with varPropertyValue.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully written.

Remarks

A property bag is used to store information about the events the subscriber needs to be notified about. For example, if a subscriber to a sports ticker is to obtain only baseball scores, it could use the property bag in the subscription object to specify this restriction.


IEventSubscription::PutSubscriberProperty

Writes a named property and its value to the property bag of the subscriber specified by the SubscriberID property.

HRESULT PutSubscriberProperty(
  BSTR bstrPropertyName,     //Name of the property
  VARIANT varPropertyValue   //Value of the property
);

Parameters

bstrPropertyName
[in] Name of the property whose value is to be written to the property bag. If the property is not in the property bag, this method adds it.
varPropertyValue
[in] Value of the property to be written to the property bag. If the property is already in the property bag, this method overwrites the current value with varPropertyValue.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully written.

Remarks

A property bag is used to store information about the events the subscriber needs to be notified about. For example, if a subscriber to a sports ticker is to obtain only baseball scores, it could use the property bag in the subscription object to specify this restriction.


IEventSubscription::RemovePublisherProperty

Removes a named property and its value from the property bag of the publisher specified by the PublisherID property.

HRESULT RemovePublisherProperty(
  BSTR bstrPropertyName
);

Parameters

bstrPropertyName
[in] Name of the property whose value is to be removed from the property bag.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully removed.

Remarks

A property bag is used to store information about the events the subscriber needs to be notified about. For example, if a subscriber to a sports ticker is to obtain only baseball scores, it could use the property bag in the subscription object to specify this restriction.


IEventSubscription::RemoveSubscriberProperty

Removes a named property and its value from the property bag of the subscriber specified by the SubscriberID property.

HRESULT RemoveSubscriberProperty(
  BSTR bstrPropertyName
);

Parameters

bstrPropertyName
[in] Name of the property whose value is to be removed from the property bag.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully removed.

Remarks

A property bag is used to store information about the events the subscriber needs to be notified about. For example, if a subscriber to a sports ticker is to obtain only baseball scores, it could use the property bag in the subscription object to specify this restriction.


IEventSystem

Used only by the System Event Notification Service (SENS) that ships with Microsoft® Internet Explorer 5, the IEventSystem interface provides access to the event data store.

When to Implement

You do not need to implement the IEventSystem interface. A system-supplied EventSystem object (CLSID_CEventSystem) implements IEventSystem.

When to Use

If you are programming to Internet Explorer 5 and SENS, you call the methods of IEventSystem to add objects to, and remove them from, the event store and to obtain objects from the event store.

Note Because IEventPublisher and the Publisher object are no longer supported, EventObjectChange will not be called on the ChangedPublisher method.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces that an object provides (either 0 or 1).
GetTypeInfo | Gets the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
IEventSystem Methods | Description
Query | Obtains a collection of subscription or event objects, based on a query specification.
Store | Adds or modifies a subscription or event object within the event system, based on an end-user copy of the object.
Remove | Removes a subscription or event object from the event system, based on a query specification.
get_EventObjectChangeEventClassID | Obtains the CLSID of the event class object used to subscribe to events from the event system.
QueryS | Obtains a collection of subscription or event objects, based on a query specification. Can be accessed from script.
RemoveS | Removes a subscription or event object from the event system, based on a query specification. Can be accessed from script.


IEventSystem Properties

The method of the IEventSystem interface described in this topic gets the EventObjectChangeClassID property associated with this interface.

In Visual Basic, programs get this property directly. In C++, programs call a method of the IEventSystem interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Parameters

The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the EventObjectChangeClassID property is a BSTR variable. The method that gets this property has the following prototype;

get_EventObjectChangeClassID(BSTR * pbstrEventClassID);

Properties

The following table lists the properties that are managed by the IEventSystem interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
EventObjectChangeClassID | G | BSTR | CLSID of an event class object that will notify the caller of changes to the event store.

Remarks

Subscriptions can use the EventObjectChangeClassID property to obtain a pointer to an event class object that will notify them when subscribers or events are modified, or when they are added to or deleted from the event store. Subscribers to these events must implement the IEventObjectChange interface.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained.


IEventSystem::Query

Obtains a collection of subscription or event objects from the event data store.

HRESULT Query(
  BSTR ProgID,
  BSTR QueryCriteria,
  int *ErrorIndex,
  IUnknown **ppInterface
);

Parameters

ProgID
[in] ProgID of the object class to be queried. Must identify a valid event object class. Allowable values are:
  • PROGID_EventSubscription
  • PROGID_EventSubscriptionCollection
  • PROGID_EventClass
  • PROGID_EventClassCollection
QueryCriteria
[in] String specifying the query criteria. For details on forming a valid expression for this parameter, see the Remarks section below.
ErrorIndex
[out] The location, expressed as an offset, of an error in the QueryCriteria parameter.
ppInterface
[out] Address of a pointer to the object obtained as a result of the query. Cannot be NULL. Depending on the object specified by the progID parameter, this will be a pointer to one of the following interfaces:
  • IEventSubscription
  • IEventClass
  • IEventObjectCollection

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The query was successfully completed.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.

Remarks

The caller is responsible for freeing memory allocated through the ppInterface parameter.

The query criteria specified by the QueryCriteria parameter can be "ALL", to specify a request for all objects of the requested class, or a Boolean expression denoting one or more conditions an object must meet to be included in the query result. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"
"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"


IEventSystem::QueryS

Obtains a collection of subscription or event objects from the event data store. This method can be accessed from script.

HRESULT QueryS(
  BSTR ProgID,
  BSTR QueryCriteria,
  IUnknown **ppInterface
);

Parameters

ProgID
[in] ProgID of the object class to be queried. Must identify a valid event object class. Allowable values are:
  • PROGID_EventSubscription
  • PROGID_EventSubscriptionCollection
  • PROGID_EventClass
  • PROGID_EventClassCollection
QueryCriteria
[in] String specifying the query criteria. For details on forming a valid expression for this parameter, see the Remarks section below.
ppInterface
[out] Address of a pointer to the object obtained as a result of the query. Cannot be NULL. Depending on the object specified by the progID parameter, this will be a pointer to one of the following interfaces:
  • IEventSubscription
  • IEventClass
  • IEventObjectCollection

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The query was successfully completed.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.

Remarks

The caller is responsible for freeing memory allocated through the ppInterface parameter.

The query criteria specified by the QueryCriteria parameter can be "ALL", to specify a request for all objects of the requested class, or a Boolean expression denoting one or more conditions an object must meet to be included in the query result. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"


IEventSystem::Remove

Removes one or more subscription or event objects from the event data store.

HRESULT Remove(
  BSTR ProgID,
  BSTR QueryCriteria,
  int *ErrorIndex
);

Parameters

ProgID
[in] ProgID of the event objects to be removed. Must identify a valid event object class. Allowable values are:
  • PROGID_EventSubscription
  • PROGID_EventSubscriptionCollection
  • PROGID_EventClass
  • PROGID_EventClassCollection
QueryCriteria
[in] String specifying the criteria for objects to be removed. For details on forming a valid expression for this parameter, see the Remarks section below.
ErrorIndex
[out] The location, expressed as an offset, of an error in the rQueryCriteria parameter.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event object or objects were successfully removed.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.

Remarks

The criteria specified by the QueryCriteria parameter can be "ALL", to specify a request for all objects of the requested class, or a Boolean expression denoting one or more conditions an object must meet to be removed. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"


IEventSystem::RemoveS

Removes one or more subscription or event objects from the event data store. This method can be accessed from script.

HRESULT RemoveS(
  BSTR ProgID,
  BSTR QueryCriteria,
);

Parameters

ProgID
[in] ProgID of the event objects to be removed. Must identify a valid event object class. Allowable values are:
  • PROGID_EventSubscription
  • PROGID_EventSubscriptionCollection
  • PROGID_EventClass
  • PROGID_EventClassCollection
QueryCriteria
[in] String specifying the criteria for objects to be removed. For details on forming a valid expression for this parameter, see the Remarks section below.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event object or objects were successfully removed.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.

Remarks

The criteria specified by the QueryCriteria parameter can be "ALL", to specify a request for all objects of the requested class, or a Boolean expression denoting one or more conditions an object must meet to be removed. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"


IEventSystem::Store

Creates or modifies an event or subscription object within the event system.

HRESULT Store(
  BSTR ProgID,
  IUnknown *pInterface
);

Parameters

ProgID
[in] ProgID of the event object to be added. Must identify a valid event object class. The allowable values are PROGID_EventSubscription and PROGID_EventClass.
pInterface
[in] Pointer to the object to be added. Depending on the object specified by the progID parameter, this will be a pointer to the IEventSubscription or IEventClass interface.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The object was successfully added.
EVENT_E_INVALID_PER_USER_SID
The owner SID on a per-user subscription does not exist.


IFiringControl

The IFiringControl interface fires an event to a single subscription.

When to Implement

You do not normally implement IFiringControl. This interface is implemented on a system-supplied object contained within an event class object.

When to Use

Call the method of IFiringControl from a publisher filter object to fire an event to a single subscriber.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IFiringControl Method | Description
FireSubscription | Fires an event to a single subscriber.


IFiringControl::FireSubscription

Fires an event to a single subscriber.

HRESULT FireSubscription(
  IEventSubscription *pSubscription
);

Parameters

pSubscription
[in] Pointer to the IEventSubscription interface on a subscription object.

Return Values

This method supports the standard return values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event was fired successfully.

Remarks

The FireSubscription method fires an event to the subscriber associated with the subscription object identified by the pSubscription parameter. A publisher filter typically iterates through a filtered list of subscriptions and calls FireSubscription for each associated subscriber. Note that all standard delivery processing is done by the event object for the subscription, including:

  • Any standard parameter filtering.
  • Activating the subscriber object (optional, for persistent subscriptions).
  • Depending on parameter filtering, invoking the event method that originally caused entry into the publisher filter on the subscriber.


IMessageMover

The IMessageMover interface moves messages from one queue to another queue.

When to Implement

You do not need to implement the IMessageMover interface. The interface is implemented by the Queued Components Message Mover.

When to Use

Use IMessageMover to move messages from queue to queue. If queue attributes permit, the messages are moved transactionally, so that they are not lost or duplicated in the event of failure during the move.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IMessageMover Methods | Description
get_SourcePath | Obtains the current source path name.
put_SourcePath | Writes the Message Queuing pathname for the source (input) queue.
get_DestPath | Obtains the current destination pathname.
put_DestPath | Writes the Message Queuing pathname for the destination (output) queue.
get_CommitBatchSize | Obtains the commit batch size property.
put_CommitBatchSize | Writes the number of messages that should be moved from source to destination queue between Commit operations.
MoveMessages | Moves all the messages from the queue named by the source queue to the destination queue.

See Also

IPlaybackControl


IMessageMover Properties

The IMessageMover interface exposes the properties described in this topic.

[Visual Basic]

In Visual Basic, programs read (get) and write (put) these properties directly.

[C/C++]

In C++, programs call methods of the IMessageMover interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters [C/C++]

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the SourcePath property is a BSTR variable. The methods that get and put this property have the following prototypes;

get_SourcePath (BSTR * pbstrServerName);

put_SourcePath (BSTR bstrServerName);

Properties

The following table lists the properties that are managed by the IMessageMover interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
SourcePath | GP | BSTR | Specifies the path of the source (input) queue.
DestPath | GP | BSTR | Specifies the path of the destination (output) queue.
CommitBatchSize | GP | long | Value specifying the commit batch size.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.


IMessageMover::MoveMessages

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IMessageMover::MoveMessages [C/C++]

MessageMover.MoveMessages [Visual Basic]

Moves all the messages from the source queue to the destination queue.

Syntax [Visual Basic]

Function MoveMessages() As Long

Syntax [C/C++]

HRESULT IMessageMover::MoveMessages(
  long *plMoved
);

Parameters [C/C++]

plMoved [out]
Address of a pointer to a Long specifying where the number of messages that were moved from source to destination queue can be returned.

Return Values [C/C++]

S_OK
All the messages on the source queue were moved to the destination queue.
E_*
Error codes from the underlying Message Queuing operations.

Remarks [C/C++]

Messages are moved one at a time unless both the source and destination queue are transacted. In this case, CommitBatchSize specifies the number of messages that are moved before Commit is invoked. There is no provision for moving fewer than all of the messages on the queue.


IMultiInterfaceEventControl

The IMultiInterfaceEventControl interface controls the behavior of an event object, the object that fires an event to its subscribers. The IMultiInterfaceEventControl interface differs from the IEventControl interface in that it supports multiple event interfaces for the event object.

When to Implement

You do not need to implement the IMultiInterfaceEventControl interface. When you register an event publisher, COM Events creates an event object class that implements the defined event interface and IMultiInterfaceEventControl.

When to Use

Call the methods of IMultiInterfaceEventControl to specify the way an event object fires its events.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IMultiInterfaceEventControl Methods | Description
SetMultiInterfacePublisherFilter | Assigns a publisher filter to an event method at run time.
get_AllowInprocActivation | Determines whether subscribers can be activated in the publisher's process.
put_AllowInprocActivation | Specifies whether subscribers can be activated in the publisher's process.
get_FireInParallel | Determines whether events can be delivered to two or more subscribers in parallel.
put_FireInParallel | Specifies whether events can be delivered to two or more subscribers in parallel.
GetSubscriptions | Obtains the collection of subscriptions associated with an event method.
SetDefaultQuery | Establishes a default query to determine subscribers when not filtering.


IMultiInterfaceEventControl Properties

The methods of the IMultiInterfaceEventControl interface get and put the properties described in this topic.

In Visual Basic and Java, programs get and set these properties directly. In C++, programs call methods of the IMultiInterfaceEventControl interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the AllowInProcActivation property is a BOOL variable. The methods that get and put this property have the following prototypes;

get_AllowInProcActivation(BOOL * AllowInProcActivation);

put_AllowInProcActivation(BOOL AllowInProcActivation);

Properties

The following table lists the properties that are managed by the IMultiInterfaceEventControl interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

Property | Get/Put | Data type | Description
AllowInprocActivation | GP | BOOL | If TRUE, subscribing components created by the COM event system do not have to support being called as LocalServer. Default is FALSE.
FireInParallel | GP | BOOL | If TRUE, subscribing components created by the COM event system can be delivered to multiple subscribers in parallel, rather than one at a time in serial order. Default is FALSE.

Return Values

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.


IMultiInterfaceEventControl::GetSubscriptions

Obtains a collection of subscription objects associated with an event method.

HRESULT GetSubscriptions(
  REFIID Iid,
  BSTR MethodName,                   //Event method
  BSTR OptionalCriteria,
  int *pOptionalErrorIndex,
  IEventObjectCollection **ppCollection  //Subscription collection
);

Parameters

Iid
[in] Interface identifier to the firing interface.
MethodName
[in] Event method associated with the subscription collection.
OptionalCriteria
[in] String specifying the query criteria. If NULL, the default query specified by the SetDefaultQuery method is used. For details on forming a valid expression for this parameter, see the Remarks section below.
pOptionalErrorIndex
[in] The location, expressed as an offset, of an error in the OptionalCriteria parameter. Cannot be NULL.
ppCollection
[out] Address of a pointer to IEventObjectCollection interface on a collection object that enumerates the subscriptions associated with the event object.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The subscription collection was successfully obtained.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.

Remarks

This method is a more specialized form of the IEventSystem::Query method. In addition to obtaining only subscription objects, a collection obtained by calling GetSubscriptions is automatically updated whenever the subscription collection changes.

The query criteria specified by the OptionalCriteria parameter can be "ALL", to specify a request for all subscription objects, or a Boolean expression denoting one or more conditions a subscription object must meet to be included in the query result. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"

See Also

IEventControl::SetDefaultQuery, IEventSystem::Query


IMultiInterfaceEventControl::SetDefaultQuery

Establishes the default query to be used when a publisher filter is not associated with an event method.

HRESULT SetDefaultQuery(
  REFIID Iid,
  BSTR MethodName,
  BSTR Criteria,
  int *pErrorIndex
);

Parameters

Iid
[in] Interface identifier to the firing interface.
MethodName
[in] Name of the method to which the default query is assigned.
Criteria
[in] String specifying the query criteria. Cannot be NULL. For details on forming a valid expression for this parameter, see the Remarks section below.
pErrorIndex
[out] The location, expressed as an offset, of an error in the Criteria parameter.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The default query was successfully assigned.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.

Remarks

The query criteria specified by the OptionalCriteria parameter can be "ALL", to specify a request for all subscription objects, or a Boolean expression denoting one or more conditions a subscription object must meet to be included in the query result. Valid expressions are of the form:

[NOT] propertyname relationalOperator value

Valid relational operators are:

  • ==
  • =
  • !=
  • <>
  • ~=

Valid values are:

  • "string"
  • 'string'
  • {GUID}
  • TRUE
  • FALSE
  • NULL

Individual Boolean expressions can be joined with AND or OR. Expressions can be nested in parentheses to enforce a specific order of evaluation.

Here are some examples of valid query criteria:

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF}"

"EventClassID == {F89859D1-6565-11D1-88C8-0080C7D771BF} AND MethodName = 'StockPriceChange'"

See Also

IMultiInterfaceEventControl::GetSubscriptions, IEventSystem::Query


IMultiInterfaceEventControl::SetMultiInterfacePublisherFilter

Allows the publisher to assign a publisher filter to an event method at run time.

HRESULT SetMultiInterfacePublisherFilter(
  IMultiInterfacePublisherFilter *pclassFilter   //Publisher filter
);

Parameters

pclassFilter
[in, unique] Pointer to the IMultiInterfacePublisherFilter interface on the publisher filter associated with the specified method.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The publisher filter was successfully assigned.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.

Remarks

An event publisher can install a publisher filter at run time to fire an event only to subscribers that meet the criteria specified in the filter.

Note This method sets the specified publisher filter for all methods of all event interfaces for the event object.


IMultiInterfacePublisherFilter

The IMultiInterfacePublisherFilter interface manages a filtered subscription cache for an event method. Only subscribers who meet the criteria specified by the filter are notified when the associated event is fired. The IMultiInterfacePublisherFilter interface differs from the IPublisherFilter interface in that it supports multiple event interfaces for the event object.

When to Implement

Implement the IMultiInterfacePublisherFilter on a publisher filter object. IMultiInterfacePublisherFilter acts as a callback interface, so that event publishers can control which subscribers receive event notifications or the order in which subscribers are notified.

When to Use

Event class objects call the Initialize method of IMultiInterfacePublisherFilter immediately after creating the filter object, and then call the PrepareToFire method. The COM Events system uses this interface so publishers can determine which subscriptions they will fire events to.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IMultiInterfacePublisherFilter Methods | Description
Initialize | Initializes the publisher filter object.
PrepareToFire | Prepares the filter to fire subscriptions through the event class object.


IMultiInterfacePublisherFilter::Initialize

Associates an event class object with a publisher filter.

HRESULT Initialize(
  IMultiInterfaceEventControl *pIEC
);

Parameters

pIEC
[in] Points to the IMultiInterfaceEventControl interface on an event class object.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The publisher filter was successfully initialized.

Remarks

The publisher filter uses the pointer passed in pIEC to obtain a list of subscribers, by calling IMultiInterfaceEventControl::GetSubscriptions.


IMultiInterfacePublisherFilter::PrepareToFire

Prepares a publisher filter to begin firing a filtered list of subscriptions using a provided firing control. The firing control is contained in the event class object.

HRESULT PrepareToFire(
  REFIID iid,                      //IID of interface being fired
  BSTR bstrMethodName,             //Name of event method
  IFiringControl *pFiringControl  //Firing control
);

Parameters

iid
[in] The interface ID of the interface being fired.
bstrMethodName
[in] Name of the event method to be fired.
pFiringControl
[in] Pointer to the IFiringControl interface on the firing control object.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event class object is ready to fire the event.

Remarks

Prior to invoking the application event interface method, the event object invokes this method one time on the publisher filter for each published event.


IObjectContext

The IObjectContext interface provides access to the current object's context.

Remarks

You obtain a reference to the IObjectContext interface by calling the MTx.GetObjectContext method. As with any COM object, you must release an ObjectContext object when you're finished using it, unless it's a local variable.

You can use an object's ObjectContext to:

  • Declare that the object's work is complete.
  • Prevent a transaction from being committed, either temporarily or permanently.
  • Instantiate other COM+ objects and include their work within the scope of the current object's transaction.
  • Find out if a caller is in a particular role.
  • Find out if security is enabled.
  • Find out if the object is executing within a transaction.

The IObjectContext interface provides the following methods.

Method | Description
CreateInstance | Instantiates another COM+ object.
DisableCommit | Declares that the object hasn't finished its work and that its transactional updates are in an inconsistent state. The object retains its state across method calls, and any attempts to commit the transaction before the object calls EnableCommit or SetComplete will result in the transaction being aborted.
EnableCommit | Declares that the object's work isn't necessarily finished, but its transactional updates are in a consistent state. This method allows the transaction to be committed, but the object retains its state across method calls until it calls SetComplete or SetAbort, or until the transaction is completed.
IsCallerInRole | Indicates whether the object's direct caller is in a specified role (either directly or as part of a group).
IsInTransaction | Indicates whether the object is executing within a transaction.
IsSecurityEnabled | Indicates whether security is enabled. COM+ security is enabled unless the object is running in the client's process.
SetAbort | Declares that the object has completed its work and can be deactivated on returning from the currently executing method, but that its transactional updates are in an inconsistent state or that an unrecoverable error occurred. This means that the transaction in which the object was executing must be aborted. If any object executing within a transaction returns to its client after calling SetAbort, the entire transaction is doomed to abort.
SetComplete | Declares that the object has completed its work and can be deactivated on returning from the currently executing method. For objects that are executing within the scope of a transaction, it also indicates that the object's transactional updates can be committed. When an object that is the root of a transaction calls SetComplete, COM+ attempts to commit the transaction on return from the current method.


IObjectContext::CreateInstance

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::CreateInstance [C/C++]

ObjectContext.CreateInstance Method [Visual Basic]

The component's context object implements IObjectContext to perform context-specific initialization whenever it's activated. COM+ creates context objects.

Syntax [C/C++]

HRESULT IObjectContext::CreateInstance(
  REFCLSID clsid,
  REFID iid,
  LPVOID FAR* ppvObj
);

Parameters [C/C++]

clsid
[in] The clsid of the type of object to instantiate.
iid
[in] Any interface that's implemented by the object you want to instantiate.
ppvObj
[out] A reference to the requested interface on the new object.

Return Values [C/C++]

S_OK
The object was created and a reference to it is returned in the ppvObj parameter.
REGDB_E_CLASSNOTREG
The component specified by rclsid is not registered as a COM component.
E_OUTOFMEMORY
There's not enough memory available to instantiate the object.
E_INVALIDARG
The argument passed in the ppvObj parameter is invalid.
E_UNEXPECTED
An unexpected error occurred. This can happen if one object passes its IObjectContext pointer to another object, and the other object calls CreateInstance using this pointer. An IObjectContext pointer is not valid outside the context of the object that originally obtained it.

Syntax [Visual Basic]

CreateInstance (ProgID)

Parts [Visual Basic]

ProgID
A string expression that is the class ID of the new object's component.

Remarks

CreateInstance creates a COM object. However, the object will have context only if its component is registered with COM+.

When you create an object by using CreateInstance, the new object's context is derived from the current object's ObjectContext and the declarative properties of the new object's component. The new object always executes within the same activity as the object that created it. If the current object has a transaction, the transaction attribute of the new object's component determines whether or not the new object will execute within the scope of that transaction.

If the component's transaction attribute is set to either Requires a transaction or Supports transactions, the new object inherits its creator's transaction. If the component's transaction attribute is set to Requires a new transaction, COM+ initiates a new transaction for the new object. If the component's transaction attribute is set to Does not support transactions, the new object doesn't execute under any transaction.

CreateInstance always returns the IUnknown interface on the newly instantiated object. You should immediately cast the returned value to the interface through which you want to communicate with the new object. The interface ID you pass in the iid parameter doesn't have to be the same interface as the one to which you cast the returned value, but it must be an interface that's implemented by the object you're instantiating.


IObjectContext::DisableCommit

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::DisableCommit [C/C++]

ObjectContext.DisableCommit Method [Visual Basic]

Declares that the object's transactional updates are inconsistent and can't be committed in their present state.

Syntax [C/C++]

HRESULT IObjectContext::DisableCommit ( );

Return Values [C/C++]

S_OK
The call to DisableCommit succeeded. The object's transactional updates can't be committed until the object calls either EnableCommit or SetComplete.
E_UNEXPECTED
An unexpected error occurred. This can happen if one object passes its IObjectContext pointer to another object and the other object calls DisableCommit using this pointer. An IObjectContext pointer is not valid outside the context of the object that originally obtained it.
CONTEXT_E_NOCONTEXT
The current object doesn't have a context associated with it. This is probably because it wasn't created with one of the COM+ CreateInstance methods.

Syntax [Visual Basic]

object.DisableCommit

Remarks

An object that invokes DisableCommit is stateful.

You can use the DisableCommit method to prevent a transaction from committing prematurely between method calls in a stateful object. When an object invokes DisableCommit, it indicates that its work is inconsistent and that it can't complete its work until it receives further method invocations from the client. It also indicates that it needs to maintain its state to perform that work. This prevents COM+ from deactivating the object and reclaiming its resources on return from a method call. Once an object has called DisableCommit, if a client attempts to commit the transaction before the object has called EnableCommit or SetComplete, the transaction will abort.

For example, suppose you have a General Ledger component that updates a database. A client makes multiple calls to a General Ledger object to post entries to various accounts. There's an integrity constraint that says the debits must equal the credits when the final method invocation returns, or the transaction must abort. The General Ledger object has an initialization method in which the client informs it of the sequence of calls the client is going to make, and the General Ledger object calls DisableCommit. The object maintains its state between calls so that, after the final call in the sequence is made, the object can make sure the integrity constraint is satisfied before allowing its work to be committed.


IObjectContext::EnableCommit

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::EnableCommit [C/C++]

ObjectContext.EnableCommit Method [Visual Basic]

Declares that the current object's work is not necessarily finished, but that its transactional updates are consistent and could be committed in their present form.

Syntax [C/C++]

HRESULT IObjectContext::EnableCommit();

Return Values [C/C++]

S_OK
The call to EnableCommit succeeded and the object's transactional updates can now be committed.
E_UNEXPECTED
An unexpected error occurred. This can happen if one object passes its IObjectContext pointer to another object and the other object calls EnableCommit using this pointer. An IObjectContext pointer is not valid outside the context of the object that originally obtained it.

Syntax [Visual Basic]

object.EnableCommit

Remarks

When an object calls EnableCommit, it allows the transaction in which it's participating to be committed, but it maintains its internal state across calls from its clients until it calls SetComplete or SetAbort or until the transaction completes.

EnableCommit is the default state when an object is activated. This is why an object should always call SetComplete or SetAbort before returning from a method, unless you want the object to maintain its internal state for the next call from a client.


IObjectContext::IsCallerInRole

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::IsCallerInRole [C/C++]

ObjectContext.IsCallerInRole Method [Visual Basic]

Indicates whether the object's direct caller is in a specified role (either directly or as part of a group).

Syntax [C/C++]

HRESULT IObjectContext::IsCallerInRole(
  BSTR bstrRole,
  BOOL* pflsInRole
);

Parameters [C/C++]

bstrRole
[in] The name of the role in which you want to determine whether the caller is acting.
pflsInRole
[out] TRUE if the caller is in the specified role, FALSE if not. This parameter will also be set to TRUE if security is not enabled.

Return Values [C/C++]

S_OK
The role specified in the bstrRole parameter is a recognized role, and the Boolean result returned in the pfIsInRole parameter indicates whether or not the caller is in that role.
CONTEXT_E_ROLENOTFOUND
The role specified in the bstrRole parameter does not exist.
E_INVALIDARG
One or more of the arguments passed in is invalid.
E_UNEXPECTED
An unexpected error occurred. This can happen if one object passes its IObjectContext pointer to another object and the other object calls IsCallerInRole using this pointer. An IObjectContext pointer is not valid outside the context of the object that originally obtained it.

Syntax [Visual Basic]

IsCallerInRole (Role)

Parts [Visual Basic]

Role
A string expression that contains the name of the role in which to determine if the caller is acting.

Return Values [Visual Basic]

TRUE
Either the caller is in the specified role, or security is not enabled.
FALSE
The caller is not in the specified role.

Remarks

You use this method to determine whether the direct caller of the currently executing method is associated with a specific role. A role is a symbolic name that represents a user or group of users who have specific access permissions to all components in a given COM+ application. Developers define roles when they create a component, and roles are mapped to individual users or groups at deployment time.

IsCallerInRole only applies to the direct caller of the currently executing method. (The direct caller is the process calling into the current server process. It can be either a base client process or a server process.) IsCallerInRole doesn't apply to the process that initiated the call sequence from which the current method was called, or to any other callers in that sequence.

Because IsCallerInRole returns TRUE when the object that invokes it is executing in a client's process, it's a good idea to call IsSecurityEnabled before calling IsCallerInRole. If security isn't enabled, IsCallerInRole won't return an accurate result.


IObjectContext::IsInTransaction

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::IsInTransaction [C/C++]

ObjectContext.IsInTransaction Method [Visual Basic]

Indicates whether the current object is executing in a transaction.

Syntax [C/C++]

BOOL IObjectContext::IsInTransaction();

Return Values [C/C++]

TRUE
The current object is executing within a transaction.
FALSE
The current object is not executing within a transaction.

Syntax [Visual Basic]

IsInTransaction

Return Values [Visual Basic]

TRUE
The current object is executing within a transaction.
FALSE
The current object is not executing within a transaction.

Remarks

You can use this method to make sure that an object that requires a transaction never runs without one. For example, if a component that requires a transaction is improperly configured in the Component Services administration tool, you can use this method to determine that the object doesn't have a transaction. Then you can return an error to alert the user to the problem, or take whatever action is appropriate.


IObjectContext::IsSecurityEnabled

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::IsSecurityEnabled [C/C++]

ObjectContext.IsSecurityEnabled [Visual Basic]

Indicates whether or not security is enabled for the current object.

Syntax [C/C++]

BOOL IObjectContext::IsSecurityEnabled();

Return Values [C/C++]

TRUE
Security is enabled for this object.
FALSE
Security is not enabled for this object.

Syntax [Visual Basic]

IsSecurityEnabled

Return Values [Visual Basic]

TRUE
Security is enabled for this object.
FALSE
Security is not enabled for this object.

Remarks

In the COM+ environment, both server and library applications can use role-based security. IsSecurityEnabled returns TRUE when an application uses role-based security, and role-based security is enabled both for the application and the specific component that called the method.

Note In MTS 2.0, this method always returns FALSE when the current object is running in a library application. This is because MTS library applications cannot use role-based security. However, in the COM+ environment, library applications can (but are not required to) use role-based security.


IObjectContext::SetAbort

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::SetAbort [C/C++]

ObjectContext.SetAbort Method [Visual Basic]

Declares that the transaction in which the object is executing must be aborted, and that the object should be deactivated on returning from the currently executing method call.

Syntax [C/C++]

HRESULT IObjectContext::SetAbort();

Return Values [C/C++]

S_OK
The call to SetAbort succeeded and the transaction will be aborted.
E_UNEXPECTED
An unexpected error occurred. This can happen if one object passes its IObjectContext pointer to another object and the other object calls SetAbort using this pointer. An IObjectContext pointer is not valid outside the context of the object that originally obtained it.

Syntax [Visual Basic]

object.SetAbort

Remarks

The object is deactivated automatically on return from the method in which it called SetAbort. If the object is the root of an automatic transaction, COM+ aborts the transaction. If the object is transactional, but not the root of an automatic transaction, the transaction in which it's participating is doomed to abort. (An object is the root of a transaction if the COM+ run-time environment has to initiate a new transaction for it. This is the case when the component that provides the object is configured to require a transaction and the object's creator doesn't have one, or when the component is configured to require a new transaction.)

You can call SetAbort in error handlers to ensure that a transaction aborts when an error occurs. You can also call SetAbort at the beginning of a method to protect your object from committing prematurely in the event of an unexpected return, and then call SetComplete just before the method returns, if all goes well.


IObjectContext::SetComplete

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContext::SetComplete [C/C++]

ObjectContext.SetComplete Method [Visual Basic]

Declares that the transaction in which the object is executing can be committed, and that the object should be deactivated on returning from the currently executing method call.

Syntax [C/C++]

HRESULT IObjectContext::SetComplete();

Return Values [C/C++]

S_OK
The call to SetComplete succeeded.
E_UNEXPECTED
An unexpected error occurred. This can happen if one object passes its IObjectContext pointer to another object and the other object calls SetComplete using this pointer. An IObjectContext pointer is not valid outside the context of the object that originally obtained it.

Syntax [Visual Basic]

object.SetComplete

Remarks

The object is deactivated automatically on return from the method in which it called SetComplete. If the object is the root of an automatic transaction, COM+ attempts to commit the transaction. However, if any object that was participating in the transaction has called SetAbort, or has called DisableCommit and has not subsequently called EnableCommit or SetComplete, the transaction will be aborted. (An object is the root of a transaction if the COM+ run-time environment has to initiate a new transaction for it. This is the case when the component that provides the object is configured to require a transaction and the object's creator doesn't have one, or when the component is configured to require a new transaction.)

If an object doesn't need to maintain its state after it returns from a method call, it should call SetComplete so that it can be automatically deactivated as soon as it returns and its resources can be reclaimed.


IObjectContextActivity

The IObjectContextActivity interface is used to retrieve a unique identifier associated with the current activity. This activity identifier is a GUID, and is only valid for the lifetime of the current activity.

Remarks

The header file for the IObjectContextActivity is mtx.h. You must also link mtxguid.lib to your project to use this interface.

You obtain a reference to an object's IObjectContextActivity interface by calling QueryInterface on the object's context. For example:

m_pIObjectContext->QueryInterface
    (IID_IObjectContextActivity,
    (void**)&m_pIObjectContextActivity));

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
Method | Description
GetActivityID | Retrieves the GUID associated with the current activity.


IObjectContextActivity::GetActivityID

Retrieves the GUID associated with the current activity.

[Visual Basic]

object.GetActivityId(pGUID)

[C/C++]

HRESULT IObjectContextActivity::GetActivityID(
  Guid* pActivityID
);

Parameters [Visual Basic]

pGUID
A string containing the GUID for the associated activity.

Parameters [C/C++]

pActivityID
[out] A reference to the GUID associated with the current activity.

Return Values [C/C++]

S_OK
The GUID of the current activity is returned in the parameter pActivityId.
E_INVALIDARG
The argument passed in the pActivityId parameter is a NULL pointer.
E_UNEXPECTED
An unexpected error occurred.


IObjectContextInfo

The IObjectContextInfo interface returns transaction, activity, and context information on the current context object. Using the methods of this interface, you can retrieve relevant information contained within an object context.

When to Implement

You should not implement this interface. The standard implementation provides complete functionality.

When to Use

You use this interface to track object context information based on a specific transaction, activity, or context.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
Methods | Description
IsInTransaction | Indicates whether the current object is executing in a transaction.
GetTransaction | Returns a pointer to the ITransaction interface of the current transaction.
GetTransactionId | Returns the identifier of the current transaction.
GetActivityId | Returns the identifier of the current activity.
GetContextId | Returns the identifier of the current context.

Requirements

To use the methods of this interface, you must include comsvcs.h in your file or set a reference to the comsvcs.dll in your project.

See Also

Contexts


IObjectContextInfo::GetActivityId

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContextInfo::GetActivityId [C/C++]

ContextInfo.GetActivityId [Visual Basic]

This method returns the GUID of the current activity.

[C/C++]
HRESULT IObjectContextInfo::GetActivityId(
  GUID *pGUID
);

[Visual Basic]
GetActivityId

Parameters [C/C++]

pGUID [out]
A GUID that identifies the current activity.

Return Values [C/C++]

S_OK
Returned the identifier of the current activity.
E_UNEXPECTED
An unexpected error occurred.

Remarks

If the object is not running within a synchronization domain, then COM+ returns a GUID_NULL, which consists of all zeros.

See Also

Contexts


IObjectContextInfo::GetContextId

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContextInfo::GetContextId [C/C++]

ContextInfo.GetContextId [Visual Basic]

This method returns the GUID of the current context.

[C/C++]
HRESULT IObjectContextInfo::GetContextId(
  GUID *pGuid
);

[Visual Basic]
GetContextId

Parameters [C/C++]

pGuid [out]
A GUID that identifies the current context.

Return Values [C/C++]

S_OK
Returned the identifier of the current context.
E_UNEXPECTED
An unexpected error occurred.

See Also

Contexts


IObjectContextInfo::GetTransaction

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContextInfo::GetTransaction [C/C++]

ContextInfo.GetTransaction [Visual Basic]

This method returns a pointer to the ITransaction Interface for the current transaction. You can use this pointer to manually enlist a resource manager that does not support automatic transaction.

[C/C++]
HRESULT IObjectContextInfo::GetTransaction (
  IUnknown ** pptrans
);

[Visual Basic]
GetTransaction

Parameters[C/C++]

pptrans [out]
A reference to the IUnknown interface of the transaction currently executing.

Return Values[C/C++]

S_OK
The object is executing in a transaction.
S_FAIL
The object is not executing in a transaction.
E_UNEXPECTED
An unexpected error occurred.

See Also

ITransaction Interface


IObjectContextInfo::GetTransactionId

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContextInfo::GetTransactionId [C/C++]

ContextInfo.GetTransactionId [Visual Basic]

This method returns the GUID of the current transaction.

[C/C++]
HRESULT IOjbectContextInfo::GetTransactionId(
  GUID *pGuid
);

[Visual Basic]
GetTransactionId

Parameters[C/C++]

pGuid [out]
A GUID that identifies the current transaction.

Return Values[C/C++]

S_OK
Returned the identifier of the current transaction.
CONTEXT_E_NOTRANSACTION
The object is not executing within a transaction.
E_UNEXPECTED
An unexpected error occurred.

Remarks

Objects in the same transaction share the same transaction identifier.

See Also

Automatic Transactions Through COM+


IObjectContextInfo::IsInTransaction

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectContextInfo::IsInTransaction [C/C++]

ContextInfo.IsInTransaction [Visual Basic]

This method Indicates whether the current object is executing in a transaction.

[C/C++]
BOOL IObjectContextInfo::IsInTransaction(void);

[Visual Basic]
IsInTransaction

Return Values

TRUE
The current object is executing within a transaction.
FALSE
The current object is not executing within a transaction.

See Also

Contexts


IObjectControl

You implement the IObjectControl interface when you want to define context-specific initialization and cleanup procedures for your COM+ objects, and to specify whether the objects can be recycled.

Implementing the IObjectControl interface is optional.

If you implement the IObjectControl interface in your component, the COM+ run-time environment automatically calls the IObjectControl methods on your objects at the appropriate times. Only the COM+ run-time environment can invoke the IObjectControl methods; they are not accessible to an object's clients or to the object itself. For example, if a client queries for the IObjectControl interface, QueryInterface returns a E_NOINTERFACE error.

When an object supports the IObjectControl interface, COM+ calls its Activate method once for each time the object is activated. The Activate method is called before any of the object's other methods are called. You can use this method to perform any context-specific initialization an object may require.

COM+ calls the object's Deactivate method each time the object is deactivated. This can be the result of the object returning from a method in which it calls SetComplete or SetAbort, or due to the root of the object's transaction, causing the transaction to complete. You use the Deactivate method to clean up state that you initialized in the Activate method. However, methods on components (including release) in the same activity, must never be called from inside the deactivate method.

After calling the Deactivate method, the COM+ run-time environment calls the CanBePooled method to determine whether the deactivated object is placed in an object pool for reuse or if the object is released in the usual way.

The IObjectControl interface provides the following methods.

Methods

Method | Description
Activate | Allows an object to perform context-specific initialization whenever it's activated. This method is called by COM+ before any other methods are called on the object.
CanBePooled | Allows an object to notify COM+ whether the object can be pooled for reuse.
Deactivate | Allows an object to perform whatever cleanup is necessary before it's recycled or destroyed. This method is called by COM+ whenever an object is deactivated.


IObjectControl::Activate

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectControl::Activate [C/C++]

ObjectControl.Activate [Visual Basic]

Implementing this method allows a COM+ object to perform context-specific initialization whenever it is activated. This method is called by the COM+ run-time environment before any other methods are called on the object.

Syntax [C/C++]

HRESULT IObjectControl::Activate();

Return Values [C/C++]

S_OK
Method completed successfully.
Failure HRESULT
Any error code indicating why an object was unable to activate itself.

Syntax [Visual Basic]

object.Activate

Parts [Visual Basic]

object
An object with a reference to an ObjectControl object.

Remarks

Whenever a client calls a COM+ object that isn't already active, the COM+ run-time environment automatically activates the object. This is called just-in-time (JIT) activation. For components that support IObjectControl as an interface, COM+ invokes the object's Activate method before passing the client's method call on to the object.

Any context-specific initialization procedures should be implemented in the Activate method for objects that expose IObjectControl.

For example, you can use the Activate method to obtain a reference to an object's context and store it in a member variable. Then the object context is available to any method that requires it, and you don't have to acquire a new one every time you want to use it. Once you have a reference to the object's context, you can use the IObjectContext methods to check whether security is enabled, whether the object is executing in a transaction, or whether the caller is in a particular role.

If you're enabling object recycling (by implementing the CanBePooled method to query the object), the Activate method must be able to handle both newly created and recycled objects. When the Activate method returns, there should be no distinguishable difference between a new object and a recycled one.

COM+ expressly forbids calling into an object that exposes IObjectControl before the activate method (when it is in its constructor). Such a call would result in an RPC_E_DISCONNECTED error. For example, if an object passes out a reference to itself while in its constructor, then calls back into the object prior to the call to Activate, returns the disconnected error.

[C/C++] You can also use the Activate method to obtain a reference to the object's SecurityProperty and check the security ID of the object's creator before any methods are called.


IObjectControl::CanBePooled

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectControl::CanBePooled [C/C++]

ObjectControl.CanBePooled [Visual Basic]

Implementing this method allows a COM+ object to notify the COM+ run-time environment whether it can be pooled for reuse.

Syntax [C/C++]

BOOL IObjectControl::CanBePooled();

Return Values [C/C++]

TRUE
Notifies the COM+ run-time environment that it can pool this object on deactivation for later reuse.
FALSE
Notifies the COM+ run-time environment that it should not pool this object on deactivation, but should release its last reference to the object so that the object will be destroyed.

Syntax [Visual Basic]

object.CanBePooled True | False

Parts [Visual Basic]

object
An object with a reference to an ObjectControl object.

Remarks

When an object returns TRUE from the CanBePooled method, it indicates to the COM+ run-time environment that it can be added to an object pool after deactivation rather than being destroyed. Whenever an instance is required, one is drawn from the pool rather than created.

Note Returning TRUE from the CanBePooled method doesn't guarantee that objects will be recycled; it only gives the COM+ run-time environment permission to recycle them. Returning FALSE from the CanBePooled method guarantees that instances of a component are not recycled.

The Activate method is called whether a new instance is created or a recycled instance is drawn from the pool. Similarly, the Deactivate method is called every time the object is deactivated, whether it is being destroyed or returned to the pool for recycling.

See Also

Writing Poolable Components, Object Pooling, Requirements for Poolable Objects, and How Object Pooling Works.


IObjectControl::Deactivate

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectControl::Deactivate [C/C++]

ObjectControl.Deactivate [Visual Basic]

Implementing this method allows a COM+ object to perform cleanup required before it is recycled or destroyed. This method is called by the COM+ run-time environment whenever an object is deactivated. Do not make any method calls on objects in the same activity from this method.

Syntax [C/C++]

void IObjectControl::Deactivate();

Syntax [Visual Basic]

object.Deactivate

Parameters [Visual Basic]

object
An object with a reference to a Catalog object.
optional parameter
A string containing the name of a remote computer. To connect to a local computer, supply an empty string as this argument.

Remarks

The COM+ run-time environment calls the Deactivate method whenever an object that supports the IObjectControl interface is deactivated. An object is deactivated when it returns from a method in which the method called SetComplete or SetAbort; when the transaction in which it executed is committed or aborted; or when the last client to hold a reference on the object releases its reference.

If the component supports recycling (returns TRUE from the CanBePooled method), you must use the Deactivate method to reset the object's state to the state in which the Activate method expects to find it. You can also use the Deactivate method to release the object's context or to do other context-specific cleanup. Even if an object supports recycling, it can be beneficial to release certain reusable resources in its Deactivate method. For example, ODBC provides its own connection pooling. It's more efficient to pool a database connection in a general connection pool where other objects can use it than it is to keep it tied to a specific object in an object pool.

COM+ expressly forbids calling into an object that exposes IObjectControl after the deactivate method has returned (when it is in its destructor). Such a call would result in an RPC_E_DISCONNECTED error. For example, if an object has passed out a reference to itself, then calls back into the object after Deactivate has returned results in a disconnected error.

[C/C++]

Note You cannot do this in the Release method of the destructor, because the IObjectContext interface is not accessible from the destructor or any of the IUnknown methods.


IObjectConstruct

You can use IObjectConstruct to control the object construction process by passing in parameters from other methods or objects. The IObjectConstruct interface exposes the Construct method that can be used to retrieve an object constructor string.

When to Implement

You implement this interface when you want to support object construction that can inherit parameter names from within another object or library by using an administratively supplied constructor string. To implement this kind of controlled object construction, you must derive your object from IObjectConstruct.

When object construction is administratively enabled for your component, COM+ calls the IObjectConstruct::Construct method that it implements, passing in a pointer to IObjectConstructString. This interface holds the administratively supplied constructor string as a property, which you can access and through which you can perform the appropriate initialization of your component. For details on enabling controlled object construction, see Specifying an Object Constructor String.

The IObjectConstruct interface provides the following methods.

Methods

Method | Description
Construct | Performs the construction of an object when this feature is administratively enabled that allows you to supply the parameters for the object.

See Also

Using Object Constructor Strings, Specifying an Object Constructor String, IObjectConstructString


IObjectConstruct::Construct

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectConstruct::Construct [C/C++]

IObjectConstruct.Construct [Visual Basic]

Performs the construction of an object, given an administratively supplied constructor string that allows you to control the parameters that are used in the creation of the object.

Syntax

[C/C++]
HRESULT IObjectConstruct::Construct(
  IDispatch * pCtorObj
);
[Visual Basic]
object.Construct(pCtorObj)

Parameters [C/C++]

pCtorObj [in]
A reference to an IObjectConstructString interface.

Parts [Visual Basic]

object
An object with a reference to an ObjectConstruct object.
pCtorObj
An object variable that exposes an IObjectConstructString interface.

Return Values [C/C++]

S_OK
Method completed successfully.

Remarks

When your component has object construction administratively enabled, the COM+ environment calls the Construct method. See Specifying an Object Constructor String.

[C/C++] You can use the QueryInterface method on the pointer you get back for IObjectConstructString. This interface enables you to get an administratively specified constructor string, which you can use in specifying the parameters for the construction of your object.

[Visual Basic] You can use the object reference that you get from the Construct method to get the IObjectConstructString.ConstructString property. This property contains an administratively specified constructor string, which you can use in specifying the parameters for the construction of your object.

Example [Visual Basic]

The following Visual Basic example demonstrates how to retrieve a constructor string by exposing IObjectConstruct:

  1. Reference COM+ 1.0 Services Type Library in your project.
  2. In your class module, beneath any Option statements, add the following code to store the constructor string in a private variable:
Implements IObjectConstruct
Private msConstructorString As String
  1. In the scope list box of your project, you should have a new object called IObjectConstruct. When you select it, the IObjectConstruct_Construct method will be added to your class.
  2. Add the following code to the IObjectConstruct_Construct method:
Private Sub IObjectConstruct_Construct(ByVal pCtorObj As Object)
msConstructorString = pCtorObj.ConstructString
End Sub

The constructor string will be stored in the msConstructorString variable.

See Also

Using Object Constructor Strings, Specifying an Object Constructor String, IObjectConstructString


IObjectConstructString

This interface provides access to a constructor string. Use it when you want to specify the parameters during the construction of your object.

When to Implement

You do not need to implement this interface. COM+ will supply a class object exposing IObjectConstructString when it calls IObjectConstruct::Construct.

When to Use

To support the use of object constructor strings, your object must implement IObjectConstruct. When object construction is enabled for your component, COM+ calls the IObjectConstruct::Construct method that it implements.

IObjectConstruct::Construct passes back a pointer to a IObjectConstructString. You can use get_ConstructString to retrieve the constructor string and perform the appropriate initialization of your component.

The IObjectConstructString interface provides the following methods.

Methods

Method | Description
get_ConstructString | Gets the constructor string administratively specified for the object.

See Also

IObjectConstruct, Using Object Constructor Strings, Specifying an Object Constructor String


IObjectConstructString::get_ConstructString

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

IObjectConstructString::get_ConstructString [C/C++]

IObjectConstructString.ConstructString [Visual Basic]

Gets the constructor string which has been administratively specified for the component. This property is read-only.

Syntax

[C/C++]
HRESULT IObjectConstructString::get_ConstructString(
  BSTR * pVal
);
[Visual Basic]
objectcontrol.ConstructString

Parameters [C/C++]

pVal [out]
A String containing an administratively supplied object constructor string.

Return Values [C/C++]

S_OK
Method completed successfully.

Remarks

You can use this method when implementing IObjectConstruct::Construct, which is called by the COM+ environment when your component is marked as supporting object construction.

See Also

Specifying an Object Constructor String, Using Object Constructor Strings, and IObjectConstruct.


IPlaybackControl

The IPlaybackControl interface is used in Queued Components to participate in the abnormal handling of server-side playback errors and client-side failures of the Message Queuing delivery mechanism.

When to Implement

You do not need to implement the IPlaybackControl interface. This interface is implemented by an application exception handler identified by the Exception_CLSID Catalog component.

When to Use

The Queued Components Player calls the methods of IPlaybackControl to inform the Exception Handler object that a message is about to be placed on the final resting or dead letter queue. The Exception Handler object can implement an alternative, such as gathering problem diagnosis information or generating an object or message that informs the client of the problem. If the application does not implement IPlaybackControl, the poison message is placed on the final resting or dead letter queue when all retries have been exhausted.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type descriptions.
GetTypeInfo | Retrieves a description of object’s programmable interface.
GetIDsOfNames | Maps name of method or property to DISPID.
Invoke | Calls one of the object’s methods, or gets/sets one of its properties.
IPlaybackControl Methods | Description
FinalClientRetry | Informs the client-side exception handling component that all Message Queuing attempts to deliver the message to the server were rejected, and the message ended up on the client-side Xact Dead Letter queue.
FinalServerRetry | Informs the server-side Exception_CLSID implementation that all attempts to play back the deferred activation to the server have failed, and the message is about to be moved to its final resting queue.

See Also

IMessageMover


IPlaybackControl::FinalClientRetry

Informs the client-side that all Message Queuing attempts to deliver the message to the server were rejected. The message is on the client-side Xact Dead Letter queue.

Syntax [C/C++]

HRESULT IPlaybackControl::FinalClientRetry();

Syntax[Visual Basic]

FinalClientRetry

Parameters [C/C++]

None.

Return Values [C/C++]

S_OK
Continue to call the remaining methods.
E_*
Do not call the remaining methods; leave the message on the Xact Dead Letter queue.

Remarks [C/C++]

As messages arrive on the Xact Dead Letter queue, COM+ attempts to invoke a client-side exception handler related to the server class to deliver this notification. This exception object might take exceptional action, such as recording the failure, sending a mail message to the administrator, or taking client-side compensating action (reversing the effect of an earlier transaction).

If this method is not successful, the message is left on the Xact Dead Letter queue.


IPlaybackControl::FinalServerRetry

Informs the server-side that all attempts to play back the deferred activation have failed. The message is about to be moved to the final resting queue.

Syntax [C/C++]

HRESULT IPlaybackControl::FinalServerRetry();

Syntax[Visual Basic]

FinalServerRetry

Parameters [C/C++]

None.

Return Values [C/C++]

S_OK
Continue to call the remaining methods.
E_*
Do not call the remaining methods; leave the message to the final resting queue.

Remarks [C/C++]

As the message is about to be moved to the final resting queue, the server object may attempt to record the failure, send a mail message to the administrator, or take client-side compensating action (reversing the effect of an earlier transaction). The server object should make every effort to complete this transaction successfully. Otherwise, manual intervention will be required to reprocess the message.

If this method is not successful, the message is moved to the final resting queue.


IPublisherFilter

The IPublisherFilter interface manages a filtered subscription cache for an event method. Only subscribers who meet the criteria specified by the filter are notified when the associated event is fired. The IPublisherFilter interface differs from the IMultiInterfacePublisherFilter interface in that it supports only one interface for the event object. For event classes that support more than one interface, see IMultiInterfacePublisherFilter. IPublisherFilter is supported only for backward compatibility.

When to Implement

Implement the IPublisherFilter on a publisher filter object. IPublisherFilter acts as a callback interface so event publishers can control which subscribers receive event notifications or the order in which subscribers are notified.

When to Use

Event publishers call the Initialize method of IPublisherFilter, and event class objects call PrepareToFire. The COM Events system uses this interface so publishers can determine which subscriptions they will fire events to.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IPublisherFilter Methods | Description
Initialize | Initializes the publisher filter object.
PrepareToFire | Prepares an event class object to fire an event to a filtered list of subscribers.


IPublisherFilter::Initialize

Associates an event method with a collection of subscription objects.

HRESULT Initialize(
  BSTR MethodName,            //Event method name
  IDispatch *dispUserDefined  //
);

Parameters

MethodName
[in] Name of the event method associated with the publisher filter.
dispUserDefined
[in] Pointer to the IEventSystem interface on an event system object or IEventControl interface on an event class object.

Return Values

This method returns the standard values E_INVALIDARG, E_POINTER, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The publisher filter was successfully initialized.
EVENT_S_SOME_SUBSCRIBERS_FAILED
An event was able to invoke some, but not all, of the subscribers.
EVENT_E_ALL_SUBSCRIBERS_FAILED
An event was unable to invoke any of the subscribers.
EVENT_S_NOSUBSCRIBERS
An event was published but there were no subscribers.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.
EVENT_E_INVALID_PER_USER_SID
The owner SID on a per-user subscription does not exist.
EVENT_E_USER_EXCEPTION
A user-supplied component or subscriber raised an exception.
EVENT_E_TOO_MANY_METHODS
An interface has too many methods from which to fire events.
EVENT_E_MISSING_EVENTCLASS
A subscription cannot be stored unless the event class for the subscription already exists.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.
EVENT_E_COMPLUS_NOT_INSTALLED
COM+ is required for this operation, but it is not installed.

Remarks

The publisher filter uses the pointer passed in dispUserDefined to obtain a list of subscribers, either by calling IEventSystem::Query or IEventControl::GetSubscriptions.


IPublisherFilter::PrepareToFire

Prepares a publisher filter to begin firing a filtered list of subscriptions using a provided firing control. The firing control is contained in the event class object.

HRESULT PrepareToFire(
  BSTR MethodName,             //Name of event method
  IFiringControl *pFiringControl  //Firing control
);

Parameters

MethodName
[in] Name of the event method to be fired.
pFiringControl
[in] Pointer to the IFiringControl interface on the firing control object.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The event class object is ready to fire the event.
EVENT_S_SOME_SUBSCRIBERS_FAILED
An event was able to invoke some, but not all, of the subscribers.
EVENT_E_ALL_SUBSCRIBERS_FAILED
An event was unable to invoke any of the subscribers.
EVENT_S_NOSUBSCRIBERS
An event was published but there were no subscribers.
EVENT_E_QUERYSYNTAX
A syntax error occurred while trying to evaluate a query string.
EVENT_E_QUERYFIELD
An invalid field name was used in a query string.
EVENT_E_INTERNALEXCEPTION
An unexpected exception was raised.
EVENT_E_INTERNALERROR
An unexpected internal error was detected.
EVENT_E_INVALID_PER_USER_SID
The owner SID on a per-user subscription does not exist.
EVENT_E_USER_EXCEPTION
A user-supplied component or subscriber raised an exception.
EVENT_E_TOO_MANY_METHODS
An interface has too many methods from which to fire events.
EVENT_E_MISSING_EVENTCLASS
A subscription cannot be stored unless the event class for the subscription already exists.
EVENT_E_NOT_ALL_REMOVED
Not all of the requested objects could be removed.
EVENT_E_COMPLUS_NOT_INSTALLED
COM+ is required for this operation, but it is not installed.


ISecurityCallContext

The ISecurityCallContext interface provides access to security methods and information about the security call context of the current call. COM+ applications that use role-based security have access to the security call context property collection through this interface. You can obtain information about any caller in the chain of callers, as well as methods specific to COM+ role-based security. For more information, see Programming Component Security.

Because this interface inherits from IDispatch, Visual Basic applications also have access to these properties and methods through Automation. To learn how to obtain security context information for use in Visual Basic applications, see GetSecurityCallContext.

When to Implement

You do not have to implement this interface because the system provides an implementation. C++ programmers can obtain a pointer to this implementation by calling CoGetCallContext, supplying IID_ISecurityCallContext for the riid parameter.

Note If base COM applications (or COM+ applications that do not use role-based security) request a pointer to this interface, E_NOINTERFACE will be returned.

When to Use

Call methods of this interface to gain access to items in the security call context collection. The following items are available:

  • Number of Callers
  • Minimum Authentication Level
  • Callers
  • Direct Caller
  • Original Caller

You can also use this interface to find out whether the direct caller or the specified user is in a particular role, such as IsCallerInRole or IsUserInRole, and whether role-based security is enabled for the object (IsSecurityEnabled). Some security methods are available through the IObjectContext interface. However, the security methods made available by ISecurityCallContext provide a more complete way to retrieve security properties and call security methods.

Methods in Vtable Order

For Visual Basic applications, the ISecurityCallContext methods are implemented on the SecurityCallContext object.

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces.
GetTypeInfo | Retrieves the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
ISecurityCallContext Methods | Description
get_Count | Retrieves the number of properties in the security context collection.
Get_Item | Retrieves a specified property in the security call context collection.
Get__NewEnum | Retrieves an iterator for the security call context collection.
IsCallerInRole | Determines whether the direct caller is in the specified role.
IsSecurityEnabled | Determines whether security is enabled for the object.
IsUserInRole | Determines whether the specified user is in the specified role.

See Also

Programming Component Security, ISecurityIdentityColl, SecurityIdentity Object, ISecurityCallersColl, SecurityCallers Object.


ISecurityCallContext Properties

The ISecurityCallContext interface exposes the properties described in this topic. This topic also briefly describes how these properties are retrieved. You cannot set these properties.

[Visual Basic]

Visual Basic programs read (get) properties directly using the following syntax:

object.propertyName

[C/C++]

C++ programs call methods of the ISecurityCallContext interface to retrieve properties. The methods that retrieve a property have the following form:

HRESULT  get_propertyName(PropertyDataType* pProperty);

Parameters [C/C++]

The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the Count property has the data type long. The method that gets this property has the following prototype:

HRESULT  get_Count(long*  plCount );

Properties

The following table lists the properties that are exposed by the ISecurityCallContext interface, identifies their data types, and indicates for each property whether the interface supports getting (G), putting (P), or both getting and putting (GP) the property.

Property | Get/Put | Data type | Description
Count | G | long | The number of items in the security call context collection.
Item | G | VARIANT | An indexed property used to retrieve a specified item in the security call context collection. For more information, see Remarks.
_NewEnum | G | IUnknown* | An iterator for the security call context collection.

Return Values [C/C++]

Each get_* method that retrieves a property returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained.

Remarks

[Visual Basic]

The Item property is an indexed property that allows you to retrieve a specific item in the security call context collection. The following syntax is used:

secCallCtxObj.Item(Index)

Index is a string specifying the item to be retrieved. For more information regarding items in the collection, including the string names you use to retrieve them, see SecurityCallContext object.

The Item property is the default property for a collection. Therefore, the following lines of code are equivalent:

x = secCallCtx("NumCallers")
x = secCallCtx.Item("NumCallers")

[C/C++]

In C++ programs, items in the collection are retrieved using the get_Item method, whose prototype is as follows:

HRESULT  get_Item(
  BSTR bstrItemName,  VARIANT* retval
);


ISecurityCallContext::IsCallerInRole

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISecurityCallContext::IsCallerInRole [C/C++]

SecurityCallContext.IsCallerInRole Method [Visual Basic]

Determines whether the object's direct caller is a member of the specified role.

Syntax [Visual Basic]

object.IsCallerInRole(role)

Parts of Syntax [Visual Basic]

object
An object with a reference to a SecurityCallContext object.
role
A string expression representing the name of the role whose membership will be checked.

Return Values [Visual Basic]

TRUE
If the direct caller is a member of the specified role or if role-based security is not enabled.
FALSE
The direct caller is not a member of the specified role.

Syntax [C/C++]

HRESULT IsCallerInRole(
  BSTR bstrRole,           //String indicating the role
  VARIANT_BOOL* pfInRole   //Pointer to value indicating whether
                           // the direct caller is a member of the
                           // specified role
);

Parameters [C/C++]

bstrRole
[in] String indicating the role, which can be a BSTR of any length.
pfInRole

[out] Pointer to value indicating whether the direct caller is a member of the specified role. If the specified role is not defined for the application, false is returned. If role-based security is not enabled, true is returned.

Remarks

Use this method to limit access to sections of code that should not be executed unless the caller is a member of the specified role. Windows 2000 groups and users are assigned to an application's roles using the Component Services administration tool. For more information about roles, see Role-Based Security.

IsCallerInRole only applies to the direct caller of the currently executing method. IsCallerInRole does not apply to any other caller in the call sequence from which the current method was called. However, you can obtain information about other callers in the sequence by using the Callers property of the SecurityCallContext object.

Because IsCallerInRole returns TRUE when role-based security is not enabled, it is a good idea to call IsSecurityEnabled before calling IsCallerInRole to ensure that IsCallerInRole returns useful information.

See Also

Programming Component Security


ISecurityCallContext::IsSecurityEnabled

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISecurityCallContext::IsSecurityEnabled [C/C++]

ISecurityCallContext::IsSecurityEnabled Method [Visual Basic]

Determines whether role-based security is enabled for the object. It returns true if the application uses role-based security and role checking is currently enabled for the object; otherwise, it returns false.

Syntax [C/C++]

HRESULT IsSecurityEnabled(
  VARIANT_BOOL* pfIsEnabled  //Pointer to value indicating whether
                            // role-based security is enabled for
                            // the object.
);

Parameters [C/C++]

pfIsEnabled
[out] Pointer to value indicating whether role-based security is enabled for the object.

Syntax [Visual Basic]

object.IsSecurityEnabled

Parts of Syntax [Visual Basic]

object
An object with a reference to a SecurityCallContext object.

Return Values [Visual Basic]

True
Role-based security is enabled for this object.
False
Role-based security is not enabled for this object.

Remarks

COM+ applications can use one of two types of security: role-based security or process access permissions. If role-based security is being used by the application but is currently disabled, either at the application or component level, this method will return false. Similarly, if the COM+ application uses process access permissions instead of role-based security, this method will return false.

You can use this method to find out whether role-based security is enabled before you check role membership using IsCallerInRole. The reason for doing this is that IsCallerInRole always returns true when role-based security is not enabled.

See Also

Programming Component Security, Role-Based Security


ISecurityCallContext::IsUserInRole

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISecurityCallContext::IsUserInRole [C/C++]

SecurityCallContext.IsUserInRole Method [Visual Basic]

Determines whether the specified user is a member of the specified role.

Syntax [Visual Basic]

object.IsUserInRole(User, role)

Parts of Syntax [Visual Basic]

object
An object with a reference to a SecurityCallContext object.
User
A Variant representing the user ID whose role membership will be checked.
role
A string expression representing the name of the role whose membership will be checked.

Return Values [Visual Basic]

True
If the specified caller is a member of the specified role or if role-based security is not enabled.
False
The specified caller is not a member of the specified role.

Syntax [C/C++]

HRESULT IsUserInRole(
  VARIANT* pUser,          //Pointer to value holding UserID
  BSTR bstrRole,           //String indicating the role
  VARIANT_BOOL* pfInRole   //Pointer to value indicating whether
                           // the specified user is a member of the
                           // specified role
);

Parameters [C/C++]

pUser
[in] Pointer to value holding the User ID of the user whose role membership is to be checked. If you intend to pass the security identifier (SID) to IsUserInRole, pUser should pass the following check:
V_VT(pUser) == (VT_ARRAY|VT_UI1) && V_ARRAY(pUser)->cDims == 1
bstrRole
[in] String indicating the role, which can be a BSTR of any length.
pfInRole
[out] Pointer to value indicating whether the direct caller is a member of the specified role. If the specified role is not defined for the application, false is returned. If role-based security is not enabled, true is returned.

Remarks

Use this method to limit access to sections of code that should not be executed unless the caller is a member of the specified role. Windows 2000 groups and users are assigned to an application's roles using the Component Services administration tool. For more information about roles, see Role-Based Security.

Because IsUserInRole returns True when role-based security is not enabled, it is a good idea to call IsSecurityEnabled before calling IsUserInRole to ensure that IsUserInRole returns useful information.

See Also

Programming Component Security


ISecurityCallersColl

The ISecurityCallersColl provides access to information about individual callers in a collection of callers exposed by ISecurityCallContext. The collection represents the chain of calls ending with the current call, and each caller in the collection represents the identity of one caller. Only callers who cross a boundary where security is checked are included in the chain of callers. (In the COM+ environment, security is checked at application boundaries.) Access to information about a particular caller's identity is provided through ISecurityIdentityColl, an identity collection.

Because this interface inherits from IDispatch, Visual Basic applications also have access to these properties and methods through Automation. To learn how to obtain security context information for use in Visual Basic applications, see GetSecurityCallContext.

When to Implement

You do not have to implement this interface because the system provides an implementation. C++ programmers can obtain access to items in the security callers collection by first calling CoGetCallContext to get a pointer to ISecurityCallContext. Then, call ISecurityCallContext::get_Item requesting the Callers property. A pointer to an ISecurityCallersColl is returned.

Note If a COM+ application that does not use role-based security tries to obtain a pointer to ISecurityCallContext, E_NOINTERFACE will be returned.

When to Use

The SecurityCallersColl interface gains access to information about an individual caller in the security callers collection. Once you have access to an individual caller, you can use the ISecurityIdentity interface to gain access to further more specific information about that caller.

To access a particular caller in the callers collection, C++ programmers can call ISecurityCallersColl::get_Item, passing an index between zero and n-1 (one less than the number of callers in the collection).

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces.
GetTypeInfo | Retrieves the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
ISecurityCallersColl Methods | Description
get_Count | Retrieves the number of callers in the security callers collection.
get_Item | Retrieves a specified caller in the security callers collection.
get__NewEnum | Retrieves an enumerator for the security callers collection.

See Also

CoGetCallContext, ISecurityCallContext, ISecurityIdentityColl


ISecurityCallersColl Properties

The ISecurityCallersColl interface exposes the properties described in this topic. This topic also briefly describes how these properties are retrieved. You cannot set these properties.

[Visual Basic]

Visual Basic programs read (get) properties directly using the following syntax:

object.propertyName

[C/C++]

C++ programs call methods of the ISecurityCallersColl interface to retrieve properties. The methods that retrieve a property have the following form:

HRESULT  get_propertyName(PropertyDataType* pProperty);

Parameters [Visual Basic]

The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the Count property has the data type long. The method that gets this property has the following prototype:

HRESULT  get_Count(long*  plCount );

Properties

The following table lists the properties that are exposed by the ISecurityCallersColl interface, identifies their data types, and indicates for each property whether the interface supports getting (G), putting (P), or both getting and putting (GP) the property.

Property | Get/Put | Data type | Description
Count | G | long | The number of items in the security callers collection.
Item | G | VARIANT | An indexed property used to retrieve a specified item in the security callers collection. For more information, see Remarks.
_NewEnum | G | IUnknown* | An iterator for the security callers collection.

Return Values [C/C++]

Each get_* method that retrieves a property returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained.

Remarks [Visual Basic]

The Item property is an indexed property that allows you to retrieve a specific item in the security call context collection. The following syntax is used:

secCallersObj.Item(Index)

Index is an integer specifying the item to be retrieved. For more information regarding items in the collection, see SecurityCallers object.

The Item property is the default property for a collection. Therefore, the following lines of code are equivalent:

x = secCallersObj.Item(2)
x = secCallersObj(2)

Remarks [C/C++]

In C++ programs, items in the collection are retrieved using the get_Item method, whose prototype is as follows:

HRESULT  get_Item(
  BSTR bstrItemName,  VARIANT* retval
);


ISecurityIdentityColl

The ISecurityIdentityColl interface provides access to a collection of security information representing a caller's identity. The items available in this collection are the SID, the account name, the authentication service, the authentication level, and the impersonation level.

This interface is used to find out about a particular caller in a chain of callers that is part of the security call context. For more information about how security call context information is accessed, see Programming Component Security.

Because this interface inherits from IDispatch, Visual Basic applications also have access to these properties and methods through Automation. To learn how to obtain security context information for use in Visual Basic applications, see GetSecurityCallContext.

When to Implement

You do not have to implement this interface because the system provides an implementation.

Note COM+ applications that do not use role-based security and base COM applications cannot call methods of ISecurityIdentityColl. The reason for this is that they cannot obtain the necessary pointer to ISecurityCallContext. For more information, see CoGetCallContext.

When to Use

You can call methods of this interface to obtain access to security identity information, which represent the identity of a caller. You might need to retrieve security identity information to perform event logging or to see whether the caller is using a sufficiently secure connection.

To obtain security identity information, C++ programmers call CoGetCallContext to get a pointer to the ISecurityCallContext interface. Next, call ISecurityCallContext::get_Item requesting a security call context item that is a security identity collection (such as "DirectCaller" or "OriginalCaller"). Then, call ISecurityIdentityColl::get_Item to retrieve a security identity item such as "Name" or "AuthenticationService".

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces.
GetTypeInfo | Retrieves the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
ISecurityIdentityColl Methods | Description
get_Count | Retrieves the number of properties in the security identity collection.
Get_Item | Retrieves a specified property in the security identity collection.
Get__NewEnum | Retrieves an enumerator for the security identity collection.

See Also

Programming Component Security, SecurityIdentity Object, CoGetCallContext


ISecurityIdentityColl Properties

The ISecurityIdentityColl interface exposes the properties described in this topic. This topic also briefly describes how these properties are retrieved. You cannot set these properties.

[Visual Basic]

Visual Basic programs read (get) properties directly using the following syntax:

object.propertyName

[C/C++]

C++ programs call methods of the ISecurityIdentityColl interface to retrieve properties. The methods that retrieve a property have the following form:

HRESULT  get_propertyName(PropertyDataType* pProperty);

Parameters [C/C++]

The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the Count property has the data type long. The method that gets this property has the following prototype:

HRESULT  get_Count(long*  plCount );

Properties

The following table lists the properties that are exposed by the ISecurityIdentityColl interface, identifies their data types, and indicates for each property whether the interface supports getting (G), putting (P), or both getting and putting (GP) the property.

Property | Get/Put | Data type | Description
Count | G | long | The number of items in the security identity collection.
Item | G | VARIANT | An indexed property used to retrieve a specified item in the security identity collection. For more information, see Remarks.
_NewEnum | G | IUnknown* | An iterator for the security identity collection.

Return Values [C/C++]

Each get_* method that retrieves a property returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained.

Remarks [Visual Basic]

The Item property is an indexed property that allows you to retrieve a specific item in the security identity collection. The following syntax is used:

secIdentityObect.Item(Index)

Index is a string specifying the item to be retrieved. For more information regarding items in the collection, including the string names you use to retrieve them, see SecurityIdentity object.

The Item method is the default method for a collection. Therefore, the following lines of code are equivalent:

x = secIdentity("SID")
x = secIdentity.Item("SID")

Remarks [C/C++]

In C++ programs, items in the collection are retrieved using the get_Item method, whose prototype is as follows:

HRESULT  get_Item(
  BSTR bstrItemName,  VARIANT* retval
);


ISecurityProperty

The ISecurityProperty interface allows you to determine the security ID of the current object's original caller or direct caller. However, the preferred way to get information about an object's callers is to use the ISecurityCallContext interface.

For Visual Basic programmers, the functionality provided by ISecurityProperty is provided on the SecurityProperty object.

When to Implement

You do not need to implement the ISecurityProperty interface because the system supplies an implementation of this interface. C++ programmers obtain a reference to an object's ISecurityProperty interface by calling QueryInterface on the object's ObjectContext, as in the following example:

m_pIObjectContext->QueryInterface (IID_ISecurityProperty, (void**)&m_pISecurityProperty);

When to Use

You can call the GetDirectCallerSID and GetOriginalCallerSID methods of ISecurityProperty to obtain an object's direct caller and original caller, respectively.

Warning You should not use GetDirectCreatorSID or GetOriginalCreatorSID in COM+ applications because their behaviors are unpredictable.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ISecurityProperty Methods | Description
GetDirectCallerSID | Retrieves the security ID of the external process that called the currently executing method.
GetDirectCreatorSID | In MTS 2.0, this method retrieves the security ID of the external process that directly created the current object. In COM+ 1.0, do not use this method because its behavior is unpredictable.
GetOriginalCallerSID | Retrieves the security ID of the base process that initiated the call sequence from which the current method was called.
GetOriginalCreatorSID | In MTS 2.0, this method retrieves the security ID of the base process that initiated the activity in which the current object is executing. In COM+ 1.0, do not use this method because its behavior is unpredictable.
ReleaseSID | Releases the security ID returned by one of the other ISecurityProperty methods.

See Also

Programming Component Security, IObjectContext, ISecurityCallContext


ISecurityProperty::GetDirectCallerSID

Retrieves the security ID of the external process that called the currently executing method. You can also obtain this information using ISecurityCallContext.

Syntax [Visual Basic]

object.GetDirectCallerSID(pSID)

Visual Basic users should see GetDirectCallerName for more information on implementing this method.

Syntax [C++]

HRESULT ISecurityProperty::GetDirectCallerSID(
  PSID *ppSid
);

Parameters [C++]

ppSid
[out] A reference to the security ID of the process from which the current method was invoked.

Return Values [C++]

S_OK
The security ID of the process that called the current method is returned in the parameter ppSid.
E_INVALIDARG
The argument passed in the ppSid parameter is a NULL pointer.
E_UNEXPECTED
An unexpected error occurred.

Remarks [C++]

You use the GetDirectCallerSID method to determine the security ID of the process that called the object's currently executing method. Security is enforced across process boundaries. This means that the security ID returned by GetDirectCallerSID is the security ID associated with the process that called into the process in which the current object is running, not necessarily the immediate caller into the object itself. If an object calls into another object within the same process, when the second object calls GetDirectCallerSID, it will get the security ID of the most immediate caller outside its own process boundary, not the security ID of the object that directly called into it.

The following scenarios illustrate the functionality of the GetDirectCallerSID method:

  • A base process running on server A, as user A, calls into object X on server B, running as user B. Then object X calls into object Y, running on server C. If object Y calls GetDirectCallerSID, the security ID of user B is returned.
  • A base process, running on server A as user A, calls into object X on server B, running as user B. Then object X calls into object Y, running in the same process as object X, also on server B. When object Y calls GetDirectCallerSID, the security ID of user A is returned , not the security ID of user B.

You must call ReleaseSID on a security ID when you finish using it.

Example

See Also [C++]

Programming Component Security, IObjectContext


ISecurityProperty::GetDirectCreatorSID

In MTS 2.0, this method retrieves the security ID of the current object's creator.

Warning You should not use this method in COM+ applications because their behaviors are unpredictable.

Syntax [Visual Basic]

object.GetDirectCreatorSID(pSID)

Visual Basic users should see GetDirectCreatorName for more information on implementing this method.

Syntax [C++]

HRESULT ISecurityProperty::GetDirectCreatorSID(
  PSID *ppSid
);

Parameters [C++]

ppSid
[out] A reference to the security ID of the process that directly created the current object.

Return Values [C++]

S_OK
The security ID of the process that directly created the current object is returned in the parameter ppSid.
E_INVALIDARG
The argument passed in the ppSid parameter is a NULL pointer.
E_FAIL
An unexpected error occurred.

See Also [C++]

Programming Component Security, IObjectContext


ISecurityProperty::GetOriginalCallerSID

You can use this method to retrieve the security ID of the base process that initiated the sequence of calls from which the call into the current object originated. However, the preferred way to obtain information about the original caller is to use the ISecurityCallContext interface.

Syntax [Visual Basic]

object.GetOriginalCallerSID(pSID)

Visual Basic users should see GetOriginalCallerName for more information on implementing this method.

Syntax [C++]

HRESULT ISecurityProperty::GetOriginalCallerSID(
  PSID *ppSid
);

Parameters [C++]

ppSid
[out] A reference to the security ID of the base process that initiated the call sequence from which the current method was called.

Return Values [C++]

S_OK
The security ID of the base process that originated the call into the current object is returned in the parameter ppSid.
E_INVALIDARG
The argument passed in the ppSid parameter is a NULL pointer.
E_FAIL
An unexpected error occurred.

Remarks [C++]

You use the GetOriginalCallerSID method to determine the security ID of the original process that initiated the call sequence from which the current method was called, not the originator (or creator) of the process. Although a pointer to an object can be passed through a series of servers and users, GetOriginalCallerSID always returns the first server and user of the process, even if that user was not the original creator of the object. The following scenario illustrates the functionality of the GetOriginalCallerSID method.

Base process one, running on server A as user A, creates an object, X, on server B, running as user B. You can have base process one pass its reference for object X to base process two, running on server D as user D. Then, base process two uses that reference to call into object X. Object X then calls into object Y, running on server C. If object Y then calls GetOriginalCallerSID, the security ID of user D is returned, not user A, who originally created the object.

[C++]

Note Usually, an object's original caller is the same process as its original creator. The only situation in which the original caller and the original creator would be different is one in which the original creator passes a reference to another process, and the other process initiates the call sequence (as in the preceding example).

The path to the original caller is broken if any object along the chain was created by some other means than IObjectContext::CreateInstance or ITransactionContext::CreateInstance. For example, if base process 1 uses CoCreateInstance to create X, when Y calls GetOriginalCallerSID, the security ID it gets back will be the security ID of user B, not user D. This is because the call sequence is traced back through the objects' context and COM+ can only create a context for an object that is created with either IObjectContext::CreateInstance or ITransactionContext::CreateInstance.

You must call ReleaseSID on a security ID when you finish using it.

Example

See Also [C++]

Programming Component Security, IObjectContext


ISecurityProperty::GetOriginalCreatorSID

In MTS 2.0, this method was used to retrieve the security ID of the original base process that initiated the activity in which the current object is executing.

However, you should not use this method in COM+ applications because its behavior is unpredictable.

Syntax [Visual Basic]

object.GetOriginalCreatorSID(pSID)

Visual Basic users should see GetOriginalCreatorName for more information on implementing this method.

Syntax [C++]

HRESULT ISecurityProperty::GetOriginalCreatorSID(
  PSID *ppSid
);

Parameters [C++]

ppSid
[out] A reference to the security ID of the base process that initiated the activity in which the current object is executing.

Return Values [C++]

S_OK
The security ID of the original creator is returned in the parameter ppSid.
E_INVALIDARG
The argument passed in the ppSid parameter is a NULL pointer.
E_FAIL
An unexpected error occurred.

See Also [C++]

Programming Component Security, IObjectContext


ISecurityProperty::ReleaseSID

Releases a security ID that was obtained from the GetDirectCallerSID, GetDirectCreatorSID, GetOriginalCallerSID, or GetOriginalCreatorSID method.

Syntax [C++]

HRESULT ISecurityProperty::ReleaseSID(
  PSID pSid
);

Parameters [C++]

pSid
[in] A reference to a security ID that was obtained by invoking one of the ISecurityProperty methods.

Return Values [C++]

S_OK
The security ID, passed in the pSid parameter, was released.
E_INVALIDARG
The argument passed in the pSid parameter is not a reference to a security ID.

Remarks [C++]

You should always invoke the ReleaseSID method to release any security ID pointers returned by the GetDirectCallerSID, GetDirectCreatorSID, GetOriginalCallerSID, and GetOriginalCreatorSID methods of the ISecurityProperty interface.

See Also [C++]

Programming Component Security, IObjectContext


ISelectCOMLBServer

The ISelectCOMLBServer interface is used to activate the COM+ component load balancing service.

When to Implement

This interface is used to activate the COM+ component load balancing service. Implement ISelectCOMLBServer in conjunction with a load balancing activator. The activator must be written so that it creates an object that implements the ISelectCOMLBServer interface, if the CLSID for that object has been added to the LocalMachine object in the COM+ catalog. If that CLSID exists, the load balancing activator calls the ISelectCOMLBServer::GetLBServer method, obtains a machine name, and notifies a separate object to redirect the activation to that machine.

When to Use

You do not call the methods of ISelectCOMLBServer . These methods are called by applications that activate the COM+ component load balancing services.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ISelectCOMLBServer Methods | Description
Init | Initializes the server object.
GetLBServer | Obtains the load balancing server.

See Also

ICOMLBArguments


ISelectCOMLBServer::GetLBServer

Obtains the machine name of the load balancing server.

HRESULT GetLBServer(
IUnknown *pUnk  //The load balancing server's machine name
);

Parameters

pUnk
[in, out] Pointer to the load balancing server's machine name.

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The machine name of the load balancing server was successfully retrieved.

See Also

ICOMLBArguments


ISelectCOMLBServer::Init

Initializes the load balancing server object.

HRESULT Init( );

Parameters

none

Return Values

This method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The server object was successfully initialized.

See Also

ICOMLBArguments


ISharedProperty Interface

The ISharedProperty interface is implemented on a SharedProperty object and exposes property methods that you can use to set or retrieve the value of a shared property. A shared property can contain any data type that can be represented by a variant.

When to Use

You can access the ISharedProperty interface by using the CreateProperty or CreatePropertyByPosition methods of ISharedPropertyGroup to create a SharedProperty object.

A SharedProperty object can be created or accessed only from within a SharedPropertyGroup.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ISharedProperty Methods | Description
get_Value | Retrieves the value of a shared property.
put_Value | Sets the value of a shared property.


ISharedProperty Properties

The ISharedProperty Interface interface is implemented on the SharedProperty object and exposes the properties described in this topic. This topic also briefly describes how these properties are retrieved.

[Visual Basic]

Visual Basic programmers read (get) and set (put) properties directly using the following syntax:

object.propertyName

[C/C++]

C++ programs call methods of the ISecurityCallContext interface to retrieve properties. The methods that retrieve a property have the following form:

HRESULT  get_propertyName(PropertyDataType* pProperty);

Parameters [Visual Basic]

The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the Count property has the data type long. The method that gets this property has the following prototype:

HRESULT  get_Count(long*  plCount );

Properties

The following table lists the properties that are exposed by the ISecurityCallContext interface on the SharedProperty object, identifies their data types, and indicates for each property whether the interface supports getting (G), putting(P), or both getting and putting (GP) the property.

Property | Get/Put | Data type | Description
Value | G | VARIANT | Retrieves or sets the value of a shared property.

Return Values [C/C++]

Each get_* method that retrieves a property returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
A reference to a VARIANT containing the value of the shared property is returned in the pVal parameter.
E_INVALIDARG
The argument passed in the pVal parameter is invalid.

Each put_* method that retrieves a property returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

DISP_E_ARRAYISLOCKED
The argument passed in the value parameter contains an array that's locked.
DISP_E_BADVARTYPE
The argument passed in the value parameter isn't a valid VARIANT type.

Examples[C/C++]

#include <mtx.h>
#include <mtxspm.h>

IObjectContext* pObjectContext = NULL;
ISharedPropertyGroupManager* pPropGpMgr = NULL;
ISharedPropertyGroup* pPropGp = NULL;
ISharedProperty* pPropNextNum = NULL;
VARIANT_BOOL fAlreadyExists = VARIANT_FALSE;
LONG lIsolationMode = LockMethod;
LONG lReleaseMode = Process;
LONG lNextValue = 0L;
BSTR stName, stNextNumber;
VARIANT vNext;
HRESULT hr = S_OK;

hr = GetObjectContext(&pObjectContext);

// Create the SharedPropertyGroupManager,
// SharedPropertyGroup, and SharedProperty.
hr = pObjectContext->CreateInstance
    (CLSID_SharedPropertyGroupManager,
    IID_ISharedPropertyGroupManager,
    (void**)&pPropGpMgr);

stName = SysAllocString(L"Counter");
hr = pPropGpMgr->CreatePropertyGroup(stName,
    &lIsolationMode, &lReleaseMode, &fAlreadyExists,
    &pPropGp);
SysFreeString(stName);

stNextNumber = SysAllocString(L"NextNum");
hr = pPropGp->CreateProperty
    (stNextNumber, &fAlreadyExists, &pPropNextNum);
SysFreeString(stNextNumber);

// Get the next number and increment the counter.
VariantInit(&vNext);
vNext.vt = VT_I4;
hr = pPropNextNum->get_Value(&vNext);
lNextValue = vNext.lVal++;
hr = pPropNextNum->put_Value(vNext);


ISharedPropertyGroup

The ISharedPropertyGroup interface is used to create and access the shared properties in a shared property group.

When to Use

You can access the ISharedPropertyGroup interface by creating a SharedPropertyGroup object with the ISharedPropertyGroupManager::CreatePropertyGroup method.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
Method | Description
CreateProperty | Creates a new shared property identified by a string expression that's unique within its property group.
CreatePropertyByPosition | Creates a new shared property identified by a numeric index within its property group.
Property Methods | Description
get_Property | Returns a reference to a shared property, given the string name by which the property is identified.
get_PropertyByPosition | Returns a reference to a shared property, given its numeric index in the shared property group.


ISharedPropertyGroup Properties

The ISharedPropertyGroup interface is implemented on the SharedPropertyGroup Object and exposes the properties described in this topic. This topic also briefly describes how these properties are retrieved.

[Visual Basic]

Visual Basic programmers read (get) and set (put) properties directly using the following syntax:

object.propertyName

[C/C++]

C++ programs call methods of the ISharedPropertyGroup interface to retrieve properties. The methods that retrieve a property have the following form:

HRESULT  get_propertyName(
  PropertyDataType* pProperty
);

Parameters[C/C++]

The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the Count property has the data type long. The method that gets this property has the following prototype:

HRESULT  get_Count(
  long*  plCount
);

Properties

The following table lists the properties that are exposed by the ISharedPropertyGroup interface on the SharedPropertyGroup object, identifies their data types, and indicates for each property whether the interface supports getting (G), putting (P), or both getting and putting (GP) the property.

Property | Get/Put | Data type | Description
Property | G | VARIANT | Returns a reference to an existing shared property identified by a string name.
PropertyByPosition | G | VARIANT | Returns a reference to an existing shared property identified by its numeric index within the property group.

Return Values [C/C++]

Each method that retrieves a property returns the following:

S_OK

The shared property specified by name was found and a reference to it is returned in the ppProperty parameter.

E_INVALIDARG

Either the argument passed in the ppProperty parameter was a null pointer, or there is no property in the shared property group with the name specified in the name parameter.


ISharedPropertyGroup::CreateProperty

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISharedPropertyGroup::CreateProperty [C/C++]

SharedPropertyGroup.CreateProperty Method [Visual Basic]

Creates and returns a reference to a new SharedProperty with a specified name. If a shared property by that name already exists, CreateProperty returns a reference to the existing property.

Syntax [Visual Basic]

CreateProperty(name, pfExists)

Syntax [C/C++]

HRESULT ISharedPropertyGroup::CreateProperty(
  BSTR name,
  VARIANT BOOL *pfExists,
  ISharedProperty **ppProp
);

Parameters

name[C/C++, Visual Basic]
[in] The name of the property to create. You can use this name later to obtain a reference to this property by using the get_Property method.
pfExists[C/C++, Visual Basic]
[out] A reference to a Boolean value that's set to VARIANT_TRUE on return from this method if the shared property specified in the name parameter existed prior to this call, and VARIANT_FALSE if the property was created by this call.
ppProp [C/C++]
[out] A reference to a SharedProperty object with the name specified in the name parameter, or NULL if an error is encountered.

Return Values [C/C++]

S_OK
A reference to a shared property with the name specified in the name parameter is returned in the parameter ppProp.
E_INVALIDARG
One or more of the arguments passed in is invalid.

Remarks

When you create a shared property, its value is set to the default, which is a VT_I4 VARIANT with a value of 0.

If you create a shared property with the CreateProperty method, you can access that property only by using the get_Property method. You can't assign a numeric index to the same property and then access it by using the get_PropertyByPosition method.

The same shared property group can contain some shared property objects that are identified by name and others that are identified by position.


ISharedPropertyGroup::CreatePropertyByPosition

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISharedPropertyGroup::CreatePropertyByPosition [C/C++]

SharedPropertyGroup.CreatePropertyByPosition Method [Visual Basic]

Creates a new shared property identified by a numeric index that's unique within the property group. If a shared property with the specified index already exists, CreatePropertyByPosition returns a reference to the existing one.

Syntax [Visual Basic]

CreatePropertyByPosition(Index, pfExists)

Syntax [C/C++}

HRESULT ISharedPropertyGroup::CreatePropertyByPosistion(
  INT Index,
  VARIANT BOOL *pfExists,
  ISharedProperty **ppProp
);

Parameters

Index[C/C++, Visual Basic]
[in] The numeric index (Long) within the SharedPropertyGroup object by which the new property will be referenced. You can use this index later to retrieve the shared property with the get_PropertyByPosition method.
pfExists[C/C++, Visual Basic]
[out] A reference to a Boolean value. If pfExists is set to VARIANT_TRUE on return from this method, the shared property specified by index existed prior to this call. If it's set to VARIANT_FALSE, the property was created by this call.
ppProp [C/C++]
[out] A reference to a shared property object identified by the numeric index passed in the index parameter, or NULL if an error is encountered.

Return Values [C/C++]

S_OK
A reference to the shared property occupying the position specified in the index parameter is returned in the ppProp parameter.
E_INVALIDARG
One or more of the arguments passed in is invalid.

Remarks

When you create a shared property, its value is set to the default, which is a VT_I4 VARIANT with a value of 0.

If you create a SharedProperty object with the CreatePropertyByPosition method, you can access that property only by using the get_PropertyByPosition method. You can't assign a string name to the same property and then access it by using the get_Property method. Accessing a property by position is faster than accessing a property by using a string name because it requires less overhead.

The same shared property group can contain some SharedProperty objects that are identified by position and others that are identified by name.


ISharedPropertyGroupManager

The ISharedPropertyGroupManager interface is implemented on the SharedPropertyGroupManager object that you can use to create shared property groups and to obtain access to existing shared property groups.

When to Use

You can access the ISharedPropertyGroupManager interface by creating an instance of the SharedPropertyGroupManager with either IObjectContext::CreateInstance or CoCreateInstance.

The Shared Property Manager is a resource dispenser that you can use to share state among multiple objects within a server process. You can't use global variables in a distributed environment because of concurrency and name collision issues. The Shared Property Manager eliminates name collisions by providing shared property groups, which establish unique name spaces for the shared properties they contain. The Shared Property Manager also implements locks and semaphores to protect shared properties from simultaneous access, which could result in lost updates and could leave the properties in an unpredictable state.

Shared properties can be shared only by objects running in the same process. If you want instances of different components to share properties, you have to install the components in the same COM+ application. Because there is a risk that administrators will move components from one application to another, it's safest to limit the use of a shared property group to instances of components that are defined in the same DLL.

It's also important for components sharing properties to have the same activation attribute. If two components in the same application have different activation attributes, they generally won't be able to share properties.

You should always instantiate the SharedPropertyGroupManager, SharedPropertyGroup, and SharedProperty objects from COM+ objects rather than from a base client. If a base client creates shared property groups and properties, the shared properties are inside the base client's process, not in a server process. This means COM+ objects can't share the properties unless the objects, too, are running in the client's process (which is generally not a good idea).

Note When you set the isolation mode to LockMethod, the Shared Property Manager requires access to the calling object's ObjectContext. You can't use this isolation mode to create a shared property group from within an object's constructor or from a non-COM+ object because ObjectContext isn't available during object construction, and a non-COM+ object doesn't have an ObjectContext.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
Method | Description
CreatePropertyGroup | Creates a new SharedPropertyGroup with a string name as an identifier. If a group with the specified name already exists, CreatePropertyGroup returns a reference to the existing group.
Property Methods | Description
get_Group | Returns a reference to an existing shared property group, given a string name by which it can be identified.
get__NewEnum | Returns a reference to an enumerator that iterates through a list of all the shared property groups in a given process.


ISharedPropertyGroupManager::CreatePropertyGroup

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISharedPropertyGroupManager::CreatePropertyGroup [C/C++]

SharedPropertyGroupManager.CreatePropertyGroup Method [Visual Basic]

Creates and returns a reference to a new shared property group. If a property group with the specified name already exists, CreatePropertyGroup returns a reference to the existing group.

Syntax [C/C++]

HRESULT ISharedPropertyGroup::CreatePropertyGroup(
  BSTR name,
  LONG *plIsoMode,
  LONG *plRelMode,
  VARIANT_BOOL *pfExists,
  ISharedPropertyGroup **ppGroup
);

Parameters [C/C++]

name
[in] The name of the shared property group to create.
plIsoMode
[in, out] A reference to a Long that specifies the isolation mode for the properties in the new shared property group. See the table that lists plIsoMode constants later in this topic. If the value of the pfExists parameter is set to VARIANT_TRUE on return from this method, the plIsoMode value you passed in is ignored and the value returned in this parameter is the isolation mode that was assigned when the property group was created.
plRelMode
[in, out] A reference to a LONG that specifies the release mode for the properties in the new shared property group. See the table that lists plRelMode constants later in this topic. If the value of the pfExists parameter is set to VARIANT_TRUE on return from this method, the plRelMode value you passed in is ignored and the value returned in this parameter is the release mode that was assigned when the property group was created.
pfExists
[out] A reference to a BOOL that's set to VARIANT_TRUE on return from this method if the shared property group specified in the name parameter existed prior to this call, and VARIANT_FALSE if the property group was created by this call.
ppGroup
[out] A reference to a shared property group identified by the BSTR passed in the name parameter, or NULL if an error is encountered.

Settings [C/C++]

The following constants are used in the plIsoMode parameter to specify the effective isolation mode for a shared property group.

Constant | Value | Description
LockSetGet | 0 | Default. Locks a property during a get_Value or put_Value call, assuring that every get or set operation on a shared property is atomic. This ensures that two clients can't read or write to the same property at the same time, but it doesn't prevent other clients from concurrently accessing other properties in the same group.
LockMethod | 1 | Locks all of the properties in the shared property group for exclusive use by the caller as long as the caller's current method is executing. This is the appropriate mode to use when there are interdependencies among properties, or in cases where a client may have to update a property immediately after reading it before it can be accessed again.

Note When you set the isolation mode to LockMethod, the Shared Property Manager requires access to the calling object's ObjectContext. You can't use this isolation mode to create a shared property group from within an object's constructor or from a non-COM+ object because ObjectContext isn't available during object construction and a base client doesn't have an ObjectContext.

The following constants are used in the plRelMode parameter to specify the effective release mode for a shared property group.

Constant | Value | Description
Standard | 0 | When all clients have released their references on the property group, the property group is automatically destroyed. (This is the default COM mode.)
Process | 1 | The property group isn't destroyed until the process in which it was created has terminated. (Objects that hold references on a property group must still call Release on their references).

Return Values [C/C++]

S_OK
A reference to the shared property group specified in the name parameter is returned in the ppGroup parameter.
CONTEXT_E_NOCONTEXT
The caller isn't executing under COM+. A caller must be executing under COM+ to use the Shared Property Manager.
E_INVALIDARG
At least one of the parameters is invalid, or the same object is attempting to create the same property group more than once.

Syntax [Visual Basic]

object.CreatePropertyGroup(name, dwIsoMode, dwRelMode, fExists)

Parts

object
An object with a reference to a SharedPropertyGroup object.

Parameters [Visual Basic]

name
A string expression that contains the name of the shared property group to create.
dwIsoMode
A Long value that specifies the isolation mode for the properties in the new shared property group. See the table that lists dwIsoMode constants later in this topic. If the value of the fExists parameter is set to TRUE on return from this method, the dwIsoMode value you passed in is ignored and the value returned in this parameter is the isolation mode that was assigned when the property group was created.
dwRelMode
A Long value that specifies the release mode for the properties in the new shared property group. See the table that lists dwRelMode constants later in this topic. If the value of the fExists parameter is set to TRUE on return from this method, the dwRelMode value you passed in is ignored and the value returned in this parameter is the release mode that was assigned when the property group was created.
fExists
A Boolean value that's set to TRUE on return from this method if the shared property group specified in the name parameter existed prior to this call, and FALSE if the property group was created by this call.

Settings [Visual Basic]

The following constants are used in the dwIsoMode parameter to specify the effective isolation mode for a shared property group.

Constant | Value | Description
LockSetGet | 0 | Default. Locks a property during a Value call, assuring that every get or set operation on a shared property is atomic. This ensures that two client's can't read or write to the same property at the same time, but it doesn't prevent other clients from concurrently accessing other properties in the same group.
LockMethod | 1 | Locks all of the properties in the shared property group for exclusive use by the caller as long as the caller's current method is executing. This is the appropriate mode to use when there are interdependencies among properties, or in cases where a client may have to update a property immediately after reading it before it can be accessed again.

Note When you set the isolation mode to LockMethod, the Shared Property Manager requires access to the calling object's ObjectContext. You can't use this isolation mode to create a shared property group from within an object's constructor or from a non-MTS object because ObjectContext isn't available during object construction and a base client doesn't have an ObjectContext.

The following constants are used in the dwRelMode parameter to specify the effective release mode for a shared property group.

Constant | Value | Description
Standard | 0 | When all clients have released their references on the property group, the property group is automatically destroyed.
Process | 1 | The property group isn't destroyed until the process in which it was created has terminated. You must still release all SharedPropertyGroup objects by setting them to Nothing.

Remarks [Visual Basic]

The CreatePropertyGroup method sets the value in fExists to TRUE if the property group it returns existed prior to the current call. This occurs when another object in the same process has already called CreatePropertyGroup with the same property group name. The CreatePropertyGroup method sets the value in fExists to FALSE if the returned property group was created by the current call.

The isolation mode and release mode are assigned when the property group is originally created and aren't changed if a subsequent call passes different values in these parameters. The caller should always check the value of fExists on return from this method. If fExists is set to TRUE, the caller should check the values returned in dwIsoMode and dwRelMode to determine the isolation and release modes in effect for the property group. For example:

Dim isolationMode As Long
Dim releaseMode As Long

Set isolationMode = LockMethod
Set releaseMode = Process
Set spmGroup = spmMgr.CreatePropertyGroup _
    ("Counter", isolationMode, releaseMode, fExists)

If fExists Then
    If isolationMode <> LockMethod _
        Or releaseMode <> Process Then
        ' Do something appropriate.
    EndIf
EndIf

You can pass the constants, LockGetSet or LockMethod as the dwIsoMode argument, and Standard or Process as the dwRelMode argument, directly to the CreatePropertyGroup method. However, when you pass a constant instead of a variable, the CreatePropertyGroup method can't return the isolation and release modes currently in effect if the requested property group already exists.

Note An object should never attempt to pass a shared property group reference to another object. If the reference is passed outside of the object that acquired it, it's no longer a valid reference.

Remarks [C/C++]

The CreatePropertyGroup method sets the value in pfExists to VARIANT_TRUE if the property group it returns existed prior to the current call. This occurs when another object in the same process has already called CreatePropertyGroup with the same property group name. The CreatePropertyGroup method sets the value in pfExists to VARIANT_FALSE if the returned property group was created by the current call.

The isolation mode and release mode are assigned when the property group is originally created and aren't changed if a subsequent call passes different values in these parameters. The caller should always check the value of pfExists on return from this method. If it is set to VARIANT_TRUE, the caller should check the values returned in plIsoMode and plRelMode to determine the isolation and release modes in effect for the property group. For example:

hr = pPropGpMgr->CreatePropertyGroup(stName,
    &lIsolationMode, &lReleaseMode, &fAlreadyExists,
    &pPropGp);
if (fAlreadyExists) {
    if ((lIsolationMode != LockMethod) ||
        (lReleaseMode != Process)) {
        // Do something appropriate.
    }
}
If*

Note An object should never attempt to pass a shared property group reference to another object. If the reference is passed outside of the object that acquired it, it's no longer a valid reference.


ISharedPropertyGroupManager::get_Group

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISharedPropertyGroupManager::get_Group [C/C++]

SharedPropertyGroupManager.get_Group [Visual Basic]

Returns a reference to an existing shared property group.

Syntax [Visual Basic]

Set propertygroup = sharedpropertygroupmanager.Group(
  name
)

Parts of Syntax [Visual Basic]

propertygroup
An object variable that evaluates to a SharedPropertyGroup object.
sharedpropertygroupmanager
An object variable that represents the SharedPropertyGroupManager for the current process.
name
A string expression that contains the name of the shared property group to retrieve.

Syntax [C/C++]

HRESULT ISharedPropertyGroupManager::get_Group(
  BSTR name,
  ISharedPropertyGroup **ppGroup
);

Parameters [C/C++]

name
[in] The name of the shared property group to retrieve.
ppGroup
[out] A reference to the shared property group specified in the name parameter, or NULL if the property group doesn't exist.

Return Values [C/C++]

S_OK
The shared property group exists, and a reference to it is returned in the ppGroup parameter.
E_INVALIDARG
The shared property group with the name specified in the name parameter doesn't exist.


ISharedPropertyGroupManager::get__NewEnum

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ISharedPropertyGroupManager::get__NewEnum [C/C++]

SharedPropertyGroupManager.get__NewEnum [Visual Basic]

Returns a reference to an enumerator that you can use to iterate through all the shared property groups in a process.

Remarks [Visual Basic]

You do not need to use _NewEnum. This must be present in an object's type library for Visual Basic to be able to enumerate through a collection containing that object.

Syntax [C/C++]

HRESULT ISharedPropertyGroupManager::get__NewEnum(
  IUnknown **ppEnumerator
);

Parameters [C/C++]

ppEnumerator
[out] A reference to the IUnknown interface on a new enumerator object that you can use to iterate through the list of all the shared property groups in the process.

Return Values [C/C++]

S_OK
A reference to the requested enumerator is returned in the ppEnumerator parameter.

Remarks [C/C++]

You use the get_NewEnum method to obtain a reference to an enumerator object.

[C/C++] You should immediately call QueryInterface on the returned IUnknown for the IEnumVARIANT interface.

This interface exposes several methods you can use to iterate through a list of string expressions representing shared property group names. Once you have a name, you can use the get_Group method to obtain a reference to the shared property group it represents.

When you enumerate the shared property groups, all groups will be included. However, if you then call CreatePropertyGroup to add a new group, the existing enumerator won't include the new group even if you call Reset or Clone. To include the new group, you must create a new enumerator by calling get__NewEnum again.

[C/C++]

Note get__NewEnum has two underscore characters between get and NewEnum.


ITransactionContextEx Interface

The ITransactionContextEx interface provides a generic transactional object that begins a transaction. By calling the methods of this interface, you can compose the work of multiple COM+ objects in a single transaction and explicitly commit or abort the transaction.

When to Implement

You should not implement this interface. The standard implementation provides complete transaction functionality.

When to Use

Any non-transactional object can create a transaction context object and begin a transaction. Using the methods of this interface, the client can call additional COM objects that, if configured to participate in a transaction, execute within the transaction boundary of the transaction context object. Based on its business logic, the client can explicitly commit or abort the transaction.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces that an object provides (either 0 or 1).
GetTypeInfo | Gets the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
Method | Description
Abort | Aborts the work of all COM objects participating in the current transaction. The transaction ends on return from this method.
Commit | Attempts to commit the work of all COM objects participating in the current transaction. The transaction ends on return from this method.
CreateInstance | Creates another COM object. If the component that provides the object is configured to support or require a transaction, then the new object runs under the transaction of the transaction contextobject.

Requirements [C/C++]

To use this interface, you must include txctx.h in your file and link mtxquid.lib to your project.

Remarks

Using the transaction context object to control a transaction limits the reuse of the business logic driving the transaction and should be used sparingly.

You obtain a reference to the ITransactionContextEx interface by creating a transaction context object with the appropriate call. For example:

[C/C++]
CoCreateInstance(CLSID_TransactionContextEx, NULL, CLSCTX_INPROC,
IID_ITransactionContextEx, (void**)&m_pTransactionContext);

See Also

Configuring Transactions


ITransactionContextEx::Abort

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITransactionContextEx::Abort [C/C++]

TransactionContext.Abort [Visual Basic]

Aborts the work of all COM objects participating in the current transaction. The transaction ends on return from this method.

Syntax [C/C++]

HRESULT ITransactionContextEx::Abort( );

Syntax [Visual Basic]

object.Abort

Parts

object

An object with a reference to a TransactionContext object.

Return Values [C/C++]

S_OK
The transaction was aborted.
E_FAIL
The TransactionContextEx object is not running under a COM+ process, possibly indicating a corrupted registry entry for the TransactionContextEx component.
E_UNEXPECTED
An unexpected error occurred.

Remarks

Calling Abort ends the transaction on return of the method and automatically deactivates all participating objects. Each resource manager enlisted in the transaction rolls back the operations performed on behalf of those objects.

Example

See Also

ITransactionContextEx Interface [C/C++]

TransactionContext Object [Visual Basic]


ITransactionContextEx::Commit

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITransactionContextEx::Commit [C/C++]

TransactionContext.Commit [Visual Basic]

Attempts to commit the work of all COM objects participating in the current transaction.

Syntax [C/C++]

HRESULT ITransactionContextEx::Commit( );

Syntax [Visual Basic]

object.Commit

Return Values [C/C++]

S_OK
The transaction was committed.
E_FAIL
The TransactionContextEx object is not running under a COM+ process, possibly indicating a corrupted registry entry for the TransactionContextEx component.
E_UNEXPECTED
An unexpected error occurred.
CONTEXT_E_ABORTED
The transaction was aborted.

Remarks

Calling Commit attempts to commit a transaction. The transaction aborts if a participating object returns from a method after calling SetAbort, if an object calls DisableCommit and returns without calling EnableCommit or SetComplete, or if an error causes Microsoft Distributed Transaction Coordinator (MDTC) to abort.

When the method returns, regardless of whether the transaction commits or aborts, the transaction ends.

Example

See Also

ITransactionContextEx Interface


ITransactionContextEx::CreateInstance

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITransactionContextEx::CreateInstance [C/C++]

TransactionContext.CreateInstance [Visual Basic]

Creates a COM+ object that can execute within the scope of the transaction that was initiated by the transaction context object.

Syntax [C/C++]

HRESULT ITransactionContextEx::CreateInstance(
  REFCLSID rclsid,
  REFIID riid,
  LPVOID FAR *ppvObj
);

Syntax [Visual Basic]

CreateInstance(pszProgid)

Parameters

rclsid [C/C++]
[in] A reference to the CLSID of the type of object to instantiate.
riid [C/C++]
[in] A reference to the interface ID of the interface through which you want to communicate with the new object.
ppvObj [C/C++]
[out] A reference to a new object of the type specified by the rclsid argument, through the interface specified by the riid argument.
pszProgID [Visual Basic]
The programmatic Id of the new object's component.

Return Values [C/C++]

S_OK
A reference to the object is returned in the ppvObj parameter.
REGDB_E_CLASSNOTREG
The component specified by rclsid is not registered as a COM component.
E_OUTOFMEMORY
There's not enough memory available to instantiate the object.
E_INVALIDARG
The argument passed in the ppvObj parameter is invalid.
E_UNEXPECTED
An unexpected error occurred.

Remarks

If the Microsoft Distributed Transaction Coordinator is not running and the object is transactional, the object is successfully created. However, method calls to that object will fail with CONTEXT_E_TMNOTAVAILABLE. Objects cannot recover from this condition and should be released.

COM+ always uses standard marshaling. Even if a component exposes the IMarshal interface, its IMarshal methods will never be called by COM+.

Note You cannot create COM objects as part of an aggregation. In this respect, using CreateInstance is comparable to using CoCreateInstance and specifying NULL for the controlling IUnknown interface (pUnkOuter).

Example

See Also

ITransactionContextEx Interface


ITxProperty

The ITxProperty interface is implemented on a transacted property object and provides methods that you can use to set or retrieve the value assigned to a transacted property.

When to Implement

You do not implement this interface. The system supplies an implementation.

When to Use

You use the methods of this interface to set or retrieve the value assigned to a transacted property. This value is available to components across processes and is an excellent way to store unpersisted state information.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces that an object provides (either 0 or 1).
GetTypeInfo | Gets the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
ITxProperty Methods | Description
get_Value | Retrieves the value of a transacted property.
put_value | Sets the value of a transacted property.

Requirements

[C/C++] To use this interface, you must include the msimdb.h in your project.

[Visual Basic] To use these properties, you must set a reference to comsvcs.dll.

See Also

ITxPropertyGroupManager

ITxPropertyGroup


ITxProperty Properties

The ITxProperty properties govern the retrieving and setting of the value of a transacted property. They also indicate the transacted property group it belongs to and the name of the transacted property.

[Visual Basic]

In Visual Basic, programs read (get) and write (put) properties directly.

[C/C++]

In C++, programs call methods of the ITxProperty interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the MajorVersion property is a long variable. The method that gets this property has the following prototype:

HRESULT get_MajorVersion(long * retval);

Properties

The following table lists the properties that are managed by the ITxProperty interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

The following table lists the properties that are managed by the ICOMAdminCatalog interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

Property | Description
Name G (BSTR) | Read-only property returns the name of the property.
PropertyGroup G (ITxPropertyGroup) | Read-only property returns an interface to the property group in which this property resides.
Value GP (VARIANT) | Read/write, the value of the property.

Remarks

The variant value types that are supported by ITxProperty are:

VT_NULL

VT_I2

VT_I4

VT_R4

VT_R8

VT_CY

VT_DATE

VT_BSTR

VT_ERROR

VT_BOOL

VT_I1

VT_UI1

VT_UI2

VT_UI4

VT_INT

VT_UINT

Requirements

[C/C++] To use these methods, you must include the msimdb.h in your project.

[Visual Basic] To use these properties, you must set a reference to comsvcs.dll.


ITxPropertyGroup

The ITxPropertyGroup interface is used to create and access transacted properties contained in a transacted property group. You can use it to create transacted properties and to obtain access to existing transacted properties across processes.

You can access the ITxPropertyGroup interface by creating an instance of the transacted property group object using either IObjectContext::CreateInstance or CoCreateInstance. Transacted property groups contain name/value pairs called transacted properties.

When to Implement

You do not need to implement this interface. The system supplies an implementation.

When to Use

After you have created a transacted property group manager and have created a transacted property group, you can use the ITxPropertyGroup interface and methods to create transacted properties. Transacted properties are name/value pairs contained in a transacted property group.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces that an object provides (either 0 or 1).
GetTypeInfo | Gets the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
ITxPropertyGroup Methods | Description
CreateProperty | Creates a transacted property.
GetProperty | Gets a transacted property by name.
RemoveProperty | Removes a transacted property by name.
Get__NewEnum | Returns an enumerator over the transacted property group (IEnumVariant).

Requirements

[C/C++] To use this interface, you must include the msimdb.h in your project.

[Visual Basic] To call this method you must set a reference to comsvcs.dll.

See Also

ITxPropertyGroupManager

ITxProperty


ITxPropertyGroup Properties

The ITxPropertyGroup interface provides access to the properties described in this topic. These properties govern the types of access available, the concurrency model, and indicate the number of properties available under the transaction property group.

[Visual Basic]

In Visual Basic, programs read (get) and write (put) properties directly.

[C/C++]

In C++, programs call methods of the ITxPropertyGroup interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the MajorVersion property is a long variable. The method that gets this property has the following prototype:

HRESULT get_MajorVersion(long * retval);

Properties

The following table lists the properties that are managed by the ITxPropertyGroup interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

Property | Description
Name G (VT_BSTR) | Read-only property returns the name of the transacted property group.
WriteThrough G (VT_BOOL) | Read-only property returns the current write-through level.
PropertyGroupManager G (VT_IUNKNOWN) | Read-only property returns an interface to the transacted property group manager this group was created in.
Count G (VT_I4) | Read-only property returns the number of transacted properties in the group.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.


ITxPropertyGroup::CreateProperty

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITxPropertyGroup::CreateProperty [C/C++]

TxPropertyGroup.CreateProperty[Visual Basic]

The CreateProperty method creates a new transacted property with a string property name as an identifier. If a transacted property already exists with that name in that transacted property group, CreateProperty returns a reference to the existing transacted property.

Syntax [C/C++]

HRESULT CreateProperty
  (
  BSTR bstrPropertyName,
  VARIANT_BOOL *pvarboolExists,
  ITxProperty **ppTxProperty
  );

Syntax [Visual Basic]

CreateProperty(bstrPropertyName, pvarboolExists)

Parameters

bstrPropertyName
[in] The unique name of the transaction property.
pvarboolExists
[out] Specifies whether a property with the same name in this property group existed prior to this create call.

VARIANT_TRUE — This property already exists and a copy of this property will be provided in the ppTxProperty parameter.

VARIANT_FALSE — This property group did not exist prior to this create call and was added to the cache.

ppTxProperty [C/C++]
[out] Address of a pointer to a TxProperty object with the name specified in the name parameter. Returns NULL if an error is encountered.

Return Values [C/C++]

This method returns the standard HRESULT values including:

S_OK
A property was created for this property group and a reference to a TxProperty object was returned in the ppTxProperty parameter.
S_FALSE
The attempt to create the property failed because the property group currently does not exist. This occurs when a client runs read-committed isolation; in this case it is possible for another transaction to delete the current TxPropertyGroup object.
E_INVALIDARG
One or more parameters are invalid. The ppTxProperty parameter is set to NULL.
E_FAIL
Unexpected failure. The ppTxProperty parameter is set to NULL.


ITxPropertyGroup::get__NewEnum

The get_NewEnum method can be called against a transacted property group to enumerate the transacted properties it contains. The method returns a reference to an IEnumVARIANT enumeration interface that you can use to iterate through groups accessible by the current security access level.

HRESULT ITxPropertyGroup::get__NewEnum(
IUnknown **ppEnumVARIANT
);

Parameters

ppEnumVARIANT
A reference to IUnknown on a new enumerator object. You can use it to iterate through the list of all the property groups in the process.

Return Values

S_OK
A reference to the requested enumerator is returned in the ppEnumVARIANT parameter.

Remarks

You use the get__NewEnum method to obtain a reference to an enumerator object. It returns an IEnumVARIANT enumeration interface that allows you to iterate over properties within a property group. This method is an easy way of finding out the names of transaction properties in a property group.

With Visual C++, you can browse a collection to find a particular item by using the get_NewEnum method. In Visual Basic, you do not need to use get_NewEnum because it is automatically used in the implementation of For Each ... Next.

The IEnumVARIANT interface provides a number of methods you can use to iterate through a list of string expressions representing property group names. Once you have a name, you can use the get_Group method to obtain a reference to the property group it represents. Callers of this interface do not need to know the specific type (or types) of the elements in the collection.


ITxPropertyGroup::GetProperty

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITxPropertyGroup::GetProperty [C/C++]

TxPropertyGroup.GetProperty [Visual Basic]

The GetProperty method retrieves a transacted property with a string property name as an identifier.

Syntax [C/C++]

HRESULT GetProperty
..(
..BSTR bstrPropertyName,
..ITxProperty **ppTxProperty
..);

Syntax [Visual Basic]

GetProperty(bstrPropertyName)

Parameters

bstrPropertyName
[in] The unique name of the transaction property to retrieve.
ppTxProperty [C/C++]
[out] Address of a pointer to a transacted property object with the name specified in the name parameter. Returns NULL if an error is encountered.

Return Values [C/C++]

This method returns the standard HRESULT values including:

S_OK
A property associated with this group with bstrPropertyName parameter setting was found and an address of a pointer to a transacted property group object returned in the ppTxProperty parameter.
S_FALSE
A property associated with this group with bstrPropertyName parameter setting was not found. The ppTxProperty parameter is set to NULL.
E_INVALIDARG
One or more parameters are invalid. The ppTxProperty parameter is set to NULL.
E_FAIL
Unexpected failure. The ppTxProperty parameter is set to NULL.


ITxPropertyGroup::RemoveProperty

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITxPropertyGroup::RemoveProperty [C/C++]

TxPropertyGroup.RemoveProperty[Visual Basic]

The RemoveProperty method removes a transacted property with a string property name from the property group. A transacted property is removed from a group if all business objects are read-committed, or if one or more business objects that had repeatable reads are closed.

Syntax [C/C++]

HRESULT RemoveProperty
..(
..BSTR bstrPropertyName,
..);

Syntax [Visual Basic]

RemoveProperty(bstrPropertyName)

Parameters

bstrPropertyName
[in] The unique name of the transaction property to be removed from this property group.

Return Values [C/C++]

This method returns the standard HRESULT values including:

S_OK
The transaction property specified by name was found and removed from this group.
S_FALSE
The transaction property specified by name was found but was not removed because one or more business objects have repeatable reads on this property.
E_INVALIDARG
Invalid name specified or transaction property not found.
E_ FAIL
Unexpected failure.


ITxPropertyGroupManager

The ITxPropertyGroupManager interface is used to create a container for property groups. Using this interface, a client can create shared property groups and obtain access to existing shared property groups across processes. The ITxPropertyGroupManager interface is implemented on the transacted property group manager object.

You can access the ITxPropertyGroupManager interface by creating an instance of the transacted property group manager object by using either IObjectContext::CreateInstance or CoCreateInstance.

When to Implement

You do not implement this interface. This interface is system-supplied.

When to Use

The transacted property group manager is a resource dispenser that you can use to share state among multiple objects within a server process. You cannot normally use global variables in a distributed environment because of concurrency and name collision issues. The transacted property group manager eliminates name collisions by providing property groups that can be shared across processes, establishing unique name spaces for the properties they contain. The transacted property group manager also implements locks and semaphores to protect shared properties from simultaneous access, which could result in lost updates and could leave the properties in an unpredictable state.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispatch Methods | Description
GetTypeInfoCount | Retrieves the number of type information interfaces that an object provides (either 0 or 1).
GetTypeInfo | Gets the type information for an object.
GetIDsOfNames | Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs.
Invoke | Provides access to properties and methods exposed by an object.
ITxPropertyGroupManager Methods | Description
CreatePropertyGroup | Creates a new transacted property group with a property group name as an identifier. If a group with the same name and coherent cache state already exists, CreatePropertyGroup returns a reference to the existing transacted property group.
GetPropertyGroup | Gets an existing transacted property group.
RemovePropertyGroup | Removes an existing transacted property group.
Get__NewEnum | Returns an enumerator over the property group (IEnumVariant). This can be used to determine what property groups are contained in the property group manager.

Requirements

[C/C++] To use this interface, you must include the msimdb.h in your project.

[Visual Basic] To call this method you must set a reference to comsvcs.dll.

See Also

ITxPropertyGroup

ITxProperty


ITxPropertyGroupManager Properties

The ITxPropertyGroupManager interface provides access to the properties described in this topic. These properties govern the types of access available and the concurrency model as well as indicate the number of property groups available under the transacted property group manager.

[Visual Basic]

In Visual Basic, programs read (get) and write (put) properties directly.

[C/C++]

In C++, programs call methods of the ITxPropertyGroupManager interface. Methods that get a property are of the form:

HRESULT get_propertyName(datatype * pProperty);

Methods that put a property are of the form:

HRESULT put_propertyName(datatype property);

Parameters [C/C++]

The single parameter of each put_* method is an input variable of the data type appropriate for the property. The single argument of each get_* method is an output variable that is a pointer of the appropriate data type to the address of the property.

For example, the AddEnabled property is a VARIANT_BOOL variable. The method that gets this property has the prototype:

HRESULT AddEnabled( VARIANT_BOOL * retval );

Properties

The following table lists the properties that are managed by the ICatalogCollection interface and their data types and indicates for each property whether the interface supports getting (G), putting (P), or getting and putting (GP) the property.

Property | Description
IsolationLevel GP | Defines the isolation level used for all operations on property groups and properties accessed through the property group manager. Read-committed, read-repeatable and serializable isolation levels are supported. The default value is IsoLevelReadCommitted. The value of this ITxPropertyGroupManager property cannot be changed once any of ITxPropertyGroupManager functions that create, get, or remove a ITxPropertyGroup are called (this includes CreatePropertyGroup, GetPropertyGroup, RemovePropertyGroup, get_Count, and _NewEnum). Since all lookups are singleton, serializable isolation is not applicable and therefore not supported.
ConcurrencyMode GP | Defines the concurrency mode used for all operations on a property group or property that is accessed through this PropertyGroupManager object. Optimistic and pessimistic concurrency levels are supported. The default value is ConcurModeOptimistic. The value of this ITxPropertyGroupManager property cannot be changed once any of ITxPropertyGroupManager functions that creates, gets or removes a ITxPropertyGroup are called (e.g., this includes CreatePropertyGroup, GetPropertyGroup, RemovePropertyGroup, get_Count, and _NewEnum).
Count G (VT_I4) | Read-only property that returns the number of property groups that are accessible with current security level.

Return Values [C/C++]

Each property method returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The property was successfully obtained or written.
Property Description
IsolationLevel Returns E_FAIL if you attempt to set the Isolation level to serializable while its concurrency mode is set to optimistic.

Returns E_FAIL if you attempt to set this property after the PropertyGroup has been opened, indicating that the value for this property has not been changed.
ConcurrencyMode Returns E_FAIL if you attempt to set the Concurrency mode to optimistic while its isolation level is set to serializable.

Returns E_FAIL if you attempt to set this property after the PropertyGroup has been opened, indicating that the value for this property has not been changed.


ITxPropertyGroupManager::CreatePropertyGroup

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITxPropertyGroupManager::CreatePropertyGroup [C/C++]

TxPropertyGroupManager.CreatePropertyGroup [Visual Basic]

The CreatePropertyGroup method creates a new transacted property group with a string group name as an identifier. This transacted property group can then be used as a container for name/variable pairs called properties.

Syntax[C/C++]

HRESULT CreatePropertyGroup
  (
  BSTR bstrPropertyGroupName,
  VARIANT_BOOL *pvarboolExists,
  VARIANT_BOOL varboolWriteThrough,
  VARIANT_BOOL varboolRemoveAtProcessTermination,
  BSTR bstrAccessAccounts,
  VARIANT_BOOL varboolReserved,
  ITxPropertyGroup **ppTxPropertyGroup
  );

Syntax[Visual Basic]

CreatePropertyGroup(bstrPropertyGroupName, pvarboolExists, _
  varboolWriteThrough, varboolRemoveAtProcessTermination, _
  eSecuritySetting, bstrAccessAccounts, varboolReserved, _
  ppTxPropertyGroup)

Parameters

bstrPropertyGroupName
[in] The name of the property group to create.
pvarboolExists
[out] Specifies whether a property group with the same name existed prior to this create call.

If the return value is TRUE, this group already existed and a copy of this group will be provided in the TxPropertyGroup parameter with the provided write-through mode as set in WriteThrough parameter.

If the return value is FALSE, the property group did not exist prior to this create call and was created.

varboolWriteThrough
[in] Specifies whether properties in this property group will function in a write-through mode. This means that as properties of this group are changed, inserted, or removed, updates to the property are done outside the transaction and these changes will be visible from other transactions before the current transaction commits.

If set to TRUE, write-through functionality is activated. This means that changes will not roll back on abort.

If set to FALSE, transactional boundaries are observed.

varboolRemoveAtProcessTermination
[in] Specifies the removal of this group from cache upon termination of the current process.

If set to TRUE, this group will be removed when the current process is terminated.

If set to FALSE , this group will continue to persist in cache even after the current process has been terminated.

eSecuritySetting
[in] Security setting for this group.

If set to SecurityAllAccess, all accounts have access to the property group.

If set to SecurityUserAccess, only the creator of the property group has access.

If set to SecuritySelectedAccounts, only the creator of the property group and accounts specified in the bstrAccessAccounts parameter have access to the property group.

bstrAccessAccounts
[in] A comma-separated string of account names allowed access to this property group. This parameter is used only if the uintSecuritySetting parameter is set to SecuritySelectedAccounts. If selected accounts are not to be specified, this parameter should be set to NULL or an empty string.
varboolReserved
[in] This flag is currently reserved. This flag must be set to FALSE.
ppTxPropertyGroup [C/C++]
[out] Address of a pointer to a shared property group identified by the BSTR passed in the PropertyGroupName parameter. NULL is returned if an error is encountered.

Return Values [C/C++]

This method returns the standard HRESULT values as well as the following:

S_OK
A property group was created and an instance of TxPropertyGroup returned in the ppTxPropertyGroup parameter.
E_INVALIDARG
One or more parameters are invalid and the ppTxPropertyGroup parameter is set to NULL.
E_ACCESSDENIED
Security parameters provided would not provide permission to create a property group and the ppTxPropertyGroup parameter is set to NULL.

If the property group already existed, then the stored security parameters of this group would not provide permission to get a property group and the ppTxPropertyGroup parameter is set to NULL.

E_FAIL
Unexpected failure and the ppTxPropertyGroup parameter is set to NULL.

Remarks

This method creates a new transacted property group with a string group name as an identifier. If a group with the same group name already exists, CreatePropertyGroup returns a reference to the existing group; otherwise it fails.

Do not try to create property groups with multiple settings of the varboolWriteThrough parameter. This will cause a classic nested transaction deadlock if the DTC timeout is not set.

Since the first call CreatePropertyGroup has not committed, the second CreatePropertyGroup is left waiting for the first. If DTC time-out is not set, then a deadlock situation has occurred. The only way to avoid this deadlock is to set DTC time-out; this will cause the first call to CreatePropertyGroup to abort.


ITxPropertyGroupManager::get__NewEnum

The get_NewEnum method can be called against a transacted property group manager to enumerate the transacted property groups it contains. The method returns a reference to an IEnumVARIANT enumeration interface that you can use to iterate through groups accessible by the current security access level.

Syntax

HRESULT ITxPropertyGroupManager::get__NewEnum(
IUnknown **ppEnumVARIANT
);

Parameters

ppEnumVARIANT
A reference to the IUnknown interface on a new enumerator object that you can use to iterate through the list of all the property groups in the process.

Return Values

S_OK
A reference to the requested enumerator is returned in the ppEnumVARIANT parameter.

Remarks

You use the get__NewEnum method to obtain a reference to an enumerator object. With Visual C++, you can browse a collection to find a particular item by using the get_NewEnum method. In Visual Basic, you do not need to use the get_NewEnum method because it is automatically used in the implementation of For Each ... Next.

The IEnumVARIANT interface provides a number of methods you can use to iterate through a list of string expressions representing property group names. Once you have a name, you can use the get_Group method to obtain a reference to the property group it represents. Callers of this interface do not need to know the specific type (or types) of the elements in the collection.

Note that get__NewEnum has two underscore characters between get and NewEnum.


ITxPropertyGroupManager::GetPropertyGroup

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITxPropertyGroupManager::GetPropertyGroup [C/C++]

TxPropertyGroupManager.GetPropertyGroup[Visual Basic]

The GetPropertyGroup method retrieves an existing transacted property group with a string group name and sets its write-through mode.

Syntax[C/C++]

HRESULT GetPropertyGroup
  (
  BSTR bstrPropertyGroupName,
  VARIANT_BOOL varboolWriteThrough,
  ITxPropertyGroup **ppTxPropertyGroup
  );

Syntax[Visual Basic]

CreatePropertyGroup(bstrPropertyGroupName, varboolWriteThrough)

Parameters

bstrPropertyGroupName
[in] The name of the property group to retrieve.
varboolWriteThrough
[in] Specifies if properties in this property group will function in a write-through mode. This means that as properties of this group are changed, inserted, or removed, updates to the property are done outside the transaction, and these changes will be visible from other transactions before the current transaction commits.

If set to TRUE, write-through functionality is activated. This means that changes will not roll back on abort.

If set to FALSE, transactional boundaries are observed.

ppTxPropertyGroup [C/C++]
[out] Address of a pointer to a shared property group identified by the BSTR passed in the PropertyGroupName parameter. NULL is returned if an error is encountered.

Return Values [C/C++]

This method returns the following HRESULT values:

S_OK
A property group with bstrPropertyGroupName parameter setting was found and an instance of TxPropertyGroup returned in the ppTxPropertyGroup parameter.
S_FALSE
A property group with bstrPropertyGroupName parameter setting was not found. The ppTxPropertyGroup parameter is set to NULL.
E_INVALIDARG
One or more parameters are invalid. The ppTxPropertyGroup parameter is set to NULL.
E_ACCESSDENIED
Security parameters provided during property group create would not provide permission to get a property group. The ppTxPropertyGroup parameter is set to NULL.
E_FAIL
Unexpected failure. The ppTxPropertyGroup parameter is set to NULL.

Remarks

The GetPropertyGroup method retrieves an existing TxPropertyGroup with a string group name and sets its write-through mode.


ITxPropertyGroupManager::RemovePropertyGroup

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

ITxPropertyGroupManager::RemovePropertyGroup [C/C++]

TxPropertyGroupManager.RemovePropertyGroup [Visual Basic]

The RemovePropertyGroup method removes an existing transacted property group with a string group name.

Syntax[C/C++]

HRESULT RemovePropertyGroup  (
  BSTR bstrPropertyGroupName
  );

Syntax[Visual Basic]

RemovePropertyGroup(bstrPropertyGroupName)

Parameters

bstrPropertyGroupName
[in] The name of the property group to delete.

Return Values [C/C++]

This method returns the following HRESULT values:

S_OK
A property group with bstrPropertyGroupName parameter setting was found and removed.
S_FALSE
A property group with bstrPropertyGroupName parameter setting was not found and subsequently not removed.
E_INVALIDARG
The parameter is invalid.
E_ACCESSDENIED
User did not have sufficient security to remove this group.
E_FAIL
Unexpected failure.

Remarks

The RemovePropertyGroup method removes an existing transacted property group with a string group name.

A transacted property group is removed if its associated transacted properties can be removed. A transacted property can be removed if all business objects are read-committed, or if one or more business objects that had repeatable reads on the transacted properties of this transacted property group are closed.


Functions

Function | Description
GetObjectContext | Obtains a reference to the ObjectContext that's associated with the current COM+ object.
GetSecurityCallContext | Obtains a reference to the SecurityCallContext object that is associated with the current call.
SafeRef | Do not use in COM+. This was used in MTS 2.0 and is no longer required.
RecycleSurrogate | Retrieves the reason code for a recycled process.

Note These functions are provided by the COM+ Services Type Library DLL (comsvcs.dll).


GetObjectContext

Obtains a reference to the ObjectContext that's associated with the current COM+ object.

Syntax [C/C++]

HRESULT GetObjectContext (
  IObjectContext** ppInstanceContext
);

Parameters[C/C++]

ppInstanceContext
[out] A reference to IObjectContext on the object's context. If the object's component hasn't been imported into an MTS package, or if the GetObjectContext method is called from a constructor or an IUnknown method, this will be set to a NULL pointer.

Return Values[C/C++]

S_OK
A reference to the IObjectContext interface on the current object's context is returned in the ppInstanceContext parameter.
E_INVALIDARG
The argument passed in the ppInstanceContext parameter is invalid.
E_UNEXPECTED
An unexpected error occurred.
CONTEXT_E_NOCONTEXT
The current object doesn't have a context associated with it, because either the component wasn't imported into an application or the object wasn't created with one of the COM+ CreateInstance methods. This error will also be returned if the GetObjectContext method was called from the constructor or from an IUnknown method.

Remarks[C/C++]

An object's context is not accessible from an object's constructor or from any IUnknown method (QueryInterface, AddRef, or Release).

An object should never attempt to pass its ObjectContext reference to another object. If you pass an ObjectContext reference to another object, it will no longer be a valid reference.

When an object obtains a reference to its ObjectContext, it must release the ObjectContext object when it's finished with it.

Syntax[Visual Basic]

object.GetObjectContext

Parts of Syntax[Visual Basic]

object
An object with an ObjectContext reference.

Remarks[Visual Basic]

You cannot pass an ObjectContext reference to another object. If you attempt to pass an ObjectContext reference to another object, the reference will no longer be valid.

When an object obtains a reference to its context object, it must release the ObjectContext object when it's finished with it.


GetObjectContext Function, CreateInstance Method Example

Dim ctxObject As ObjectContext
Dim objAccount As Bank.Account

' Get the object's ObjectContext.
Set ctxObject = GetObjectContext()

' Use it to instantiate another object.
Set objAccount = ctxObject.CreateInstance("Bank.Account")


GetSecurityCallContext

Obtains a reference to the SecurityCallContext object that is associated with the current call. Using this reference, you can retrieve items in the security call context collection such as the minimum authentication level, the direct caller, the original caller, the chain of callers, and the number of callers. You can also call IsSecurityEnabled and IsCallerInRole to ensure that a particular section of code is executed. However, you can call these methods only if role-based security is enabled and if the direct caller is a member of a specified role.

This function is intended for use in Visual Basic applications. C++ applications can obtain access to security call context information by calling CoGetCallContext to obtain a pointer to ISecurityCallContext.

To use the GetSecurityCallContext function, you must set a reference to the COM+ Services Type Library (comsvcs.dll).

Syntax [Visual Basic]

object.GetSecurityCallContext

Parameters

object
An object with a SecurityCallContext reference that belongs to the current call.

Remarks

When an object obtains a reference to its SecurityCallContext, it should release the SecurityCallContext object when it is finished with it.

Example

See Also

SecurityCallContext, SecurityIdentity, SecurityCallers


RecycleSurrogate

This function retrieves the reason code for a recycled process. Processes can be recycled based on a specified number of activations, a specified number of calls to configured objects in the application, a specified number of minutes that an application runs before recycling, and a specified amount of memory usage that a process cannot exceed.

Syntax [C/C++]

HRESULT RecycleSurrogate (
  LONG lReasonCode  \\Reason code for a recycled process
);

Parameters [C/C++]

lReasonCode
[in] The reason code that explains why a process was recycled. The reason code is exported from comsvcs.dll.

Return Values [C/C++]

RecycleSurrogate returns the standard values E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, and E_FAIL, as well as the following:

S_OK
The reason code was successfully obtained.

Syntax [Visual Basic]

object.RecycleSurrogate(lReasonCode)

Parts of Syntax [Visual Basic]

lReasonCode
The reason code that explains why a process was recycled.

Remarks

If you select more than one criterion for recycling a process, the RecycleSurrogate function provides a means of finding out which criterion caused COM+ to recycle the process. COM+ recycles a process after the first of the set of criteria is satisfied. The returned reason code allows you to programmatically respond to any one of these events.

See Also

IComAdminCatalog2::RecycleProcess


SafeRef

Do not use in COM+. In MTS, this was used by an object to obtain a reference to itself that is safe to pass outside its context wrapper. With contexts in COM+, this is no longer necessary.

Syntax [C/C++]

void* SafeRef (
  REFIID riid
  UNKNOWN * pUnk
);

Parameters [C/C++]

riid
[in] A reference to the interface ID of the interface that the current object wants to pass to another object or client.
pUnk
[in] A reference to an interface on the current object.

Return Values [C/C++]

Non-NULL
A pointer to the interface specified in the riid parameter that's safe to pass outside the current object's context.
NULL
The object is requesting a safe reference on an object other than itself, or the interface requested in the riid parameter is not implemented.

Syntax [Visual Basic]

object.SafeRef(vRefIn)

Parts of Syntax [Visual Basic]

object
An object with a reference to a Variant representing the current object that's safe to pass to another object or client.
vRefIn
The object reference that is safe to pass. Usually references the Me keyword.

Remarks

Do not use SafeRef in COM+. In MTS, SafeRef was used by an object to obtain a reference to itself that was safe to pass outside its context wrapper. In COM+, with contexts and interception fully integrated into COM+, this is no longer necessary. See Contexts.


Enumerations

Enumeration | Description
EOC_ChangeType | Indicates the nature of the change to an event object.
TransactionVote | Indicates the readiness of an object to commit or abort the current transaction.


EOC_ChangeType

The EOC_ChangeType enumeration constants indicate the nature of the change to an event object. Values from this enumeration are passed to methods of IEventObjectChange.

typedef enum
{
    EOC_NewObject       //A new object was added
    EOC_ModifiedObject  //An object was modified
    EOC_DeletedObject   //An object was deleted
}EOC_ChangeType;

Elements

EOC_NewObject
A new object was added.
EOC_ModifiedObject
An existing object was modified.
EOC_DeletedObject
An existing object was deleted.

See Also

IEventObjectChange


TransactionVote

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

tagTransactionVote

The tagTransactionVote enumeration constants indicate the readiness of an object to commit or abort the current transaction. Values from this enumeration are passed to the methods of IContextState.

typedef
enum tagTransactionVote
    {   TxCommit   = 0,
   TxAbort   = TxCommit + 1
    }   TransactionVote;

Elements

TxCommit
An existing object votes to commit the current transaction.
TxAbort
An existing object votes to abort the current transaction.

See Also

IContextState


Tools Developer's Guide

The Tools Developer's Guide consists of two major topic descriptions:

Topic | Description
Tools Developer Concepts | This section provides a conceptual description of the Microsoft Distributed Transaction Coordinator (MS DTC), the Compensating Resource Manager (CRM), Resource Dispensers, and COM+ Event sinks. It also provides links to the associated reference material for each element of the Tools Developer's Guide.
Tools Developer Reference | This section provides detailed reference material to help developers create transactions, transactional objects, MS DTC interfaces, and MS DTC functions.


Tools Developer Concepts

This section provides a conceptual description of the Microsoft Distributed Transaction Coordinator (MS DTC), which provides transaction services to ensure successful and complete transactions. This section also provides tool developers with an understanding of the Compensating Resource Manager (CRM), resource dispensers, and COM+ event sinks. The major topics are:

Topic | Description
Microsoft Distributed Transaction Coordinator | Provides an introduction to transactions, distributed transactions, and the role of MS DTC.
The Compensating Resource Manager (CRM) | Describes a quick, alternative method to integrate application resources with Distributed Transaction Coordinator (DTC) transactions.
Resource Dispensers | Describes resource dispensers and how application components use them to access shared information.
COM+ Instrumentation | Describes how COM+ Instrumentation allows clients to receive notifications for a variety of COM+ events.


Microsoft Distributed Transaction Coordinator

Microsoft® Distributed Transaction Coordinator (MS DTC) is a distributed transaction facility for Microsoft Windows 2000®, Microsoft Windows NT, Microsoft Windows 98, and Microsoft Windows 95. MS DTC uses proven transaction processing technology: it is robust despite system failures, process failures, and communication failures; it exploits loosely coupled systems to provide scalable performance; and is easy to install, configure, and manage. The MS DTC service:

  • Lowers the cost of Enterprise computing—MS DTC provides a sophisticated, low cost distributed transaction facility for users of networked commodity-priced PCs and servers.
  • Simplifies application development—MS DTC transactions greatly simplify the application programmer's task of preserving consistency, despite failures that can occur when updating application data.
  • Provides a consistent transaction model—MS DTC supports a variety of resource managers, including relational databases, object-oriented databases, file systems, document storage systems, and message queues.
  • Enables software development using distributed, object-oriented, software components—MS DTC is based on the OLE Transactions interface protocol, which provides a simple, object-oriented application programming interface for initiating and controlling transactions.

With MS DTC:

  • Application programs can reliably update data residing in two or more OLE transactions-compliant resource managers such as Microsoft SQL Server or Microsoft Message Queue. The client application and the resource managers may reside on a single Windows 2000, Windows NT, Windows 98, or Windows 95 system. Alternatively the client application and the resource managers may be distributed across two or more Windows systems.
  • Application programs can reliably update data residing in one or more XA compliant resource managers such as Oracle, IBM DB2, Informix, Sybase, or Ingres.
  • Application programs can use an OLE Transactions-compliant resource manager such as Microsoft SQL Server or Microsoft Message Queue with an X/Open-compliant Transaction Processing monitor, such as Encina, TopEnd, and Tuxedo.
  • Application programs can perform transactions spanning multiple transaction managers communicating via the Transaction Internet Protocol (TIP).
  • Windows application programs can invoke CICS transaction programs through COMTI. The Windows application program and the CICS transaction program can participate in a single distributed transaction through MS DTC’s IBM LU6.2 two-phase commit protocol support.


Transaction Properties

Transactions are atomic, consistent, isolated, and durable (ACID) modules of execution. They complement the Microsoft Component Object Model (COM) program module structure.

Transactions provide the following ACID properties:

  • Atomicity—A transaction will either commit or abort. If a transaction commits, all of its effects remain; if it aborts, all of its effects are undone. For example, when you rename an object, either the new name is created and the old name is deleted (commit), or the object is not renamed (abort).
  • Consistency—A transaction is a correct transformation of the system state; it preserves the state invariants. For example, when you add an element to a double-linked list, all four forward and backward pointers are updated.
  • Isolation—Concurrent transactions are isolated from the updates of other incomplete transactions; these updates do not constitute a consistent state. This property is often called serializability. For example, a second transaction traversing the double-linked list mentioned in the previous consistency example will see the list before or after the insert, but will only see complete changes.
  • Durability—Once a transaction commits, its effects will persist even if there are system failures. For example, after the object in the previous atomicity example is renamed, it will have the new name even if the system fails and reboots right after the commit completes.


Distributed Transactions

A distributed transaction is a transaction that updates data on two or more networked computer systems. Distributed transactions extend the benefits of transactions to applications that must update distributed data. Implementing robust distributed applications is difficult because these applications are subject to multiple failures, including failure of the client, the server, and the network connection between the client and server. In the absence of distributed transactions, the application program itself must detect and recover from these failures.

For distributed transactions, each computer has a local transaction manager. When a transaction does work at multiple computers, the transaction managers have to interact with other transaction managers via either a superior or subordinate relationship. These relationships are relevant only for a particular transaction (they are discussed in more detail in the next section). Each transaction manager performs all the enlistment, prepare, commit, and abort calls for its enlisted resource managers (usually those that reside on that particular computer). When committing a transaction that is distributed among several computers, the transaction manager sends prepare, commit, and abort messages to all its subordinate transaction managers. When a transaction manager is in-doubt about a distributed transaction, the transaction manager queries the superior transaction manager. The root transaction manager is never in-doubt. If an in-doubt transaction persists for too long, the system operator can force the transaction to commit or abort.

See How Distributed Transactions Work for more information.


How Distributed Transactions Work

Microsoft Distributed Transaction Coordinator (MS DTC) supports transactions that are distributed across two or more Windows 95 or Windows 2000 systems. Each system has a local transaction manager. All applications and resource managers communicate with their local transaction managers. The transaction managers cooperatively manage transactions that span systems.

When a request arrives with a new transaction, a superior-subordinate relationship is established between the two systems. Usually the transaction manager on the system making the request becomes superior to the transaction manager on the system receiving the request. The idea behind the superior-subordinate relationship is that the superior system drives all the systems subordinate to it using the 2-phase-coordinate protocol. Furthermore each system can have many systems subordinate to it, but it can have at most one superior. Thus these superior and subordinate relationships form a tree of relationships called the transaction's commit tree. The enlisted resource managers are also members of this commit tree: they usually have a subordinate relationship to their local transaction manager. The superior and subordinate relationships are only relevant for a particular transaction. It is possible that a transaction manager A that is a superior to another transaction manager B on a particular transaction can be a the subordinate to transaction manager B on another transaction.

These outgoing and incoming relationships form a tree of transaction manager relationships called the transaction's commit tree. The enlisted resource managers are also members of this commit tree: they have an outgoing and incoming relationship to their local transaction manager.

When a distributed transaction commits or aborts, the prepare, commit and abort messages flow outward on the commit tree. Any node of the tree can unilaterally abort a transaction anytime before it agrees to the prepare request sent in the first phase. Once a node has prepared, it remains prepared and in-doubt until the commit coordinator tells it to commit or abort the transaction. The root transaction manager of the commit tree is called the global commit coordinator. This coordinator makes the decision to either commit or abort the transaction and is never in doubt.

If a computer fails, then restarts, the transaction manager at that computer tries to determine the outcome of all in-doubt transactions in which it participated.

The transaction manager reads its log file to determine the outcomes of transactions for which it was the commit coordinator:

  1. If the transaction had superior transaction manager, then the local transaction manager determines if it was previously notified of the outcome of the transaction by the superior transaction manager.
  2. If the transaction manager is in-doubt regarding a particular transaction, then it queries it’s superior to learn the transaction’s outcome.

The transaction manager also responds to queries from subordinate transaction managers regarding in-doubt transactions, similar to the protocol that transaction managers and resource managers follow at restart. The transaction manager determines the outcome of each in-doubt transaction and informs the resource managers of the transaction's outcome.

System or communication failures can leave transactions in-doubt for extended periods of time. While a transaction is in-doubt, the resources modified by the transaction remain locked and unavailable to others. The system operator can use the graphical management interface at the commit coordinator system to resolve transactions that remain in-doubt, or at the in-doubt system to force the transaction to either commit or abort (see Manually Resolving Transactions in Component Services administrative tool help for DTC administrator tasks).


Application Programmer's View of Transactions

The application programmer's transaction model is simple: programs either succeed or fail. When the application program begins a transaction, it gets a transaction object. All subsequent work is associated with that transaction object. When the program reaches a consistent state, it calls the Commit method. If the commit succeeds, the transaction is durably committed. If the commit fails, the transaction aborts. If the application program can't successfully complete the transaction, it may call the Abort method to undo the transaction's effects.

If the program fails before it commits the transaction, the transaction manager aborts the transaction and informs each enlisted resource manager to rollback the transaction's effects. If either the computer or resource manager fails, the transaction is also aborted.

If the transaction successfully commits, the resource managers and the transaction manager ensure that the transaction's effects are durable, even if there are subsequent failures.

See the Client Application Startup, Transaction Initiation, and Resource Manager Enlistment for more information.


Resource Manager's View of Transactions

The resource manager registers itself with the local transaction manager, then waits for execution requests from an application program. When a request arrives with a new transaction object, the resource manager enlists in the transaction by invoking the Enlist method. By enlisting, the resource manager ensures that it will get callbacks from the transaction manager when the transaction commits or aborts. The resource manager then performs the transaction's requests.

For example, the transaction might insert, delete, or update records in a relational database. The resource manager retains enough information to enable it to either undo or redo the transaction, such as by storing multiple versions of the data or keeping a log (journal) of the changes.

When the application program commits the transaction, the transaction manager initiates the two-phase commit protocol. The transaction manager first requests each enlisted resource manager to prepare to commit the transaction. The resource manager prepares to commit by storing enough state durably to either commit or abort the transaction. Typically, the old and new data is recorded in stable storage so that the resource manager can recover it even if the system fails. If the resource manager can' t prepare successfully, it informs the transaction manager that it can' t prepare and the transaction manager aborts the transaction. If the resource manager can prepare, it informs the transaction manager that it is prepared, and awaits the transaction manager's decision on whether to commit or abort the transaction.

Once prepared, a resource manager must wait until it gets a commit request or abort request from the transaction manager. Most transactions commit; a few transactions abort. The entire prepare and commit protocol typically completes within a fraction of a second, however, a system or communication failure may delay the commit or abort notification for several minutes or even hours. During this period, the resource manager is in-doubt about the outcome of the transaction; it doesn't know whether the transaction committed or aborted. While the resource manager is in-doubt about the transaction, it locks the data modified by the transaction, isolating these changes from any other transactions.

The previous example discusses how distributed transactions are made atomic in a fault-free environment. See Participating in the Two-Phase Commit Protocol for a more detailed example.

MS DTC also helps resource managers make transactions atomic and durable when a resource manager fails and then restarts. The resource manager must reconstruct the committed state of the resources it manages, reflecting all of the effects of committed transactions and none of the effects of aborted transactions.

When a resource manager fails, all of its enlisted transactions are aborted, except those which prepared or committed prior to the failure. When the resource manager restarts, it queries the transaction manager about the outcome of the in-doubt transactions in which it enlisted. The transaction manager tells the resource manager the outcome of each in-doubt transaction and the resource manager commits or aborts these transactions accordingly.

The two-phase commit protocol, combined with prepare and recovery routines of the resource managers, make transactions atomic and durable.


Transaction Manager's View of Transactions

The transaction manager creates transaction objects and manages their atomicity and durability. Applications request the creation of a transaction object by calling the transaction manager's BeginTransaction method. When a resource manager first participates in a transaction, it calls the transaction manager Enlist method to enlist in the transaction. The transaction manager tracks all the resource managers who enlist in the transaction. One of three results can occur:

  1. The application either commits or aborts the transaction.
  2. A resource manager aborts the transaction.
  3. A failure occurs.

The Commit and Abort methods can also be called on transaction objects.

When asked to commit a transaction, the transaction manager initiates the two-phase commit protocol. During the first phase, it asks all enlisted resource managers to prepare. Then, during the second phase, the transaction manger informs the resource managers whether the transaction committed or aborted.

The transaction manager maintains a log in safe storage on disk. The log is a sequential file that records transaction events. The transaction manager records transaction starts, enlistments, and commit decisions in the log. During normal processing, the transaction manager only writes to the log. However, if the transaction manager fails, it reads the log when it restarts to reconstruct the most recent state, using the log to make its state durable.

The transaction manager also provides an operator interface to manage transactions and maintains performance counters that can be displayed using the system performance monitor. The transaction manager records important operational events in the system log which can then be displayed using the system event viewer.


Commit Coordination

MS DTC uses the Presumed Abort two-phase commit protocol. See Transaction Processing: Concepts and Techniques for detailed information about the two-phase commit protocol.

MS DTC supports these two-phase commit optimizations:

Read-Only Commit Optimization

Delegated Commit Optimization


Read-Only Commit Optimization

MS DTC permits resource managers that have read but not updated transaction-protected data to reply "read-only" at phase-one. In this case, the transaction manager will not deliver the second phase notification to the resource manager.

The read-only optimization is also used between transaction managers to optimize the commitment of whole sub-trees of the transaction tree. A transaction manager replies "read-only" if all of the resource managers and transaction managers subordinate to it reply "read-only." This signifies that this transaction manager and the entire sub-tree it controls need not receive notification at phase two of commit. Using this optimization eliminates the need for certain log writes and also allows for earlier release of locks on some resources.


Delegated Commit Optimization

MS DTC permits commit coordinator responsibility to be delegated from the coordinating transaction manager to one of its subordinate transaction managers or resource managers. Commit coordinator delegation occurs when the coordinating transaction manager detects that only one subordinate resource manager or transaction manager is enlisted in the transaction.

The coordinating transaction manager delegates commit coordinator responsibility to the resource manager when both of the following two conditions are True:

  1. No subordinate transaction manager is enlisted in the transaction.
  2. Only one resource manager is enlisted in the transaction.

In this case, the coordinating transaction manager sets fSinglePhase when invoking the ITransactionResourceAsync::PrepareRequest method at phase one. This instructs the resource manager that it should act as the transaction coordinator.

MS DTC delegates commit coordinator responsibility to the subordinate transaction manager when both of the following two conditions are True:

  1. No resource manager is enlisted in the transaction with the current coordinating transaction manager.
  2. Only one subordinate transaction manager is enlisted in the transaction.

In this case, the coordinating transaction manager sends a "delegated commit" message in place of the phase one message. The "delegated commit" message transfers commit coordinator responsibility from the current coordinating transaction manager to its subordinate transaction manager. This optimization is applied recursively. A transaction manager that receives commit coordinator responsibility may delegate commit coordinator responsibility to its subordinate transaction manager or resource manager. Using this optimization eliminates the need for certain log writes and also allows for earlier release of locks on some resources.


Bring Your Own Transaction (BYOT)

BYOT (Bring Your Own Transaction) allows a component to be created with, or to inherit, an external transaction. That is, they allow a component that does not already have an associated transaction to acquire a transaction. Currently, MTS transactions are automatic; whether a component instance lives in a transaction is determined at creation time. The transactional attributes of a component and its creator determine what transaction is associated with a given instance. In all cases, MTS controls transaction lifetimes. COM+ extends this to allow setting an arbitrary pre-existing MS DTC or TIP transaction as the transaction property of a new component's context. This allows COM+ components to be associated with transactions whose lifetimes are controlled by a TP monitor, OTS, or DBMS.

Note BYOT transactions must be used with caution. In certain situations, they can result in a transaction spanning multiple synchronization domains (i.e., it allows parallelism with a transaction). For example, if a TIP transaction is introduced, using BYOT into two separate COM+ regions, the regions would enlist under distinct subordinate transactions, and would contend on lock space.

Note also that automatic transactions, rather than BYOT transactions, are the preferred programming model for writers of business components.

The interfaces for BYOT transactions include the ICreateWithTransaction Interface and the ICreateWithTIPTransaction Interface. The ICreateWithTransaction interface creates an object that is enlisted within a manual transaction. The ICreateWithTIPTransaction interface creates an object that is enlisted within a manual transaction using the Transaction Internet Protocol (TIP).


Creating BYOT Objects

A new BYOT object creates objects with manual transactions. The two interfaces, ICreateWithTransaction and ICreateWithTIPTransaction, have a single method, CreateInstance, which take an ITransaction Interface pointer and TIP URL, respectively. CreateInstance returns an interface pointer to the newly created object, which is enlisted within the specified transaction.

When an object with a manual transaction is released, COM+ does not attempt to commit the transaction. The transaction is controlled explicitly by the external Transaction Manager which dispensed the transaction under which this object had been created.

Note The Byot.ByotServerEx object needs to be imported into a COM+ application.


Inheriting Manual Transactions

If an object with a BYOT transaction in its context creates a second object, the downstream object can inherit the BYOT transaction (if configured to inherit transactions). The first object created using the BYOT gateway needs to be configured to "require" or "support" transactions. Subsequent objects in the activity could be configured based on application requirements.

For automatic transactions, the COM+ runtime does not attempt to commit the transaction until the root object indicates that it is ready (by calling SetComplete before returning from a call). Users should be aware that a BYOT transaction could commit prematurely (in that the work of child objects has not been completed), because the "root" is not running under the COM+ runtime environment, and the commit semantics are not tied to the lifetime of the object. In general, the user should take care to not violate the synchronization boundary of the transaction.

Otherwise, COM+ commit semantics apply. COM+ will not attempt to commit a transaction while an object within a synchronization boundary is in call. Also, objects can indicate their consistency via DisableCommit. If an attempt is made to commit a transaction which includes the work of an object that has called DisableCommit, the transaction will abort.


Other Transaction Standards

See the following topics for more information about other transaction standards:

X/Open Distributed Transaction Processing Standard

OSI Transaction Processing Format and Protocol


X/Open Distributed Transaction Processing Standard

The X/Open Distributed Transaction Processing (X/Open DTP) model defines a standard communication architecture that provides:

  • Concurrent execution of applications on shared resources
  • Coordination of transactions across applications
  • Components, interfaces, and protocols that define the architecture and provide portability of applications
  • Atomicity of transaction systems
  • Single-thread control and sequential, function calling sequences

This model, designed by Open Group (a vendor consortium) promotes an open standard that improves portability of applications. This standard includes the following components:

Component | Description
Application Programs | Implement transactions created by the Transaction Managers.
Communications Resource Manager | Facilitates interoperability between transaction managers residing in different environments.
Resource Managers | Implements either an OLE Transactions protocol, such as Microsoft® SQL Server, or the X/Open DTP XA standard.
Transaction Managers | Creates transaction objects and manages their atomicity and durability.

Relevancy of X/Open DTP for COM+

The two standards that are most relevant to OLE Transactions are the TX and XA standards.

  • The X/Open DTP TX standard defines the application programming interfaces that an application uses to communicate with the transaction manager. Application programs use these calls to begin, commit, and rollback transactions.
  • The X/Open DTP XA standard defines the application programming interfaces that a resource manager uses to communicate with a transaction manager. The XA interfaces enable resource managers to join transactions, to perform two-phase commit, and to recover in-doubt transactions following a failure.

MSMQ and X/Open Compliancy

MSMQ is compliant with XA-Compliant Transactions that use an XA-Compliant Transaction Manager. With this kind of transaction MS DTC acts as both the Transaction Manager and Resource Manager interfacing between the two protocols.


How OLE Transactions Differs from X/Open DTP

The OLE Transactions standard was employed over the X/Open DTP for the following reasons:

  • Microsoft's computing model employs distributed, transaction-protected, object-based components that communicate using OLE interfaces. Our transaction interfaces needed to be object-based to fit this model. The OLE Transactions standard is object-based, while the X/Open standard is not.
  • We intend to extend the transaction model to support a wide variety of transaction-protected resources. This includes documents, images, voice, queued messages, workflow and other non-database resources. To do this, we must extend the transaction model to provide richer transaction capabilities. OLE Transactions permits us to make these extensions.
  • OLE Transactions supports multi-threaded programs and doesn’t require thread specific context. A program and its threads can create and manage as many concurrent transactions as they choose yet allowing for optimal performance. XA is oriented toward a single thread of control.
  • The existing X/Open standard is loosely written. Products that claim to conform to the standard differ among themselves. There is no mechanism in the standard for supporting heuristic transaction outcomes. Unlike OLE Transactions, the X/Open standard does not support recovery that is initiated by the resource manager; therefore, all recovery must be initiated by the transaction manager.

MS DTC provides a measure of interoperability with products that comply with the X/Open DTP XA standard. See the Interoperability with Products that Comply with the X/Open DTP XA Standard topic for more information.


Interoperability with Products that Comply with the X/Open DTP XA Standard

MS DTC provides a measure of interoperability with products that comply with the X/Open DTP XA standard. The MS DTC XA Mapper permits an OLE transactions-compliant resource manager to participate in a transaction coordinated by an XA-compliant transaction manager.

MS DTC XA Mapper Support for X/Open XA


Using an OLE Transactions-Compliant Resource Manager with an X/Open-Compliant Transaction Processing Monitor

MS DTC lets OLE Transactions-compliant resource managers participate in transactions controlled by X/Open DTP XA-compliant transaction processing monitors such as Encina, TopEnd, and Tuxedo. The XA Mapper makes an OLE Transactions-compliant resource manager behave like an XA-compliant resource manager.

The XA Mapper facility can be used to perform distributed transactions that update OLE Transactions-compliant resource managers on Windows 2000 systems and other resource managers on other platforms. For example, an application can update an OLE Transactions-compliant resource manager on a Windows 2000 system and an XA-compliant database on a UNIX system.


OSI Transaction Processing Format and Protocol

The International Standards Organization (ISO) has defined a standard that permits transaction managers from different vendors to interoperate. This standard is the Open Systems Interconnect-Transaction Processing Format and Protocol (OSI-TP FAP). The OSI-TP FAP defines the message formats and protocols for doing two-phase commit coordination between one transaction manager and another. Although some transaction managers support OSI-TP, all successful transaction managers rely upon their own proprietary two-phase commit protocols. As a result, the OSI-TP standard has relatively little support in the industry. MS DTC does not support OSI-TP.


OLE Transactions Model

The OLE Transactions standard supports conventional, flat transactions. A transaction can be initiated by a client on a Windows 95 or a Windows 2000 system. Only the transaction initiator can commit the transaction, and can abort the transaction at any time by calling Abort (provided it has not previously called Commit).

The client who initiates a transaction can propagate the transaction to one or more resource managers. These resource managers can reside on a single Windows 2000 system, or they can be distributed across a network of Windows 2000 systems. A resource manager can propagate the transaction to other resource managers, and any participating resource manager can abort that transaction.

Microsoft intends to extend the OLE Transactions model by:

  • Supporting transactions that can retain locks and cursors across transaction boundaries.
  • Enabling an application component invoked as part of a larger transaction to abort and undo its work without causing the entire transaction to abort.
  • Supporting distributed two-phase commit on non-Microsoft platforms.
  • Supporting heuristic commit or abort of in-doubt transactions. (Currently, the system administrator must resolve in-doubt transactions using the MS DTC administrative utility.)


Using Microsoft Distributed Transaction Coordinator

We have organized the tools development information to meet the needs of five types of programmers:

  1. Application Programmers

    Most application programmers rely upon the automatic transaction management capabilities of COM+. As a result, these application programmers never use MS DTC directly; instead, they rely upon COM+ to call MS DTC on their behalf.

    The MS DTC information contained is this document is intended for those rare application programmers who do not use COM+ but who wish to use MS DTC transactions directly. MS DTC allows such programmers to update data managed by two or more resource managers under the control of a single atomic transaction.

    For these programmers we describe how to:

    • Connect to MS DTC.
    • Initiate, commit, and abort transactions.
    • Receive transaction outcome events.
  2. Developers of Native OLE Transactions Resource Managers

    The native OLE transaction interfaces permit a resource manager to be a full-fledged OLE transaction participant.

    For developers of native OLE Transactions resource managers we describe how to:

    • Connect to MS DTC.
    • Propagate an OLE transaction from one process to another process or from one system to another system.
    • Enlist and participate in the two phase commit protocol.
    • Perform transactional recovery.
  3. Developers of XA Compliant Resource Managers

    The OLE transaction XA interfaces permit an XA compliant resource manager to participate in an MS DTC coordinated transaction. The XA resource manager may be located on a Windows 2000 system or on a remote non-Windows system.

    For developers of XA compliant resource managers we describe how to:

    • Connect to MS DTC.
    • Convert an OLE transaction transaction identifier into an XA XID.
    • Enlist and participate in the two phase commit protocol by translating the OLE transactions prepare, commit, and abort calls into their corresponding XA counterparts.
    • Perform transactional XA recovery.
  4. Developers of Caching Resource Managers

    A “Caching” resource manager is a resource manager that acts as a front-end to another resource manager. By caching information locally, the caching resource manager reduces the cost of accessing the underlying resource. Unlike a conventional resource manager, a caching resource manager does not participate in recovery because it never permanently stores the underlying data.

    When an application program invokes the caching resource manager, the caching resource manager retrieves the requested information from it local cache, if possible. Otherwise, the caching resource manager obtains the requested information from the underlying resource manager. If the application performs an update, the updated data is only stored in the local cache. By only storing the update in the local cache, the caching resource manager avoids sending unnecessary messages to the underlying resource manager. The caching resource manager uses the OLE Transaction phase zero facility to receive notification of any impending transaction commits. This permits the caching resource manager to send its cached updates to the underlying resource manager just before the start of the two-phase commit protocol.

    For developers of caching resource managers we describe how to:

    • Connect to MS DTC.
    • Propagate an OLE transaction to the underlying resource manager.
    • Enlist and participate in the phase zero protocol.
  5. Developers of TIP Transaction Managers

    The Transaction Internet Protocol (TIP) is an industry standard network format and protocol through which two or more transaction managers can perform two-phase commit and recovery. MS DTC supports TIP. Developers of other transaction managers can use TIP to interoperate with MS DTC.

    For developers of transaction managers we describe how to use TIP to:

    • Propagate transactions from one transaction manager to another.
    • Participate in the two-phase commit protocol.
    • Perform transactional recovery.


Using Transactions in Application Programs

The native OLE transaction interfaces permit an application to initiate, commit, or abort transactions. Refer to the following sections to:

  • Initiate OLE transactions - How an Application Program Initiates a Transaction.
  • Commit OLE transactions - Transaction Commit.
  • Abort OLE transactions - Transaction Abort.

MS DTC transactions may be initiated and controlled by an application program written in C or C++. Most resource managers can participate in application program-initiated transactions. This is beneficial because the application program can:

  • Invoke any OLE Transactions-compliant resource manager.
  • Explicitly control the scope and duration of the transaction.


How an Application Program Initiates a Transaction

An application program initiates a transaction by:

  1. Connecting to MS DTC and obtaining a transaction dispenser interface that it uses to initiate transactions.
  2. Opening the appropriate resource managers, for example, by connecting to a relational database using ODBC.
  3. Initiating the MS DTC transaction by calling BeginTransaction and obtaining a transaction object that represents the transaction.
  4. Propagating the transaction to each resource manager by invoking the resource manager's transaction enlistment interface. For example, the application program uses the ODBC SQLSetConnectOption to propagate the MS DTC transaction object to resource managers that support ODBC. All subsequent work done on the ODBC connection is performed as part of the transaction. When the resource manager becomes aware of the MS DTC transaction, it enlists in the transaction with its local MS DTC transaction manager. This permits the resource manager to participate in the two-phase commit protocol and to receive transaction commit or abort notifications from MS DTC.
  5. Invoking the normal resource manager functions that update transaction-protected resource manager data.

    For example, the application might insert, delete, or update records in a relational database, or it might invoke a database stored procedure that modifies the relational database.

  6. Calling Commit when the work of the transaction is complete. In response to the Commit call, MS DTC uses the two-phase commit protocol to coordinate commitment of the transaction with all of the resource managers enlisted in the transaction. Alternatively, the application program could call Abort to undo the effects of the transaction. The application may then go on to perform more MS DTC transactions.
  7. Releasing the transaction dispenser object and closing the ODBC connections when the application program completes.

In DTC, a deadlock condition can occur if you attempt to nest transactions in the same resource manager. Consider the following example. If you have two objects (A and B) that attempt to acquire a lock on the same resource manager, the following scenario would force a deadlock condition:

  1. Object A initiates a transaction in the resource manager. In so doing, the object acquires a lock on a specific resource.
  2. Object A then invokes a method on Object B.
  3. Object B then initiates its own transaction and attempts to acquire a lock on the same resource manager.
  4. Since the lock request from Object B is running on a different transaction than Object A, the resource manager blocks the attempt of Object B to block the resource, creating a deadlock condition.

The lock manager in the resource manager cannot detect the deadlock because the transactions for each object will wait indefinitely for the other to commit their associated transactions. The DTC cannot break the deadlock either because it is "unaware" of the dependency of each object on the other.


Using an Application Program to Update Two SQL Server Databases

The following example introduces the OLE Transactions calls for initiating and committing MS DTC transactions, and the ODBC call for propagating an MS DTC transaction from an application program to a relational database. This example uses a Microsoft SQL Server database called "Pubs," identical copies of which are maintained on two different systems. It updates the address of an author on both database systems under the control of an MS DTC distributed transaction:

  1. The client application connects to MS DTC by calling DtcGetTransactionManager, which returns an interface pointer to a transaction dispenser object. The transaction dispenser object is used to initiate subsequent transactions.
    ITransactionDispenser *pTransactionDispenser;
ITransaction *pTransaction;
HRESULT hr = S_OK ;

// Obtain an interface pointer from MS DTC proxy.
hr = DtcGetTransactionManager(0, 0, IID_ITransactionDispenser, 0, 0, 0,(void **)&pTransactionDispenser);
if (FAILED (hr))
{
    printf("DtcGetTransactionManager failed: %x\n", hr);
    exit (1);
}

    Application programs do not need to call either CoInitialize or OleInitialize. The DtcGetTransactionManager doesn' t depend on these calls. The transaction dispenser object can be used to create multiple transactions.

  2. The application program connects to the two databases using ODBC. These standard ODBC calls are not affected by using MS DTC.
    // Establish connection to database on server#1
LogonToDB(&gSrv1);

// Establish connection to database on server#2
LogonToDB(&gSrv2);

void LogonToDB(DBCONN *ptr)
{
    RETCODE rc = 0;

    rc = SQLAllocConnect(gHenv, &(ptr->hdbc) );

    if (ProcessRC("SQLAllocConnect",ptr,rc))
    {
        rc = SQLConnect(ptr->hdbc,
                        (unsigned char *)(ptr->pszDSN),
                        SQL_NTS,
                        (unsigned char *)(ptr->pszUser),
                        SQL_NTS,
                        (unsigned char *)(ptr->pszPasswd),
                        SQL_NTS
                        );

        ProcessRC("SQLConnect",ptr,rc);
    }
}

The application program begins an MS DTC transaction by invoking the ITransactionDispenser::BeginTransaction method on the transaction dispenser object obtained in step one. The BeginTransaction method returns a translation object that represents the transaction.

// Initiate an MS DTC transaction

hr = pTransactionDispenser->BeginTransaction(
   NULL,                     // [in] IUnknown __RPC_FAR *punkOuter,
   ISOLATIONLEVEL_ISOLATED,  // [in] ISOLEVEL isoLevel,
   ISOFLAG_RETAIN_DONTCARE,  // [in] ULONG isoFlags,
   NULL,                     // [in] ITransactionOptions  *pOptions,
   &pTransaction             // [out] ITransaction__RPC_FAR
                             //        *__RPC_FAR *ppTransaction
     ) ;

if (FAILED (hr))
{
    printf("BeginTransaction failed: %x\n",hr);
    exit(1);
}
  1. The application program associates the transaction object with the ODBC database connections, using the new ODBC enlistment interface that directs further work on the ODBC connections to be performed under the auspices of the MS DTC transaction.
    // Enlist each of the data sources in the transaction
Enlist(&gSrv1,pTransaction);
Enlist(&gSrv2,pTransaction);

//---------------------------------------------------------------
void Enlist(DBCONN *ptr, ITransaction *pTransaction)
{
    RETCODE rc = 0;

    // Enlist database in the transaction
    rc = SQLSetConnectOption (ptr->hdbc, SQL_COPT_SS_ENLIST_IN_DTC,
                                    (UDWORD)pTransaction);

    ProcessRC("SQLSetConnectOption",ptr,rc);

}
  2. The application program associates a statement handle with each ODBC database connection. These standard ODBC calls are not affected by using MS DTC. The application program uses the ODBC database connections to do work on behalf of the transaction.
    // Generate the SQL statement to execute on each of the
// databases.
sprintf(SqlStatement,
            "update authors set address = '%s' where au_id = '%s'",
             gNewAddress,gAuthorID
        );

// Perform updates on both of the DBs participating in
// the transaction
ExecuteStatement(&gSrv1,SqlStatement);
ExecuteStatement(&gSrv2,SqlStatement);

// --------------------------------------------------
void ExecuteStatement(DBCONN *ptr, char *pszBuf)
{
    RETCODE rc = 0;

    // Allocate an ODBC statement handle

    rc = SQLAllocStmt(ptr->hdbc,&(ptr->hstmt));
    ProcessRC("SQLAllocStmt",ptr,rc);

    // Execute the passed string as a SQL statement
    rc = SQLExecDirect(ptr->hstmt,
            (unsigned char *)pszBuf,SQL_NTS);

    ProcessRC("SQLExecDirect",ptr,rc);

    // Free the statement handle
    rc = SQLFreeStmt(ptr->hstmt, SQL_DROP);
    ptr->hstmt = SQL_NULL_HSTMT;

    ProcessRC("SQLFreeStmt",ptr,rc);

}
  3. The application program calls the Commit method on the transaction object. MS DTC performs the two-phase commit protocol to commit the transaction. If any SQL Server database is unable to commit the transaction, the transaction is aborted and the transaction's effects are undone from all databases that were modified.

    The ODBC database connections can' t be used until the commit completes and another SQLSetConnectOption call is made to enlist the ODBC connection in either a new MS DTC transaction or in the null transaction.

Note Do not reuse the ODBC connection before the commit completes or another SQLSetConnectOption call is made.

When the application completes the transaction, it releases the transaction object.

// Commit the transaction
hr = pTransaction->Commit(FALSE,XACTTC_SYNC_PHASEONE,0);
if (FAILED(hr))
{
    printf("pTransaction->Commit() failed: %x\n",hr);
    exit(1);
}

// Release Transaction
pTransaction->Release();
if (FAILED(hr))
{
    printf("pTransaction->Commit() failed: %x\n",hr);
    exit(1);
}
  1. When no more transactions are needed, the program releases the transaction dispenser object and closes the ODBC connections.
    // release transaction dispenser
pTransactionDispenser->Release();

// Free ODBC handles
FreeODBCHandles(&gSrv1);
FreeODBCHandles(&gSrv2);

// Free the global ODBC environment handle.
SQLFreeEnv(gHenv);

// -------------------------------------------------------
void FreeODBCHandles(DBCONN *ptr)
{
    SQLDisconnect(ptr->hdbc);
    SQLFreeConnect(ptr->hdbc);

    ptr->hdbc   = SQL_NULL_HDBC;
    ptr->hstmt  = SQL_NULL_HSTMT;
}


Transaction Propagation: Application Program to Application Program

Although MS DTC supports the ability to propagate a transaction from one application program to another, Microsoft recommends that transaction propagation between application components should be handled by the system. That is, the database system, transaction processing monitor, object request broker, or queuing system should perform transaction propagation on behalf of the application.


Transaction Commit

The participant who called BeginTransaction is the only party who can call Commit. No other participant in the transaction can commit the transaction.

An application program should not call Commit while a resource manager operation is outstanding for the transaction. An application program which invokes asynchronous operations must wait for all asynchronous operations to complete before committing the transaction. An application program which violates this rule runs the risk of committing the transaction prematurely. MS DTC does nothing to prevent transactions from committing prematurely. Resource managers must be capable of handling premature commit requests. If a resource manager receives a commit request while doing work on behalf of a transaction, it can either abort the transaction or complete the request before committing the transaction.


Transaction Abort

Any participant in the transaction can abort the transaction. The transaction initiator may abort the transaction at any time by calling Abort so long as it has not called Commit. Any resource manager enlisted in the transaction may abort the transaction by calling Abort any time before responding “prepared" at phase one of the two-phase commit protocol. A resource manager may also abort the transaction at phase one of the two-phase commit protocol by responding E_FAIL to the prepare request from the transaction manager.


Developing OLE Transactions Resource Managers

This section describes how you can implement an OLE Transactions-compliant resource manager. It begins by describing how an OLE Transaction resource manager may initiate OLE transactions. It then describes how the resource manager propagates OLE transactions. Finally it describes how the resource manger can participate in the two-phase commit protocol.

Some OLE Transactions-compliant resource managers provide facilities for initiating and committing MS DTC transactions from within the resource manager. For example, a relational database system might provide stored procedure programming language calls or dynamic SQL calls for beginning, committing, and aborting MS DTC transactions.

MS DTC transactions may be initiated by:

  • A resource manager at the explicit request of an application. For example, a relational database that supports stored procedures might include a call in its stored procedure programming language that initiates an MS DTC transaction.
  • A resource manager implicitly. For example, a database that supports stored procedures might implicitly initiate an MS DTC transaction when a stored procedure updates transaction-protected resources or when it invokes a remote stored procedure in another database.


Resource Manager Explicitly Initiated Transactions

Some OLE Transactions-compliant resource managers provide facilities for initiating and committing MS DTC transactions from within the resource manager. For example, a relational database system might provide stored procedure programming language calls or dynamic SQL calls for beginning, committing, and aborting MS DTC transactions.

Resource manager explicitly initiated transactions are advantageous because they:

  1. Simplify application programming—the resource manager provides simple interfaces for beginning, committing, and aborting distributed transactions.
  2. Lowers the cost of committing a transaction when the resource manager begins and commits the transaction. When the resource manager initiates the MS DTC transaction, the transaction manager on the resource manager's system always acts as the transaction coordinator. This can reduce the cost of committing the transaction because the transaction manager on the client application's system need not participate in the two-phase commit protocol.
  3. Minimizes setup and administration—there is no need to install MS DTC on client machines.

Microsoft SQL Server is an example of a resource manager that supports explicit initiation of MS DTC transactions. The following example illustrates how other resource managers could exploit MS DTC transactions.


How SQL Server Explicitly Initiates a Transaction

SQL Server's Transact-SQL programming language has been extended to include the BEGIN DISTRIBUTED TRANSACTION statement. A SQL Server explicitly initiated transaction works as follows:

  1. When a stored procedure invokes the Transact-SQL BEGIN DISTRIBUTED TRANSACTION statement, SQL Server invokes the MS DTC BeginTransaction method and obtains a transaction object representing the transaction. After obtaining the transaction object, SQL Server enlists in the transaction with its local MS DTC transaction manager. This permits SQL Server to participate in the two-phase commit protocol and to receive transaction commit or abort notifications from MS DTC.
  2. All database updates, inserts, and deletes performed by the stored procedure are done under the auspices of the MS DTC transaction. If the stored procedure invokes a remote stored procedure in another database, SQL Server propagates the MS DTC transaction with the call to the remote stored procedure. All updates to both databases are protected by the MS DTC transaction.
  3. When the work of the transaction is complete, the stored procedure that initiated the transaction calls the Transact-SQL COMMIT TRANSACTION statement. In response to the COMMIT TRANSACTION call, SQL Server invokes the MS DTC Commit method. MS DTC uses the two-phase commit protocol to coordinate commitment of the transaction. Alternatively, the stored procedure could call the Transact-SQL ROLLBACK TRANSACTION statement. In this case, SQL Server calls the MS DTC Abort method to undo the effects of the transaction.
  4. The stored procedure may then go on to perform more transactions.

The following example illustrates how a distributed MS DTC transaction can be used within a stored procedure to ensure that two SQL Server databases are updated consistently. The example uses a Microsoft SQL Server database called "Pubs," identical copies of which are maintained on two different systems. The example updates the address of an author on both database systems under the control of an MS DTC distributed transaction. The stored procedure explicitly initiates the distributed transaction using the Transact-SQL BEGIN DISTRIBUTED TRANSACTION statement.

/*******************************************************/
/* Using BEGIN DISTRIBUTED TRANSACTION for explicit    */
/* server initiated transactions.                      */
/*******************************************************/
CREATE PROCEDURE change_addr(@au_id varchar(11),
                             @addr varchar(40),
                             @toserver varchar(12) ) AS
declare @execstr varchar(200)

-- 1. Start a Transaction
BEGIN DISTRIBUTED TRANSACTION

-- 2. Change local author information
update authors set address = @addr where au_id = @au_id

-- 3. Make a string with the server name, procedure to
--    execute and parameters
select @execstr = @toserver  '.pubs..update_addr '

-- 4. Update remote server
--     ( Note that these servers must be added to each
--      other via sp_addserver and sp_addremotelogin )
exec @execstr @au_id, @addr

-- 5. Commit the MS DTC transaction
COMMIT TRANSACTION

/*******************************************************/
/* Stored procedure to update an author's address on   */
/* the remote server.                                  */
/*******************************************************/
CREATE PROCEDURE update_addr(@au_id varchar(11),
                                @addr varchar(40)) AS
    update authors set address = @addr
    where au_id = @au_id


Resource Manager Implicitly Initiated Transactions

Some OLE Transactions resource managers may want to implicitly initiate MS DTC transactions on behalf of an application. For example, Microsoft SQL Server implicitly initiates MS DTC transactions when needed by a stored procedure.

There may be other uses for implicitly initiated MS DTC transactions. For example, a database system might automatically initiate an MS DTC transaction when no distributed transaction is in force and a stored procedure in one database system invokes a remote stored procedure in another database system. By doing this, the database system protects the work done in both databases using a single distributed transaction.

Resource manager implicitly initiated transactions are advantageous for four reasons:

  1. Simplifies application programming—resource managers automatically initiate distributed transactions when required.
  2. Permits existing stored procedures to exploit MS DTC transactions. For example, Microsoft SQL Server starts an MS DTC transaction when a stored procedure calls the existing Transact-SQL BEGIN TRANSACTION statement and the database administrator has enabled the Remote Procedure Transactions option.

    The Remote Procedure Transactions option controls whether SQL Server initiates an MS DTC distributed transaction or an existing SQL Server local transaction. The option is present for compatibility. When the option is reset, which it is by default, the old behavior is preserved and no MS DTC transaction is initiated. When the option is set, SQL Server starts an MS DTC transaction.

  3. Lowers the cost of committing a transaction when the resource manager begins and commits the transaction. When the resource manager initiates the MS DTC transaction, the transaction manager on the resource manager's system always acts as the transaction coordinator. This can reduce the cost of committing the transaction because the transaction manager on the client application's system need not participate in the two-phase commit protocol.
  4. Minimizes setup and administration because there is no need to install MS DTC on client machines.


How SQL Server Implicitly Initiates a Transaction

Microsoft SQL Server is an example of a resource manager that supports implicit initiation of MS DTC transactions. A SQL Server implicitly initiated transaction works as follows:

  1. When a stored procedure invokes the Transact-SQL BEGIN TRANSACTION statement, SQL Server determines whether the Remote Procedure Transactions option has been enabled by the database administrator. If the option has been enabled, SQL Server invokes the MS DTC BeginTransaction method and obtains a transaction object representing the transaction. After obtaining the transaction object, SQL Server enlists in the transaction with its local MS DTC transaction manager. This permits SQL Server to participate in the two-phase commit protocol and to receive transaction commit or abort notifications from MS DTC.
  2. All database updates, inserts, and deletes performed by the stored procedure are done under the auspices of the MS DTC transaction. If the stored procedure invokes a remote stored procedure in another database, SQL Server propagates the MS DTC transaction with the call to the remote stored procedure. All updates to both databases are protected by the MS DTC transaction.

    When the work of the transaction is complete, the stored procedure calls the Transact-SQL COMMIT TRANSACTION statement. In response to the COMMIT TRANSACTION call, SQL Server calls the MS DTC Commit method. MS DTC uses the two-phase commit protocol to coordinate commitment of the transaction. Alternatively, the stored procedure could call the Transact-SQL ROLLBACK TRANSACTION statement. In this case, SQL Server calls the MS DTC Abort method to undo the effects of the transaction.

  3. The stored procedure may then go on to perform more transactions.

The following example illustrates how Microsoft SQL Server can be used to implicitly begin an MS DTC transaction. First SP_CONFIGURE is used to enable the Remote Procedure Transactions option.

SP_CONFIGURE " REMOTE PROC TRANS"  1
RECONFIGURE WITH OVERRIDE

Other resource managers may choose to provide a similar means for existing applications to exploit MS DTC compatible.

/*******************************************************/
/* Using the server configuration parameter for        */
/* implicit server-initiated transactions.             */
/*******************************************************/

CREATE PROCEDURE change_addr(@au_id varchar(11),
                             @addr varchar(40),
                             @toserver varchar(12) ) AS

declare @execstr varchar(200)

-- 1. Start a Transaction. This transaction will become
--    an MS DTC distributed transaction when the remote
--    stored procedure is called because the server
--    configuration parameter is set.

BEGIN TRANSACTION

-- 2. Change local author information

update authors set address = @addr where au_id = @au_id

-- 4. Make a string with the server name and procedure
--    to execute

select @execstr = @toserver  '.pubs..update_addr '

-- 5. Update remote server.
--     ( Note that these servers must be added to each other
--     via sp_addserver and sp_addremotelogin )

exec @execstr @au_id, @addr

-- 6. Commit the MS DTC transaction

COMMIT TRANSACTION


Transaction Propagation from Application Program to Resource Manager

Transaction propagation between an application program and a resource manager is very common. It occurs when an application program initiates a transaction, tells the resource manager to enlist in the transaction, and directs the resource manager to do work under the protection of the transaction.

Many resource managers are implemented like the one shown above. The resource manager is composed of two parts. It includes a resource manager server process (RM) that manages the resource. It includes a resource manager proxy (RM proxy) that implements the application programming interfaces through which application programs invoke resource manager functions. The RM proxy is commonly implemented as a DLL. When the application program invokes a resource manager function, the RM proxy validates the input parameters, marshals the parameters into a request message, and sends the request message to the resource manager. When the resource manager receives the request message, it unmarshals the input parameters and performs the requested operation. When the operation is complete, the resource manager marshals the output parameters into a response message, and sends the response message to the RM proxy. The RM proxy unmarshals the response message and returns the output parameters to the application program.

As the resource manager developer, you are responsible for providing an API which the application program can use to propogate its transaction to the resource manager. You choose the syntax of the RM proxy function that the application uses to pass the transaction to your RM proxy. You implement the code to propagate the transaction from the RM proxy to the resource manager. MS DTC provides an OLE Transactions export interface which RM proxy uses to marshal a transaction object. Your RM proxy sends the marshaled form of the transaction object to the resource manager. MS DTC provides an OLE Transactions import interface that your resource manager uses to unmarshal the transaction object. After unmarshaling the transaction object, your resource manager enlists in the transaction.

Passing a Transaction Between the Application Program and the RM Proxy

A database resource manager that used the standard ODBC syntax for passing a transaction between the application program and the RM proxy would work as follows:

The application initiates the transaction by calling the OLE Transactions BeginTransaction method. In response, the application receives a transaction object that represents the transaction.

  1. The application passes the transaction to the RM proxy by calling the ODBC SQLSetConnectOption statement. The parameters to the SQLSetConnectOption statement include the ODBC connection handle and the transaction object.
  2. The RM proxy marshals the transaction object by using the OLE Transactions ITransactionExport Interface. The RM proxy places the marshaled transaction object into a request message and sends the request message to the resource manager.
  3. The resource manager takes the marshaled transaction object from the request message and unmarshals it by using the OLE Transactions ITransactionImport Interface, thereby getting a pointer to the transaction object.
  4. The resource manager enlists in the imported transaction object. By enlisting on the transaction, the resource manager enrolls itself in the two-phase commit protocol.
  5. The application program performs normal resource manager operations such as inserting, updating, or deleting records in a relational database. These operations are performed under the protection of the transaction.
  6. When the application program calls Commit, MS DTC uses the two-phase commit protocol to coordinate commitment of the transaction. MS DTC will invoke the resource manager at phase one to prepare the transaction and at phase two to commit the transaction.

You may choose your own application program interface for propagating transactions from the application program to your resource manager. For example, Microsoft SQL Server associates the transaction with the ODBC or DB-Library database connections. The SQLSetConnectOption function is used with ODBC connections The dbenlisttrans function is used with DB-Library connections. Once a transaction is associated with a connection, it remains associated with the connection until the next SQLSetConnectOption or dbenlisttrans call.

Other alternatives are possible. For example, rather than associating a transaction with a connection, you could insist that the transaction be passed as a parameter to every resource manager call. If you do this, you should ensure that you only export each transaction once, when it is first used.

Transaction Propagation: Resource Manager to Resource Manager

Some resource managers may choose to propagate MS DTC transactions from one OLE Transactions-compliant resource manager to another.

Transaction propagation from resource manager to resource manager is useful when a stored procedure in one database invokes a remote stored procedure in another database. It is also useful when a distributed update, insert, or delete alters data controlled by two or more resource managers. Finally, it is useful if a resource manager permits forwarding of updates to another type of resource manager. For example, a relational database might update a database table and then forward an insert to a transaction-protected queuing system.

Microsoft SQL Server is an example of a resource manager that propagates transactions from resource manager to resource manager. When a SQL Server stored procedure calls a remote stored procedure, SQL Server automatically propagates the MS DTC transaction from the calling SQL Server to the called SQL Server. If the called stored procedure invokes yet another remote stored procedure, the transaction is propagated to it also. This ensures that all databases remain consistent.

If a resource manager encounters an error while propagating a transaction, it normally aborts the entire transaction. In the example above, if resource manager RM #1 cannot propagate the transaction to resource manager RM #2, it will abort the transaction. This might occur if the network connection between the two systems fails. When the transaction is aborted, all work done on behalf of the transaction is undone.

Transaction Propagation: Resource Manager to Application Program

Some resource managers are capable of calling application code from within the resource manager. This permits the application programmer to perform operations that the resource manager and its stored procedure programming language do not directly support. If your resource manager supports this capability, you may choose to provide a way to propagate transactions from your resource manager to the application.

For example, your resource manager could provide a callback that returns the current transaction to the application program. The callback might have an interface such as this:

HRESULT rm_getdtcxact (SRVPROC *srvproc, void **ppv);

This interface returns a pointer to the current transaction object through ppv. If no transaction is active, ppv is null. The interface could return S_OK if successful, or E_FAIL on a failure.


Life of a Transaction

In the following sections, you will see diagrams showing various phases of MS DTC transactions. The circled areas in each diagram have supporting text that provide a description of each phase.

Installation (Phases)

a1 | When MS DTC is installed, the Setup program generates a GUID that uniquely identifies this instance of the MS DTC transaction manager. Setup permanently records this GUID (guidTM) in the system registry. This is done on every system on which an MS DTC transaction manager is installed. As a result, each MS DTC transaction manager on each system has a guidTM that uniquely identifies it.
b1 | When the resource manager setup program is run, it generates a GUID that uniquely identifies the resource manager. Setup permanently records this GUID (guidRM) in a place where the resource manager can easily retrieve it. Alternatively, the resource manager can generate and record a guidRM when it is first executed. In either case, each resource manager on each system has a guidRM that uniquely identifies it.


Resource Manager Startup

c1 | The resource manager calls the DtcGetTransactionManager Function or the DtcGetTransactionManagerEx Function in the MS DTC proxy to establish a connection to the transaction manager. The resource manager may either specify the name and location of the transaction manager it chooses to use or it may specify NULL values for these parameters. Normally, the resource manager specifies NULL values for these parameters. This causes the MS DTC proxy to establish a connection with the default MS DTC transaction manager. The name of the default transaction manager is contained in the system registry.
c2 | The DtcGetTransactionManager and DtcGetTransactionManagerEx system calls are implemented by the MS DTC proxy. The MS DTC proxy returns a pointer to the IUnknown interface of the MS DTC proxy core object.
c3.1 | The resource manager invokes the IUnknown::QueryInterface method on the MS DTC proxy core object to obtain the IResourceManagerFactory Interface.
c3.2 | The resource manager invokes the IResourceManagerFactory::Create method. The resource manager passes its own GUID (guidRM) and string name. The transaction manager will use the resource manager's string name to label the resource manager. This simplifies system administration by associating a symbolic name with the resource manager.
c4 | When the IResourceManagerFactory::Create method is called, the MS DTC proxy calls the Connection Manager to establish a connection to the transaction manager.
c5 | The transaction manager creates a internal object that represents the connection between the resource manager and the transaction manager. The transaction manager then returns to the MS DTC proxy.
c6 | The MS DTC proxy creates a resource manager object and returns a pointer to the IResourceManager Interface of that object to the resource manager. The IResourceManager interface is used by the resource manager to enlist in transactions and to perform transaction recovery.


Client Application Startup

d1 | The client calls the DtcGetTransactionManager Function or the DtcGetTransactionManagerEx Function in the MS DTC proxy. The client may either specify the name and location of the transaction manager it chooses to use or it may specify NULL values for these parameters. Normally, the client specifies NULL values for these parameters. This causes the MS DTC proxy to establish a connection with the default MS DTC transaction manager. The name of the default transaction manager is contained in the system registry. The client also specifies which MS DTC proxy core object interface pointer it chooses to be returned. Normally, the client requests the ITransactionDispenser Interface pointer.
d2 | The MS DTC proxy creates the MS DTC proxy core object and returns the requested interface pointer to the client. Typically, this is the ITransactionDispenser interface pointer.
d3 | The client calls the RM proxy to establish a connection with the resource manager. The syntax of this call is the responsibility of the resource manager developer. The client does this once for each connection it chooses to establish with the resource manager.
d4 | The RM proxy establishes a connection to the resource manager. This may involve communication between the RM proxy and the RM that is not depicted here. The RM proxy typically returns a resource manager connection handle to the client. The client uses this handle to communicate with the resource manager.


Transaction Initiation

e1 | The client invokes the ITransactionDispenser::BeginTransaction method in the MS DTC proxy.
e2 | The MS DTC proxy uses the Connection Manager to establish a connection to the transaction manager. It uses this connection to send a begin transaction message to the transaction manager.
e3 | The transaction manager creates an internal transaction object that represents the transaction. The transaction manager generates a GUID that uniquely identifies the transaction and stores the transaction identifier GUID in the internal transaction object. The transaction manager then returns the transaction identifier GUID to the MS DTC proxy.
e4 | The MS DTC proxy creates a transaction object and stores the transaction identifier GUID in the transaction object. The MS DTC proxy returns the ITransaction Interface pointer of the transaction object to the client.


Resource Manager Enlistment

f1 | The client calls the RM proxy to ask the resource manager to enlist in the transaction. The syntax of this call is the responsibility of the resource manager developer. Typically, the call includes at least two parameters. One parameter identifies the resource manager connection handle that the client chooses to use. The other parameter is a pointer to the transaction object. For example, if your RM proxy is based upon ODBC, you might use the SQLSetConnectionOption call.
f2 | If this is the RM proxy's first enlistment with this resource manager, then the RM proxy must create an export object for the resource manager. The RM proxy creates the export object as described immediately below. If the RM proxy already has an export object for this resource manager, then the RM proxy uses the existing export object and proceeds directly to Exporting a Transaction as described further below.


Creating an Export Object I

g1 | The RM proxy sends a "Get Whereabouts" message to its resource manager asking for the whereabouts of the resource manager's transaction manager. The form of the "Get Whereabouts" message is proprietary to the RM proxy and the resource manager.
g2.1 | The resource manager responds to the "Get Whereabouts" message by invoking the IUnknown::QueryInterface method on the MS DTC proxy core object to obtain the ITransactionImportWhereabouts Interface.
g2.2 | The resource manager invokes the ITransactionImportWhereabouts::GetWhereaboutsSize method to determine the size of the whereabouts.
g3 | The MS DTC proxy returns the byte length of the whereabouts to the resource manager.
g4 | The resource manager invokes the ITransactionImportWhereabouts::GetWhereabouts method to obtain the whereabouts.
g5 | The MS DTC proxy returns the whereabouts that it obtains from its cache. The whereabouts is an opaque data structure that represents the address of the resource manager's transaction manager. Other transaction managers can use the information in the whereabouts to locate and communicate with the resource manager's transaction manager.
g6 | The resource manager inserts the whereabouts in a "Return Whereabouts" message and returns this message to the RM proxy on the client's system. The form of the "Return Whereabouts" message is proprietary to the RM proxy and the resource manager.


Creating an Export Object II

g7.1 | The RM proxy invokes the QueryInterface method on the transaction object to obtain the IGetDispenser Interface .
g7.2 | The RM proxy invokes the IGetDispenser::GetDispenser method to obtain the ITransactionExportFactory Interface.
g7.3 | The RM proxy invokes the ITransactionExportFactory::Create method to create the export object. The RM proxy passes the whereabouts it received from its resource manager in the "Return Whereabouts" message.
g8 | The MS DTC proxy sends the whereabouts to the client's transaction manager.
g9 | The client's transaction manager stores the whereabouts in the transaction manager's internal export object. The client's transaction manager then replies to the client's MS DTC proxy.
g10 | The MS DTC proxy creates an export object and returns a pointer to the ITransactionExport Interface of the export object to the RM proxy.


Exporting a Transaction I

h1 | The RM proxy invokes the ITransactionExport::Export method on the export object, passing the pointer to the transaction object that the client specified when it asked the resource manager to enlist in the transaction at step "f1".
h2 | The MS DTC proxy sends the transaction identifier GUID of the exported transaction to the client's transaction manager.
h3.1 | The client's transaction manager checks its internal export object to see whether a Connection Manager connection has been established with the resource manager's transaction manager. If not, the client's transaction manager obtains the whereabouts from the internal export object and passes the whereabouts to the Connection Manager. The Connection Manager establishes a connection to the resource manager's transaction manager.
h3.2 | The client's transaction manager sends the transaction identifier GUID of the exported transaction to the resource manager's transaction manager.
h4 | The resource manager's transaction manager creates an internal transaction object for the exported transaction. It then stores the transaction identifier GUID in the transaction object. It marks the transaction object to indicate that it was received from the client's transaction manager. The resource manager's transaction manager then replies to the client's transaction manager.
h5 | The client's transaction manager returns the transaction identifier GUID to the MS DTC proxy.
h6 | The MS DTC proxy constructs a transaction cookie that represents the transaction. The transaction cookie is an opaque marshaled form of the transaction object. The MS DTC proxy responds to the ITransactionExport::Export method invocation by returning the byte length of the transaction cookie to the RM proxy.
h7 | The RM proxy invokes the ITransactionExport::GetTransactionCookie method on the export object, passing three input parameters. The first is the pointer to the transaction object to be exported. The second is the length of the buffer into which the transaction cookie is to be placed. The third is a pointer to the buffer where the transaction cookie will be returned.
h8 | The MS DTC proxy returns the transaction cookie and its actual length to the RM proxy.


Exporting a Transaction II

h9 | The RM proxy passes the transaction cookie to the resource manager by means of an "Export Request" message. The format of the "Export Request" message is proprietary to the RM proxy and the resource manager.
h10.1 | The resource manager responds to the "Export Request" message by invoking the IUnknown::QueryInterface method on the MS DTC proxy core object to obtain the ITransactionImport Interface.
h10.2 | The resource manager invokes the ITransactionImport::Import method, passing the transaction cookie it received from the RM proxy.
h11 | The MS DTC proxy converts the transaction cookie into the appropriate transaction identifier GUID and passes the transaction identifier to the resource manager's transaction manager.
h12 | The transaction manager uses the transaction identifier to locate the internal transaction object for the imported transaction. It updates the internal transaction object to indicate that this resource manager is participating in this transaction. It then returns to the MS DTC proxy.
h13 | The MS DTC proxy creates a transaction object for the imported transaction and returns a pointer to the ITransaction Interface of the transaction object to the resource manager.
h14 | The resource manager associates the transaction object with the RM proxy-to-resource manager session on which the transaction was exported. The resource manager then replies to the RM proxy, indicating that the transaction has been exported.
h15 | The RM proxy responds to the resource manager enlistment call that the client made at step "f1". The response indicates that a successful enlistment has occurred.


Enlistment in a Transaction I

i1 | The client invokes the RM proxy, asking it to perform a resource manager operation. For a relational database this might involve inserting, deleting, or updating a record, or invoking a stored procedure that updates the database.
i2 | The RM proxy sends a message to the resource manager asking it to perform the appropriate operation.
i3 | The resource manager determines which transaction, if any, is associated with this RM proxy-to-resource manager session. If a transaction is associated with the session, the resource manager determines if it has already enlisted in this transaction. If not, it invokes the IResourceManager::Enlist method. The first Enlist parameter is a pointer to the transaction object. The second Enlist parameter is a pointer to the ITransactionResourceAsync Interface. The resource manager is responsible for implementing the ITransactionResourceAsync interface. This interface includes the PrepareRequest, CommitRequest, AbortRequest and TMDown callback methods. The transaction manager will invoke these resource manager callback methods to deliver phase one and phase two notifications to the resource manager.
i4 | The MS DTC proxy communicates with the transaction manager, informing it that the resource manager chooses to enlist in the transaction.


Enlistment in a Transaction II

i5 | The transaction manager creates an internal enlistment object to record the fact that the resource manager is participating in the transaction. It then returns to the MS DTC proxy.
i6 | The MS DTC proxy creates an enlistment object and returns the ITransactionEnlistmentAsync Interface pointer of the enlistment object to the resource manager. The ITransactionEnlistmentAsync interface contains the PrepareRequestDone, CommitRequestDone, and AbortRequestDone methods. These are the transaction manager-implemented methods that the resource manager invokes after successfully processing an asynchronous PrepareRequest, CommitRequest, or AbortRequest. The MS DTC proxy also returns a GUID identifying the transaction. The resource manager can use this transaction identifier GUID to ensure that the client is sending a request on the same transaction that the resource manager expects. Finally, the MS DTC proxy returns the isolation level specified by the client when it called ITransactionDispenser::BeginTransaction.
i7 | The resource manager performs the resource manager operation which the client requested. For example, it might insert, update, or delete a database record. The resource manager responds to the RM proxy, informing it that the requested resource manager operation has been performed.
i8 | The RM proxy responds to the client, informing it that the requested resource manager operation has been performed.


Transaction Commit Phase 1-Prepare I

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

Transaction Commit Phase 1–Prepare I

j1 | The client invokes the ITransaction::Commit method in the MS DTC proxy.
j2 | The MS DTC proxy communicates with the client's transaction manager.
j3.1 | The client's transaction manager initiates phase one of the two-phase commit process. All of the work of preparing the transaction is done in parallel. The client's transaction manager determines if any resource managers on the client's system have enlisted in the transaction. If so, the client's transaction manager asks each of these resource managers to prepare. In our example, no resource managers on the client's system participated in the transaction.
j3.2 | The client's transaction manager determines which subordinate transaction managers have participated in the transaction and sends each of them a Prepare message. These Prepare messages are sent to the subordinate transaction managers in parallel.
j4.1 | The resource manager's transaction manager determines whether any transaction managers are subordinate to it. In our example, the resource manager's transaction manager has no subordinates. If the resource manager's transaction manager has subordinates, it sends each of them a Prepare message. These Prepare messages are sent to the subordinate transaction managers in parallel.
j4.2 | The resource manager's transaction manager uses its internal enlistment objects to determine which resource managers have enlisted in the transactions. It sends a Prepare message to the MS DTC proxy of each enlisted resource manager. These Prepare messages are sent to the MS DTC Proxies in parallel.
j4.3 | The resource manager's transaction manager awaits notification from all of the resource managers involved in the transaction that they have completed their prepare work.
j5 | Each MS DTC proxy invokes the resource manager's ITransactionResourceAsync::PrepareRequest method. This method invocation informs the resource manager that it should perform phase one of the two-phase commit protocol.
j6 | Each resource manager immediately responds to the PrepareRequest, thereby acknowledging that the PrepareRequest has been received. After responding to the PrepareRequest method invocation, the resource manager begins the work necessary to prepare the transaction.


Transaction Commit Phase 1-Prepare II

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

Transaction Commit Phase 1–Prepare II

j8.1 | The resource manager invokes the QueryInterface method on the enlistment object to obtain the IPrepareInfo Interface .
j8.2 | The resource manager invokes the IPrepareInfo::GetPrepareInfoSize method to determine the length of the prepare information. The prepare information is an opaque data item that identifies the transaction. The prepare information is used during failure recovery. At failure recovery time, the resource manager sends the prepare information to the transaction manager to learn the outcome of the transactions.
j9 | The MS DTC proxy returns the byte length of the prepare information. The MS DTC proxy cached the prepare information when the resource manager enlisted in the transaction.
j10 | The resource manager invokes the IPrepareInfo::GetPrepareInfo method to retrieve the prepare information.
j11 | The MS DTC proxy returns the prepare information to the resource manager.
j12.1 | The resource manager does the work necessary to prepare the transaction. This includes writing all changes made on behalf of the transaction to the resource manager's log file. The resource manager then writes a Prepare record for the transaction to the log. The Prepare record must contain the prepare information obtained from MS DTC.
j12.2 | The resource manager invokes the ITransactionEnlistmentAsync::PrepareRequestDone method to inform the MS DTC proxy that it has completed the prepare phase of the two-phase commit protocol.
j13 | The MS DTC proxy informs the resource manager's transaction manager that the resource manager has completed phase one.
j14 | When all of the resource managers subordinate to the transaction manager involved complete phase one, then the transaction manager writes a Prepared record to its log file. The resource manager's transaction manager then informs the client's transaction manager that phase one is complete.


Transaction Commit Phase 2-Commit I

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

Transaction Commit Phase 2–Commit I

k1.1 | The client's transaction manager writes the transaction Commit record to the transaction manager log file.
k1.2 | If the client requested transaction outcome notification, then the client's transaction manager notifies the client's MS DTC proxy that the transaction has completed phase one.
k1.3 | The client's transaction manager initiates the second phase of the two-phase commit process. All of the work of committing the transaction is done in parallel. The client's transaction manager determines if any resource managers on the client's system have enlisted in the transaction. If so, the client's transaction manager asks each of these resource managers to commit. In our example, no resource managers on the client's system participated in the transaction.
k1.4 | The client's transaction manager determines which subordinate transaction managers have participated in the transaction and sends each of them a Commit message. These Commit messages are sent to the subordinate transaction managers in parallel. The Commit message informs the subordinate transaction managers to perform phase two processing.
k2 | The MS DTC proxy returns from the ITransaction::Commit method invocation.
K3 | The client is informed that phase one has completed.
k4.1 | The resource manager's transaction manager writes a Commit record to its local transaction manager log file.
k4.2 | The resource manager's transaction manager determines whether any transaction managers are subordinate to it. In our example, the resource manager's transaction manager has no subordinates. If the resource manager's transaction manager has subordinates, it sends each of them a Commit message. These Commit messages are sent to the subordinate transaction managers in parallel.
k4.3 | The resource manager's transaction manager uses its internal enlistment objects to determine which resource managers have enlisted in the transactions. It sends a Commit message to the MS DTC proxy of each enlisted resource manager. These Commit messages are sent to the MS DTC Proxies in parallel.
k4.4 | The resource manager's transaction manager awaits notification from all of the resource managers involved in the transaction that they have completed their commit work.
k5 | Each MS DTC proxy invokes the resource manager's ITransactionResourceAsync::CommitRequest method. This method invocation informs the resource manager that it should perform the second phase of the two-phase commit protocol.
k6 | Each resource manager replies to the CommitRequest call from the MS DTC proxy to acknowledge that the CommitRequest has been received.
K7 | After responding to the CommitRequest method invocation, the resource manager begins the work necessary to commit the transaction.


Transaction Commit Phase 2-Commit II

Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

Transaction Commit Phase 2–Commit II

k8.1 | The resource manager does the work necessary to commit the transaction. This includes releasing all locks held on behalf of the transaction. The resource manager then writes a Commit record for the transaction to the resource manager's log file. If it chooses, the resource manager can do a lazy log file write to economize on log I/Os. When the write to the log finishes, the resource manager proceeds to the next step.
k8.2 | The resource manager invokes the ITransactionEnlistmentAsync::CommitRequestDone method to inform the MS DTC proxy that it has completed the commit phase of the two-phase commit protocol.
k9 | The MS DTC proxy informs the resource manager's transaction manager that the resource manager has completed phase two processing.
k10.1 | When all of the resource managers on the system have completed their phase two processing, the resource manager's transaction manager writes a Forget record to its local transaction manager log file. If it chooses, the transaction manager can do a lazy log file write to economize on log I/Os. After the log write completes, the transaction manager forgets the transaction and proceeds to the next step.
k10.2 | The resource manager's transaction manager informs the client's transaction manager that phase two is complete.
k11 | The client's transaction manager waits until all of its subordinate transaction managers have responded. It then writes a Forget record to the transaction manager log file. If it chooses, the transaction manager can do a lazy log file write to economize on log I/Os. The transaction manager then forgets the transaction.


Transaction Recovery

m1.1 | During recovery, the resource manager first does the Resource Manager Start Up procedure described above. As a result of these start-up steps, the resource manager obtains a pointer to the IResourceManager Interface.
m1.2 | The resource manager reads its log file and determines which transactions are in-doubt. For each of these transactions it calls the IResourceManager::Reenlist method. The resource manager passes in both the prepare information it was originally given by the transaction manager and a time-out value which indicates how long the resource manager is willing to wait to learn the outcome of the transaction.
m2 | The MS DTC proxy communicates this information to the transaction manager.
m3 | The transaction manager determines the outcome of the transaction, if possible, and returns the transaction outcome to the MS DTC proxy.
m4 | The MS DTC proxy responds to the resource manager indicating whether the in-doubt transaction was committed or aborted. If the transaction's outcome cannot be determined before the time-out expires, then a re-enlistment time-out error is returned to the resource manager.
m5.1 | The resource manager records each transaction's outcome by writing a commit or abort record in the resource manager log file.
m5.2 | When the resource manager has determined the outcome of all in-doubt transactions, it invokes the IResourceManager::ReenlistmentComplete method. The resource manager uses this method to inform the transaction manager that the resource manager knows the outcome of all in-doubt transactions in which it is involved.
m6 | The MS DTC proxy informs the transaction manager that recovery is complete.
m7 | The transaction manager discards any information it was keeping regarding committed transactions that this resource manager might have been involved in.


Implementing a Resource Manager

This section describes the development environment and the interfaces that need to be implemented by an OLE Transactions-compliant resource manager. Also described in this section are ways for a resource manager to participate in an application-initiated transaction, and propagation of a transaction from one resource manager to another. The topics describe:

  • The development environment
  • Implementing interfaces
  • Transaction initiated by an in-process application component
  • Transaction propagation
  • Obtaining the whereabouts
  • Obtaining a transaction dispenser from a transaction
  • Participating in the two-phase commit protocol


Development Environment

All the transaction interfaces are COM (Component Object Model) interfaces and, therefore, the natural language of choice is C++. The interfaces are available in the following header files:

Comsvcs.H

Transact.H

Txdtc.H

XoleHlp.H

The header file “Transact.h” contains interfaces that an application will use to interact with the transaction coordinator (such as MS DTC); interfaces such as ITransactionDispenser Interface, ITransaction Interface, and so forth. The header file “Txdtc.h” contains interfaces which deal with the interaction between the resource manager and the transaction coordinator. The header file “XoleHlp.H” contains API definitions used to connect to MS DTC. All of these header files are available with the MS DTC Software Development Kit (SDK).


Implementing Interfaces

A resource manager needs to implement only two interfaces in order to work with MS DTC:

IResourceManagerSink Interface

ITransactionResourceAsync Interface

The IResourceManagerSink interface is required to build a relationship between the resource manager and the transaction coordinator. The ITransactionResourceAsync interface is required to receive the two-phase notifications for a transaction on which the resource manager is enlisted. There is one instance of ITransactionResourceAsync per enlistment. Typically, there is one enlistment per transaction, however, a resource manager can choose to enlist multiple times on the same transaction.

A resource manager generally follows these steps:

  1. Building a Relationship with MS DTC
  2. Performing Recovery
  3. Enlisting in New Transactions

Building a Relationship with MS DTC

The resource manager calls DtcGetTransactionManager Function to get a reference to the IUnknown interface on the MS DTC Proxy Core object. Using this reference, the resource manager can call QueryInterface for the IResourceManagerFactory Interface. The resource manager then calls the IResourceManagerFactory::Create method to get a reference to the IResourceManager Interface of the resource manager object. The IResourceManager interface is used by a resource manager to enlist in new transactions and to perform recovery.

The Distributed Transaction Manager object obtained by calling DtcGetTransactionManager function.

Performing Recovery

The recovery process is actually comprised of two steps. In the first step, the resource manager resolves all in-doubt transactions. In the second step, the resource manager lets the transaction coordinator know that it has completed recovery and, therefore, has no more transactions in-doubt. The resource manager performs the following actions:

  1. Examines the log file to identify all the prepare information records for transactions that are in-doubt. For each such transaction, it invokes the IResourceManager::Reenlist method. This method (via an out parameter), provides the outcome for that transaction. If the Distributed Transaction Coordinator (MS DTC) doesn't know the outcome of the transaction, then the Reenlist method will fail with an XACT_E_REENLISTTIMEOUT error message. In this case the resource manager will need to retry at a later time.
  2. Invokes the IResourceManager::ReenlistmentComplete method when the resource manager learns the outcome to all the in-doubt transactions. This method completes the recovery and also informs the MS DTC that the resource manager has no more in-doubt transactions. By invoking this method, the resource manager guarantees that it will not invoke the Reenlist method again. It is not correct for an RM to ask the outcome of a transaction by invoking the Reenlist method once it has invoked the ReenlistmentComplete method.

Note It is not necessary for a resource manager to resolve all in-doubt transactions before it enlists in new transactions. Step 1 can be performed at any time after the resource manager establishes a relationship with MS DTC. Step 2 can be repeated multiple times without affecting the outcome of transactions. A resource manager can invoke the IResourceManager::Reenlist method for the same transaction multiple times. However, once step 1 has been performed, step 1 can't be performed again.

Enlisting in New Transactions

The resource manager can start enlisting in new transactions after it establishes a relationship with MS DTC. The resource manager then obtains an ITransaction Interface to a transaction and enlists in this transaction by invoking the IResourceManager::Enlist method. One of the parameters to this method is an instance of ITransactionResourceAsync Interface. Once the resource manager has enlisted in a transaction, it is expected to participate in the two-phase commit protocol. When the initiator of the transaction invokes the ITransaction::Commit method, MS DTC initiates the voting phase of the two-phase commit protocol. The first phase notifications are delivered to each participant (such as a resource manager) that is enlisted in the transaction. This notification is delivered by invoking the ITransactionResourceAsync::PrepareRequest method. The resource manager then performs the relevant work to move from an active state to a prepared state and on moving to the prepared state invokes the ITransactionEnlistmentAsync::PrepareRequestDone method. Similarly, the decision phase notification is provided to each enlisted participant by the invocation of the ITransactionResourceAsync::CommitRequest method. A resource manager responds to this notification by invoking the ITransactionEnlistmentAsync::CommitRequestDone method. The Abort notification also works the same way as the first phase notification. However, there is no second phase in the case of an Abort.

A resource manager can obtain the ITransaction interface for enlistment in the following ways:

  1. A resource manager can initiate a transaction. The resource manager obtains the MS DTC transaction by invoking the ITransactionDispenser::BeginTransaction method.
  2. An in-process application component can initiate a transaction. See the Transaction Initiated by an In-Process Component topic for more information.
  3. Propagation of a transaction. See the Transaction Propagation topic for more information.


Transaction Initiated by an In-Process Application Component

Application code (such as a stored procedure) may exist in-process with a resource manager. This application code could obtain an MS DTC transaction, and because it is in-process with the resource manager, it could provide a reference to the ITransaction Interface on the transaction object to the resource manager; which then can enlist in that transaction.

In DTC, a deadlock condition can occur if you attempt to nest transactions in the same resource manager. Consider the following example. If you have two objects (A and B) that attempt to acquire a lock on the same resource manager, the following scenario would force a deadlock condition:

  1. Object A initiates a transaction in the resource manager. In so doing, the object acquires a lock on a specific resource.
  2. Object A then invokes a method on Object B.
  3. Object B then initiates its own transaction and attempts to acquire a lock on the same resource manager.
  4. Since the lock request from Object B is running on a different transaction than Object A, the resource manager blocks the attempt of Object B to block the resource, creating a deadlock condition.

The lock manager in the resource manager cannot detect the deadlock because the transactions for each object will wait indefinitely for the other to commit their associated transactions. The DTC cannot break the deadlock either because it is "unaware" of the dependency of each object on the other.


Transaction Propagation

A transaction begun in one process can be propagated to another process. Resource managers built on a client/server architecture, have a server side and a client side. The server side enlists in a transaction so that it can participate in the two-phase commit. However, because the transaction (MS DTC transaction) might have been initiated on the client side, such resource managers use a mechanism to propagate a transaction from the client side to the server side. This mechanism is implemented entirely by MS DTC. See Exporting a Transaction and Importing a Transaction topics for more detailed information.

Exporting a Transaction

The resource manager proxy (RM proxy) on the client side can provide a function which an application can call to request a resource manager to enlist in a transaction. The transaction (ITransaction Interface *) to enlist in can be provided via a parameter to the enlist function. After obtaining the transaction to enlist in, the RM proxy uses the ITransactionExport Interface to propagate the transaction to the transaction coordinator.

To export a transaction

  1. The application client obtains an ITransaction interface by invoking the ITransactionDispenser::BeginTransaction method.
  2. The application client calls the RM_Enlist function, passing it the ITransaction transaction on which it wants the RM to enlist.
  3. Within the RM_Enlist function, the RM proxy does the following:
    • Invokes the ITransactionExport::Export method, passing it the ITransaction provided by the client. The mechanism for obtaining the ITransactionExport Interface is described in the Obtaining the Whereabouts topic.
    • If the previous step succeeds, then the RM proxy obtains the transaction cookie by invoking the ITransactionExport::GetTransactionCookie method.
    • The RM proxy then sends the transaction cookie to the resource manager. The transaction cookie is transported from the RM proxy to the resource manager by a communication pipe which is used for the transmission of all messages between the RM proxy and the resource manager server.

Importing a Transaction

After the resource manager server receives the transaction cookie, it invokes the ITransactionImport::Import method, providing it with the cookie that it had received from its proxy. This invocation translates the cookie to an ITransaction Interface, and if it succeeds, then the resource manager also has an interface to the same transaction which the application client had obtained in step 1 of Exporting a Transaction earlier in this topic.


Obtaining the Whereabouts

Resource managers which are designed as client/server systems, will generally have the resource manager server on one node and the resource manager proxy on other nodes. If the application client begins the transaction and wants the resource manager to enlist in the transaction, then it will do so by invoking a function in the RM proxy (such as RM_Enlist) and providing it with the ITransaction Interface which it wants the resource manager to enlist in.

If the transaction is begun on Node A, then before the resource manager on Node B can enlist in the transaction, the transaction needs to be propagated to the transaction coordinator on Node B. RM proxy needs to request MS DTC on its node to propagate the transaction to node B. Before making this request, it needs to know which MS DTC should the transaction be propagated to. To obtain this information, the RM proxy, sends a message to its resource manager asking for the whereabouts of the MS DTC which the resource manager is working with. The resource manager does the following steps to obtain the whereabouts:

  1. It obtains the ITransactionImportWhereabouts Interface. There are multiple ways to obtain this interface, such as by calling QueryInterface, or by calling DtcGetTransactionManager Function, or by calling the QueryInterface method on the IUnknown that the resource manager might have obtained from a previous call to DtcGetTransactionManager.
  2. It then calls ITransactionImportWhereabouts::GetWhereabouts, to obtain the whereabouts of the MS DTC which it is working with. Having obtained this information once, it can be cached and therefore, future calls of this method can be avoided. What is obtained from this call is a binary large object (BLOB).

After obtaining the whereabouts BLOB, the resource manager sends it to the RM proxy. RM proxy after receiving the whereabouts BLOB does the following steps to obtain an ITransactionExport Interface.

  1. It obtains the ITransactionExportFactory Interface from the MS DTC proxy. This interface is obtained by invoking QueryInterface. See the section titled "Obtaining Transaction Dispenser from a Transaction" for more details.
  2. It then invokes ITransactionExportFactory::Create, passing it the whereabouts BLOB which it had received from the resource manager. As a result of this invocation, it obtains an ITransactionExport interface to an export object, which it can then keep for exporting transaction to the MS DTC with which its resource manager is working.

Note Even in cases where the RM proxy might be on the same node as the resource manager, the steps for obtaining the whereabouts and propagating the transaction need to be performed.


Obtaining a Transaction Dispenser from a Transaction

When the application client calls the RM_Enlist function, passing it the ITransaction Interface to the transaction object, the RM proxy needs to know the transaction dispenser from which the transaction object was obtained. This is essential because there can be multiple transaction dispensers, and the transaction can be propagated only by the transaction coordinator which dispensed the transaction. To get to the appropriate transaction dispenser from a transaction:

  1. Invoke the QueryInterface to obtain the IGetDispenser Interface.
  2. Invoke the IGetDispenser::GetDispenser method to obtain the ITransactionDispenser interface.
  3. Then invoke the QueryInterface to obtain the ITransactionExportFactory Interface.


Participating in the Two-Phase Commit Protocol

After a resource manager enlists in a transaction, it needs to participate in the two-phase commit protocol. The following figure shows the relationship between the objects that participate in the two-phase commit.

A resource manager enlists in a transaction by calling the IResourceManager::Enlist method and passes an instance of the ITransactionResourceAsync Interface. The transaction coordinator delivers the Prepare, Commit, and Abort notifications to the resource manager via this callback interface. The following state diagrams show the states of the enlistment object as it exists in the MS DTC proxy and the states of the resource manager from the perspective of the enlistment object in the MS DTC proxy.

The State Machine Within an Enlistment Object

A Resource Manager's State Diagram from an Enlistment's Perspective

Built on Monday, January 22, 2001


Developing XA Compliant Resource Managers

Many resource managers, especially those that are developed from UNIX systems, support XA open TCP transaction protocol. The interfaces described here allow COM+ application developers to access XA-compliant databases and create resource managers that operate with relational databases, message-queueing, transactional files, and object-oriented databases.

Although Microsoft does not directly support the XA protocol, Microsoft does support translation facilities between OLE transactions and XA. That is, these facilities allow the developer to produce a resource manager that is written in OLE but operates in XA compliant databases.

This section describes information about OLE translation facilities and defines the supporting interfaces. The information includes:

  • Mapping OLE transactions to the XA protocol
  • Steps in the life of an XA transaction
  • XA recovery process
  • XA interfaces


Mapping OLE Transactions to the XA Protocol

The Microsoft Distributed Transaction Coordinator (MS DTC) provides a transaction coordination facility using the OLE Transactions protocol. This document describes how the OLE Transactions protocol can be mapped to the X/Open (XA) protocol.

The shaded components in the previous illustration represent parts of MS DTC: the DTC Proxy, the XA transaction manager (TM), and the distributed transaction coordinator (DTC). The components marked as solid represent the resource manager (RM): the RM proxy, and the RM itself.

An application gets new transactions by invoking the ITransactionDispenser Interface offered by the DTC Proxy DLL, and it uses an RM proxy to communicate with an RM such as SQL Server, DB2, Informix, and Oracle, among others. To get an ODBC connection to enlist on a DTC transaction, the application sets an attribute called SQL_ATTR_ENLIST_IN_DTC on that connection. An ODBC driver is DTC-compliant only if it accepts this attribute. Some resource managers are natively OLE Transactions-compliant, in which case the ODBC driver performs all necessary work for OLE Transactions. See the Resource Manager Implementation Guide for information about what ODBC drivers need to do to map the OLE Transactions protocol to the XA protocol.


Transaction States

When the ODBC connection is initially obtained, it is in a local transaction state. An application enlists in a distributed transaction by setting the connection attribute SQL_ENLIST_IN_DTC and passing in a non-null transaction pointer. It remains in that state until the application sets the connection attribute SQL_ENLIST_IN_DTC with a null transaction pointer.

When the connection transitions from the local transaction state to the distributed transaction state, the RM proxy should call the IDtcToXaMapper::RequestNewResourceManager to obtain a RM cookie for the resource manager. The resource manager in this case is defined by the Data Source Name (DSN).

Driver implementers should not use the same RM cookie for two separate ODBC connections if the DSN on both connections is the same.

Calling RequestNewResourceManager results in a message from the DTC proxy to the XA TM. When the XA TM receives a message that contains the DSN and the name of the client DLL, it first checks to see if it already has an XA connection to the resource manager with the same DSN. If not, then the XA TM does the following:

  1. Loads the client DLL.
  2. Gets the address of the GetXaSwitch Function.
  3. Calls the GetXaSwitch function to obtain the XA_Switch.
  4. Calls the xa_open function to open an XA connection with the resource manager.

In step 4, when the RM's xa_open function is called, the DTC TM passes in the DSN as the OPEN_STRING. The implementation of the xa_open function should create the appropriate OPEN_STRING based on the DSN. For example, if it needs any user id or security information, it can get that from the registry or anywhere else where it would have been stored at the time the DSN was created.

When the RequestNewResourceManager method call returns with a success two things are TRUE:

  1. There is an XA Connection open from the XA TM to the RM proxy for the resource manager.
  2. There is an RM cookie to DSN entry available in the mapping table which maps an RM cookie to a DSN. For example:
    const XID XID_NULL = {-1, 0, 0, '\0'}


Implementing Algorithms

The ODBC drivers are expected to implement several high-level algorithms in order to be fully integrated with MS DTC and, therefore, with Microsoft Transaction Server:

On SQL_ENLIST_IN_DTC with a Non-NULL Transaction Value

if  (Connection_State   EQUALS   LOCAL_TRANSACTION_STATE) then
do begin
invoke pIDtcToXaMapper->RequestNewResourceManager (   "Accounts",
"SQLODBC32.DLL",
&dwRMCookie)

do close the database if it is open
do xa_open or its equivalent

set Connection_State to DISTRIBUTED_TRANSACTION_MODE
end if

invoke pIDtcToXaMapper->TranslateTridToXid    (   pITransaction,
   dwRMCookie,
   &XID
);
do xa_start or its equivalent

invoke pIDtcToXaMapper->EnlistResourceManager (dwRMCookie, pITransaction)

do xa_end or its equivalent if needed

On SQL_ENLIST_IN_DTC with a NULL Transaction Value

if (Connection_State EQULS LOCAL_TRANSACTION_STATE) then
   return ERROR_UNEXPECTED_CALL

set Connection_State to LOCAL_TRANSACTION_MODE

do xa_close or its equivalent if needed


Steps in the Life of an XA Transaction

The steps in the life of an XA transaction include:

  • One-Pipe Resource Manager Connection
  • One-Pipe Resource Manager Enlistment
  • One-Pipe Resource Manager Commit Phase 1 - Prepare
  • One-Pipe Resource Manager Commit Phase 2 - Commit
  • Two-Pipe Resource Manager Connection
  • Two-Pipe Resource Manager Enlistment
  • Two-Pipe Resource Manager Commit Phase 1 - Prepare
  • Two-Pipe Resource Manager Commit Phase 2 - Commit

One-Pipe Resource Manager Connection (A)

  1. The application calls SQLConnect in the ODBC driver manager passing the Data Source Name (DSN), User identifier, and Authentication string.
  2. The ODBC driver manager calls SQLConnect in the ODBC driver.
  3. The ODBC driver connects to the resource manager. Typically, the ODBC driver opens a non-transactional resource manager connection because it does not yet know whether the connection will require a transaction.
  4. The ODBC driver manager calls SQLSetConnectAttr(SQL_ATTR_ENLIST_IN_DTC, pITransaction) in the ODBC driver. This instructs the ODBC driver to enlist in the specified transaction.
  5. The ODBC driver determines whether it already has a transactional connection open to the resource manager. If so, it proceeds directly to "One-Pipe Resource Manager Enlistment" as described below.If the ODBC driver has a non-transactional connection open to the resource manager, it closes it. It then creates a new transactional resource manager connection as described directly below.

One-Pipe Resource Manager Connection (B)

  1. The ODBC driver calls the DtcGetTransactionManager Function in the MS DTC proxy to establish a connection to the transaction manager. The resource manager may either specify the name and location of the transaction manager it chooses to use or it may specify NULL values for these parameters. Normally, the resource manager specifies NULL values for these parameters. This causes the MS DTC proxy to establish a connection with the default MS DTC transaction manager. The name of the default transaction manager is contained in the system registry.
  2. The DtcGetTransactionManager system call is implemented by the MS DTC proxy. The MS DTC proxy returns a pointer to the IUnknown interface of the MS DTC proxy core object.
  3. The ODBC driver invokes the IUnknown::QueryInterface method on the MS DTC proxy core object to obtain the IDtcToXaHelperSinglePipe Interface.
  4. The ODBC driver opens a new transactional connection to the resource manager by sending an xa_open message to it.
  5. The ODBC driver invokes IDtcToXaHelperSinglePipe::XARMCreate passing in the DSN name and the name of the ODBC driver DLL.
  6. MS DTC proxy forwards the DSN name and the name of the ODBC driver DLL to the DTC transaction manager.
  7. In the steps that follow, the DTC transaction manager connects to the resource manager to ensure that it can do so should recovery be necessary. It then records the information needed to reestablish the connection in its log file.
    • The DTC transaction manager calls LoadLibrary to load the ODBC driver DLL. It calls GetProcAddress to obtain the address of the GetXASwitch function. It calls GetXASwitch to obtain the address of the XASwitch data structure implemented by the ODBC driver.
    • The DTC transaction manager connects to the resource manager by calling xa_open using the DSN provided in the XARMCreate call. It then closes the resource manager connection by calling xa_close.
    • The DTC transaction manager generates an RM GUID for each connection request it receives. The transaction manager writes a record to the DTCXATM.LOG file indicating that a new resource manager connection is being established. The log record contains the DSN name, the name of the ODBC driver DLL, and the RM GUID. The transaction manager uses this information to reconnect to the resource manager should recovery be necessary.
    • The transaction manager returns the RM GUID it generated to the MS DTC proxy.
  8. The MS DTC proxy calls the MS DTC Connection Manager to establish a connection to the transaction manager.
  9. The transaction manager creates a internal object that represents the connection between the resource manager and the transaction manager. The transaction manager then returns to the MS DTC proxy.
  10. The MS DTC proxy creates a resource manager object and returns an opaque pointer to that object as the RMCookie. This RMCookie represents the connection to the transaction manager.

One-Pipe Resource Manager Enlistment

  1. The ODBC driver invokes the IDtcToXaHelperSinglePipe::ConvertTridToXid method to convert the OLE transaction identifier (TRID) to an XA transaction identifier (XID). It passes in the ITransaction pointer, the RMCookie, and a pointer to a pre-allocated XID structure.
  2. The MS DTC proxy generates an XID and returns it in the XID structure.
  3. The ODBC driver constructs an xa_start message containing the XID and sends it to the resource manager.
  4. The resource manager associates the connection with the XID and then replies to the xa_start message.
  5. The ODBC driver invokes the IDtcToXaHelperSinglePipe::EnlistWithRM method. It passes in the RMCookie, a pointer to the transaction object, and a pointer to its ITransactionResourceAsync Interface. The ODBC driver is responsible for implementing the ITransactionResourceAsync interface. This interface includes the PrepareRequest, CommitRequest, AbortRequest and TMDown callback methods. The transaction manager will invoke these callback methods to deliver phase one and phase two notifications to the ODBC driver.
  6. The MS DTC proxy informs the transaction manager that the ODBC driver wishes to enlist in the transaction.
  7. The transaction manager creates an internal enlistment object to record the fact that the ODBC driver is participating in the transaction. It then returns to the MS DTC proxy.
  8. The MS DTC proxy creates an enlistment object and returns the ITransactionEnlistmentAsync interface pointer of the enlistment object to the ODBC driver. The ITransactionEnlistmentAsync interface contains the PrepareRequestDone, CommitRequestDone, and AbortRequestDone methods. These are the transaction manager-implemented methods that the ODBC driver invokes after successfully processing an asynchronous PrepareRequest, CommitRequest, or AbortRequest.
  9. The ODBC driver returns from the SQLSetConnectAttrcall.
  10. The application is then free to performs work using the enlisted resource manager connection.

One-Pipe Resource Manager Commit Phase 1 - Prepare

  1. When ITransaction::Commit is called, the transaction manager initiates phase one of the two-phase commit process. The transaction manager determines which ODBC drivers have enlisted in the transactions and sends a Prepare message to the MS DTC proxy of each enlisted ODBC driver. These Prepare messages are sent to the MS DTC Proxies in parallel.
  2. The transaction manager awaits notification from all of the enlistees involved in the transaction that they have completed their prepare work.
  3. Each MS DTC proxy invokes the ODBC driver’s ITransactionResourceAsync::PrepareRequest method to informs the ODBC driver that it should perform phase one of the two-phase commit protocol.
  4. Each ODBC driver should immediately respond to the PrepareRequest to acknowledge its receipt.
  5. The ODBC driver sends an xa_prepare message to the resource manager.
  6. The resource manager prepares and then replies to the xa_prepare message.
  7. When the ODBC driver receives the reply to the xa_prepare message, it invokes the ITransactionEnlistmentAsync::PrepareRequestDone method to inform the MS DTC proxy that it has completed the prepare phase of the two-phase commit protocol.
  8. The MS DTC proxy informs the transaction manager that the ODBC driver has completed phase one.
  9. When all of the ODBC drivers on the system complete phase one, the transaction manager writes a Prepared record to its log file. Phase one is now complete.

One-Pipe Resource Manager Commit Phase 2 - Commit

  1. The transaction manager writes the transaction Commit record to the transaction manager log file.
  2. The Transaction Manager initiates the following sequence:
    • The transaction manager initiates phase two of the two-phase commit process. The transaction manager sends a Commit message to the MS DTC proxy of each enlisted ODBC driver. These Commit messages are sent to the MS DTC Proxies in parallel.
    • The transaction manager awaits notification from all of the enlistees involved in the transaction that they have completed their commit work.
  3. Each MS DTC proxy invokes the ODBC driver’s ITransactionResourceAsync::CommitRequest method. This method invocation informs the ODBC driver that it should perform phase two of the two-phase commit protocol.
  4. Each ODBC driver should immediately respond to the CommitRequest to acknowledge its receipt.
  5. The ODBC driver sends an xa_commit message to the resource manager.
  6. The resource manager commits and then replies to the xa_commit message.
  7. When the ODBC driver receives the reply to the xa_commit message, it invokes the ITransactionEnlistmentAsync::CommitRequestDone method to inform the MS DTC proxy that it has completed the commit phase of the two-phase commit protocol.
  8. The MS DTC proxy informs the transaction manager that the ODBC driver has completed phase two.
  9. When all of the ODBC drivers on the system complete phase two, the transaction manager writes a Forget record to its log file. If it chooses, the transaction manager can do a lazy log file write to economize on log I/Os. The transaction manager then forgets the transaction.

Two-Pipe Resource Manager Connection (A)

  1. The application calls SQLConnect in the ODBC driver manager passing the Data Source Name (DSN), User identifier, and Authentication string.
  2. The ODBC driver manager calls SQLConnect in the ODBC driver.
  3. The ODBC driver connects to the resource manager. Typically, the ODBC driver opens a non-transactional resource manager connection because it does not yet know whether the connection will require a transaction.
  4. The ODBC driver manager calls SQLSetConnectAttr(SQL_ATTR_ENLIST_IN_DTC, pITransaction) in the ODBC driver. This instructs the ODBC driver to enlist in the specified transaction.
  5. The ODBC driver determines whether it already has a transactional connection open to the resource manager. If so, it proceeds directly to "Two-Pipe Resource Manager Enlistment" as described in the next topic.If the ODBC driver has a non-transactional connection open to the resource manager, it closes it. It then creates a new transactional resource manager connection as described directly below.

Two-Pipe Resource Manager Connection (B)

  1. The ODBC driver calls the DtcGetTransactionManager procedure in the MS DTC proxy to establish a connection to the transaction manager. The resource manager may either specify the name and location of the transaction manager it chooses to use or it may specify NULL values for these parameters. Normally, the resource manager specifies NULL values for these parameters. This causes the MS DTC proxy to establish a connection with the default MS DTC transaction manager. The name of the default transaction manager is contained in the system registry.
  2. The DtcGetTransactionManager system call is implemented by the MS DTC proxy. The MS DTC proxy returns a pointer to the IUnknown interface of the MS DTC proxy core object.
  3. The ODBC driver invokes the IUnknown::QueryInterface method on the MS DTC proxy core object to obtain the IDtcToXaMapper Interface.
  4. The ODBC driver opens a new transactional connection to the resource manager by sending an xa_open message to it.
  5. The ODBC driver invokes IDtcToXaMapper::RequestNewResourceManager passing in the DSN name and the name of the ODBC driver DLL.
  6. MS DTC proxy forwards the DSN name and the name of the ODBC driver DLL to the DTC transaction manager.
  7. In the steps that follow, the DTC transaction manager connects to the resource manager.This does two things. It creates the connection used to send xa_prepare and xa_commit messages to the resource manager. It also ensures that the transaction manager can reconnect to the resource manager should recovery be necessary The transaction manager then records the information needed to reestablish the connection in its log file.
    • The DTC transaction manager calls LoadLibrary to load the ODBC driver DLL. It calls GetProcAddress to obtain the address of the GetXASwitch function. It calls GetXASwitch to obtain the address of the XASwitch data structure implemented by the ODBC driver.
    • The DTC transaction manager connects to the resource manager by calling xa_open using the DSN provided in the XARMCreate call.
    • The DTC transaction manager generates an RM GUID for each connection request it receives. The transaction manager writes a record to the DTCXATM.LOG file indicating that a new resource manager connection is being established. The log record contains the DSN name, the name of the ODBC driver DLL, and the RM GUID. The transaction manager uses this information to reconnect to the resource manager should recovery be necessary.
    • The transaction manager returns the RM GUID it generated to the MS DTC proxy.
  8. The MS DTC proxy calls the MS DTC Connection Manager to establish a connection to the transaction manager.
  9. The transaction manager creates a internal object that represents the connection between the resource manager and the transaction manager. The transaction manager then returns to the MS DTC proxy.
  10. The MS DTC proxy creates a resource manager object and returns an opaque pointer to that object as the RMCookie. This RMCookie represents the connection to the transaction manager.

Two-Pipe Resource Manager Enlistment

  1. The ODBC driver invokes the IDtcToXaMapper::TranslateTridToXid method to convert the OLE transaction identifier (TRID) to an XA transaction identifier (XID). It passes in the ITransaction pointer, the RMCookie, and a pointer to a pre-allocated XID structure.
  2. The MS DTC proxy generates an XID and returns it in the XID structure.
  3. The ODBC driver constructs an xa_start message containing the XID and sends it to the resource manager.
  4. The resource manager associates the connection with the XID and then replies to the xa_start message.
  5. The ODBC driver invokes the IDtcToXaMapper::EnlistResourceManager method. It passes in the RMCookie and a pointer to the transaction object, and a pointer to its ITransactionResourceAsync Interface.
  6. The MS DTC proxy informs the transaction manager that the ODBC driver wishes to enlist in the transaction.
  7. The ODBC driver returns from the SQLSetConnectAttr call.
  8. The application is then free to performs work using the enlisted resource manager connection.

Two-Pipe Resource Manager Commit Phase 1 - Prepare

  1. When ITransaction::Commit is called, the transaction manager initiates phase one of the two-phase commit process.
  2. The transaction manager determines which XA resource managers have enlisted in the transactions and sends an xa_prepare message to each one. These xa_prepare messages are sent in parallel.
  3. The XA resource manager prepares and then replies to the xa_prepare message.
  4. When all of the resource managers on the system complete phase one, the transaction manager writes a Prepared record to its log file. Phase one is now complete.

Two-Pipe Resource Manager Commit Phase 2 - Commit

  1. The transaction manager writes the transaction Commit record to the transaction manager log file.
  2. The transaction manager initiates phase two of the two-phase commit process. The transaction manager sends an xa_commit message to each enlisted XA resource manager. These xa_commit messages are sent in parallel.
  3. The resource manager commits and then replies to the xa_commit message.
  4. When all of the resource managers on the system complete phase two, the transaction manager writes a Forget record to its log file. If it chooses, the transaction manager can do a lazy log file write to economize on log I/Os. The transaction manager then forgets the transaction.


XA Recovery Process

There are two forms of recovery: cold recovery, and hot recovery:

  • Cold recovery is performed if the transaction manager process fails while a connection to an XA resource manager is open. When the transaction manager restarts, it reads the transaction manager log file and re-establishes the connection to the XA resource manager by calling xa_open. It then initiates XA recover by calling xa_recover.
  • Hot recovery is performed if the transaction manager remains up while the connection between the transaction manager and the XA resource manager fails because the XA resource manager or the network fails. After the failure, the transaction manager periodically calls xa_open to reconnect to the XA resource manager. When the connection is reestablished, the transaction manager initiates XA recover by calling xa_recover.


Mapping XA Interfaces

The following interfaces map between OLE Transactions and XA protocol when the XA is being used as the native protocol for distributed transactions:

  1. IDtcToXaMapper Interface
  2. IDtcToXaHelperFactory Interface
  3. IDtcToXaHelperSinglePipe Interface


Using XA Compliant Transaction Manager Applications

MS DTC lets OLE Transactions-compliant resource managers participate in transactions controlled by X/Open DTP XA-compliant transaction processing monitors such as Encina, TopEnd, and Tuxedo. The XA Mapper makes an OLE Transactions-compliant resource manager behave like an XA-compliant resource manager.

The XA Mapper facility can be used to perform distributed transactions that update OLE Transactions-compliant resource managers on Windows 2000 systems and other resource managers on other platforms. For example, an application can update an OLE Transactions-compliant resource manager on a Windows 2000 system and an XA-compliant database on a UNIX system.


Developing Caching Resource Managers

Phase Zero notification interfaces allow applications to detect when a transaction is ready to proceed with a two-phase commit (2PC) protocol, so that they can perform such operations and communicate to the Transaction Manager when they have been completed.

Certain distributed transaction applications require a mechanism by which they can learn that a transaction is ready to enter the prepare state of the 2PC protocol. For example, an application that participates in a transaction might possess data that has been modified, but not yet written to stable storage. If the application is not capable of providing the durability guarantees required by transactions (e.g. by acting as a resource manager and participating in 2PC and recovery), then it must ensure that it has flushed all modified data to a full-service resource manager before the 2PC protocol is initiated.

The Phase Zero (phase0) notification mechanism is provided by Phase0 Enlistment objects and Phase0 Notification objects. These objects implement the ITransactionPhase0EnlistmentAsync Interface and ITransactionPhase0NotifyAsync Interface, respectively. The former is implemented by the MS Distributed Transaction Coordinator (MS DTC) proxy while the latter is implemented by the application that needs to participate in Phase0 (Phase0 participant). Both interfaces are exchanged as sinks when a Phase0 Enlistment object is created.

The Phase0 notification mechanism introduces three new interfaces:

  1. ITransactionPhase0Factory Interface - exports a method to create a Phase0 Enlistment object in the MS DTC proxy and exchange.
  2. ITransactionPhase0EnlistmentAsync Interface - indicates the completion of all Phase0 processing, or that it is no longer interested in Phase0 notifications.
  3. ITransactionPhase0NotifyAsync Interface - notifies Phase0 participants of the Phase0 event.


Using MS DTC with other TIP Transaction Managers

This section introduces concepts for application developers building bridges and gateways between MS DTC and other Transaction Internet Protocol (TIP) compliant transaction managers. Such bridges and gateways are useful for providing solutions spanning heterogeneous transaction processing systems and component object systems.

Note In this section an application refers to any piece of code that has the ability to deal with transactions through either the OLE Transactions interfaces or any other transactional API.

In a transaction processing system or a component object system spanning a homogenous environment the TM-to-TM communication can take place using a proprietary protocol. But in a heterogeneous environment the TM-to-TM communication needs to occur using a well documented and standardized protocol (e.g. TIP, LU6.2). To that intent MS DTC supports the Transaction Internet Protocol (TIP): an Internet Engineering Task Force (IETF) proposed standard. This section describes additions to the OLE Transactions specification to allow applications like bridges and gateways to utilize OLE Transactions and MS DTC’s TIP support to coordinate transactions with other transaction managers supporting TIP.

For example, using Application A and Application B, application A is using TM-X as its transaction manager and Application B is using TM-Y as its transaction manager. Assuming that Application A has begun a transaction with TM-X. If Application A now wants to request some service from Application B and would like the request to be a part of the transaction that it started, then Application A will propagate the transaction to Application B and TM-Y using the TIP extensions to OLE Transactions. At commit time both the TMs will coordinate and all the work done by Application A and Application B will be committed as an atomic unit. More detailed examples are covered in the section titled "Usage Scenarios".


Background for TIP Extensions

Both OLE Transactions and TIP implicitly assume a two-pipe architecture, as shown below. In this architecture the messages describing the work flows on one pipe, the application-application pipe, and messages controlling the transaction flows on another pipe, the TM-TM pipe. The only exception to this rule is that a few of the transaction propagation messages flow on the application-application. These propagation messages are required to establish transaction context on every application that is going work on the transaction. OLE Transactions and TIP also require that the application establish this transaction context with the help of its TM. There are two models that can be used to establish transaction context on applications involved in the transaction. They are the push model and the pull model. The push model requires the following steps to flow the transaction context from Application A to Application B:

  1. Application A asks its TM, TM-X to propagate the transaction to Application B’s TM, TM-Y.
  2. Application A gets a handle from TM-X that identifies the transaction on TM-Y.
  3. Application A sends the handle from step 2 over to Application B.
  4. Application B asks TM-Y to establish transaction context for itself using the handle that it got in step 3.

In contrast the pull model requires the following step:

  1. Application A gets a handle for the transaction from TM-X. This handle identifies both the transaction and the network location of TM-X.
  2. Application A sends the handle from step 2 over to Application B.
  3. Using the handle from step 3, Application B asks TM-Y to propagate the transaction from TM identified in the handle i.e. TM-X. This step also establishes transaction context for Application B.


TIP Extensions to OLE Transactions

The new interfaces added to the OLE Transactions specification are: ITipTransaction Interface, ITipHelper Interface and ITipPullSink Interface. Objects in the transaction manager implement the ITipTransaction and the ITipHelper interfaces and objects in the application implement the ITipPullSink interface. Specifically, the transaction object in the transaction manager supports the ITipTransaction interface. The ITipTransaction interface provides methods to get a transaction’s TIP Transaction URL and to push a transaction from MS DTC to another TIP TM. The format of the TIP Transaction URL is as described in the TIP specification. The core TM object of the transaction manager supports the ITipHelper interface. The ITipHelper interface provides methods to pull transactions from a TIP TM to MS DTC and to query the MS DTC’s TIP TM URL. The format of TIP TM URL is as described in the TIP specification. If a version of MS DTC does not support TIP then calling QueryInterface for ITipTransaction and ITipHelper will fail with the error E_NOINTERFACE. The ITipPullSink interface is implemented by the application.


TIP Usage Scenarios

This section shows two different usage scenarios for the OLE Transactions TIP extension interfaces. Each scenario outlines the order of method calls and the message flows made to propagate transaction context using the new interfaces.

Scenario 1

In this scenario a client application is requesting work from a server application in the scope of a transaction. The client application is using MS DTC as its transaction manager and the server application is using a non-MS DTC TM that supports TIP. This layout is shown in Figure 3. Since the transaction can be propagated using either the pull model or the push model, this scenario has two cases. For each of these cases the steps to propagate the transaction and send the work request are listed next:

Case A – Propagation occurs using the push model

  1. The client begins a transaction T1 with TM-X using ITransactionDispenser::BeginTransaction.
  2. The client gets a pointer to the ITipTransaction interface on the transaction object by calling on ITransaction::QueryInterface(IID_ITipTransaction,…).
  3. The client asks the server for the TIP TM URL of TM-Y.
  4. The client calls on ITipTransaction::Push using the TIP TM URL it got from the server in step 3. This will cause TM-X to send a TIP "PUSH" command to TM-Y. TM-X will return a TIP Transaction URL to the client. The TIP Transaction URL is created by concatenating the TIP TM URL of TM-Y with the transaction identifier received in the "PUSHED" command from TM-Y to TM-X.
  5. The client sends the work request to the server. The TIP Transaction URL that the client received in step 4 is sent with the work request.
  6. The server then enlists the work on the transaction using the TIP Transaction URL. The details of how the server enlists on the transaction depend upon transaction API supported by TM-Y.

Case B – Propagation occurs using the pull model

  1. The client begins a transaction T1 with TM-X using ITransactionDispenser::BeginTransaction.
  2. The client gets a pointer to the ITipTransaction interface on the transaction object by calling on ITransaction::QueryInterface(IID_ITipTransaction,…).
  3. The client gets the TIP Transaction URL of transaction T1 by calling on ITipTransaction::GetTransactionUrl.
  4. The client sends the work request to the server. The TIP Transaction URL that the client received in step 3 is sent with the work request.
  5. The server then asks TM-Y to pull the transaction identified by the TIP Transaction URL accompanying the work request. This will cause TM-Y to send a TIP "PULL" command to TM-X.

Scenario 2

In this scenario a client application is requesting work from a server application in the scope of a transaction. The client application uses a non-MSDTC TM that supports TIP. The server application is using MS DTC as its transaction manager. This layout is shown in Figure 4. The TIP Transaction URL of transaction that is to scope the work is also sent with the work request. The steps required to create a transaction object and enlist on that transaction are listed below:

  1. The server receives a work request from the client. This work request contains a TIP Transaction URL that identifies the transaction that should scope the work.
  2. The server calls on the ITipHelper::Pull passing in the TIP Transaction URL that it got in step 5. If the TIP Transaction URL refers to a transaction on TM-X, TM-Y will send a TIP "PULL" command to TM-X if the transaction doesn’t already exist in its data structures. The server receives an ITransaction pointer to the transaction object created in TM-Y once the pull completes.
  3. The server calls on IResourceManager::Enlist to enlist on the transaction.

In addition to the above steps, if the client-server protocol uses the push model, the client will require the server to identify its TM using the TIP TM URL format. Using this TIP Transaction URL the client will push the transactions before work requests are sent to the server. The following steps describe how the server gets the TIP TM URL of its TM:

  1. The server receives a request from the client asking it to send the TIP TM URL of the server’s TM.
  2. The server gets a pointer to the ITipHelper interface on the core TM object.
  3. The server calls on ITipHelper::GetTLocalTmUrl to get the TIP TM URL for TM-Y.
  4. The server sends the TIP TM URL from step 3 back to the client.

Other TIP Details

In the scenarios mentioned previously, it is assumed that all TMs implement the Transaction Internet Protocol correctly and send the "IDENTIFY" command before beginning a conversation with their partner. Once the transaction propagation and work completes in the above scenarios, the client is likely to commit or abort the transaction. If the client decides to commit the transaction, the client’s TM will send a TIP "COMMIT" command to its partner and start the two-phase commit. If on the other hand the client decides to abort the transaction, then the client’s TM will send a TIP "ABORT" command to its partner to abort the transaction. Needless to say, in either case the TMs must do the regular processing to commit or abort the resources enlisted on the transaction.


The Compensating Resource Manager

The Compensating Resource Managers (CRM) feature of Component Services provides a quick and easy way to integrate application resources with Microsoft Distributed Transaction Coordinator (MS DTC) transactions. It is an alternative to developing a full Microsoft Transaction Services resource manager. By developing a pair of COM components and implementing specific interfaces, your application resources can vote on the outcome of the transaction, and can receive final notification of its outcome. A durable log is provided so that your application resources can write records that survive failures. Recovery on this log file is provided automatically by the CRM feature when the application restarts.

A CRM is provided as a pair of COM components – a CRM Worker and a CRM Compensator. The CRM Worker is responsible for doing the main work of the specific CRM and will implement a COM interface specific to the task it needs to perform. The CRM infrastructure provides an interface to the CRM Worker through which the CRM Worker can write records to a durable log file on disk. The CRM Worker must write records to the log and make them durable before it performs its work so that, if a crash occurs, recovery can occur correctly.

The CRM Compensator is the component that is created by the CRM infrastructure at the completion of the transaction. It implements a defined interface by which the CRM infrastructure can pass on notifications of transaction completion and the log records that were previously written by the CRM Worker.


Using a CRM

The information in this section is intended for users of CRM components. This section includes:

  • Installing CRM Components
  • Start Up and Recovery


Installing CRM Components

CRM components can be installed either into a COM+ Server application or a COM+ Library application. However, they must always run in a COM+ server application. If they are installed in a COM+ Library application they are not available for use in client processes.

The difference to installing the CRM components in a library or server application is that if they are installed in a library application they are available to more than one server application. If installed in a specific server application then they are available only to that specific server application.

To enable use of a CRM in a server application

  1. From Component Services, under the server application properties page, click the Advanced tab.
  2. Click the Enable Compensating Resource Managers option for that server application. If this option is not clicked, then attempts to use a CRM within this server application will fail.

If installed in a library application, it is not necessary to click the Enable Compensating Resource Managers option for that library application, but this option must be clicked for the server application in which the CRM is intended to run.

It is recommended that the CRM Worker and CRM Compensator components for a specific CRM be installed in the same application.

The recommended settings for CRM components are as follows:

  • CRM Worker – transaction = required, sync = yes, JIT = yes, threading model = Both (or Apartment)
  • CRM Compensator – transaction = disabled, sync = disabled, JIT = no, threading model = Both (or Apartment)

Note Components that use the CRM must explicitly specify a threading model when they are registered. The default, 'Main Thread Apartment,' is not supported.

The only two threading models supported are "Apartment" and "Both."


Start Up and Recovery

If a server application has the Enable Compensating Resource Managers option clicked, then the first time it starts up it will create a CRM log file to be used by all CRMs in that server application process.

The name of the CRM log file created for the server application will be based on the AppId (a GUID) of the server application, and the CRM log file will be placed in the same directory as the DTC log file (normally your %SystemRoot%\winnt\system32\DtcLog directory). CRM log files have the extension "crmlog".

It is possible that the CRM log file could contain sensitive information that must be secured. For this reason, if the server application is running under any identity other than "Interactive User" when the CRM log file is first created, the CRM log file will be secured for that user only. This feature is only available on the NTFS file system. If the identity of the server application is subsequently changed, then the security information for the CRM log file is not automatically changed. It can be changed manually using existing Windows 2000 administration tools. The alternative is to simply delete the CRM log file when it is in a clean state (which is expected after a controlled shutdown of the server application).

When a server application (that is CRM-enabled) starts up and finds that a CRM log file already exists for that server application, it performs recovery on that CRM log file. Recovery involves reading the CRM log file for any transactions that were not fully completed and passing the log records associated with those transactions on to the correct CRM Compensators.

CRM components can be deployed in exactly the same way as any other components within the limitations noted above.

Starting of a CRM server application for recovery is not automatically initiated. Some external action must be taken to start the CRM server application where recovery is required. Typically this would be creating a component in that server application.


Developing a CRM

The information in this topic is intended for developers of CRM components. This topic discusses the following subsections:

  • Normal Operation
  • Recovery
  • Error Handling
  • Advanced CRM Topics


Normal Operation in the CRM

In normal operation, an application component running in a server application process would use a CRM by creating a CRM Worker. The CRM Worker implements a COM interface specific to the task it is designed to perform. The application component must be running under a transaction so that the CRM Worker inherits the transaction of the application component. CRM Workers always require a transaction.

To access the CRM features, the CRM Worker first obtains ICrmLogControl Interface. This is the interface that allows the CRM Worker to write records to the durable log. The CRM Worker obtains this interface by creating a CRM Clerk component.

The first thing the CRM Worker must do is to tell the CRM Clerk the name of the CRM Compensator it wants to use. It does this by calling a method on ICrmLogControl called RegisterCompensator. After this method is called, the CRM Compensator will be created by the CRM infrastructure once the transaction completes.

After the CRM Worker has registered its CRM Compensator, it can write records to the CRM log using ICrmLogControl. The CRM Worker must perform "write ahead." That is, it must write a record to the log describing the action before it actually performs the action. In case a crash occurs immediately after completing the action. If no log records had been written, then there would be no possibility of correcting for the action. Note also that write ahead means that the CRM Compensator, which is the component that receives the log records on recovery, must deal with the case where the log records were written but the action did not in fact occur. Actions by the CRM Compensator must be idempotent, that is, they should be capable of being performed more than once but should lead to the same outcome. For example, setting an account balance to the value of $100 is an idempotent action; adding $100 to the account balance is not.

The ICrmLogControl interface provides two methods for writing log records. WriteLogRecordVariants is a method for writing a structured log record that is built up as a collection of variants. It is primarily for use when developing CRMs in Microsoft Visual Basic (VB). WriteLogRecord is a method for writing an unstructured log record as BLOBs of bytes. It is primarily for use when developing CRMs in Microsoft Visual C++. Because record structures in C are often made up of a set of headers and fields in the record that may be scattered in memory, the WriteLogRecord method implements a gather capability that will reduce the copying of data. Note, however, that you should not user pointer types within data structures in a log record. Pointers will no longer be valid during recovery phase, as in this case the CRM Compensator runs in a different process than that of the CRM Worker that wrote the log record. Including pointer types in a log record may cause an application to crash or corrupt itself during recovery.

Both of these write methods will write a log record to disk, but they do not guarantee their durability. A ForceLog method is provided that will guarantee that all writes done by this CRM are durable on disk. This is important for failure recovery, but allowing lazy writes to accumulate before forcing to disk can also improve performance.

When the CRM Worker is done with its actions and has finished writing and forcing records to the log, it must release ICrmLogControl. When the transaction completes (typically due to the application component calling SetComplete or SetAbort) the CRM infrastructure will create the CRM Compensator. The CRM Compensator is a component that implements either the ICrmCompensator Interface, or the ICrmCompensatorVariants Interface. These interfaces are used to pass the unstructured (Visual C++) or structured (VB) records to the CRM Compensator along with the transaction outcome notifications. The CRM Compensator is first notified of the prepare phase of the transaction completion, and can vote either yes or not to the prepare request. If the CRM Compensator votes no, then it will not receive any further abort notifications. If it votes yes to the prepare request, then the CRM Compensator will receive either the commit or abort notifications. Note that in the case of a client abort, no prepare notifications will be received, only abort notifications. The CRM Compensator must be prepared to handle all these cases, and in addition, it must handle the case where no log records were successfully written by the CRM Worker. The CRM Compensator must not assume that the same CRM Compensator instance will receive both the phase 1 (prepare) and phase 2 (commit or abort) notifications, as these could be interrupted by recovery.

Typically a CRM Compensator uses the abort notification to reverse the action that was performed by the CRM Worker. The CRM Worker might leave some state available in case it needs to reverse its action. That state might be fully contained in the log records, or it might not be, in which case the CRM Compensator needs to clean up that state if the transaction commits. This is the reason why the CRM Compensator receives the commit notification. Note that the CRM Compensator does not run under a MS DTC transaction.

The CRM Compensator can log new records if required using ICrmLogControl which it receives as it is created. Both the CRM Worker and CRM Compensator can also forget the last log record they wrote if required. This might be required to avoid unnecessary recovery.


Recovery in the CRM

Recovery is the process of completing any transactions that were interrupted by a failure. Recovery is performed when a server application starts up. If the server application has the CRM enabled, and if it finds a CRM log file for that server application, it performs recovery on that CRM log file.

During recovery, the CRM infrastructure will read the CRM log file and determine whether any transactions did not fully complete. If it finds any, it will first contact the DTC to determine the transaction outcome. It will then create the CRM Compensator and pass on the commit or abort notifications as required, together with the associated log records. Note that prepare notifications will not be received by the CRM Compensator during recovery. The CRM Compensator has a flag to distinguish whether it is being called during normal operation or during recovery.

Recovery will normally only find uncompleted transactions if the server application has been shutdown abnormally, either due to a server application process crash or a machine crash. If the server application is allowed to shutdown normally, either due to the idle timeout or manual shutdown via Component Services administrative tool, then the log file will be clean.


Error Handling in the CRM

COM+ server applications implement a fail fast policy. If a serious internal error is detected, then the server application process will exit and write an error message to the Windows Event Log. This allows quick detection of problems and is possible due to the protection of application data by transactions. Always check the Windows 2000 event log for any errors from the CRM, either during development or final deployment.

Basic errors in using the CRM interfaces, such as invalid arguments or sequence errors (for example, trying to write a log record before registering the compensator) will return error codes, and should not cause fail fast. These error codes are documented in the section on CRM Interfaces. In addition, for CRM development, the VTRACE1 registry key may be set (see section on Registry Settings) which causes an informational message about the specific error cause to appear in the debugger output window.

Transient errors can also occur. These are errors that are caused by timing conditions, and will result in an error code being returned. The most common cause of these is the transaction completing earlier than expected. The CRM developer should ensure that these error conditions are handled. For example, while writing a log record the transaction could, at that point, have been aborted due to a timeout. The method call will return an error indicating that the transaction has completed.


Advanced CRM Topics

This section includes the following advanced topics:

  • Registry Settings
  • CRM Log Files
  • Monitoring
  • Isolation
  • Object Pooling
  • Clusters


Registry Settings

There are several registry settings available to modify CRM behavior to assist with troubleshooting and development. This section of the document lists the registry settings and what they do. All of these registry settings are optional; none are required for normal operation of the CRM.

All CRM registry settings are under:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\COM3\CRM

Create the CRM key under the COM3 key if it is not already there.

VTRACE1
DWORD value. Setting this value to anything other than zero enables debug trace messages on warnings or errors. This can help with development of your CRM. These messages can be seen in the debugger output window. This value should only be set for development and not during normal deployment. This value is read when a CRM server application starts up and applies to all such server applications (not just a specific server application).
IgnoreCompensatorErrors
DWORD value. Setting this value to anything other than zero allows the CRM infrastructure to ignore all errors returned from CRM Compensators. If recovery is failing due to an error from a CRM Compensator, setting this value will allow recovery to be completed. This value is read when a CRM server application starts up and applies to all such server applications (not just a specific server application).
CheckpointIntervalInSec
DWORD value. This is the checkpoint interval in seconds. The default checkpoint interval is 30 seconds. Checkpoints are used to reclaim space from the CRM log file. Increasing the checkpoint interval can perhaps increase performance at the expense of increased recovery time and a larger CRM log file. This value is read when a CRM server application starts up and applies to all such server applications (not just a specific server application).
InitialLogFileSizeInKB
DWORD value. This is the initial CRM log file size in KB. The default CRM log file size is 1 MB (1024 KB). The CRM log file will automatically extend to meet the transaction load imposed upon it, but if heavy loads are anticipated then it might be necessary to increase this value. This value is read when a CRM enabled COM+ server application starts up and applies to all such server applications (not just a specific server application). However, if the CRM log file already exists for a CRM server application then this value is ignored for that server application.
RecoveryTraceEnabled
DWORD value. Setting this value to anything other than zero will enable a recovery trace. The recovery trace is a text file that has the same name as the CRM log file and the following additional extension:
recoverytrace.txt.

This file is located in the same directory as the CRM log file. The recovery trace provides a trace of the CRMs activity during recovery, which can be used for problem diagnosis. This value is read when a CRM enabled COM+ server application starts up and applies to all such server applications (not just a specific server application). However, a unique recovery trace file is produced for each CRM server application.


CRM Log Files

The location of the CRM log files can be changed using the COM+ administration SDK. The property name is CRMLogFile and it exists on the Application object. For more information, see the COM+ admin SDK documentation for details.

It may be necessary to change the default location of a CRM log file due to performance reasons (to have the MSDTC log file on a different disk than the CRM log file) or perhaps due to use of the CRM in a cluster environment.


Monitoring

The CRM infrastructure provides a set of interfaces that can be used for monitoring the CRMs within a particular server application. To access the monitoring interfaces, a component running within the server application must first create a specialized CRM Clerk called the CRM Recovery Clerk. Using the ICrmMonitor Interface, a snapshot can be obtained of the current set of active CRM Clerks within the server application. From this, a particular CRM Clerk of interest can be located and queried, including the current state of its transaction and the log records written by the CRM.

Optionally, a CRM Compensator can implement ICrmFormat, which defines a way to format CRM log records into a viewable format, for display by monitoring applications.


Isolation

CRMs provide atomicity with transactional notifications, and durability with the CRM log, but they do not provide isolation of resources. In a multi-threaded environment, it is the responsibility of the CRM developer to ensure that access to resources, either by multiple CRM Workers or external applications, is serialized while in a transaction. Also note that once the transaction has passed the prepare phase, the CRM Compensator and CRM Workers can be running concurrently. It is possible for the CRM Worker component of a new transaction to become active while the CRM Compensator of a previous transaction is still processing the previous transaction.

During failures prior to recovery of the CRM server application, an interrupted transaction should be considered active and not complete. It should not be possible for external processes to access the resources that were being changed by this particular transaction prior to recovery of the CRM server process.


Object Pooling

CRM Workers and CRM Compensators can use the new object pooling feature of COM+ if required within the limitations given in the section Installing CRM Components.


Clusters

When developing CRMs to work in cluster environments the main factor to consider is whether the specific CRM cares which node of the cluster it is operating on. For example, if the resource managed by the CRM is the machine file system or registry, any changes will be specific to the node that the CRM server application is running on at the time. In this case, failover of the CRM server application to another node would not be desirable. The other case is where the CRM is managing some resource common to the cluster. In this case, failover of the CRM server application to another node is useful.

The default directory location for CRM log files is the same directory as the DTC log file. On clusters, the DTC log file is placed on a shared disk that is failed over between the nodes of the cluster. This means that the default behavior for CRM server applications is to failover between nodes of the cluster. If a specific CRM requires the alternative behavior of not failing over between nodes, then the location of the CRM log file for that particular CRM server application should be changed.

In addition, if fail over is required for the CRM application, it should be configured as a Generic Application in a cluster group. Its dependency should be MS DTC.


Troubleshooting the CRM

This section lists the most common problems encountered when developing and using the CRM. Please refer to this section before calling support:

  • Event log messages - As noted previously, if the CRM server application encounters a serious internal error it will failfast (terminate the CRM server application process) and write a message to the Windows 2000 event log. Please refer to the Windows 2000 event log if any problems are encountered.
  • Exceptions from the CRM Compensator - The CRM infrastructure creates the CRM Compensator and passes it the transaction outcome notifications and the log records written by the CRM Worker. If the CRM Compensator returns an error or throws an exception, it will be caught by the CRM infrastructure and will cause a failfast. A message will be seen in the Windows 2000 event log indicating that an exception was received from the CRM Compensator. It is possible to force these exceptions to be ignored (see the section Registry Settings). Exceptions from the CRM Compensator most likely mean a problem in the specific CRM Compensator component and not in the CRM infrastructure itself.
  • Recovery trace - The recovery trace can be very useful to determine problems during recovery. For more information, see the section Registry Settings.
  • Trying to run with the CRM not enabled - It is not sufficient to place the CRM Worker and CRM Compensator components into the COM+ server application. Support for CRMs must be specifically enabled for the specific COM+ server application using the "Enable Compensating Resource Managers" option (see the section on Installing CRM Components). If an attempt is made to use a CRM inside a server application that does not have the CRM enabled, then an error code will be returned to the CRM Worker.
  • Trying to run CRMs in client processes - CRMs will not run in client processes, they must run in a COM+ server application process. CRM components may be placed in a library package for use by multiple COM+ server applications, but they are not available for use within client processes. Attempting to use the CRM interfaces inside a client process will return an error code to the CRM Worker.
  • Recovery in progress - Recovery starts when a CRM server application starts. However, recovery occurs in the background to the normal processing of the CRM server application. The CRM Worker may be created prior to recovery being completed. CRMs cannot be used in a CRM server application process until recovery has been successfully completed. In this case, the CRM Worker will receive a "recovery in progress" error code as it tries to register the CRM Compensator. The CRM Worker should poll or otherwise delay until recovery has been completed. Note that the time taken for recovery is very specific to a particular type of CRM, and this should be considered when designing the CRM. Long duration recoveries are not desirable.
  • Security on the CRM log file - If access to the CRM log file is denied, please review the Start Up and Recovery section for a description of how security is set on the CRM log file.
  • In doubt transactions - In rare cases, a DTC transaction might go into the "in-doubt" state, that is, DTC cannot determine the transaction outcome. For these cases, during recovery, the CRM will maintain the log records for that transaction in the CRM log file. Once the in-doubt transaction has been resolved by DTC, performing another CRM recovery will complete the transaction.
  • Create and Release of CRM Compensator - The first time a particular CRM Compensator is registered by a CRM Worker, it is created by the CRM infrastructure and queried to see which of the CRM Compensator interfaces it supports. It is then immediately released. CRM Compensators will need to support this behavior, of being created and released without having had any intervening method calls. If the CRM Compensator cannot be created correctly, perhaps due to incorrect COM registration, or if it does not support the at least one of the correct CRM Compensator interfaces, an error code will be returned to the CRM Worker.


Design Suggestions

Here are some suggested steps for developing a CRM -

  1. Before starting development, set the transaction timeout to zero (using the Component Services administrative tool). Set the VTRACE1 registry flag (see the section Registry Settings) to see CRM warning and error messages on the debug trace.
  2. Determine which set of interfaces will be used, structured (variants) or non-structured (see the section CRM Interfaces). This will depend on the tool with which you develop your CRM, C++, VB or Java.
  3. Develop the CRM Worker first. Determine the information that will be required in the log records. Define the types of log records required and their format.
  4. A debug CRM Compensator is provided as part of the CRM samples (on the Platform SDK). This can be used temporarily when debugging the CRM Worker in place of the real CRM Compensator.
  5. When the CRM Worker is working correctly, develop the real CRM Compensator and replace the debug CRM compensator with the real CRM Compensator.
  6. It may be desirable to initially not test the recovery case. If so, delete the CRM log file for the CRM server application each time before starting that CRM server application.

Points to Consider

  1. Write ahead - The CRM Worker component must write ahead, that is, it must write a log record indicating it is going to perform an action before actually performing that action. In addition, this log record must be forced to disk after the write and before the action is performed.
  2. Isolation - The CRM does not enforce isolation. The CRM design must provide isolation between multiple clients on separate transactions, and must also consider the case prior to recovery.
  3. Recovery in progress - The CRM Worker must handle the "recovery in progress" error code. See the section Recovery in the CRM.
  4. Error handling -The CRM Worker must cope with the case where the transaction is aborted earlier than expected. See the section Error Handling in the CRM.
  5. Recovery time - The CRM Compensator should be designed to perform recovery quickly so that new work for that CRM server application does not have to wait.
  6. Idempotence - It is possible that a CRM Compensator might receive the same log record again, to undo or redo the an action that has already been undone or redone. Actions that the CRM Compensator might perform must be idempotent, which often means that the error codes returned from these actions should be ignored.
  7. Initiation of recovery - Recovery of a CRM server application is perfomed when that CRM server application starts up. However, there is no automatic start up of a CRM server application. The application developer should consider how start up, and hence recovery, will be initiated.


CRM Interfaces

The following are CRM interfaces:

  • ICrmLogControl Interface
  • ICrmCompensator Interface
  • ICrmCompensatorVariants Interface
  • ICrmMonitor Interface
  • ICrmMonitorClerks Interface
  • ICrmMonitorLogRecords Interface
  • ICrmFormatLogRecords

The CRM interfaces are required to provide support for CRM Workers and CRM Compensators developed using VB, VJ and VC. Compatibility with VJ requires that all interface types be automation compatible. In addition, it is easier for components written with VB to build up a log record as a collection of variants. Another issue is that VB components will be Apartment threaded, which implies that it must be possible to marshal the interfaces from the MTA to an STA. CRM components developed with VC or VJ could also be Apartment threaded, although it would be recommended that these were Both threaded.

The CRM defines 3 interface types for the basic CRM functions:

  1. ICrmLogControl is implemented on the CRM clerk and is used by the CRM Worker to write log records to the log. It can also used by the CRM Compensator.
  2. ICrmCompensator Interface and ICrmCompensatorVariants Interface are implemented on the CRM Compensator. Normally the CRM Compensator would implement only one of these interfaces, depending on whether it required unstructured or structured log records (respectively). Structured log records are those that are built up as a collection of variants, and are typically for use by VB. Unstructured log records are just a buffer of bytes and are typically for use by VC or VJ. These interfaces are used to deliver transaction outcome notifications and their associated log records to the CRM Compensator.

    A CRM Compensator can implement both of the compensator interfaces; however, only one will be used at a time to deliver log records.

  3. Monitoring Interfaces


Monitoring Interfaces

There are 3 monitoring interfaces:

  1. ICrmMonitor Interface
  2. ICrmMonitorClerks interface
  3. ICrmMonitorLogRecords Interface

In addition, an ICrmFormat interface is defined which the CRM Compensator can optionally implement to format its log records into a viewable format.


Using the Monitoring Interfaces

The monitoring interfaces are intended to be used by monitoring tools as follows. In normal use of CRMs, transactions are expected to short lived, and hence CRM Workers and CRM Compensators exist for a brief period of time, typically of the order of a few seconds at most. The monitoring interfaces are therefore designed to give a snapshot of the state of the executing CRMs at a particular point in time. If any of the CRMs are giving problems, then the monitoring interfaces can be used to zero in on the troublesome CRM, to inspect its log records and to abort its transaction if required.

A monitoring tool would initially get the ICrmMonitor Interface, implemented by the CRM recovery clerk (a singleton). It would use this interface to get a snapshot of the current state of the CRM clerks by calling the method ICrmMonitor::GetClerks. This returns a clerks collection object which implements the ICrmMonitorClerks Interface. This clerks collection object can be browsed for information about the state of the clerks at the moment it was obtained. This information includes the number of clerks, the ProgId of the CRM Compensator used by the clerk, the description provided at the time the CRM Compensator was registered (via ICrmLogControl::RegisterCompensator), the transaction Unit Of Work (UOW) id, and the activity id. Individual clerks are also uniquely identified by a "clerk instance CLSID". Note that this is not a COM CLSID in the usual sense of the term, but simply a unique GUID that identifies this particular clerk for its lifetime.

Once the monitoring tool has determined which clerk is of interest, it calls ICrmMonitor::HoldClerk to get an ICrmMonitorLogRecords Interface on that particular clerk. Note that at this point the monitoring tool is holding a reference to that clerk, and if the transaction completes the clerk will remain held in memory and will not be released until the monitoring tool is done. The ICrmMonitorLogRecords Interface can be used to query the current state of the transaction, to find out how many log records this CRM clerk has written, and to get the actual log record data.

The ICrmFormat interface is an optional interface which can be implemented by a CRM Compensator. The log records are provided from the ICrmMonitorLogRecords interface in the same format that they were originally written (using ICrmLogControl). ICrmFormat can be used to convert the log records to viewable format so they can be presented using a generic monitoring tool.

In addition, because the ICrmMonitorLogRecords interface is implemented directly on the CRM clerk, you can QueryInterface for ICrmLogControl (also implemented on the CRM clerk). This can then be used to directly abort the transaction if required (ICrmLogControl::ForceTransactionToAbort).


Resource Dispensers

Resource dispensers are part of the COM+ programming model. Application components use resource dispensers to access shared information.

A resource dispenser can be any component that is compatible with COM+ in a standard way, regardless of the interface that it presents to the user.

The COM+ programming model includes declarative transactions, which protect the work performed by an application object during its lifetime. When an application object uses resource dispensers, the work it performs is automatically transactional; that is, the component doesn't have to explicitly declare transactions. These transactions are defined in the OLE Transactions specification, implemented by the Microsoft Distributed Transaction Coordinator (MS DTC), and initiated on behalf of the application object by COM+. See the Microsoft Distributed Transaction Coordinator for more information.

At runtime, dynamic pools of resources are made available to resource dispensers, such as database connections, network connections, connections to queues, threads, objects, and memory blocks. The application process achieves high performance by using a minimum number of frequently used resources.

Resource dispensers are managed by the Resource Dispenser Manager (DispMan). DispMan provides resource pooling for the resource dispensers and ensures that a resource supplied by a resource dispenser is correctly enlisted in the application object's transaction. DispMan automatically reclaims resources that are still reserved at the end of an object's lifetime, eliminating the possibility of resource "leaks."

DispMan uses the Inventory Statistics Manager to manage pool resource inventory levels. DispMan can request a resource dispenser to create a new resource, or to destroy idle resources when necessary to adjust for inventory levels, rather than using static settings.

A resource dispenser can also function independently of COM+, providing only resource pooling capabilities. When COM+ is present, it can automate transactions and reclamation.


Resources

A resource is anything a resource dispenser creates. For example, a connection to a resource manager is a common resource.

Resources reside in the resource dispenser's memory; they are never copied to DispMan. A resource is known only by an opaque handle (RESID). Resources may or may not be capable of performing transactions.


Dispenser Manager (DispMan)

DispMan is the controlling executive that manages the loading and unloading of resource dispensers, interfaces with COM+ for context, and it controls the Inventory Statistics Manager.

DispMan polls each Holder every 10 seconds to allow them to readjust their resource inventory. Each holder calls the Inventory Statistics Manager to suggest inventory levels for each type of resource. As a result, the holder may ask the resource dispenser to either create or destroy some inventory.


Holder

A holder is a component created by DispMan that lists the resource inventory for each resource dispenser.

The holder and resource dispenser communicate to request resources of a particular type. The follow relationships exist between the holder and resource dispenser:

  • The holder requests a resources from the resource dispenser. The resource dispenser either returns an available resource or creates a new one.
  • The holder notifies the resource dispenser that an application no longer needs a resource and returns it to the resource pool.
  • The holder and the resource dispenser maintain the size of the resource pool.


Resource Dispenser Requirements

A resource dispenser is a dynamic-link library (DLL) component which provides two interfaces. The first (IDispenserDriver Interface) provides the holder with basic information on how to create, destroy, and enlist its own type of resources. The second is exposed to the application and can be either a COM interface or set of interfaces, or an application programming interface (API) to which a component is linked via an import library.

Resource dispensers manage nondurable shared state within a process. Although the resources managed may often be connections to a component managing a durable state, the connections themselves are not durable. A resource dispenser will often use a related resource manager to retain the durable state.

An application can call any resource dispenser, which in turn may offer any API to the application. A resource dispenser is instantiated when an application component refers to it. On startup, a resource dispenser must register itself with Dispenser Manager (DispMan).

A transactional resource dispenser must enlist in an MS DTC transaction. This implies use of either an internal or external (to the dispenser) resource manager that is OLE Transactions-compliant.


Implementing a Resource Dispenser as a COM Component

Resource dispenser interfaces exposed to the application are not required to be COM interfaces. This allows DispMan to be used in a process without initializing COM, for example, to support the ODBC Resource Dispenser.

A resource dispenser maybe implemented as a COM component. If a resource dispenser exposes an API (like ODBC), then the resource dispenser might only be a DLL accessed by the application via an import library (or using LoadLibrary and GetProcAddress). A resource dispenser may also be a COM component which an application accesses by calling CoCreateInstance. If the resource dispenser is an Automation component, then the resource dispenser may be accessed from Microsoft Visual Basic®.


Threading Issues

Calls into a resource dispenser may originate in one of the following threads:

  • Apartment thread (STA)
  • Free thread (MTA)
  • Non-COM thread (application or DispMan's garbage-collector thread)

If a resource dispenser is not a COM object, then it must be able to handle calls arriving from any thread at any time. If a resource dispenser is a COM object, then the COM object should be registered with a Threading Model of Both. This allows STA or MTA threads to create and use the resource dispenser without a thread switch.

If a resource dispenser creates and uses another COM object (for example, an out-of-process resource manager) then the resource dispenser may need to maintain multiple proxies to this other COM object, and ensure that calls to this other COM object are made using the appropriate proxy for the calling thread. When the resource dispenser creates this object, it marshals and saves the reference. Before calling the object again, it must unmarshal to create a proxy for the calling thread.

It may be more efficient to cache these per-thread proxies by keeping a map from the ThreadId to a proxy pointer. This map will continue to expand as new threads are used in the process.


Inventory Statistics Manager

The current implementation of the Inventory Statistics Manager is very simple. Resources are removed from inventory when they have not been used for x seconds, where x is set per resource when the resource is created.

This may be extended in the future so that more involved statistics will be gathered and used to make better inventory-level decisions.


Resource Pooling

At any one time, a resource is either in use or not in use, and is either enlisted or not enlisted in a transaction. This yields four possible resource states.


Resources in Unenlisted Inventory

A resource which is not in use by a object and not enlisted in a transaction is in unenlisted inventory. A resource in general inventory is available for assignment.


Resources in Enlisted Inventory

A resource which is not in use by a object but is enlisted in a transaction is in enlisted inventory. Such a resource is available for assignment only to objects running in the same transaction. A resource moves from enlisted inventory to unenlisted inventory when COM+ notifies DispMan that the transaction is complete.


Resources In Unenlisted Use

If a resource is assigned to a object, and the instance is not running in a transaction, or the resource dispenser has identified the resource as not transactional, then this resource is in unenlisted use.


Resources In Enlisted Use

If a resource is assigned to a object, the instance is running in a transaction, and the resource dispenser has successfully enlisted the resource in the transaction, then this resource is in enlisted use.


Allocating Resources

Each time a resource dispenser allocates a resource from its holder, the following occurs:

  1. The resource dispenser declares a resource type identifier (RESTYPID), which describes the type of resource required.
  2. The resource dispenser calls the holder's IHolder::AllocResource method passing this RESTYPID.
  3. The holder generates a candidate list from the available resources. Candidates are resources which are either not enlisted in a transaction, or already enlisted in the calling object's transaction.
  4. These candidates are individually passed to the resource dispenser's IDispenserDriver::RateResource method where they are rated (on a scale of 0 to 100) by how well the candidate resource matches the desired RESTYPID.
  5. The holder chooses the resource which the resource dispenser rates as highest.
  6. The resource dispenser can terminate the rating loop early by assigning the candidate a resource rating of 100 (a perfect fit). A rating of 100 would normally be reserved for candidate resources that are already properly enlisted, unless the resource dispenser concludes that enlistment is an inexpensive operation. If all candidate resources (if any) are rated 0 (unusable) then a new resource will be created by calling IDispenserDriver::CreateResource.
  7. If the resource chosen previously is not already enlisted in the calling object's transaction, then the resource dispenser's IDispenserDriver::EnlistResource interface is called.
  8. The AllocResource method call returns to the resource dispenser with the enlisted resource.


Enlisting In a Transaction

After a resource is allocated, but just before returning the resource to the resource dispenser, DispMan checks with COM+ to see if the calling object is running within a transaction. If the calling object is running within a transaction, then DispMan calls back to the resource dispenser and asks it to enlist the resource in the transaction. Then the resource is returned to the resource dispenser, which then returns it to the calling instance.

The resource dispenser must be able to enlist in an OLE Transactions transaction with the Microsoft Distributed Transaction Coordinator (MS DTC).

Transaction enlistment is optional when a resource dispenser dispenses non-transactional resources, such as memory or threads.

COM+ notifies DispMan when a transaction is complete, whether it committed or aborted. Then DispMan notifies each resource dispenser's holder that any resources enlisted in this transaction can now be moved to general inventory.


Automatically Reclaiming Resources

COM+ notifies DispMan each time an object's lifetime ends. DispMan then notifies each registered resource dispenser's holder to verify if it has any resources still held by this instance. If so, the resource is freed, thus preventing the possibility of resource leaks by components that get resources through a resource dispenser.

The auto-reclamation feature is an option that is turned off by default. A resource dispenser can choose to enable this option and, in doing so, guarantees that a reference to any resource dispensed to an object will never be passed out of the object.


Tracking Resources

DispMan can track a resource which is not inventoried, based on knowledge of the object's lifetime. When a tracked (as opposed to allocated) resource is freed, it is destroyed and therefore not returned to inventory. This mode is useful for resources which are inexpensive to create and destroy rather than storing them in inventory, for a memory dispenser, or for a resource which is difficult to inventory because there are too many different types. In this case, a dispenser directly creates a resource instead of asking DispMan to allocate one from inventory. Before returning this resource to the requesting application component, the resource dispenser tells DispMan to track the resource. This ensures that even if the component neglects to free the resource, DispMan will do so when the component's lifetime is over.


Destroying Inactive Resources

Upon resource creation (IDispenserDriver::CreateResource), the resource dispenser may specify a destruction timeout. This is interval of time that an idle resource is allowed to remain in the pool before it's destroyed. A thread that runs in DispMan is always looking for these idle resources.


Non-Transactional Resources

Resources need not be transactional. A resource dispenser which pools non-transactional resources can still achieve high performance by allowing application objects to access a shared pool of these resources. This type of resource dispenser returns S_FALSE from the IDispenserDriver::EnlistResource method, which means that the resource dispenser did not enlist the resource because the resource is not transactional.


Operating without COM+

A resource dispenser can operate with or without COM+. The DispMan will operate with or without COM+ in the process. Without COM+, resource pooling still provides a performance benefit. Without COM+ a resource dispenser's IDispenserDriver::EnlistResource method will never be called, because DispMan has no knowledge of the current component transaction.


Resource Dispenser Startup and Shutdown

When a resource dispenser's DLL loads, it must register itself immediately (before user calls) with DispMan. The resource dispenser first calls the GetDispenserManager Function and then calls the IDispenserManager::RegisterDispenser method, passing the IDispenserDriver pointer that the resource dispenser implements. This call returns a reference to Iholder Interface. To shut down, a resource dispenser calls IHolder::Close.

In order to ensure a clean package shutdown, a resource dispenser must be able to handle the situation when calls continue to arrive from business objects after COM+ has asked the dispenser to shut down.


Implementing a Resource Dispenser

The following steps outline a general procedure for implementing a resource dispenser:

  1. Decide on RESTYPID format which categorizes how your resources differ from each other.
  2. Use the Mtxdm.h and mtxdm.lib header file and library, respectively.
  3. Build a DLL which implements the IDispenserDriver Interface and the API you expose to applications.
  4. In the startup (DllMain or first call to the dispenser API), call GetDispenserManager Function. This returns a pointer to the DispMan's IDispenserManager Interface.
  5. Call IDispenserManager::RegisterDispenser, passing a pointer to your implementation of IDispenserDriver. This will cause DispMan to create a holder (pooling manager) for your resource dispenser and then return the pointer to your Iholder Interface.
  6. Store this pointer in order to call Iholder::AllocResource and Iholder::FreeResource.
  7. You can now (in response to calls to your API) make calls to AllocResource and FreeResource. AllocResource will initially respond by calling back to your CreateResource method, but later AllocResource calls will be serviced from the growing pool of resources.

For more information, see the TxFileDisp sample.


Types

The following types are used in the interfaces:

  • RESTYPID
  • RESID
  • SRESID
  • TRANSID
  • TIMEINSECS


RESTYPID

RESTYPID is a DWORD which identifies a type of resource, not a particular resource. A RESTYPID will most likely be a pointer to a structure in the dispenser's memory which describes the resource type. DispMan does not understand (and does not need to understand) this structure within the resource dispenser's memory. DispMan only uses RESTYPID to refer to a resource type within a resource dispenser.


RESID

RESID is a DWORD which identifies a particular resource, as opposed to a type of resource. A RESID will most likely be a (void *) which points to a structure in the resource dispenser's memory which represents the resource. DispMan does not need to understand this structure within the resource dispenser's memory. DispMan uses RESID to refer to a particular resource within a resource dispenser.


SRESID

A Unicode string version of RESID, used in the Iholder::TrackResourceS and Iholder::UntrackResourceS methods. Strings are sometimes useful when only a small amount of information needs to be recorded about a resource, and the entire description of the resource can be contained in the SRESID. In particular, using the SRESID can sometimes eliminate the need for a map in the resource dispenser when the resource represents a relationship between two (or more) things.


TRANSID

Identifies a transaction. This may be cast to the ITransaction Interface.


TIMEINSECS

Used to indicate how long a resource can be inactive before it is destroyed.


COM+ Instrumentation

The purpose of COM+ instrumentation is to enable the development of monitoring and managing COM+ applications by exposing a set of COM+ metrics. The COM+ metrics are published to the client by using the COM+ Events service, a loosely coupled events (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. COM+ metrics provide information about specific COM+ objects, COM+ applications, and COM+ services by subscribing to the events published by the system events publisher.

By using COM+ instrumentation, clients can receive notifications for a variety of COM+ metrics by implementing COM+ instrumentation interfaces. Several new metrics and interfaces have been developed for this version of Component Services. The COM+ metrics provide enough information for the monitoring application to correlate them with Microsoft Windows® 2000 metrics for performance analysis, capacity planning, and for modeling and prediction.

You can use COM+ instrumentation to build your own COM+ monitoring and logging programs. COM+ instrumentation can also be used to receive user-defined events as well as to convert COM+ events to VSA format when you are upgrading MTS packages that are receiving MTS events. The following COM+ instrumentation samples are provided to demonstrate these features:

  • COMSPY Sample—Demonstrates how to display and log COM+ metrics.
  • User Events Sample—Demonstrates how to receive user-defined events.
  • Visual Studio Analyzer COM+ Event Bridge Sample—Subscribes to COM+ 1.0 events and converts COM+ Events to Visual Studio Analyzer events.

COM+ instrumentation does not guarantee the delivery of an event.

For information on the Platform SDK COM+ samples, see COM+ Instrumentation Samples.


COM+ Metrics

The COM+ metrics are published to the clients using COM+ Events, a loosely coupled events (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. The metrics are grouped in categories by the type of object for which they provide information. For each category, there is a correspondent interface to which the client can subscribe. By doing this, the client will receive all the metrics in that category. The client can also subscribe to specific methods on the interface to receive specific metrics through filtering metrics.

Every metric has a timestamp. This is the time when the metric was generated, not the time that it was dispatched or received. The client can correlate the timestamp and find out the cost of running a COM+ application, of a transaction executed inside a COM+ application, or of a method call inside of a COM+ application.

To receive notifications from the ComServiceEvents class, you will implement the COM+ instrumentation interfaces that expose the metrics described in the following table.

Metrics | Descriptions
Application start and shutdown | The user implements IComAppEvents to be notified when a server application starts, shuts down, or is forced to shut down.
Activity | The user implements IComActivityEvents to be notified when an activity is created, destroyed, or timed out.
Application installation and deletion | The user implements IComAdmAppEvents to be notified if an application is installed from an MSI file. The subscriber is also notified if a new application is created or when an existing application is deleted or updated.
Just-In-Time (JIT) object creation and release | The user implements IComObjectEvents to be notified when a JIT object is created or released.
User-defined metrics | The user implements IComUserEvent to be notified when a user-defined event has occurred.
Component installation and deletion | The user implements IComAdmCompEvents to be notified when a component is installed, imported, deleted, or changed in an application.
Method call, return, and exceptions | The user implements IComMethodEvents or IComMethod2Events to be notified when an object's method is called, returned, or generates an exception.
Transaction startup, preparing to commit, and abort | The user implements IComTransactionEvents to be notified when a distributed transaction of a component is committed or aborted.
Resource dispenser connection, allocation, and recycling | The user implements IComResourceEvents to be notified when a new resource is created, allocated, destroyed, or tracked.
Object Pooling | The user implements IComObjectPoolEvents or IComObjectPoolEvents2 to be notified when a new pool is created or an object is returned or obtained from the pool.
Queued Components | The user implements IComQCEvents to be notified when a queued message is created or de-queued.
User Exception | The user implements IComExceptionEvents to be notified when a user exception has occurred in a transactional component.
Component Resource Manager (CRM) | The user implements IComCRMEvents to be notified when the CRM recovery starts or completes.
Process Recycling | The user implements IComApp2Events to be notified of a recycled process.
Pausing and Disabling COM+ Applications | The user implements IComApp2Events to be notified if a COM+ server application is paused or a COM+ library application is disabled.


COM+ Metrics Filtering

When the user subscribes to a COM+ instrumentation interface or method, the user can specify properties for the subscription in the event structure such as the application ID (guidApp parameter) or the process ID (dwPid parameter). When the application ID is specified, the user will receive only the metrics from the specified application. If the process ID is specified, the user will receive metrics from the specified server application and library applications that are loaded in that process (because the server application calls them). The user can specify both the application ID and the process ID. However, the application ID has to be that of the server application running in the process with the specified process ID. If neither is specified, the user will receive metrics from all the server and library applications.


COMSPY Sample

The COMSPY sample implements notification sinks for the various COM+ instrumentation interfaces. These interfaces encapsulate events about areas of COM+ functionality such as transactions, threading, and activation. For more information on these interfaces, see the COM+ Instrumentation interfaces.

When metrics are enabled through the registry key setting, you will incur a performance cost of an extra method call per metric and the memory needed to allocate the metric.

For the sample link and readme documentation, see COM+ Instrumentation Samples.


Visual Studio Analyzer COM+ Event Bridge Sample

COM+1.0 generates events that are not compatible with Visual Studio Analyzer (VSA) events. When you upgrade MTS packages to COM+ 1.0 by installing Microsoft Windows® 2000, you can no longer get COM+ events with Visual Studio Analyzer. Only after you install the COM+ Event Bridge will you be again able to analyze COM+ components. The COM+ Event Bridge fixes the problem by subscribing to COM+ events and converting them to Visual Studio Analyzer events.

When to use

You should use COM+ Event Bridge if you intend to analyze MTS components with the Component Services Explorer (COM+ 1.0) and the Visual Studio Analyzer 6.0 with MTS 2.0.

Requirements

You must install the COM+ 1.0 Event Bridge if you have upgraded to COM+ 1.0 and are using Visual Studio Analyzer 6.0 with MTS 2.0.

For the sample link and the readme documentation, see COM+ Instrumentation Samples.

For more information on how to use Visual Studio Analyzer to collect COM+ metrics, see Collecting COM+ Metrics.


Collecting COM+ Metrics

After you install the COM+ Event Bridge, it becomes a registered Visual Studio Analyzer component with the name COM+ Event Source. Some of the original metrics generated by the MTS Event Source are also generated by the COM+ Event Source. Because there is new functionality in COM+ 1.0, there are also new metrics being generated. These new metric names are prefixed with COM+—for example, COM+ User Exception.

Note You must modify filters that specify the MTS Event Source directly so that they reference the COM+ Event Source. Filters that specify "All Components" need no modification.


User Events Sample

The User Events sample shows how to generate application specific events.

For the sample link and the readme documentation, see COM+ Instrumentation Samples.


COM+ Instrumentation Samples

The following are the COM+ instrumentation samples:

  • COMSPY Sample
  • Visual Studio Analyzer COM+ Event Bridge Sample
  • User Events Sample

Click the buttons below to jump to the specified sample.

COMSPY Sample SDK Not Installed SDK Not Installed

COM+ Event Bridge Sample SDK Not Installed SDK Not Installed

Microsoft Visual C++ User Events Sample SDK Not Installed SDK Not Installed

Microsoft Visual Basic User Events Sample SDK Not Installed SDK Not Installed


Tools Developer Reference

This section provides detailed reference information about the Microsoft Distributed Transaction Coordinator (MS DTC). It describes the interaction between transactions, objects, functions, and the interfaces that control them.

Topic | Description
Transactions | Describes how transactions enlist, commit, abort, and inquire about other transactions.
Objects | Describes seven types of objects that developers use within the MS DTC realm when developing resource managers. It describes, for example, when to use interfaces for creating transaction objects, transaction options objects, export objects, and resource manager objects.
Interfaces | Describes interfaces and how resource managers use them to enlist, to propagate from process to process or from system to system, and to participate in the two-phase commit protocol.
Functions | Describes special functions that developers use to create transaction managers, to dispense transactions, and to implement the data structure used by the resource manager proxy.


Transactions

This section describes how transactions enlist, commit, abort, and inquire about other transactions. It also describes OLE transactions and its early role in the development of COM+. The topics are:

Topic | Description
OLE Transactions | Describes OLE Transactions as Microsoft's interface standard for transaction management. OLE Transactions. It also defines the interfaces that applications, resource managers, and transactions managers use to participate in transactions.
Differences between OLE Transactions and COM | Describes how the OLE Transactions interface is similar to the Component Object Model (COM+), yet differ in several respects.


OLE Transactions Reference

OLE Transactions is Microsoft’s interface standard for transaction management. OLE Transactions defines the interfaces that applications, resource managers, and transactions managers use to participate in transactions. Applications use OLE Transactions interfaces to initiate, commit, abort, and inquire about transactions. Resource managers use OLE Transactions interfaces to enlist in transactions, to propagate transactions from process to process or from system to system, and to participate in the two-phase commit protocol.

The OLE Transactions interfaces are based on the Component Object Model (COM) Even though these interfaces look like COM interfaces they differ from COM in several respects. These differences are described BELOW. The OLE Transactions standard describes the objects, interfaces, and methods used to perform transactions.

The OLE Transactions standard is composed of several object classes. For example, the Transaction Object represents a transaction, the Resource Manager Object represents a transactional resource manager, and the Enlistment Object represents the enlistment of a resource manager in a transaction.

Each OLE Transactions object implements one of more OLE Transactions interfaces. For example, the Transaction Object implements the ITransaction, ITipTransaction, and IGetDispenser interfaces. The ITransaction interface is used to commit or abort the transaction. The ITipTransaction interface is used to perform TIP operations such as obtaining the TIP URL for the transaction. The IGetDispenser interface is used to obtain an interface on the MS DTC Proxy Core object.

OLE Transactions also consists of helper functions that are implemented as application programming interfaces (APIs).

The MS DTC system implements most OLE Transactions objects, interfaces, and methods. Resource managers that wish to use OLE Transactions must implement some OLE Transactions objects, interfaces, and methods.

The MS DTC proxy core object is obtained by calling the DtcGetTransactionManager function.


Differences between OLE Transactions and Component Object Model (COM)

The OLE Transactions specification is based upon COM but it differs from COM in the following respects:

  1. OLE Transaction objects cannot be created using the COM CoCreate* API’s.
  2. References to OLE Transaction objects are always direct. As a consequence of this no proxies/stubs are created for inter-apartment, inter-process or inter-node calls. Thus OLE Transactions references cannot be marshalled using standard COM marshalling.
  3. All references to OLE Transaction objects and their sinks are completely free threaded and cannot rely upon COM concurrency control models e.g. You cannot pass a reference to a IResourceManagerSink that lives on the single-threaded apartment and expect the call-back to occur only on the same single threaded apartment.


Objects, Interfaces and Functions Summary

The OLE Transactions interfaces and functions can be divided into the following groups based on the services they provide:

Topic | Description
Utility Interfaces and Functions | Establishes the initial connection to MS DTC and locates the MS DTC proxy core object given a transaction object.
Transaction Initiation and Control Interfaces | Used by application programs and resource managers to begin, commit, and abort transactions, and to determine the status of transactions.
Transaction Propagation Interfaces | Used by the RM proxy and resource managers to propagate transactions between processes and between systems.
Resource Manager Interfaces | Used by transaction managers and resource managers to communicate. The resource manager uses these interfaces to enlist in transactions and to recover transactions following a failure. The resource manager implements one of these interfaces as a callback interface. The resource manager is called on this interface if the transaction manager fails.
Transaction Coordination Interfaces | Used by transaction managers and resource managers to perform the two-phase commit protocol.
Transaction Voter Interfaces | Used to notify application servers of distributed transaction outcomes and to veto atomic commitment during the first phase of the two-phase commit protocol.


Utility Interfaces and Functions

The utility interfaces and functions include the function for establishing the initial connection to MS DTC and the interface for locating the MS DTC proxy core object given a transaction object. These interfaces and functions include the following:

DtcGetTransactionManager Function

DtcGetTransactionManagerEx Function

IGetDispenser Interface


Transaction Initiation and Control Interfaces

These are the interfaces that application programs and resource managers use to begin, commit, and abort transaction, and to determine the status of transactions.

ITransactionDispenser Interface

ITransactionOptions Interface

ITransaction Interface

ITransactionOutcomeEvents Interface


Transaction Propagation Interfaces

The RM proxy and resource manager use the transaction propagation interfaces to propagate transactions between processes and between systems. These interfaces include the following:

ITransactionImportWhereabouts Interface

ITransactionExportFactory Interface

ITransactionExport Interface

ITransactionImport Interface


Resource Manager Interfaces

Transaction managers and resource managers use these interfaces to communicate. The resource manager uses these interfaces to enlist in transactions and to recover transactions following a failure. The resource manager implements one of these interfaces as a callback interface. The resource manager is called on this interface if the transaction manager fails. This informs the resource manager that it must perform recovery.

IResourceManagerFactory Interface

IResourceManager Interface

IResourceManagerSink Interface


Transaction Coordination Interfaces

The transaction manager and resource manager use the transaction coordination interfaces (also called two-phase commit interfaces) to perform the two-phase commit protocol.

ITransactionResourceAsync Interface

IPrepareInfo Interface

ITransactionEnlistmentAsync Interface


Phase 0 Notification Interfaces

Phase Zero notification interfaces allow applications to detect when a transaction is ready to proceed with a two-phase commit (2PC) protocol, so that they can perform such operations and communicate to the Transaction Manager when they have been completed.

Certain distributed transaction applications require a mechanism by which they can learn that a transaction is ready to enter the prepare state of the 2PC protocol. For example, an application that participates in a transaction might possess data that has been modified, but not yet written to stable storage. If the application is not capable of providing the durability guarantees required by transactions (e.g. by acting as a resource manager and participating in 2PC and recovery), then it must ensure that it has flushed all modified data to a full-service resource manager before the 2PC protocol is initiated.

The Phase Zero (phase0) notification mechanism is provided by Phase0 Enlistment objects and Phase0 Notification objects. These objects implement the ITransactionPhase0EnlistmentAsync Interface and ITransactionPhase0NotifyAsync Interface, respectively. The former is implemented by the MS Distributed Transaction Coordinator (MS DTC) proxy while the latter is implemented by the application that needs to participate in Phase0 (Phase0 participant). Both interfaces are exchanged as sinks when a Phase0 Enlistment object is created.

The Phase0 notification mechanism introduces three new interfaces:

  1. ITransactionPhase0Factory Interface - exports a method to create a Phase0 Enlistment object in the MS DTC proxy and exchange.
  2. ITransactionPhase0EnlistmentAsync Interface - indicates the completion of all Phase0 processing, or that it is no longer interested in Phase0 notifications.
  3. ITransactionPhase0NotifyAsync Interface - notifies Phase0 participants of the Phase0 event.


Transaction Voter Interfaces

The transaction voter interfaces are designed to provide mechanisms to notify application servers of distributed transaction outcomes and to veto atomic commitment during the first phase of the two-phase commit protocol. Transaction voters are application server components that support both these functions. Transaction voters are short-lived because they maintain no durable transaction state, however, they are allowed to vote against the commitment of a transaction if an object is in an inconsistent state on initiation of the prepare phase of the two-phase commit protocol.

The veto and event notification mechanisms are provided by transaction voter and transaction notification objects. These objects implement the ITransactionVoterBallotAsync and ITransactionVoterNotifyAsync interfaces, respectively. The ITransactionVoterBallotAsync interface is implemented by the MS DTC proxy and the ITransactionVoterNotifyAsync interface is implemented by a transaction voter. Both interfaces are exchanged as sinks when a transaction voter object is created. The following figure illustrates the creation of the transaction voter object.

Creation of a transaction voter object

ITransactionVoterFactory2 Interface

ITransactionVoterBallotAsync Interface

ITransactionVoterNotifyAsync Interface


XA Interfaces

The XA Interfaces allow an XA compliant resource manager to map between OLE Transactions and the XA transaction protocol:

  1. IDtcToXaMapper Interface
  2. IDtcToXaHelperFactory Interface
  3. IDtcToXaHelperSinglePipe Interface


Objects

This section describes objects that developers use within the MS DTC realm when developing resource managers.

Object | Description
MS DTC Proxy Core Object | Provides MS DTC proxy interfaces for creating transaction objects, transaction options objects, export objects, and resource manager objects.
Transaction Object | Represents the MS DTC transaction.
Transaction Options Object | Contains transaction attribute information, such as the time-out for the transaction and the transaction name.
Export Object | Represents a connection between an RM proxy and a resource manager. The export object is used to propagate transactions between processes or systems.
Enlistment Object | Created each time a resource manager enlists in a transaction. MS DTC uses the enlistment object to determine which resource managers to involve in the two-phase commit process.
Voter Object | Represents an application's vote for committing or aborting a distributed transaction.
Resource Manager Object | Created when a resource manager initially connects to a transaction manager.
Transaction Phase0 Enlistment Object | Notifies an application of a particular transaction that the client has initiated the transaction commit or abort but before the 2-phase processing has been initiated.
XA Two-Pipe Resource Manager Pseudo-Object | Represents a XA Resource Manager based on the two-pipe coordination model implemented by the MSDTC XA Transaction Manager.
XA Single-Pipe Resource Manager Object | Represents a XA Resource Manager based on the one-pipe coordination model implemented by the MSDTC XA Transaction Manager.
XA Single-Pipe Resource Manager Pseudo-Object | Represents a XA Resource Manager Helper based on the one-pipe coordination model implemented by the MSDTC XA Transaction Manager.


MS DTC Proxy Core Object

The MS DTC proxy core object is the root or central MS DTC object. This object provides many essential MS DTC proxy interfaces, such as the interfaces for creating Transaction objects, Transaction Options objects, Export objects, and Resource Manager objects.

Origin: | Created by the application program or resource manager when it calls the DtcGetTransactionManager function. This call is typically made during program initialization.
Occurrences: | One per call to DtcGetTransactionManager. Application programs and resource managers typically maintain a connection to only one transaction manager. However, they may connect to as many transaction managers as they choose. The DtcGetTransactionManagerEx function offers the same functionality as the DtcGetTransactionManager function but helps reduce the boot time and minimize resource consumption for Windows 2000 and adds the ability to demand start DTC on Windows 2000 to compensate for removing boot start.
Duration: | Normally exists for the life of the application program or resource manager. It should be released at the completion of the program.
Interfaces: IUnknown
IDtcToXaHelperSinglePipe
IDtcToXaMapper
IDtcToXaHelperFactory
IResourceManagerFactory
IResourceManagerFactory2
ITipHelper
ITransactionDispenser
ITransactionImportWhereabouts
ITransactionImport
ITransactionExportFactory
ITransactionVoterFactory
IXATransLookup
IXaMapperFactory
IXAConfig


Transaction Object

The Transaction object represents the MS DTC transaction.

Origin: | Created by an application program or resource manager that calls the ITransactionDispenser::BeginTransaction method. Occurs each time a new transaction is required. A resource manager creates a transaction object by calling the ItransactionImport::Import method each time a transaction is imported by the resource manager.
Occurrences: | One instance for each transaction the application program or resource manager initiates. A process may begin as many transactions as it chooses. One instance of the transaction object is present for each transaction that the resource manager imports. A resource manager may import on as many transactions as it chooses.
Duration: | The transaction object exists for the life of the transaction. It should be released when the transaction completes.
Interfaces: | IUnknown ITransaction IGetDispenser ITipTransaction ITransactionPhase0Factory


Transaction Options Object

The transaction options object contains transaction attribute information such as the time-out for the transaction and the name of the transactions. The transaction options object is passed as a parameter to the ITransactionDispenser::BeginTransaction method when creating a new transaction. The transaction attributes contained in the transaction options object are inherited by the newly created transaction object. A transaction options object can be used across multiple transactions.

Origin: | An application program or resource manager creates a transaction options object by calling the ITransactionDispenser::GetOptionsObject method. This is typically done during program initialization.
Occurrences: | One instance of the transaction options object is present for each call to the ITransactionDispenser::GetOptionsObject method. Typically an application program or resource manager will create one or two transaction options objects. However, a program may create as many transaction options objects as it chooses.
Duration: | The transaction options object normally exists for the life of the program. It should be released at the completion of the program.
Interfaces: | IUnknown ITransactionOptions


Export Object

The export object represents a connection between an RM proxy and a resource manager. The export object is used to propagate transactions between processes or systems. The export object contains the name and location of the resource manager' s transaction manager. When the RM proxy exports a transaction to a resource manager, the RM proxy' s transaction manager uses the export object to locate the resource manager' s transaction manager.

Origin: | An RM proxy creates an export object by calling the ITransactionExportFactory::Create method. The RM proxy should create the export object when it first connects to a resource manager or, at latest, when it first attempts to export a transaction to the resource manager.
Occurrences: | One instance of the export object is present for each call to ITransactionExportFactory::Create. Typically, an RM proxy creates one export object for each resource manager connection that it establishes.
Duration: | The export object normally exists for the life of the RM proxy-to-resource manager connection. It should be released when the connection is closed.
Interfaces: | IUnknown ITransactionExport


Enlistment Object

The enlistment object represents the relationship between a resource manager and a transaction object on which the resource manager has enlisted. An enlistment object is created each time a resource manager enlists in a transaction. MS DTC uses the enlistment object to determine which resource managers to involve in the two-phase commit process.

Origin: | A resource manager creates an enlistment object by calling the IResourceManager::Enlist method. The resource manager typically does this as part of importing a transaction.
Occurrences: | One instance of the enlistment object is present for each call to the IResourceManager::Enlist method. Typically, a resource manager enlists in each transaction only once. However, MS DTC permits a resource manager to enlist in a transaction as many times as it chooses. Multiple enlistments could occur, for example, if the same transaction is imported to the resource manager from more than one RM proxy.
Duration: | The enlistment object exists for the life of the transactions. It should be released when the transaction completes.
Interfaces: | IUnknown ITransactionEnlistmentAsync IPrepareInfo


Voter Object

The voter object represents an application's vote for committing or aborting a distributed transaction.

Origin: | A transaction voter creates a voter object by calling the ITransactionVoterFactory::Create method.
Occurrences: | One instance of the voter object is present for each call to the ITransactionVoterFactory::Create method. A transaction voter calls this method on the transaction object for any transaction for which it needs notification of outcome events or would like to veto.
Duration: | The lifetime of a transaction voter object matches that of the transaction with which it is employed.
Interfaces: | IUnknown ITransactionVoterBallotAsync


Resource Manager Object

The resource manager object represents the connection between a resource manager and a transaction manager. A resource manager object is created when a resource manager initially connects to a transaction manager.

Origin: | A resource manager creates a resource manager object by calling the IResourceManagerFactory::Create method. This call is typically made during resource manager initialization.
Occurrences: | One instance of the resource manager object is present for each resource manager to transaction manager connection. The resource manager passes its RMGUID when calling IResourceManagerFactory::Create. The transaction manager uses the RMGUID to ensure that a resource manager connects to the transaction manager only one time. Typically, a resource manager only connects to one transaction manager, namely its local MS DTC transaction manager.
Duration: | The resource manager object exists for the life of the resource manager-to-transaction manager connection. Typically, this connection exists for the life of the resource manager. The resource manager object should be released before the resource manager terminates.
Interfaces: | IUnknown IResourceManager IResourceManager2


Transaction Phase0 Enlistment Object

The Phase0 Enlistment Object is used by applications to receive notification on a particular transaction that the client has initiated the transaction commit or abort but before the 2-phase processing has been initiated.

Origin: | The application creates a phase0 enlistment object by calling the ITransactionPhase0Factory::Create. The ITransactionPhase0Factory interface is implemented by the transaction object.
Occurrences: | One instance of the phase 0 enlistment object is present for each call to the ITransactionPhase0Factory::Create method. A transaction phase 0 enlistee calls this method for every transaction for which it needs phase 0 notification.
Duration: | The lifetime of a phase 0 enlistment object matches that of the transaction with which it is employed.
Interfaces: | IUnknown ITransactionPhase0EnlistmentAsync


XA Two-Pipe Resource Manager Pseudo-Object

The XA Two-Pipe Resource Manager pseudo-object represents a XA Resource Manager based on the two-pipe coordination model implemented by the MSDTC XA Transaction Manager.

Origin: | The application creates a XA Two-Pipe Resource Manager object by calling the IDtcToXaMapper::RequestNewResourceManager method. The pszRMCookie output parameter on this method call represents this object.
Occurrences: | There is a unique XA Two-Pipe Resource Manager psuedo-object for every open string and XA resource manager dll combination speficied by client applications. This object is in the XATM. Proxies to this object are exposed by the MSDTC Proxy.
Duration: | The lifetime of this object is scoped by the open references to this object plus by pending transactions enlisted on this resource manager.
Interfaces: | None


XA Single-Pipe Resource Manager Object

The XA Single-Pipe Resource Manager object represents a XA Resource Manager based on the one-pipe coordination model implemented by the MSDTC XA Transaction Manager.

Origin: | The application creates a XA Single-Pipe Resource Manager object by calling the IDtcToXaHelperFactory::Create.
Occurrences: | Every call to IDtcToXaHelperFactory::Create creates a new instance of this object.
Duration: | The lifetime of this object is scoped by the open references to this object plus by pending transactions enlisted on this resource manager.
Interfaces: | IUnknown IDtcToXaHelper


XA Single-Pipe Resource Manager Pseudo-Object

The XA Single-Pipe Resource Manager pseudo-object represents a XA Resource Manager Helper based on the one-pipe coordination model implemented by the MSDTC XA Transaction Manager.

Origin: | The application creates a XA Two-Pipe Resource Manager object by calling the IDtcToXaHelperSinglePipe::XARMCreate method. The pszRMCookie output parameter on this method call represents this object.
Occurrences: | Every call to IDtcToXaHelperSinglePipe::XARMCreate creates a new instance of this object.
Duration: | The lifetime of this object is scoped by the open references to this object plus by pending transactions enlisted on this resource manager.
Interfaces: | None


Interfaces

This section describes interfaces and how resource managers use them to enlist, to propagate from process to process or from system to system, and to participate in the two-phase commit protocol. The topics include:

Topic | Description
DTC Interfaces | Describes interfaces for the Microsoft Distributed Transactions Controller (MS DTC).
CRM Interfaces | Describes interfaces for the Compensating Resource Manager (CRM).
Resource Dispenser Interfaces | Describes interfaces for the Resource Dispenser (RD).
COM+ Instrumentation Interfaces | Describes the COM+ Event Sinks interfaces that allow clients to receive notifications for COM+ events.


DTC Interfaces

The following alphabetized DTC interfaces provide detailed interface descriptions for developers of native OLE Transactions resource managers, developers of XA Compliant Resource Managers, and developers of Caching Resource Managers. The interfaces are:

Interfaces | Description
ICreateWithTIPTransaction | This interface creates an object that is enlisted within a manual transaction using the Transaction Internet Protocol (TIP).
ICreateWithTransaction | This interface creates an object that is enlisted within a manual transaction.
IDtcToXaMapper | The RM proxy uses the IDtcToXaMapper interface to map between OLE Transactions and XA protocol when the XA is being used as the native protocol for distributed transactions.
IDtcToXaHelperFactory | Resource managers use this interface to map between OLE Transactions and the XA protocol when XA is being used as the native protocol for distributed transactions.
IDtcToXaHelper | Resource manager proxies use this interface to map between OLE Transactions and the XA protocol.
IDtcToXaHelperSinglePipe | This interface is a protocol for catching events that provides user specific metrics.
IGetDispenser | The resource manager proxy uses this interface to implement its transaction enlistment interface.
IPrepareInfo | The resource manager uses this interface to retrieve prepare information from the transaction manager.
IResourceManager | The resource manager uses this interface to enlist in distributed transactions.
IResourceManager2 | The resource manager uses this interface to enlist in distributed transactions.
IResourceManagerFactory | This interface contains a single method that is used to create a new resource manager object.
IResourceManagerFactory2 | This interface contains a single method that is used to create a new resource manager object.
ITipHelper | This interface provides methods to pull transactions and to get the TIP TM URL of the local TM.
ITipPullSink | An application uses this interface to provide an ITipPullSink pointer.
ITipTransaction | This interface provides methods to support TIP specific functionality on the transaction object.
ITransaction | This interface is used to commit and abort transactions and to obtain status information about transactions.
ITransaction2 | This interface is to replicate the NT 4 version of the ITransaction Interface.
ITransactionCloner | This interface clones an MTS NT 4.0 transaction.
ITransactionDispenser | This interface is used to create transactions and transaction options.
ITransactionImport | The resource manager uses this interface to transform an imported transaction cookie into a transaction object.
ITransactionImportWhereabouts | This interface is used when propagating transactions from one process to another or one system to another.
ITransactionExport | This interface is used to marshal a transaction object.
ITransactionExportFactory | This interface is used to create a new export object.
ITransactionOptions | This interface contains methods that control the attributes of new transactions such as their time-out periods and descriptions.
ITransactionOutcomeEvents | This interface is used by application programs that require asynchronous notification about transaction outcomes.
ITransactionResourceAsync | This is a callback interface implemented by the resource manager.
ITransactionPhase0Factory | The interface contains a single method that creates a new phase0 enlistment object.
ITransactionPhase0EnlistmentAsync | This interface is used by a Phase0 participant to indicate that it is ready to receive phase0 notification, that phase0 processing has completed, or that phase0 notification is no longer desired.
ITransactionPhase0NotifyAsync | The MS DTC Proxy calls the methods of this interface to deliver phase zero notification to a Phase0 participant, and to notify the participant that the asynchronous enlistment has completed.
ITransactionEnlistmentAsync | The resource manager uses this interface to notify the transaction manager that it has completed the prepare, abort, or commit request on the transaction object associated with this enlistment object.
ITransactionVoterFactory2 | This interface is used to create a new transaction voter object.
ITransactionVoterBallotAsync | This interface is used to sanction or veto a transaction during the prepare phase of the two-phase commit protocol.
ITransactionVoterNotifyAsync | This interface is used to notify a transaction voter of a vote request during the first phase of the two-phase commit protocol.


ICreateWithTIPTransaction Interface

The ICreateWithTIPTransaction interface creates an object that is enlisted within a manual transaction using the Transaction Internet Protocol (TIP).

When to Implement

This interface is implemented by COM+.

When to Use

Use this interface to ensure that your component runs in the context of a TIP transaction.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICreateWithTIPTransaction Methods | Description
CreateInstance | Receives a TIP URL to specify the transaction.

Remarks

An ICreateWithTIPTransaction pointer is obtained by calling QueryInterface on the ManualTransaction object.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface

ICreateWithTransaction Interface


ICreateWithTIPTransaction::CreateInstance

This method creates a COM+ object that will execute within the scope of the manual transaction specified by a TIP transaction URL.

HRESULT CreateInstance(
   BSTR bstrTipUrl,
   REFCLSID rclsid,
   REFIID riid,
   void ** ppvObj
);

Parameters

bstrTipUrl
[in] A TIP URL indicating the transaction that the object to be created is to be manually enlisted.
rclsid
[in] A reference to the CLSID of the type of object to instantiate.
riid
[in] A reference to the interface ID of the interface to communicate with the new object.
ppvObj
[out] A reference to a new object of the type specified by the rclsid argument, through the interface specified by the riid argument.

Return Values

S_OK
A reference to the object is returned in the ppvObj parameter.
REGDB_E_CLASSNOTREG
The component specified by rclsid is not registered as a COM+ component.
E_OUTOFMEMORY
Not enough memory available to instantiate the object.
E_INVALIDARG
The argument passed in the ppvObj parameter is invalid.
E_UNEXPECTED
An unexpected error occurred.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface

ICreateWithTransaction Interface


ICreateWithTransaction Interface

The ICreateWithTransaction interface creates an object that is enlisted within a manual transaction.

When to Implement

This interface is implemented by COM+.

When to Use

Use this interface to ensure that your component operates within the context of a manually started OLE Transactions transaction.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICreateWithTransaction Methods | Description
CreateInstance | Receives an ITransaction Interface pointer to specify a transaction.

Remarks

An ICreateWithTransaction pointer is obtained by calling QueryInterface on the Bring Your Own Transaction (BYOT) object.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface

ICreateWithTIPTransaction Interface


ICreateWithTransaction::CreateInstance

Creates a COM+ object that will execute within the scope of a manual transaction specified with an ITransaction Interface pointer.

C++ Syntax

HRESULT CreateInstance(
   ITransaction * pTransaction,
   REFCLSID rclsid,
   REFIID riid,
   void ** ppvObj
);

Parameters

pTransaction
[in] An ITransaction interface pointer indicating the transaction that the object to be created is to be manually enlisted.
rclsid
[in] The CLSID of the type of object to instantiate.
riid
[in] The interface ID of the interface through which you want to communicate with the new object.
ppvObj
[out] A new object of the type specified by the RCLSID argument through the interface specified by the riid argument.

Return Values

S_OK
A reference to the object is returned in the ppvObj parameter.
REGDB_E_CLASSNOTREG
The component specified by RCLSID is not registered as a COM+ component.
E_OUTOFMEMORY
Not enough memory available to instantiate the object.
E_INVALIDARG
The argument passed in the ppvObj parameter is invalid.
E_UNEXPECTED
An unexpected error occurred.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface, ICreateWithTIPTransaction Interface.


IDtcToXaMapper Interface

Resource manager proxies can use the IDtcToXaMapper interface to map between OLE Transactions and XA protocol when the XA is being used as the native protocol for distributed transactions. ODBC is an example of an RM proxy. The following sections use ODBC as a specific example to facilitate the understanding of what needs to be done in the resource manager proxy to map OLE Transaction to the XA protocol.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

Use this interface to map between OLE Transactions and XA protocol using the two-pipe connection model.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDtcToXaMapper Methods | Description
RequestNewResourceManager | Obtains a RM cookie which is stored in the connection object.
TranslateTridToXid | Creates an XID from an ITransaction object.
EnlistResourceManager | Instructs the DTC Proxy to enlist on behalf of the XA resource manager.
ReleaseResourceManager | Instructs the DTC Proxy to release an RM cookie that was obtained from the call to RequestNewResourceManager

Remarks

Either call the DtcGetTransactionManager Function with a riid of IID_IDtcToXaMapper when initially connecting to MS DTC or call QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_IDtcToXaMapper

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaHelperFactory Interface, IDtcToXaHelper Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaMapper::EnlistResourceManager

Instructs the DTC Proxy to enlist on behalf of the XA resource manager. The EnlistResourceManager method must be called for every transaction that the connection is requested to be enlisted in. This interface method should be called after the XA resource manager has the XID.

When called, a message is sent to the XA TM module in MS DTC, which then enlists with the MS DTC TM module. At the time of two-phase commit, this enlistment receives the prepare, commit, and abort messages which the XA TM module translates into appropriate XA function calls such as xa_prepare, xa_commit, and xa_abort.

If this method fails, the ODBC driver must call ReleaseResourceManager using the cookie specified in dwRMCookie.

C++ Syntax

HRESULT EnlistResourceManager (
   DWORD dwRMCookie,
   DWORD * pdwITransaction
);

Parameters

dwRMCookie
[in] A cookie representing the RM which was obtained from the call to RequestNewResourceManager.
pdwITransaction
[in] A pointer to ITransaction Interface which the application passes in as a value for the SQL_ENLIST_IN_DTC connection attribute.

Return Values

S_OK
Success.
E_FAIL
TM enlisted failed.
E_INVALIDARG
One or more of the parameters are not valid.
E_OUTOFMEMORY
Unable to do a new enlistment.
E_UNEXPECTED
An unexpected error occurred.
XACT_E_CONNECTION_DENIED
The transaction manager refused to accept a connection.
XACT_E_CONNECTION_DOWN
Lost connection with DTC TM.
XACT_E_LOGFULL
TM has run out of log space.
XACT_E_NOTRANSACTION
No transaction corresponding to pdwITransaction.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaHelperFactory Interface, IDtcToXaHelper Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaMapper::ReleaseResourceManager

Instructs the DTC Proxy to release an RM cookie previously obtained from a call to RequestNewResourceManager. This method allows the DTC Proxy to free up any resources tied to the RM cookie. The RM cookie should not be used after this call.

C++ Syntax

HRESULT ReleaseResourceManager (
   DWORD dwRMCookie
);

Parameters

dwRMCookie
[in] The RM cookie that was obtained from the call to RequestNewResourceManager.

Return Values

S_OK
Success.
E_INVALIDARG
One or more of the parameters are not valid.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaHelperFactory Interface, IDtcToXaHelper Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaMapper::RequestNewResourceManager

This method obtain a RM cookie which is stored in the connection object. The RequestNewResourceManager method is invoked only once per ODBC connection. It is not required after the connection transitions from the local transaction state to the distributed transaction state.

An ODBC connection can be in one of two states, distributed transaction state, or non-distributed transaction state as shown in the Transaction States topic.

C++ Syntax

HRESULT RequestNewResourceManager(
   CHAR * pszDSN,
   CHAR * pszClientDllName,
   DWORD * pdwRMCookie
);

Parameters

pszDSN
[in] A string containing the Data Source Name (DSN).
pszClientDllName
[in] A string containing the name of the resource manager's client DLL.
pdwRMCookie
[in/out] A cookie representing the RM corresponding to the DSN is returned via this parameter.

Return Values

S_OK
Success.
E_FAIL
The attempt to create the resource manager failed due to a bad installation of the XA TM or the DTC TM.
E_INVALIDARG
One or more of the parameters are not valid.
E_OUTOFMEMORY
Unable to allocate resources for a new resource manager.
E_UNEXPECTED
An unexpected error occurred.
XACT_E_CONNECTION_DOWN
Lost connection with DTC TM.
XACT_E_TMNOTAVAILABLE
Unable to establish a connection with DTC service.Failure—the TMs log is full.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaHelperFactory Interface, IDtcToXaHelper Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaMapper::TranslateTridToXid

This method is called to obtain an XID from an ITransaction Interface pointer. The ODBC driver calls this method each time a connection is enlisted on a new transaction. The ITransaction pointer is offered by a transaction object. The transaction object contains a DTC transaction that is identified by a transaction identifier (TRID) which is a globally unique identifier (GUID). Given a TRID, one can always create an XID.

The XID should be stored in the connection object as it may be needed in the future. After obtaining the XID, the ODBC driver should issue an xa_start or its equivalent on the back-end resource manager to associate the XID with the connection.

C++ Syntax

HRESULT TranslateTridToXid(
   DWORD * pdwITransaction,
   DWORD dwRMCookie,
   XID * pXid
);

Parameters

pdwITransaction
[in] A pointer to ITransaction object which the application passes in as a value for the SQL_ENLIST_IN_DTC connection attribute.
dwRMCookie
[in] A cookie representing the RM which was obtained from the call to RequestNewResourceManager.
pXid
[in/out] A pointer to the caller allocated XID structure.
 #define XIDDATASIZE      128   /* size in bytes */
 typedef struct xid_t {
  LONG     formatID;
  LONG     gtrid_length;
  LONG     bqual_length;
  CHAR     data[XIDDATASIZE];
  } XID;

Return Values

S_OK
Success.
E_INVALIDARG
One or more of the parameters are not valid.
XACT_E_NOTRANSACTION
No transaction corresponding to pdwITransaction.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaHelperFactory Interface, IDtcToXaHelper Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaHelperFactory Interface

Resource manager proxies can use the IDtcToXaHelperFactory interface to map between OLE Transactions and XA protocol when the XA is being used as the native protocol for distributed transactions. ODBC is an example of an RM proxy. The following sections use ODBC as a specific example to facilitate the understanding of what needs to be done in the resource manager proxy to map OLE Transaction to the XA protocol.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

Use this interface to map between OLE Transactions and the XA protocol using the one-pipe connection model.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDtcToXaHelperFactory Methods | Description
Create | Obtains a RM cookie which is stored in the connection object.

Remarks

Either call DtcGetTransactionManager Function with a riid of IID_IDtcToXaHelperFactory when initially connecting to MS DTC or call QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_IDtcToXaHelperFactory.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelper Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaHelperFactory::Create

Creates the XA Helper object which exposes the interface to map between OLE Transactions and the XA protocol. The Create method is typically invoked only once per ODBC connection.

C++ Syntax

HRESULT Create (
   CHAR * pszDSN,
   CHAR * pszClientDllName,
   GUID * pguidRm,
   IDtcToXaHelper ** ppXaHelper
);

Parameters

pszDSN
[in] A string containing the Data Source Name (DSN).
pszClientDllName
[in] A string containing the name of the client DLL.
pguidRm
[out] Pointer to the GUID that DTC generates to uniquely identify this connection to the resource manager.
ppXaHelper
[out] Pointer to the pointer to the IDtcToXaHelper Interface on the newly created XA Helper object.

Return Values

S_OK
Sd1
E_FAIL
The attempt to create the XA Helper object failed due to a bad installation of the MS DTC.
E_INVALIDARG
One or more of the parameters are NULL or valid.
E_OUTOFMEMORY
Unable to allocate resources for a XA Helper object.
E_UNEXPECTED
An unexpected error occurred.
XACT_E_CONNECTION_DOWN
Lost connection with DTC TM.
XACT_E_TMNOTAVAILABLE
Unable to establish a connection with MS DTC service.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelper Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaHelper Interface

Resource manager can proxies use the IDtcToXaHelper interface to map between OLE Transactions and XA protocol when the XA is being used as the native protocol for distributed transactions. ODBC is an example of an RM proxy. The following sections use ODBC as a specific example to facilitate the understanding of what needs to be done in the resource manager proxy to map OLE Transaction to the XA protocol.

This interface differs from the IDtcToXaSinglePipeHelper interface in that it requires that the resource manager proxy developer explicitly use the IResourceManager interface.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

Use this interface to map between OLE Transactions and the XA protocol using the one-pipe connection model.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDtcToXaHelper Methods | Description
Close | Closes the connection between the RM proxy and the DTC transaction manager thereby signifying that the RM proxy has closed its connection to the resource manager.
TranslateTridToXid | Creates an XID from an ITransaction object.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaHelper::Close

Closes the connection between the resource manager proxy and the MS DTC transaction manager thereby signifying that the resource manager proxy has closed its connection to the resource manager.

C++ Syntax

HRESULT Close (
   BOOL i_fDoRecovery
);

Parameters

i_fDoRecovery
[in] Boolean indicating whether the MS DTC XA transaction manager must initiate XA recovery with the resource manager. TRUE indicates that the DTC transaction manager should initiate recovery. FALSE indicates that this resource manager does not require recovery.

Return Values

S_OK
Success.
E_FAIL
The attempt to close the connection to the DTC transaction manager was unsuccessful.
E_UNEXPECTED
An unexpected error occurred.
XACT_E_CONNECTION_DOWN
Lost connection with DTC transaction manager.
XACT_E_CONNECTION_DENIED
The DTC transaction manager did not accept a connection request.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaHelper::TranslateTridToXid

This method is called to obtain an XID from an ITransaction interface pointer. The ODBC driver calls this method each time a connection is enlisted on a new transaction. The ITransaction pointer is offered by a transaction object. The transaction object contains a DTC transaction that is identified by a transaction identifier (TRID) which is a globally unique identifier (GUID). Given a TRID, one can always create an XID.

The XID should be stored in the connection object as it may be needed in the future. After obtaining the XID, the ODBC driver should issue an xa_start or its equivalent on the back-end resource manager to associate the XID with the connection.

C++ Syntax

HRESULT TranslateTridToXid (
   ITransaction * pITransaction,
   GUID * pguidBqual,
   XID * pXid
);

Parameters

pITransaction
[in] A pointer to the ITransaction object for the active DTC transaction that the XA resource manager wishes to enlist in.
pguidBqual
[in] A pointer to a GUID representing.
pXid
[out] A pointer to the caller allocated XID structure to receive the newly generated XID.

Return Values

S_OK
Success.
E_INVALIDARG
One or more of the parameters are not valid.
E_FAIL
Unable to generate a valid XID for this transaction. The generated GTRID or BQUAL was too large to fit in the XID structure.
E_UNEXPECTED
An unknown error occurred. No information is returned.
XACT_E_NOTRANSACTION
Unable to retrieve information for the transaction because it was already completed. No information is returned.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelperSinglePipe Interface.


IDtcToXaHelperSinglePipe Interface

The resource manager proxy uses the IDtcToXaHelperSinglePipe interface to map between OLE Transactions and XA protocol when the XA is being used as the native protocol for distributed transactions. ODBC is an example of an RM proxy. The following sections use ODBC as a specific example to facilitate the understanding of what needs to be done in the resource manager proxy to map OLE Transaction to the XA protocol.

This interface differs from the IDtcToXaHelper interface in that it abstracts away the need to use the IResourceManager interface.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

Use this interface to map between OLE Transactions and the XA protocol using the one-pipe connection model but without explicitly using the IResourceManager interface.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDtcToXaHelperSinglePipe Methods | Description
XARMCreate | ODBC drivers call this method each time they open a new ODBC connection to the database. The information the ODBC driver provides, makes it possible for the MS DTC transaction manager to perform database recovery.
ConvertTridToXID | Creates an XID from an ITransaction object.
EnlistWithRM | Instructs the MS DTC Proxy to enlist on behalf of the XA resource manager. The EnlistResourceManager method must be called for every transaction that the connection is requested to be enlisted in.
ReleaseRMCookie | Closes the connection between the RM proxy and the DTC transaction manager thereby signifying that the RM proxy has closed its connection to the resource manager.

Remarks

Either call DtcGetTransactionManager Function with a riid of IID_IDtcToXaHelperSinglePipe when initially connecting to MS DTC or call QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_IDtcToXaHelperSinglePipe

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelper Interface.


IDtcToXaHelperSinglePipe::ConvertTridToXID

The ODBC driver calls this method once each time an ODBC database connection is enlisted on a new transaction. This method creates an XID from the ITransaction object that the ODBC driver received from the ODBC driver manager in the SQLSetConnectAttr(SQL_ATTR_ENLIST_IN_DTC, pITransaction) call. After obtaining the XID, the ODBC driver sends the XID to the database server in an xa_start message.

C++ Syntax

HRESULT ConvertTridToXID (
   DWORD * pdwITransaction,
   DWORD dwRMCookie,
   XID * pXid
);

Parameters

pdwITransaction
[in] A pointer to the ITransaction object that the ODBC driver received from the ODBC driver manager in the SQLSetConnectAttr(SQL_ATTR_ENLIST_IN_DTC, pITransaction) call.
dwRMCookie
[in] The cookie obtained by calling IDtcToXaHelperSinglePipe::XARMCreate.
pXid
[in/out] A pointer to the caller allocated XID structure.
 #define XIDDATASIZE  128 /* size in bytes */
 typedef struct xid_t {
  LONG     formatID;
  LONG     gtrid_length;
  LONG     bqual_length;
  CHAR     data[XIDDATASIZE];
  } XID;

Return Values

S_OK
Success.
E_INVALIDARG
One or more of the parameters are not valid.
XACT_E_NOTRANSACTION
No transaction corresponding to pdwITransaction.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelper Interface.


IDtcToXaHelperSinglePipe::EnlistWithRM

Instructs the MS DTC Proxy to enlist on behalf of the XA resource manager. The EnlistResourceManager method must be called for every transaction that the connection is requested to be enlisted in.

This method causes the MS DTC Proxy module to enlist with the MS DTC TM module on behalf of the XA resource manager. Note that the EnlistWithRM method should be called after the XA resource manager has the XID. At the time of two-phase commit, this enlistment receives the prepare, commit, and abort messages which are in turn delivered on the ITransactionResourceAsync interface supplied by the ODBC driver. The ODBC driver should then translate the callbacks into appropriate XA function calls such as xa_prepare, xa_commit, and xa_abort on the real resource manager.

If this method fails, the ODBC driver must call ReleaseResourceManager using the cookie specified in dwRMCookie.

C++ Syntax

HRESULT EnlistWithRM (
   DWORD dwRMCookie,
   DWORD * pdwITransaction,
   ITransactionResourceAsync * pRes,
   ITransactionEnlistmentAsync ** ppIEnlist
);

Parameters

dwRMCookie
[in] The cookie obtained by calling IDtcToXaHelperSinglePipe::XARMCreate.
pdwITransaction
[in] A pointer to ITransaction Interface which the application passes in as a value for the SQL_ENLIST_IN_DTC connection attribute.
pRes
[in] A pointer to the ITransactionResourceAsync Interface. The ODBC driver is responsible for implementing the ITransactionResourceAsync interface. This interface includes the PrepareRequest, CommitRequest, AbortRequest and TMDown callback methods. The transaction manager will invoke these resource manager callback methods to deliver phase one and phase two notifications to the ODBC driver.
ppIEnlist
[out] The MS DTC proxy returns the ITransactionEnlistmentAsync Interface pointer to the ODBC driver. The ITransactionEnlistmentAsync interface contains the PrepareRequestDone, CommitRequestDone, and AbortRequestDone methods. These are the transaction manager-implemented methods that the ODBC driver invokes after successfully processing an asynchronous PrepareRequest, CommitRequest, or AbortRequest.

Return Values

S_OK
Success.
E_FAIL
TM enlisted failed.
E_INVALIDARG
One or more of the parameters are not valid.
E_OUTOFMEMORY
Unable to create a new enlistment due to lack of memory.
E_UNEXPECTED
An unexpected error occurred.
XACT_E_CONNECTION_DENIED
The transaction manager refused to accept a connection.
XACT_E_CONNECTION_DOWN
Lost connection with DTC TM.
XACT_E_LOGFULL
TM has run out of log space.
XACT_E_NOTRANSACTION
No transaction corresponding to pdwITransaction.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelper Interface.


IDtcToXaHelperSinglePipe::ReleaseRMCookie

The ODBC driver calls the ReleaseRMCookie method to signify that it has closed it ODBC connection to the database.

The i_fNormal flag indicates whether the ODBC database connection was closed normally. A value of TRUE indicates the connection was closed normally and database recovery is not needed. A value of FALSE indicates that a failure occurred and that XA recovery is needed. The MS DTC transaction manager will immediately attempt to initiate recovery with the database.

C++ Syntax

void ReleaseRMCookie(
   DWORD dwRMCookie,
   BOOL i_fNormal
);

Parameters

dwRMCookie
[in] The cookie obtained by calling IDtcToXaHelperSinglePipe::XARMCreate.
i_fNormal
[in] A boolean signifying whether the ODBC database connection was closed normally. A value of TRUE indicates the connection was closed normally and database recovery is not needed. A value of FALSE indicates that a failure occurred and that XA recovery is needed.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelper Interface.


IDtcToXaHelperSinglePipe::XARMCreate

ODBC drivers call this method each time they open a new ODBC connection to the database. The information the ODBC driver provides, makes it possible for the MS DTC transaction manager to perform database recovery.

An ODBC driver must call the XARMCreate method each time it opens a new ODBC connection to the database. The information provided in the XARMCreate method calls, makes it possible for the transaction manager to connect to the database to perform recovery. The transaction manager durably records this information in its log file. If recovery is necessary, the transaction manager reads the log file, reconnects to the database, and initiates XA recovery.

C++ Syntax

HRESULT XARMCreate (
   CHAR * pszDSN,
   CHAR * pszClientDllName,
   DWORD * pdwRMCookie
);

Parameters

pszDSN
[in] A string containing the Data Source Name (DSN).
pszClientDllName
[in] A string containing the name of the client DLL.
pdwRMCookie
[out] RMCookie representing the ODBC connection. The RMCookie is an input parameter in all later IDtcToXaHelperSinglePipe calls.

Return Values

S_OK
Success.
E_FAIL
The attempt to create the XA Helper object failed due to a bad installation of the MS DTC.
E_INVALIDARG
One or more of the parameters are NULL or invalid.
E_OUTOFMEMORY
Unable to allocate resources for a XA Helper object.
E_UNEXPECTED
An unexpected error occurred.
XACT_E_CONNECTION_DOWN
Lost connection with DTC TM.
XACT_E_TMNOTAVAILABLE
Unable to establish a connection with MS DTC service.

Requirements

To use the methods of this interface, you must include oletx2xa.h in your project.

See Also

IDtcToXaMapper Interface, IDtcToXaHelperFactory Interface, and IDtcToXaHelper Interface.


IGetDispenser Interface

This interface contains a single method IGetDispenser::GetDispenser. The GetDispenser method is used by procedures that are passed a transaction object as a parameter and need to obtain an interface on the MS DTC proxy core object.

For example, the RM proxy uses this method to implement its transaction enlistment interface. Application programs call the transaction enlistment interface and pass a transaction object. The RM proxy uses the GetDispenser method on the transaction object to locate the interfaces on the MS DTC proxy core object.

When to Implement

You do not need to implement this interface. It is implemented by the transaction object of the MS DTC Proxy.

When to Use

Processes use this interface to obtain an interface on the MS DTC proxy core object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IGetDispenser Methods | Description
GetDispenser | Receives an interface on the MS DTC proxy core object.

Remarks

You obtain a pointer to this interface by calling QueryInterface on the ITransaction interface for the transaction object with a riid of IID_IGetDispenser.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionDispenser Interface


IGetDispenser::GetDispenser

Used by procedures that have an interface on a transaction object and need an interface on the MS DTC proxy core object.

HRESULT GetDispenser(
   REFIID riid,
   void** ppvObject
);

Parameters

riid
[in] IID of the requested interface on the MS DTC proxy core object.
ppvObject
[out] Pointer to the pointer to the requested interface.

Return Values

S_OK
Success.
E_INVALIDARG
The value of ppvObject is NULL.
E_UNEXPECTED
An unexpected error occurred.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionDispenser Interface


ILastResourceManager Interface

The LRM uses this interface to perform recovery. An LRM can use this interface to notify the transaction manager of the outcome of all transactions for which the LRM believes the transaction manager is in doubt.

When to Implement

This object is implemented by the MS DTC Proxy.

When to Use

An LRM invokes the methods of this interface to communicate the results of in-doubt transactions to the transaction manager.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ILastResourceManager Methods | Description
TransactionCommitted | An LRM can invoke this method to inform the transaction manager that the transaction was committed.
RecoveryDone | An LRM invokes this method to inform the transaction manager that recovery has been completed.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

IResourceManager Interface


ILastResourceManager::RecoveryDone

The Last Resource Manager (LRM) invokes this method after informing the transaction manager of the outcome of all of the committed transactions for which it believes the transaction manager is in doubt. The idea behind this method is to plug the hole where the transaction manager thinks it has delegated the commit decision to the LRM but the LRM never received the ITransactionLastResourceAsync::DelegateCommit call. When the LRM invokes this method, the transaction manager will know that the LRM is oblivious about any transactions it has not informed the transaction manager about and therefore can presume them to have been aborted.

The presumed abort two-phase commit protocol allows the resource managers to enlist in new transactions while the in-doubt transactions are being resolved. The coordinator is able to segregate new transactions from the old transactions, based on the following conditions:

  • New transactions are those that the resource manager enlists in after the new resource manager-coordinator relationship is established.
  • Old transactions are those enlisted in prior to the establishment of the new relationship.
HRESULT RecoveryDone (void);

Return Values

S_OK
Success.
XACT_E_NOTSUPPORTED
Indicates that the version of the associated transaction manager does not support the LRM functionality. The LRM should never get this error, because it should not have progressed this far if the transaction manager was not the correct version.
XACT_E_LRMRECOVERYALREADYDONE
The RecoveryDone method was invoked at least once after this interface was obtained. Therefore, the LRM recovery is already complete.
E_INVALIDARG
One or more arguments are invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
An unexpected error has occurred.
XACT_E_CONNECTION_DOWN
The connection with the transaction manager was lost.

See Also

IResourceManager Interface


ILastResourceManager::TransactionCommitted

This method should only be called by a resource manager that has previously requested to be the Last Resource Manager (LRM) in the transaction. Failure to abide by this rule results in the error code XACT_E_NOTLASTRESOURCEMANAGER.

A Last Resource Manager (LRM) can invoke this method to inform the transaction manager that the transaction was committed. When the LRM has called this method, all transactions whose outcomes have not been reported via this method are presumed to have aborted.

If the outcome is aborted, it is not necessary to notify the MS DTC Proxy of the transaction outcome, because the transaction manager in MS DTC uses a presumed abort protocol.

At recovery, the LRM must inform the transaction manager about all transactions that were committed for which it believes the transaction manager is in-doubt. Before replying to a ITransactionResourceAsync::PrepareRequest call with a prepared message, the LRM obtains prepare information from the enlistment object by using the IPrepareInfo::GetPrepareInfo method. This prepare information is persisted by the resource manager in its log before it replies with a prepared message. The prepare information is passed as an argument to the TransactionCommitted method.

After the transaction manager has persisted the decision to delegate the commit to an LRM, the transaction is in-doubt from the transaction manager's perspective until it receives a TransactionCommitted or ILastResourceManager::RecoveryDone method call from the LRM. If a fault happens that causes the enlistment and the resource manager objects to go away, and the transaction was committed, the LRM uses TransactionCommitted to inform the transaction manager about the transaction. Such a transaction is said to have been committed only when the LRM has successfully persisted its decision to commit the transaction.

Caution It is not correct to call this method after the RecoveryDone method has been called. Failure to abide by this rule results in the error code of XACT_E_LRMRECOVERYALREADYDONE.

HRESULT TransactionCommitted (
   unsigned char * pPrepInfo,
   ULONG cbPrepInfo
);

Parameters

pPrepInfo
[in] Binary data containing the prepare information previously obtained from the enlistment object and written into the resource manager's log.
CbPrepInfo
[in] Length in bytes of pPrepInfo.

Return Values

S_OK
Success.
XACT_E_NOTSUPPORTED
Indicates that the version of the associated transaction manager does not support the LRM functionality. The LRM should never get this error, because it should not have progressed this far if the transaction manager was not the correct version.
XACT_E_LRMRECOVERYALREADYDONE
The RecoveryDone method was invoked at least once after this interface was obtained. Therefore, the LRM recovery is complete. This method cannot be called after recovery has completed.
E_INVALIDARG
One or more arguments are invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
An unexpected error has occurred.
XACT_E_CONNECTION_DOWN
The connection with the transaction manager was lost.

See Also

IResourceManager Interface


IPrepareInfo Interface

The resource manager uses this interface to retrieve prepare information from the transaction manager. The resource manager writes this prepare information to its log file when preparing at phase one. The prepare information is only needed if failure recovery is necessary. During recovery, the resource manager identifies the transactions that were prepared but not yet committed or aborted at the time of the failure. The resource manager is in-doubt about the outcome of these transactions. The resource manager provides the prepare information for these in-doubt transactions to the transaction manager. The transaction manager uses the prepare information to locate the in-doubt transactions, determine their outcomes, and return the outcomes to the resource manager. This permits the resource manager to resolve its in-doubt transactions.

When to Implement

You do not need to implement this interface. It is implemented by the enlistment object of the MS DTC Proxy.

When to Use

Use this interface to retrieve prepare information from the transaction manager.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IPrepareInfo Methods | Description
GetPrepareInfoSize | Determines the size in bytes of the prepare information.
GetPrepareInfo | Retrieves the transaction prepare information.

Remarks

Call QueryInterface on the ITransactionEnlistmentAsync Interface on the enlistment object with a riid of IID_IPrepareInfo.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface


IPrepareInfo::GetPrepareInfo

This method is called by the resource manager to get the transaction prepare information.

HRESULT GetPrepareInfo(
  unsigned char * pPrepInfo
);

Parameters

pPrepInfo
[out] Pointer to the caller allocated buffer to receive the prepare information. The size of pPrepInfo is determined by calling IPrepareInfo::GetPrepareInfoSize.

Return Values

S_OK
Success.
E_INVALIDARG
The value of pPrepInfo is NULL.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface


IPrepareInfo::GetPrepareInfoSize

This method is called by the resource manager to determine the size in bytes of the prepare information that needs to be logged.

HRESULT GetPrepareInfoSize(
  ULONG * pcbPrepInfo
);

Parameters

pcbPrepInfo
[out] A pointer to the size in bytes of the prepare information. The actual prepare information is available by a call to IPrepareInfo::GetPrepareInfo.

Return Values

S_OK
Success.
E_INVALIDARG
The value of pcbPrepInfo is NULL.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface


IResourceManager Interface

The resource manager uses this interface to enlist in distributed transactions. Following a failure, the resource manager uses this interface to determine the outcome of in-doubt transactions.

When to Implement

You do not need to implement this interface. It is implemented by the resource manager object of the MS DTC Proxy.

When to Use

Use this interface to enlist in distributed transactions and to determine the outcome of in-doubt transactions.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IResourceManager Methods | Description
Enlist | Enlists a resource manager in a transaction.
Reenlist | Re-enlists a resource manager in a transaction.
ReenlistmentComplete | Notifies coordinator to forget obligations to any transaction.
GetDistributedTransactionManager | Obtains an interface on the Distributed Transaction Coordinator.

Remarks

A pointer to this call is returned by the IResourceManagerFactory::Create method.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface


IResourceManager::Enlist

Enlists a resource manager in a transaction.

HRESULT Enlist(
  ITransaction * pTransaction,
  ITransactionResourceAsync * pRes,
  XACTUOW * pUOW,
  LONG * pisoLevel,
  ITransactionEnlistmentAsync** ppEnlist
);

Parameters

pTransaction
[in] Pointer to the transaction object in which the resource manager wishes to enlist.
pRes
[in] Pointer to the resource manager's ITransactionResourceAsync interface. The resource manager developer must implement the methods on this interface.
pUOW
[out] Pointer to the transaction identifier GUID.
pisoLevel
[out] Pointer to the value of the client specified isolation level.
ppEnlist
[out] Pointer to the pointer to the ITransactionEnlistAsync interface on the enlistment object.

Return Values

S_OK
Success.
E_INVALIDARG
One or more parameters were invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
Something unexpected happened.
XACT_E_ABORT
The transaction has aborted.
XACT_E_CONNECTION_DOWN
Lost connection with the TM.
XACT_E_NOTRANSACTION
For some reason the transaction could not be found. Perhaps it was not exported or it could have been aborted and forgotten before the enlist call was made.
XACT_E_LOGFULL
Unable to enlist as the LOG is full.
XACT_E_TOOMANY_ENLISTMENTS
The coordinator already has maximum number of Resources Enlisted in the transaction is unable to enlist any more. Typically Coordinators should not have an arbitrary limit as to the maximum number of enlistments they can support.

Remarks

An instance of ITransactionResourceAsync is passed as an argument. This interface is implemented by the RM and there is an instance of it per transaction enlistment. If the Coordinator is successful in enlisting the RM on the requested transaction then the RM will receive an instance of ITransactionEnlistmentAsync as an out parameter to the Enlist method. The thing to note is that an ITransaction instance is being provided to the method as in argument, however the transaction in the general case would have been begun by the application. The RM somehow needs to obtain that transaction from the client before it can request to be enlisted in it. The process for propagating the transaction from the application to the RM is discussed later. In brief the application calls a function or invokes a method in the RM proxy, asking it to enlist in the transaction. The RM proxy then with the help of MS DTC proxy is responsible for propagating the transaction to the resource manager server.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface


IResourceManager::GetDistributedTransactionManager

Returns an interface pointer on MS DTC from the resource manager object.

HRESULT GetDistributedTransactionManager(
  REFIID riid,
  void** ppvObject
);

Parameters

riid
[in] IID of the requested interface.
ppvObject
[out] Pointer to the pointer to the requested interface.

Return Values

S_OK
Success.
E_NOINTERFACE
Unable to provide the requested interface.

Remarks

The IResourceManager interface was obtained by calling the Create method on IResourceManagerFactory interface. The IResourceManagerFactory and IResourceManagerfactory2 interfaces can be obtained by calling QueryInterface on one of the other interfaces supported by the MS DTC object or by calling the DtcGetTransactionManager function.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface


IResourceManager::Reenlist

This method re-enlists a resource manager in a transaction.

HRESULT Reenlist(
  unsigned char * pPrepInfo,
  ULONG cbPrepInfo,
  ULONG ulTimeout,
  XACTSTAT * pXactStat
);

Parameters

pPrepInfo
[in] Binary BLOB containing the prepare information previously obtained from the Enlistment object and written into the resource manager's log.
cbPrepInfo
[in] Length in bytes of pPrepInfo.
ulTimeout
[in] How long the RM is willing to wait for the outcome of a transaction, in milliseconds. 0x0 defined as XACTCONST_TIMEOUTINFINITE is the infinite time-out value.
pXactStat
[out] TM provides the status of the transaction. One of the following values:

XACTSTAT_ABORTED
XACTSTAT_COMMITTED

Return Values

S_OK
Success.
E_INVALIDARG
One or more arguments are invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
Something unexpected occurred.
XACT_E_CONNECTION_DOWN
Lost connection with the TM.
XACT_E_REENLISTTIMEOUT
The re-enlist request timed out. XACTSTAT_NONE is returned via *pXactStat when this error occurs.
XACT_E_RECOVERYALREADYDONE
ReenlistmentComplete method was invoked at least once after this interface was obtained. Therefore, the recovery is complete. Cannot re-enlist after recovery has completed.

Remarks

At recovery, the RM reregisters with the coordinator to re-establish its relationship with it and obtains a new resource manager object representing the new relationship. After obtaining the IResourceManager interface, it starts asking the coordinator for the outcome of all transactions that are in-doubt from the resource manager's perspective. Before replying with a Prepared message on a Prepare Request, the resource manager needs to obtain prepare information from the Enlistment object by using the IPrepareInfo::GetPrepareInfo method. This BLOB is persisted by the RM in its log before it replies with a Prepared message. After the RM is prepared, the transaction is in-doubt from it's perspective until it receives an Abort or a Commit Request from the coordinator. If a fault was to happen that causes the enlistment and the resource manager object to go away, then the RM needs to use this method to determine the final outcome of the transaction. The prepare information is passed as a parameter to the Reenlist method call.

The outcome can be either COMMITTED or ABORTED. There can be no other outcome the call times out and a XACT_E_REENLISTTIMEOUT error is returned. MS DTC uses the presumed abort protocol; this protocol lets the coordinator to unilaterally abort a transaction if a fault occurs prior to it having made a COMMIT decision. A transaction is said to have been committed only when the Coordinator has successfully persisted its decision to COMMIT the transaction.

Caution It is not correct to ask for the outcome of a transaction after it has completed. The coordinator is responsible for providing the outcome only for those transactions which it remembers. All aborted transactions are forgotten immediately and no information regarding those transactions persists. All committed transactions are forgotten after all the resource managers that were enlisted in that transaction have replied with a "Commit Request Done" message, meaning that the Coordinator successfully obtained a reply to the second phase from each of the resource managers that was enlisted in that transaction. Only under certain optimizations will the resource manager or managers not receive the second phase notifications.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface


IResourceManager::ReenlistmentComplete

The resource manager calls ReenlistmentComplete after resolving all the in-doubt transactions it knows about.

HRESULT ReenlistmentComplete();

Return Values

S_OK
Success.
E_INVALIDARG
One or more arguments are invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
Something unexpected occurred.
XACT_E_CONNECTION_DOWN
Lost connection with the TM.
XACT_E_RECOVERYALREADYDONE
The ReenlistmentComplete method was called at least once after this interface was obtained. Therefore, the recovery is already complete.

Remarks

This lets the Coordinator forget any transactions that it was remembering, as it had an obligation to remember those transactions until it was certain that the resource manager knew the outcome of those transactions. An RM will forget a transaction before responding to the second phase, this allows for a window in which an RM would have forgotten a transaction but not the TM. This Window exists because the COMMITTED message from the RM to the Coordinator can get lost on its way due to some fault. A Coordinator would not know if the resource manager has received the COMMIT notification or not, unless it receives the COMMITTED message from the RM. Until it receives the COMMITTED message, it cannot forget the transaction. The RM when it reestablishes a relationship with the Coordinator will query the status for all the in-doubt transactions but it will not ask for the transactions that it had already forgotten. After resolving all the in-doubt transactions, it simply calls the IResourceManager::ReenlistmentComplete method which then lets the TM to forget the transactions.

This protocol lets the recovery process be repeated multiple times without affecting the outcome of transactions. Any number of failures such as crashes can occur during recovery, but the results will always be the same. This protocol also lets the resource managers enlist in new transactions while the in-doubt transactions are being resolved. The Coordinator is able to discern between the new transactions and the old transactions. New transactions are the ones that the RM enlists in from the point the new RM-Coordinator relationship is established, and all the old transactions are the ones that it had enlisted in prior to the establishment of the new relationship.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface


IResourceManager2 Interface

The resource manager uses this interface to enlist in distributed transactions. Following a failure, the resource manager uses this interface to determine the outcome of in-doubt transactions. The IResourceManager2 interface differs from the IResourceManager interface in that there is no need to query for the prepare information during the prepare phase of two-phase commit. Instead the resource manager can directly log the XID returned by the Enlist2 method call during the prepare phase. During recovery, the resource manager can also use the same XID to query the outcome of the transaction by calling on the Reenlist2 method.

When to Implement

You do not need to implement this interface. It is implemented by the resource manager object of the MS DTC Proxy.

When to Use

Use this interface to enlist in distributed transactions or determine the outcome of in-doubt transactions.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IResourceManager2 Methods | Description
Enlist2 | Enlists a resource manager in a transaction.
Reenlist2 | Re-enlists a resource manager in a transaction.

Remarks

A pointer to this call is returned by the IResourceManagerFactory2::CreateEx method.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface

Built on Monday, January 22, 2001


IResourceManager2::Enlist2

Enlists a resource manager in a transaction and return an XID that can be used to query the outcome of the transaction during recovery.

HRESULT Enlist2(
  Itransaction * pTransaction,
  ITransactionResourceAsync * pRes,
  XACTUOW * pUOW,
  LONG * pisoLevel,
  XID * pxid,
  ITransactionEnlistmentAsync ** ppEnlist
);

Parameters

pTransaction
[in] Pointer to the transaction object in which the resource manager wishes to enlist.
pRes
[in] Pointer to the resource manager's ITransactionResourceAsync interface. The resource manager developer must implement the methods on this interface.
pUOW
[out] Pointer to the transaction identifier GUID.
pisoLevel
[out] Pointer to the value of the client specified isolation level.
pxid
[in] A pointer to the XID structure that contains the transaction identifier of the transaction.
ppEnlist
[out] Pointer to the pointer to the ITransactionEnlistAsync interface on the enlistment object.

Return Values

S_OK
Success.
E_INVALIDARG
One or more parameters were invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
Something unexpected happened.
XACT_E_ABORT
The transaction has aborted.
XACT_E_CONNECTION_DOWN
Lost connection with the TM.
XACT_E_NOTRANSACTION
For some reason the transaction could not be found. Perhaps it was not exported or it could have been aborted and forgotten before the enlist call was made.
XACT_E_LOGFULL
Unable to enlist as the LOG is full.
XACT_E_TOOMANY_ENLISTMENTS
The coordinator already has maximum number of Resources Enlisted in the transaction is unable to enlist any more. Typically Coordinators should not have an arbitrary limit as to the maximum number of enlistments they can support.

Remarks

An instance of ITransactionResourceAsync is passed as an argument. This interface is implemented by the RM and there is an instance of it per transaction. If the Coordinator is successful in enlisting the RM on the requested transaction then the RM will receive an instance of ITransactionEnlistmentAsync as an out parameter to the Enlist method. The thing to note is that an ITransaction instance is being provided to the method as in argument, however the transaction in the general case would have been begun by the application. The RM somehow needs to obtain that transaction from the client before it can request to be enlisted in it. The process for propagating the transaction from the application to the RM is discussed later. In brief the application calls a function or invokes a method in the RM proxy, asking it to enlist in the transaction. The RM proxy then with the help of MS DTC proxy is responsible for propagating the transaction to the resource manager server.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface


IResourceManager2::Reenlist2

Re-enlists a resource manager in a transaction using an XID to identify the transaction.

HRESULT Reenlist2(
  XID * pXid,
  DWORD dwTimeout,
  XACTSTAT * pXactStat
);

Parameters

pXid
[in] A pointer to the XID structure that contains the transaction identifier of the transaction.
dwTimeout
[in] How long the RM is willing to wait for the outcome of a transaction, in milliseconds. 0x0 defined as XACTCONST_TIMEOUTINFINITE is the infinite time-out value.
pXactStat
[out] TM provides the status of the transaction. One of the following values:

XACTSTAT_ABORTED
XACTSTAT_COMMITTED

Return Values

S_OK
Success.
E_INVALIDARG
One or more arguments are invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
Something unexpected occurred.
XACT_E_CONNECTION_DOWN
Lost connection with the TM.
XACT_E_REENLISTTIMEOUT
The re-enlist request timed out. XACTSTAT_NONE is returned via *pXactStat when this error occurs.
XACT_E_RECOVERYALREADYDONE
ReenlistmentComplete method was invoked at least once after this interface was obtained. Therefore, the recovery is complete. Cannot re-enlist after recovery has completed.

Remarks

At recovery, the RM reregisters with the coordinator to re-establish its relationship with it and obtains a new resource manager object representing the new relationship. After obtaining the IResourceManager2 interface, it starts asking the coordinator for the outcome of all transactions that are in-doubt from the resource manager's perspective. During the prepare phase the resource manager should log the XID returned from the Enlist2 method call instead of logging the prepare information. After the RM is prepared, the transaction is in-doubt from it's perspective until it receives an Abort or a Commit Request from the coordinator. If a fault was to happen that causes the enlistment and the resource manager object to go away, then the RM needs to use this method to determine the final outcome of the transaction. The XID is passed as a parameter to the Reenlist2 method call.

The outcome can be either COMMITTED or ABORTED. There can be no other outcome the call times out and a XACT_E_REENLISTTIMEOUT error is returned. MS DTC uses the presumed abort protocol; this protocol lets the coordinator to unilaterally abort a transaction if a fault occurs prior to it having made a COMMIT decision. A transaction is said to have been committed only when the Coordinator has successfully persisted its decision to COMMIT the transaction.

Caution It is not correct to ask for the outcome of a transaction after it has completed. The coordinator is responsible for providing the outcome only for those transactions which it remembers. All aborted transactions are forgotten immediately and no information regarding those transactions persists. All committed transactions are forgotten after all the resource managers that were enlisted in that transaction have replied with a "Committed" message, meaning that the Coordinator successfully obtained a reply to the second phase from each of the resource managers that was enlisted in that transaction. Only under certain optimizations will the resource manager or managers not receive the second phase notifications.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager2 Interface


IResourceManagerFactory Interface

This interface contains a single method that is used to create a new resource manager object. The resource manager object represents the active connection between the resource manager and the transaction manager. Resource managers use this interface to register themselves with the transaction manager.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

A process uses the IResourceManagerFactory interface to create a new resource manager object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IResourceManagerFactory Methods | Description
Create | Creates a resource manager object.

Remarks

The interface source is returned by the IResourceManagerFactory::Create method.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManagerFactory2 Interface


IResourceManagerFactory::Create

This method is used to create a resource manager object.

HRESULT Create(
  GUID * pguidRM,
  TCHAR * pszRMName,
  IResourceManagerSink * pIResMgrSink,
  IResourceManager** ppResMgr
);

Parameters

pguidRM
[in] A UUID that uniquely identifies this resource manager.
pszRMName
[in] A string name that identifies this resource manager.
pIResMgrSink
[in] Pointer to the resource manager's IResourceManagerSink interface. The resource manager developer must implement the TMDown method on this interface.
ppResMgr
[out] Pointer to the pointer to the IResourceManager interface on the resource manager object.

Return Values

S_OK
Success.
E_NOINTERFACE
Requested interface is not available.
E_OUTOFMEMORY
Unable to allocate memory.
XACT_E_TMNOTAVAILABLE
Unable to connect to the transaction manager.
XACT_E_CONNECTION_DOWN
Connection with the transaction manager was lost.
XACT_E_CONNECTION_REQUEST_DENIED
The transaction manager refused to accept a connection.
XACT_E_DUPLICATE_GUID
There is already a resource manager connected to the transaction manager with the same GUID as was passed in pguidRM.
E_UNEXPECTED
An unexpected error has occurred.

Remarks

The resource manager object represents the connection between the resource manager and the transaction manager. The resource manager object supports the IResourceManager Interface that resource manager use to enlist in transactions and to perform transaction recovery.

A resource manager typically invokes the IResourceManagerFactory::Create method when the resource manager first starts. By doing this the resource manager registers itself with the transaction manager. The resource manager retains the resource manager object until it no longer needs the services of the transaction manager. It then releases IResourceManager interface. This ends the connection with the transaction manager. A resource manager typically retains the transaction manager connection until the resource manager stops.

If the connection between the transaction manager and the resource manager fails, the MS DTC proxy invokes the resource manager's TMDown method. This callback informs the resource manager that its transaction manager connection has failed. The resource manager must invoke the Create method again to reregister with the transaction manager and perform recovery.


IResourceManagerFactory2 Interface

This interface contains a single method that is used to create a new resource manager object. The resource manager object represents the active connection between the resource manager and the transaction manager. Resource managers use this interface to register themselves with the transaction manager.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

A resource manager will use this interface to register themselves with the transaction manager.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IResourceManagerFactory2 Methods | Description
CreateEx | Creates a resource manager object.

Remarks

Call QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_IResourceManagerFactory2.

Requirements

To use the methods of this interface, you must include Txdtc.h in your project.

See Also

IResourceManagerFactory Interface


IResourceManagerFactory2::CreateEx

This method is used to create a resource manager object.

HRESULT CreateEx(
  GUID * pguidRM,
  TCHAR * pszRMName,
  IResourceManagerSink * pIResMgrSink,
  REFIID riidRequested,
  IResourceManager** ppResMgr
);

Parameters

pguidRM
[in] A UUID that uniquely identifies this resource manager.
pszRMName
[in] A string name that identifies this resource manager.
pIResMgrSink
[in] Pointer to the resource manager's IResourceManagerSink interface. The resource manager developer must implement the TMDown method on this interface.
riidRequested
[in] Pointer to the ID requested by the resource manager.
ppResMgr
[out] Pointer to the pointer to the interface on the resource manager object, whose iid is specified in the riidRequested parameter.

Return Values

S_OK
Success.
E_NOINTERFACE
Requested interface is not available.
E_OUTOFMEMORY
Unable to allocate memory.
XACT_E_TMNOTAVAILABLE
Unable to connect to the transaction manager.
XACT_E_CONNECTION_DOWN
Connection with the transaction manager was lost.
XACT_E_CONNECTION_REQUEST_DENIED
The transaction manager refused to accept a connection.
XACT_E_DUPLICATE_GUID
There is already a resource manager connected to the transaction manager with the same GUID as was passed in pguidRM.
E_UNEXPECTED
An unexpected error has occurred.

Remarks

The resource manager object represents the connection between the resource manager and the transaction manager. The resource manager object supports the IResourceManager2 interface that resource manager use to enlist in transactions and to perform transaction recovery.

A resource manager typically invokes the IResourceManagerFactory2::CreateEx method when the resource manager first starts. By doing this the resource manager registers itself with the transaction manager. The resource manager retains the resource manager object until it no longer needs the services of the transaction manager. It then releases IResourceManager2 interface. This ends the connection with the transaction manager. A resource manager typically retains the transaction manager connection until the resource manager stops.

If the connection between the transaction manager and the resource manager fails, the MS DTC proxy invokes the resource manager's IResourceManagerSink::TMDown method. This callback informs the resource manager that its transaction manager connection has failed. The resource manager must invoke the IResourceManagerFactory2::CreateEx method again to reregister with the transaction manager and perform recovery.

Requirements

To call this method you must include Txdtc.h in your project.

See Also

IResourceManagerFactory Interface


IResourceManagerSink Interface

This is a callback interface implemented by the resource manager. The interface is passed as a parameter to IResourceManagerFactory::Create and registered in the resource manager object. The MS DTC proxy calls the resource manager's IResourceManagerSink:TMDown callback method if the transaction manager fails. This informs the resource manager that it must perform recovery.

If the connection between the MS DTC proxy and the transaction manager fails, the MS DTC proxy first calls the resource manager's ITransactionResourceAsync::PrepareRequest and ITransactionResourceAsync::CommitRequest methods for each transaction enlistment whose outcome is known. The MS DTC proxy calls the resource manager's ITransactionResourceAsync::TMDown method once for each transaction enlistment whose outcome is not known. In affect, the MS DTC proxy will run-down all of the resource manager enlistment's. The MS DTC proxy then calls the resource manager's IResourceManagerSink::TMDown method. This signals the resource manager that all enlistments have been run-down and the resource manager can perform recovery. Note that only the transaction enlistments that received the ITransactionResourceAsync::TmDown method call will need to be recovered.

When to Implement

You do not need to implement this interface. It is implemented by the resource manager of the MS DTC Proxy.

When to Use

Use this interface to inform the resource manager that it must perform recovery for a failed transaction manager.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IResourceManagerSink Methods | Description
TMDown | Called by the DTC proxy to inform the RM that it must perform recovery.

Remarks

The MS DTC proxy invokes this method if the transaction manager fails.

Requirements

To use the methods of this interface, you must include Txdtc.h in your project.

See Also

IResourceManagerFactory Interface


IResourceManagerSink::TMDown

The MS DTC proxy calls the resource manager's IResourceManagerSink:TMDown callback method if the transaction manager fails. This informs the resource manager that it must perform recovery.

interface IResourceManagerSink : IUnknown
{
   void   TMDown (void) ;
}


ITipHelper Interface

The ITipHelper and the ITipTransaction interfaces provide functionality to propagate transaction objects using the Transaction Internet Protocol (TIP). The ITipHelper interface provides methods to pull transactions given a TIP Transaction URL and to get the TIP TM URL of the local TM.

When to Implement

You do not need to implement this interface. The core TM object in the MS DTC Proxy implements this interface.

When to Use

Use this interface to pull transactions from a TIP Transaction manager (TM) to an OLE Transaction TM and to query the OLE Transactions TIP TM URL of the TM.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITipHelper Methods | Description
Pull | Returns an ITransaction pointer to the transaction object created corresponding to the transaction identified by the TIP Transaction URL pszTxUrl.
PullAsync | Provides the option for applications to asynchronously pull a transaction
GetLocalTmUrl | Retrieves the TIP TM URL identifying the application's OLE Transaction TM.

Remarks

To get a pointer to this interface, applications can either call QueryInterface on the core TM object or call DtcGetTransactionManager. Both these calls would use IID_ITipHelper as the IID of the interface to return.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipTransaction Interface

ITipPullSink Interface


ITipHelper::GetLocalTmUrl

The application calls this method to get the TIP TM URL identifying the application's OLE Transaction TM. The TIP TM URL identifies the TM in a network of computers. It is of the form "tip://<tcp-ip endpoint>/<path>". For example, "tip://www.microsoft.com:4321/" would be a valid TIP TM URL for a transaction manager running on the server "www.microsoft.com" listening for TIP requests on port 4321.

HRESULT GetLocalTmUrl(
  char ** ppszLocalTmUrl
);

Parameters

ppszLocalTmUrl
[out] This parameter returns the TIP TM URL of the application's Transactions TM. The application must free this parameter by calling CoTaskMemFree after it is finished using it.

Return Values

S_OK
Success—the TIP TM URL was returned.
E_OUTOFMEMORY
Failure—out of resources.
E_INVALIDARG
Failure—one or more of the parameters are not valid.
E_FAIL
Failure—generic failure while attempting to get the local TM's TIP TM URL.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_TIP_DISABLED
Failure—the Transaction Internet Protocol (TIP) service is disabled by default.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipTransaction Interface

ITipPullSink Interface


ITipHelper::Pull

This method returns an ITransaction pointer to the transaction object created corresponding to the transaction identified by the TIP Transaction URL pszTxUrl. pszTxUrl can refer to either a transaction on the applications local TM or a transaction on a remote TIP TM. In the former case, the local TM expects the transaction to exist in its data structures. In the latter case, the local TM will check to determine whether the transaction was pulled at some earlier time; if not, it will send a TIP pull message to the remote TIP TM.

HRESULT Pull(
  char * pszTxUrl,
  ITransaction ** ppITransaction
);

Parameters

pszTxUrl
[in] Specifies the TIP Transaction URL of the transaction to pull.
ppITransaction
[out] Returns an ITransaction pointer to the transaction object corresponding to the transaction identified by pszTxUrl.

Return Values

S_OK
Success—the transaction pull completed.
E_OUTOFMEMORY
Failure—out of resources.
E_INVALIDARG
Failure—one or more of the parameters are not valid.
E_FAIL
Failure—generic failure while pulling the transaction from the remote TM.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_TMNOTAVAILABLE
Failure—unable to establish a connection with the DTC service.
XACT_E_CONNECTION_DOWN
Failure—the connection to the local TM is down.
XACT_E_CONNECTION_DENIED
Failure—the local TM refused the application's connection request.
XACT_E_LOGFULL
Failure—the TM's log is full.
XACT_E_TIP_DISABLED
Failure—the Transaction Internet Protocol (TIP) service is disabled by default.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipTransaction Interface

ITipPullSink Interface


ITipHelper::PullAsync

This method provides applications with the option to asynchronously pull a transaction. By asynchronously pulling a transaction, the application can start work on the transaction before the pull completes. This mechanism provides for more parallelism. The application provides the TIP Transaction URL of the transaction to pull. The application also provides a pointer to a sink that will receive the pull completion status. The TM returns an ITransaction pointer to a transaction object. Similar to the ITipHelper::Pull method, the pszTxUrl parameter can refer to a transaction on the applications local TM or to a transaction on a remote TIP TM.

HRESULT PullAsync(
  char ** pszTxUrl
  ITipPullSink * pTipPullSink
  ITransaction ** ppITransaction
);

Parameters

pszTxUrl
[in] This parameter specifies the TIP Transaction URL of the transaction to pull.
pTipPullSink
[in] This parameter specifies the sink to call upon completion of the asynchronous pull operation.
ppITransaction
[out] This parameter returns an ITransaction pointer to the transaction object identified by pszTxUrl.

Return Values

S_OK
Success—the asynchronous pull request was queued.
E_OUTOFMEMORY
Failure—out of resources.
E_INVALIDARG
Failure—one or more of the parameters are not valid.
E_FAIL
Failure—generic failure while attempting to pull the transaction from the remote TM.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_TMNOTAVAILABLE
Failure—unable to establish a connection with the DTC service.
XACT_E_CONNECTION_DOWN
Failure—the connection to the local TM is down.
XACT_E_CONNECTION_DENIED
Failure—the local TM refused the applications connection request.
XACT_E_TIP_DISABLED
Failure—the Transaction Internet Protocol (TIP) service is disabled by default.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipTransaction Interface

ITipPullSink Interface


ITipPullSink Interface

The application provides the MSDTC Proxy with an ITipPullSink pointer when it calls on ITipHelper::PullAsync. The TM will in turn call on the ITipPullSink interface once the asynchronous pull operation completes.

When to Implement

The application is responsible for implementing this interface. Applications are free to choose which objects implement it.

When to Use

An application uses this interface to provide an ITipPullSink pointer.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITipPullSink Methods | Description
PullComplete | The OLE Transaction manager calls on this method, once it has determined that the asynchronous pull operation has completed to return its completion status.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipTransaction Interface and the ITipHelper Interface


ITipPullSink::PullComplete

The OLE transactions TM calls on this method once it has determined that the asynchronous pull operation has completed. The completion status of the pull operation is reflected in the hrPull parameter.

C++ Syntax

HRESULT PullComplete(
  HRESULT * hrPull,
);

Parameters

hrPull
[in] Retrieves detailed completion status of the asynchronous pull operation.

Return Values for hrPull

S_OK
Success—the transaction pull completed.
E_OUTOFMEMORY
Failure—out of resources.
E_FAIL
Failure—generic failure while attempting to pull the transaction from the remote TM.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_LOGFULL
Failure—the TMs log is full.
XACT_E_NOTRANSACTION
Failure—the transaction committed or aborted before the pull operation could complete.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipTransaction Interface and the ITipHelper Interface


ITipTransaction Interface

This interface provides methods to support TIP specific functionality on the transaction object.

When to Implement

You do not need to implement this interface. The core TM object in MSDTC Proxy implements this interface.

When to Use

Use this interface to retrieve a Transaction URL and to push the transaction from an OLE Transaction Manager to a TIP Transaction Manager.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITipTransaction Methods | Description
Push | The Transaction Manager (TM) sends the TIP "PUSH" command to the remote TIP TM.
GetTransactionUrl | Retrieves the TIP Transaction URL identifying the transaction object.

Remarks

To get a pointer to this interface the application calls IUnknown::QueryInterface on the transaction object passing in an IID of IID_ITipTransaction.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipHelper Interface and ITipPullSink Interface


ITipTransaction::GetTransactionURL

The application calls this method to get the TIP Transaction URL identifying the transaction object. The TIP Transaction URL identifies the transaction in a network of computers. It is of the form "tip://<tcp-ip endpoint>/<path>?<transaction identifier in ASCII>". For example, "tip://www.microsoft.com/?oletx-0000000-0000-0000-0000-000000000001" would be a valid TIP Transaction URL for a transaction object with the identifier "0000000-0000-0000-0000-000000000001" created by a DTC service running on the server "www.microsoft.com". The previous example assumes that the DTC service is listening for a TIP request on the default transaction service port number. This port number is defined in the TIP specification.

HRESULT GetTransactionUrl(
  char ** ppszLocalTxUrl
);

Parameters

ppszLocalTxUrl
[out] This parameter returns the TIP Transaction URL identifying the transaction object. The application must free this parameter by calling CoTaskMemFree after it is finished using it.

Return Values

S_OK
Success—the TIP Transaction URL was returned.
E_OUTOFMEMORY
Failure—out of resources.
E_INVALIDARG
Failure—one or more of the parameters are not valid.
E_FAIL
Failure—generic failure occurred while trying to get the TIP Transaction URL of the transaction specified.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_NOTRANSACTION
Failure—the transaction has already committed or aborted.
XACT_E_TIP_DISABLED
Failure—the Transaction Internet Protocol (TIP) service is disabled by default.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipHelper Interface and ITipPullSink Interface


ITipTransaction::Push

A call to this method causes the Transactions Transaction Manager (TM) to send the TIP push command to the remote TIP transaction manager. The transaction identifier accompanying the push command is a string form of the Unit of Work Identifier of the transaction object on which the ITipTransaction::Push call was made. For the DTC, the string form of the Unit of Work Identifier is the string "oletx-" followed by the string form of a Universally Unique Identifier (UUID); that is, it is of the form "oletx-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", where the Xs are the ASCII representation of hexadecimal digits.

HRESULT Push(
  char * pszRemoteTmUrl,
  char ** ppszRemoteTxUrl
);

Parameters

pszRemoteTmUrl
[in] Specifies the destination transaction manager's TIP TM URL.
ppszRemoteTxUrl
[out] Returns the TIP Transaction URL identifying the transaction on the remote TM. The application must free this parameter by calling CoTaskMemFree after it is finished using it.

Return Values

S_OK
Success—the transaction push completed.
E_OUTOFMEMORY
Failure—out of resources.
E_INVALIDARG
Failure—one or more parameters are not valid.
E_FAIL
Failure—generic failure while pushing the transaction to the remote TM.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_TMNOTAVAILABLE
Failure—unable to establish a connection with DTC service.
XACT_E_CONNECTION_DOWN
Failure—the connection to the local TM is down.
XACT_E_CONNECTION_DENIED
Failure—the local TM refused the application's connection request.
XACT_E_LOGFULL
Failure—the TMs log is full.
XACT_E_NOTRANSACTION
Failure—the transaction has already committed or aborted.
XACT_E_TIP_DISABLED
Failure—the Transaction Internet Protocol (TIP) service is disabled by default.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITipHelper Interface

ITipPullSink Interface


ITransaction Interface

The ITransaction interface is used to commit and abort transactions and to obtain status information about transactions.

When to Implement

You do not need to implement this interface. It is implemented by the transaction object of the MS DTC Proxy.

When to Use

Application programs and resource managers that commit and abort transactions use this interface to obtain status information about transactions.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransaction Methods | Description
Commit | Commits the transaction.
Abort | Aborts the transaction.
GetTransactionInfo | Returns information regarding a transaction object.

Remarks

You obtain a pointer to this interface by calling the ITransactionDispenser::BeginTransaction method or the ITransactionImport::Import method.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionImport Interface or the ITransactionDispenser Interface.


ITransaction::Abort

This method aborts the transaction.

HRESULT Abort(
  BOID * pboidReason,
  BOOL fRetaining,
  BOOL fAsync
);

Parameters

pboidReason
[in] An optional BOID that indicates why the transaction is being aborted. This argument may be NULL indicating that no abort reason is provided.
fRetaining
[in] Must be FALSE.
fAsync
[in] When fAsync is TRUE, an asynchronous abort is performed and the caller must use ITransactionOutcomeEvents to learn the outcome of the transaction.

Return Values

S_OK
Success: the transaction was successfully aborted.
XACT_S_ASYNC
An asynchronous Abort was specified. The abort operation has begun but its outcome is not yet known. When the transaction completes, notification will be sent on the ITransactionOutcomeEvents interface if any connection point sinks are registered with the transaction object.
XACT_E_NOTRANSACTION
Unable to abort the transaction because it had already been committed or aborted. This call was ignored.
XACT_E_ALREADYINPROGRESS
A Commit operation was already in progress. This call was ignored.
XACT_E_CANTRETAIN
Retaining Abort is not supported. This call was ignored.
E_FAIL
The transaction failed to abort for an unspecified reason.
E_UNEXPECTED
An unexpected error has occurred. The transaction status is unknown.
XACT_S_ABORTING
An Abort operation was already in progress. This call was ignored.
XACT_E_INDOUBT
This error can only be returned if the calling application did not initiate the transaction. This error implies that the MSDTC Proxy issued the abort operation on the MSDTC TM but before transaction manager could confirm that the transaction was aborted the connection between the proxy and the tm was broken. The transaction may have aborted or the transaction may still be active.
XACT_E_CONNECTION_DOWN
No longer able to communicate with the transaction manager because the connection to the transaction manager failed. The transaction state is unknown.

Remarks

The initiator of the transaction may abort the transaction as may any resource manager enlisted on the transaction.

Abort may be invoked on a transaction repeatedly. XACT_S_ABORTING HRESULT will be returned following the first invocation of Abort.

If a communication failure occurs during a call to Commit or Abort, the status of the transaction is unknown.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionImport Interface or the ITransactionDispenser Interface.


ITransaction::Commit

This method commits the transaction. The Commit method may only be called by the initiator of the transaction.

HRESULT Commit(
  BOOL fRetaining,
  DWORD grfTC,
  DWORD grfRM
);

Parameters

fRetaining
[in] Must be FALSE.
grfTC
[in] Values taken from the enumeration XACTTC.
Flag | Meaning
XACTTC_ASYNC | When this flag is specified, an asynchronous commit is performed. This flag may not be specified with any other flags.
XACTTC_ASYNC_PHASEONE | Same as XACTTC_ASYN_PHASEONE.
XACTTC_SYNC_PHASEONE | When this flag is specified, the call to Commit returns after phase one of the two-phase commit protocol. This flag may not be specified with any other flags.
XACTTC_SYNC_PHASETWO | This flag is not supported. When this flag is specified, the call to Commit returns after phase two of the two-phase commit protocol. This flag may not be specified with any other flags..
XACTTC_SYNC | This flag is not supported. Same as XACTTC_SYNC_PHASETWO.
grfRM
[in] Must be zero.

Return Values

S_OK
Success. Transaction was successfully committed.
XACT_S_ASYNC
An asynchronous commit was specified. The commit operation has begun but its outcome is not yet known. When the transaction completes, notification will be sent on the ITransactionOutcomeEvents interface if any connection point sinks are registered with the transaction object.
XACT_E_NOTRANSACTION
Unable to commit the transaction because it had already been committed or aborted. This call was ignored.
XACT_E_ALREADYINPROGRESS
A commit or abort operation was already in progress. This call was ignored.
XACT_E_NOTSUPPORTED
An invalid combination of commit flags was specified. This call was ignored.
XACT_E_CANTRETAIN
Retaining commit is not supported. This call was ignored.
XACT_E_COMMITFAILED
The transaction failed to commit for an unknown reason. The transaction was aborted.
E_FAIL
The transaction failed to commit for an unknown reason. The transaction was aborted.
XACT_E_INDOUBT
The MSDTC Proxy issued a transaction commit operation to the MSDTC TM but before the transaction manager could return the outcome of the commit to the MSDTC Proxy the connection between the MSDTC Proxy and the TM was broken. The transaction may have committed or aborted.
E_UNEXPECTED
An unexpected error has occurred. The transaction status is unknown.
XACT_E_ABORTED
The transaction was aborted before Commit was called.
XACT_E_CONNECTION_DOWN
No longer able to communicate with the transaction manager because the connection to the transaction manager failed. The transaction was aborted.
XACT_E_COMMITPREVENTED
Cannot call commit on this transaction object because the calling application did not initiate the transaction.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionImport Interface or the ITransactionDispenser Interface.


ITransaction::GetTransactionInfo

This method returns information regarding a transaction object.

HRESULT    GetTransactionInfo(
  XACTTRANSINFO * pinfo
);

Parameters

pinfo
[out] Pointer to the caller allocated XACTTRANSINFO structure which will receive information about the transaction. Must not be NULL.

XACTTRANSINFO is defined as follows:

typedef struct XACTTRANSINFO {
    XACTUOW  uow;
    ISOLEVEL isoLevel;
    ULONG    isoFlags;
    DWORD    grfTCSupported;
    DWORD    grfRMSupported;
    DWORD    grfTCSupportedRetaining;
    DWORD    grfRMSupportedRetaining;
    } XACTTRANSINFO;

Members

uow
The unit of work associated with this transaction.
isoLevel
The isolation level associated with this transaction object. ISOLATIONLEVEL_UNSPECIFIED indicates that no isolation level was specified.
isoFlags
Will be zero.
grfTCSupported
This bit mask indicates which grfTC flags that this transaction implementation supports.
grfRMSupported
Will be zero.
grfTCSupportedRetaining
Will be zero.
grfRMSupportedRetaining
Will be zero.

Return Values

S_OK
Success.
XACT_E_NOTRANSACTION
Unable to retrieve information for the transaction because it was already completed. No information is returned.
E_UNEXPECTED
An unknown error occurred. No information is returned.
E_INVALIDARG
The value of pinfo was NULL.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionImport Interface or the ITransactionDispenser Interface.


ITransaction2 Interface

The ITransaction2 interface derives from The ITransactionCloner Interface. The interface implements a new behavior for ITransaction Interface.

When to Implement

You do not need to implement this interface. It is implemented by the transaction object of the MS DTC Proxy.

When to Use

Use this interface to retrieve information of a transaction after it has completed.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransaction2 Methods | Description
GetTransactionInfo2 | Returns information regarding a transaction object.

Remarks

The behavior of GetTransactionInfo2 differs from that of GetTransactionInfo by allowing the calling application to retrieve information about the transaction after it has completed.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionCloner Interface


ITransaction2::GetTransactionInfo2

This method returns information regarding a transaction object.

HRESULT GetTransactionInfo2(
  XACTTRANSINFO * pinfo
);

Parameters

pinfo
[out] Pointer to the caller allocated XACTTRANSINFO structure which will receive information about the transaction. Must not be NULL.

XACTTRANSINFO is defined as follows:

typedef struct XACTTRANSINFO {
    XACTUOW  uow;
    ISOLEVEL isoLevel;
    ULONG    isoFlags;
    DWORD    grfTCSupported;
    DWORD    grfRMSupported;
    DWORD    grfTCSupportedRetaining;
    DWORD    grfRMSupportedRetaining;
    } XACTTRANSINFO;

Members

uow
The unit of work associated with this transaction.
isoLevel
The isolation level associated with this transaction object. ISOLATIONLEVEL_UNSPECIFIED indicates that no isolation level was specified.
isoFlags
Will be zero.
grfTCSupported
This bit mask indicates which grfTC flags that this transaction implementation supports.
grfRMSupported
Will be zero.
grfTCSupportedRetaining
Will be zero.
grfRMSupportedRetaining
Will be zero.

Return Values

S_OK
Success.
E_UNEXPECTED
An unknown error occurred. No information is returned.
E_INVALIDARG
The value of pinfo was NULL.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionCloner Interface


ITransactionCloner Interface

The ITransactionCloner interface is used to make clones of transaction objects such that the ITransaction::Commit method on the cloned transaction object will always fail with XACT_E_COMMITPREVENTED.

When to Implement

You do not need to implement this interface. It is implemented by the transaction object of the MS DTC Proxy.

When to Use

Use this interface to clone an MTS Windows NT 4.0 version of ITransaction Interface.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionCloner Methods | Description
CloneWithCommitDisabled | Receives the cloned ITransaction interface

Remarks

The returned ITransaction Interface disables ITransaction::Commit, leaving ITransaction::Abort and ITransaction::GetTransactionInfo as the active function.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction2 Interface.


ITransactionCloner::CloneWithCommitDisabled

This method disables ITransaction::Commit, leaving ITransaction::Abort and ITransaction::GetTransactionInfo as the active function.

HRESULT CloneWithCommitDisabled(
   ITransaction ** ppITransaction
);

Parameters

ppITransaction
[out] Address of pointer variable that receives the cloned interface pointer. Successful return contains the cloned ITransaction interface with ITransaction::Commit disabled.

Return Values

S_OK
Success.
E_INVALIDARG
If the method fails.
XACT_E_COMMITPREVENTED
Return value for ITransaction::Commit.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction2 Interface


ITransactionDispenser Interface

This interface contains two methods. The BeginTransaction method creates new transaction objects. The GetOptionsObject method creates new transaction options objects.

When to Implement

You do not need to implement this interface. It is implemented by the core TM object of the MS DTC Proxy.

When to Use

Use this interface to create transactions and transaction options.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionDispenser Methods | Description
GetOptionsObject | Creates a transaction options object.
BeginTransaction | Initiates a new transaction and returns a new transaction object.

Remarks

Call the DtcGetTransactionManager Function with a riid of IID_ITransactionDispenser when initially connecting to MS DTC. You can also call QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_ITransactionDispenser.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionOptions Interface


ITransactionDispenser::BeginTransaction

This method initiates a new transaction and returns a new transaction object which represents the transaction.

HRESULT BeginTransaction(
  IUnknown punkOuter,
  ISOLEVEL isoLevel,
  ULONG isoFlags,
  ITransactionOptions * pOptions,
  ITransaction ** ppTransaction
);

Parameters

punkOuter
[in] Must be NULL.
isoLevel
[in] The isolation level to be used for this transaction. This value is ignored by MS DTC and passed on to the resource managers.
isoFlags
[in] Must be zero.
pOptions
[in] A pointer to a transaction options object. This value may be NULL. If pOptions is NULL the time-out value for the transaction is infinite and the transaction will not have a description.
ppTransaction
[out] Pointer to the pointer to the ITransaction interface on the new transaction object.

Return Values

S_OK
Success.
CLASS_E_NOAGGREGATION
punkOuter was not NULL.
XACTTC_E_LOGFULL
Unable to begin a new transaction because the log file is full.
XACT_E_NOTIMEOUT
A time-out was specified, but time-outs are not supported.
E_OUTOFMEMORY
Unable to allocate memory.
E_FAIL
An unknown error occurred.
E_UNEXPECTED
An unknown error occurred.
E_INVALIDARG
ppTransaction was NULL.
XACT_E_CONNECTION_DOWN
No longer able to communicate with the transaction manager because the connection to the transaction manager failed.
XACT_E_TMNOTAVAILABLE
Unable to connect to the transaction manager or the transaction manager is unavailable.
XACT_E_CONNECTION_REQUEST_DENIED
The transaction manager did not accept a connection request.

Remarks

A transaction options object which is passed as a parameter to BeginTransaction must not be altered while the BeginTransaction method invocation is outstanding.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionOptions Interface


ITransactionDispenser::GetOptionsObject

This method creates a transaction options object.

HRESULT GetOptionsObject(
  ITransactionOptions ** ppOptions
);

Parameters

ppOptions
[out] Pointer to the pointer to the ITransactionOptions interface on the transaction options object. Must not be NULL.

Return Values

S_OK
Success.
E_OUTOFMEMORY
Unable to allocate memory.
E_INVALIDARG
The value of ppOptions is NULL.

Remarks

The transaction options object obtained from the GetOptionsObject call can be assigned transaction attributes by calling the ITransactionOptions::SetOptions method. The transaction options object can then be passed to ITransactionDispenser::BeginTransaction. The transaction attributes from the transaction options object will be inherited by the newly created transaction object.

A process may create as many transaction options objects as it wishes.

Two or more threads may simultaneously invoke the BeginTransaction method using the same transaction options object. However, the attributes of the transaction options object must not be changed while the object is in use by the BeginTransaction method.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionOptions Interface


ITransactionImport Interface

The resource manager uses this interface to transform an imported transaction cookie into a transaction object. The resource manager calls this interface and passes an opaque marshaled form of the transaction object called a transaction cookie. The resource manager is returned a transaction object. This is referred to as importing the transaction. After importing the transaction, the resource manager uses the IResourceManager::Enlist method to enlist in the transaction.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

A process that wishes to export a transaction uses the ITransactionExport interface to marshal a transaction object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionImport Methods | Description
Import | Transforms a transaction cookie into a transaction object.

Remarks

Call QueryInterface for this interface on the MS DTC proxy core object with a riid of IID_ITransactionImport.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionExport Interface


ITransactionImport::Import

This method transforms a transaction cookie into a transaction object.

HRESULT Import(
  ULONG cbTransactionCookie,
  BYTE * rgbTransactionCookie,
  RIID * piid,
  void ** ppvTransaction
);

Parameters

cbTransactionCookie
[in] The size of the transaction cookie.
rgbTransactionCookie
[in] The transaction cookie.
piid
[in] The interface ID desired on the resulting transaction object.
ppvTransaction
[out] Pointer to the pointer to the IUnknown interface on the imported transaction object.

Return Values

S_OK
Success.
E_UNEXPECTED
An unexpected error occurred.
E_INVALIDARG
One or more parameters were invalid.
E_OUTOFMEMORY
Unable to allocate memory.
E_FAIL
The TM failed to import the transaction.
XACT_E_TMNOTAVAILABLE
Unable to connect to the TM.
XACT_E_CONNECTION_DOWN
Lost connection with the TM.
XACT_E_CONNECTION_REQUEST_DENIED
TM refused a connection request.
XACT_E_NOTRANSACTION
The transaction was not found.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionExport Interface


ITransactionImportWhereabouts Interface

ITransactionImportWhereabouts interface is used when propagating transactions from one process to another or one system to another. The resource manager uses this interface to retrieve an opaque address called the whereabouts from its transaction manager. The whereabouts describes the location of the transaction manager. The resource manager sends the whereabouts to the RM proxy. The RM proxy sends the whereabouts to its transaction manager. The whereabouts lets the transaction manager on the RM proxy's system to locate the transaction manager on the resource manager's system. This permits the two transaction managers to communicate with one another and thereby propagate a transaction from one system to the other.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

Use this interface to retrieve an opaque address called the whereabouts from its transaction manager.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionImportWhereabouts Methods | Description
GetWhereaboutsSize | Returns the length in bytes of the whereabouts of the local transaction manager.
GetWhereabouts | Returns the whereabouts of the local transaction manager.

Remarks

You can either call Call DtcGetTransactionManager Function with a riid of IID_ITransactionImportWhereabouts when initially connecting to MS DTC or Call QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_ITransactionImportWhereabouts.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionImport Interface


ITransactionImportWhereabouts::GetWhereabouts

This method returns the whereabouts of the local transaction manager.HRESULT GetWhereabouts(
  ULONG cbWhereabouts,
  BYTE * rgbWhereabouts,
  ULONG * pcbUsed
);

Parameters

cbWhereabouts
[in] The size in bytes of the rgbWhereabouts buffer.
rgbWhereabouts
[out] Pointer to the caller allocated buffer in which the whereabouts will be returned.
pcbUsed
[out] Pointer to the size in bytes of the address returned in rgbWhereabouts.

Return Values

S_OK
Success.
E_INVALIDARG
The value of either rgbWhereabouts or pcbUsed is NULL.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionImport Interface


ITransactionImportWhereabouts::GetWhereaboutsSize

This method returns the size in bytes of the whereabouts of the local transaction manager.

HRESULT GetWhereaboutsSize(
  ULONG * pcbSize
);

Parameters

pcbSize
[out] Pointer to the size in bytes of the whereabouts.

Return Values

S_OK
Success.
E_INVALIDARG
The value of pcbSize was NULL.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionImport Interface


ITransactionExport Interface

A process that wishes to export a transaction calls this interface and passes a transaction object. The process is returned an opaque marshaled form of the transaction object called a transaction cookie. The process then sends the transaction cookie to the destination process. This is referred to as exporting the transaction.

When to Implement

You do not need to implement this interface. It is implemented by the Export object of the MS DTC Proxy.

When to Use

A process that wishes to export a transaction uses the ITransactionExport interface to marshal a transaction object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionExport Methods | Description
Export | Marshals a transaction object for export.
GetTransactionCookie | Transforms a transaction object into a transaction cookie.

Remarks

You obtain a pointer to this interface by calling the ITransactionExportFactory::Create method.

Communication failures may invalidate the export object. If ITransactionExport::Export returns the error XACT_E_CONNECTION_DOWN then the current export object is invalid and a new export object must be created.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionExportFactory Interface


ITransactionExport::Export

This method is used to marshal a transaction object for export.

If the MS DTC Network Node [???] and Transaction Internet Protocol (TIP) Transactions settings are enabled and the Network Transactions setting is disabled, TIP is the protocol that is used.

HRESULT Export(
  IUnknown * punkTransaction,
  ULONG * pcbTransactionCookie
);

Parameters

punkTransaction
[in] Pointer to the IUnknown interface on the transaction object to be exported.
pcbTransactionCookie
[out] Pointer to the size in bytes of the transaction cookie.

Return Values

S_OK
Success.
E_UNEXPECTED
An unexpected error occurred.
E_INVALIDARG
The value of either punkTransaction or pcbTransactionCookie is NULL.
E_OUTOFMEMORY
Unable to allocate memory.
XACT_E_ALREADYINPROGRESS
An export is already in progress on this export object. Only one export may be done at a time.
E_NOINTERFACE
punkTransaction did not support the ITransaction Interface.
XACT_E_CONNECTION_DOWN
No longer able to communicate with the transaction manager because the connection to the transaction manager failed. This export object is now invalid.
XACT_E_NOTRANSACTION
Unable to retrieve information for the transaction because it was already completed.
XACT_E_LOGFULL
The DTC log is full.
E_FAIL
Failed to connect to the transaction coordinator.
XACT_E_NOTRANSACTION
The transaction aborted because an older version of the DTC proxy attempted to communicate with a remote DTC, with network transactions disabled.

Requirements

To call this method you must include Txcoord.h in your project.

See Also

ITransactionExportFactory Interface


ITransactionExport::GetTransactionCookie

This method transforms a transaction object into a transaction cookie.

If the MS DTC Network Node [???] and the Transaction Internet Protocol (TIP) Transactions settings are enabled, and the Network Transactions setting is disabled, TIP is the protocol that is used.

HRESULT GetTransactionCookie(
  IUnknown * pITransaction,
  ULONG cbTransactionCookie,
  BYTE * rgbTransactionCookie,
  ULONG * pcbUsed
);

Parameters

pITransaction
[in] Pointer to the IUnknown interface on the transaction object to be marshaled. The ITransactionExport::Export must have been called previously.
cbTransactionCookie
[in] The size in bytes of the transaction cookie representing the transaction object.
rgbTransactionCookie
[out] Pointer to the caller allocated buffer that will receive the transaction cookie.
pcbUsed
[out] Pointer to the size in bytes of the address returned in rgbTransactionCookie.

Return Values

S_OK
Success.
E_UNEXPECTED
An unexpected error occurred.
E_NOINTERFACE
pITransaction did not support the ITransaction interface.
E_INVALIDARG
A NULL pointer was specified.
XACT_E_PARTNER_NETWORK_TX_DISABLED
The whereabouts is from a remote node and the DTC proxy is the latest version, but network transactions have been disabled.
XACT_E_NOTRANSACTION
The transaction aborted because an older version of the DTC proxy attempted to communicate with a remote DTC.

Requirements

To call this method you must include Txcoord.h in your project.

See Also

ITransactionExportFactory Interface


ITransactionExportFactory Interface

This interface is used to create a new export object. The export object represents the connection between a process that exports transactions and a process that imports transactions. The export object is used when propagating transactions between the systems.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

Use this interface to create a new export object when propagating transactions between systems.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionExportFactory Methods | Description
GetRemoteClassId | Returns the class identifier of the local transaction manager.
Create | Creates an export object.

Remarks

You obtain a pointer to this interface by calling DtcGetTransactionManager Function with a riid of IID_ITransactionExportFactory when initially connecting to MS DTC or by calling QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_ITransactionExportFactory.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionImport Interface


ITransactionExportFactory::Create

This method creates an export object.

HRESULT Create(
  ULONG cbWhereabouts,
  BYTE * rgbWhereabouts,
  ITransactionExport ** ppExport
);

Parameters

cbWhereabouts
[in] The size in bytes of rgbWhereabouts.
rgbWhereabouts
[in] Pointer to the whereabouts.
ppExport
[out] Pointer to the pointer to the ITransactionExport interface on the export object. The export object represents the connection between the caller of ITransactionExportFactory::Create and the destination process which provided the whereabouts. The caller uses the export object returned by this method to marshal a transaction object for export to the destination process.

Return Values

S_OK
Success.
E_FAIL
The data in rgbWhereabouts is corrupted.
E_INVALIDARG
The value of either rgbWhereabouts or ppExport is NULL.
E_OUTOFMEMORY
Unable to allocate memory.
XACT_E_TMNOTAVAILABLE
Unable to connect to the transaction manager, or the transaction manager is unavailable.
XACT_E_CONNECTION_DOWN
No longer able to communicate with the transaction manager because the connection to the transaction manager failed.
XACT_E_CONNECTION_REQUEST_DENIED
The transaction manager did not accept a connection request.
XACT_E_NETWORK_TX_DISABLED
The whereabouts is from a remote node, but Network Transactions is disabled.
XACT_E_PARTNER_NETWORK_TX_DISABLED
The whereabouts is from a remote node and the DTC proxy is the latest version, but network transactions have been disabled.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionImport Interface


ITransactionExportFactory::GetRemoteClassId

GetRemoteClassId returns the class identifier of the local transaction manager. The class identifier can be used to ensure that a transaction manager of the proper type is present on the remote system. Having compatible transaction managers on the two systems makes it possible to propagate transactions between the systems.

HRESULT GetRemoteClassId(
  CLSID * pclsid
);

Parameters

pclsid
[out] Pointer to the class identifier of the local transaction manager.

Return Values

S_OK
Success.
E_INVALIDARG
The value of pclsid is NULL.

Remarks

This method need not be called when MS DTC is the only transaction manager being used. This method is present so that vendors other than Microsoft can provide OLE Transactions compliant transaction managers. These transaction managers could be used in place of MS DTC or in conjunction with it.

Resource managers that wish to work with a variety of transaction manager should have their RM proxy call this method. The RM proxy should examine the value returned in pclsid. If pclsid is CLSID_M01_MSDtcTmProxy, then MS DTC is being used as the local transaction manager. In this case, the remote resource manager can call the DtcGetTransactionManager helper function on the remote system. This will connect the remote resource manager to the MS DTC proxy Core Object on its system. The remote resource manager should call CoCreateInstance on the remote system with a class identifier of *pclsid if pclsid is other than CLSID_M01_MSDtcTmProxy. This will connect the remote resource manager to the appropriate transaction manager on that system.

Requirements

To use the methods of this interface, you must include Txcoord.h in your project.

See Also

ITransactionImport Interface


ITransactionLastEnlistmentAsync Interface

If the transaction manager has delegated the commit decision to the resource manager (thereby treating this resource manager as the Last Resource Manager [LRM]), the resource manager uses this interface to deliver the transaction outcome to the transaction manager. This interface is parallel to the interface ITransactionEnlistmentAsync but exposes only the LRM-specific functionality.

When to Implement

This object is implemented by MS DTC Proxy.

When to Use

An LRM must use this interface to communicate with the transaction manager about the outcome of a transaction for which the LRM acted as commit authority.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionEnlistmentAsync Methods | Description
TransactionOutcome | AN LRM invokes this method to report the outcome of a transaction.

Requirements

To use the methods of this interface, you must include [Txcoord.h] in your project.

See Also

ITransactionEnlistmentAsync Interface


ITransactionLastEnlistmentAsync::TransactionOutcome

A Last Resource Manager (LRM) invokes this method to inform the transaction manager of the outcome of a transaction. This method should be called only by a resource manager that has previously requested that it be the LRM in the transaction. Failure to abide by this rule results in an error code of XACT_E_NOTLASTRESOURCEMANAGER.

HRESULT TransactionOutcome(
   XACTSTAT XactStat,
   BOID* pboidReason
);

Parameters

XactStat
[in] Resource manager provides the status of the transaction.

Enum XACTSTAT {XACTSTAT_ABORTED, XACTSTAT_COMMITED}

PboidReason
[in] Resource manager provides the reason for aborting the transaction. If the resource manager decides to commit the transaction, this parameter should be NULL. Failure to abide by this rule results in a return code of E_INVALIDARG.

Return Values

S_OK
Success.
XACT_E_NOTSUPPORTED
Indicates that the version of the associated transaction manager does not support the LRM functionality. The LRM should never have received this error because it should not have progressed this far if the transaction manager was not the correct version.
E_INVALIDARG
Indicates that either the XactStat parameter was invalid (that is, the parameter was not XACTSTAT_COMMITED or XACTSTAT_ABORTED) or the pboidReason parameter was not NULL even though the transaction was committed.
E_OUTOFMEMORY
Unable to allocate memory.
E_UNEXPECTED
An unexpected error occurred.
E_FAIL
TransactionOutcome was called illegally.

See Also

ITransactionEnlistmentAsync Interface


ITransactionLastResourceAsync Interface

Once the MS DTC Proxy has accepted the resource manager as a Last Resource Manager (LRM), the MS DTC Proxy calls the methods of this interface. This interface is parallel to the interface ITransactionResourceAsync but exposes only the LRM-specific functionality.

When to Implement

This object is implemented by a Last Resource Manager.

When to Use

The MS DTC Proxy invokes this interface in response to a resource manager's need to become a last resource manager (LRM).

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionLastResourceAsync Methods | Description
DelegateCommit | The MS DTC Proxy calls this method to indicate that it has made the decision to delegate the commit to the resource manager.
ForgetRequest | The MS DTC Proxy calls on this method to indicate that it has successfully received the transaction outcome from the resource manager.

Requirements

To use the methods of this interface, you must include [Txcoord.h] in your project.

See Also

ITransactionLastEnlistmentAsync Interface


ITransactionLastResourceAsync::DelegateCommit

The MS DTC Proxy calls this method to indicate that it has made the decision to delegate the commit decision to the resource manager. If either the method fails or the resource manager or the MS DTC Proxy become unavailable during a method call, the commit decision has still been delegated. Because this is a callback method, the MS DTC Proxy ignores any error values returned. Therefore, only S_OK has been shown as a legal return value.

HRESULT DelegateCommit(
   DWORD grfRM
);

Parameters

grfRM
[in] Values from XACTRM.

Return Values

S_OK
Success

See Also

ITransactionResourceAsync


ITransactionLastResourceAsync::ForgetRequest

The MS DTC Proxy calls this method to indicate that the proxy has successfully received the transaction outcome from the resource manager and that the resource manager is allowed to forget the transaction. If the Last Resource Manager (LRM) returns with a decision to abort the transaction, the DTC Proxy will not call the ForgetRequest method. This is because the MS DTC Proxy uses a resumed abort.

Because this is a callback method, the MS DTC Proxy ignores any error values returned. Therefore, only S_OK has been shown as a legal return value.

HRESULT ForgetRequest(
   XACTUOW * pNewUOW
);

Parameters

pNewUOW
[in] NULL

Return Values

S_OK
Success

See Also

ITransaction Interface

ITipHelper Interface


ITransactionOptions Interface

This interface contains methods that control the attributes of new transactions such as their time-out periods and descriptions.

This interface is used to get and set attributes within a transaction options object. The transaction options object can be passed as a parameter to the ITransactionDispenser::BeginTransaction method. The attributes of the transaction options object are inherited by the newly initiated transaction. This lets the caller of the BeginTransaction method to control the attributes of a transaction such as its time-out period and transaction description.

When to Implement

You do not need to implement this interface. It is implemented by the transaction options object of the MS DTC Proxy.

When to Use

Application programs and resource managers that initiate transactions use this interface to control the attributes of new transactions.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionOptions Methods | Description
SetOptions | Alters transaction attributes in a transaction options object.
GetOptions | Reads transaction attributes from a transaction options object.

Remarks

You obtain a pointer to this interface by calling the ITransactionDispenser::GetOptionsObject method.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionDispenser Interface


ITransactionOptions::GetOptions

The GetOptions method is used to read transaction attributes from a transaction options object.

HRESULT GetOptions(
  XACTOPT * pOptions
);

Parameters

pOptions
[out] Pointer to a structure containing attribute information for a transaction options object. The szDescription field must be pre-allocated with a length of MAX_TRAN_DESC bytes. For a descripiton of the XACTOPT structure, see ITransactionOptions::SetOptions.

Return Values

S_OK
Success.
E_OUTOFMEMORY
Unable to allocate memory.
E_INVALIDARG
The value of pOptions is NULL.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionDispenser Interface


ITransactionOptions::SetOptions

The SetOptions method is used to alter transaction attributes in a transaction options object.

HRESULT SetOptions(
  XACTOPT * pOptions
);

Parameters

pOptions
[in] Pointer to the XACTOPT structure. This structure contains attribute information for a transaction options object.
typedef struct XACTOPT {
    ULONG         ulTimeout;
    unsigned char szDescription[ MAX_TRAN_DESC ];
    } XACTOPT;

Members

ulTimeout
The time-out limits the duration of the transaction and therefore bounds the amount of time locks are held on database records and system resources. If the time-out period expires before the transaction commits, MS DTC automatically aborts the transaction.The time-out is specified in milliseconds. A time-out value of zero indicates an infinite time-out.
szDescription
szDescription provide a textual description for a transaction. The description is displayed by the MS DTC administration tool in the MS DTC Transactions window. The description is only meaningful to the MS DTC administrator and is not processed or interpreted by MS DTC itself. The string cannot be longer than MAX_TRAN_DESC bytes in length.

Return Values

S_OK
Success.
E_OUTOFMEMORY
Unable to allocate memory.
E_INVALIDARG
The value of pOptions is NULL.

Remarks

SetOptions must not be invoked on a transaction options object which is currently in use by the ITransactionDispenser::BeginTransaction method.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransactionDispenser Interface


ITransactionOutcomeEvents Interface

This interface is used by application programs that require asynchronous notification about transaction outcomes. The application program implements the methods in this interface and registers the interface with the connection point mechanism. MS DTC calls the appropriate method on this interface to inform the application about the outcome of a transaction.

When to Implement

An application program needs to implement this interface if it requires asynchronous notification about transaction outcomes.

When to Use

Application programs us this interface to obtain asynchronous notification about transaction outcomes.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionOutcomeEvents Methods | Description
Commit | Raises an event when the transaction commits.
Abort | Raises an event when the transaction aborts.
HeuristicDecision | Raises an event when one of the participants in the transaction chose to heuristically decide the outcome of the transaction.
InDoubt | Raises an event when the outcome of the transaction is in-doubt.

Remarks

Typically, ITransaction::Commit or Abort calls are performed synchronously. This means that the calling thread is blocked until MS DTC makes a commit or abort decision (usually at the end of phase one of the two-phase commit protocol).

It is possible to avoid blocking the calling thread by using asynchronous Commit or Abort calls. Asynchronous Commit or Abort require the following:

  1. The programmer creates an OLE event sink object that implements the ITransactionOutcomeEvents interface.
  2. The programmer uses the OLE events architecture on the MS DTC transaction object to register the event sink.
  3. Calls to ITransaction::Commit are passed the value XACTTC_ASYNC in the grfTC parameter. Calls to ITransaction::Abort are passed a Boolean flag of TRUE in the fAsync parameter. Neither call blocks the calling thread.
  4. After the transaction commits or aborts, the ITransactionOutcomeEvents::Commit or ITransactionOutcomeEvents::Abort method is called on the registered event sink.
    For more information on | Refer to
    Asynchronous Commit and Abort requests | ITransaction::Commit or ITransaction::Abort
    OLE events architecture | IConnectionPoint

The ITransactionOutcomeEvents events are raised when the transaction's outcome is known. On the root transaction manager's system, the transaction outcome event is raised at the end of phase one. On the subordinate transaction managers' systems, the transaction outcome events are raised at the beginning of phase two.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface


ITransactionOutcomeEvents::Abort

This event is raised when the transaction aborted, either as a result of a call to Abort or an unsuccessful call to Commit.

HRESULT Aborted(
  BOID * pboidReason,
  BOOL fRetaining,
  XACTUOW * pNewUOW,
  HRESULT hr
);

Parameters

pboidReason
[in] A BOID indicating why the transaction aborted.
fRetaining
[in] Indicates whether retaining Commit was specified. Will be FALSE.
pNewUOW
[in] Always NULL.
hr
[in] Always S_OK.

Return Values

S_OK
The transaction aborted.
XACT_E_INDOUBT
The transaction is in-doubt.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface


ITransactionOutcomeEvents::Commit

This event is raised when the transaction committed.

HRESULT Committed(
  BOOL fRetaining,
  XACTUOW * pNewUOW,
  HRESULT hr
);

Parameters

fRetaining
[in] Indicates whether retaining Commit was specified. Will be FALSE.
pNewUOW
[in] Always NULL.
hr
[in] Always S_OK.

Return Values

S_OK
Success.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface


ITransactionOutcomeEvents::HeuristicDecision

This event is raised when one of the participants in the transaction chooses to heuristically decide the outcome of the transaction.

Note Heuristic decisions are not supported in the current release.

HRESULT HeuristicDecision(
  DWORD dwDecision,
  BOID * pboidReason,
  HRESULT hr
);

Parameters

dwDecision
[in] Values from the enumeration XACTHEURISTIC.
typedef enum XACTHEURISTIC {
    XACTHEURISTIC_ABORT,
    XACTHEURISTIC_COMMIT,
    XACTHEURISTIC_DAMAGE,
    XACTHEURISTIC_DANGER,
    } XACTHEURISTIC;
pboidReason
[in] A BOID indicating why the transaction was heuristically decided. This value is provided by the party making the heuristic decision.
hr
[in] Always S_OK.

Return Values

S_OK
Success.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface


ITransactionOutcomeEvents::InDoubt

This event is raised when the outcome of the transaction is in-doubt. The outcome of the transaction can be in-doubt if the connection between the MSDTC proxy and the MSDTC TM was broken after the proxy asked the transaction manager to commit or abort a transaction but before the transaction manager's response to the commit or abort was received by the proxy. Note: Receiving this method call is not the same as the state of the transaction being in-doubt.

HRESULT InDoubt();

Return Values

S_OK
Success.

Requirements

To use the methods of this interface, you must include transact.h in your project.

See Also

ITransaction Interface


ITransactionResourceAsync Interface

This is a callback interface implemented by the resource manager. The transaction manager invokes this callback interface to deliver phase-one and phase-two notifications to the resource manager. The communication protocol using this interface is asynchronous. When the resource manager receives a callback on this interface, it should queue the request and immediately return from the callback. The resource manager should then asynchronously process the queued request using its own threads to prepare, commit, or abort the transaction.

When to Implement

A resource manager of the MS DTC needs to implement this interface.

When to Use

The MSDTC Proxy uses this interface to deliver phase-one and phase-two notifications to the resource manager. Upon receiving the notifications the resource manager should asynchronously prepare, commit or abort the transaction.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionResourceAsync Methods | Description
PrepareRequest | The transaction manager is requesting that the resource manager prepare the transaction to commit. This is phase one of the two-phase commit protocol.
CommitRequest | The transaction manager is requesting that the resource manager commit the transaction. This is phase two of the two-phase commit protocol.
AbortRequest | The transaction manager is requesting that the resource manager abort the transaction.
TMDown | Called if connection to the transaction manager goes down after phase one has been completed but before phase two has been initiated.

Requirements

To use the methods of this interface, you must include Txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface


ITransactionResourceAsync::AbortRequest

The MS DTC proxy calls this method to abort a transaction.

HRESULT AbortRequest(
  BOID * pboidReason,
  BOOL fRetaining,
  XACTUOW * pNewUOW
);

Parameters

pboidReason
[in] A pointer to a BOID explaining why the transaction abort was requested.
fRetaining
[in] Always will be FALSE.
pNewUOW
[in] Always will be NULL.

Return Values

S_OK
Success: the resource manager's transaction object has started aborting.

Remarks

The resource manager needs to return from this call as soon as it has asynchronously started a request to abort its enlistment object. After the enlistment object is aborted, the resource manager needs to call ITransactionEnlistmentAsync::AbortRequestDone.

Requirements

To use the methods of this interface, you must include Txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface


ITransactionResourceAsync::CommitRequest

The MS DTC proxy calls this method to commit a transaction (phase two of the two-phase commit protocol).

HRESULT CommitRequest(
  DWORD grfRM,
  XACTUOW * pNewUOW
);

Parameters

grfRM
[in] Values from XACTRM.
pNewUOW
[in] Always NULL

Return Values

S_OK
Success: the resource manager's transaction object has started committing.

Remarks

The resource manager needs to return from this call as soon as it has asynchronously started a request to commit its enlistment object. After the enlistment object is committed, the resource manager needs to call ITransactionEnlistmentAsync::CommitRequestDone.

Requirements

To use the methods of this interface, you must include Txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface


ITransactionResourceAsync::PrepareRequest

The MS DTC proxy calls this method to prepare a transaction (phase one of the two-phase commit protocol).

HRESULT PrepareRequest(
  BOOL fRetaining,
  DWORD grfRM,
  BOOL fWantMoniker,
  BOOL fSinglePhase
);

Parameters

fRetaining
[in] Always FALSE.
grfRM
[in] Values from XACTRM.
fWantMoniker
[in] Always FALSE
fSinglePhase
[in] If TRUE, it indicates that the RM is the only resource manager enlisted on the transaction.

Return Values

S_OK
Success. The resource manager's transaction object has started preparing.

Remarks

The resource manager needs to return from this call as soon as it has asynchronously started a request to prepare its enlistment object. After the enlistment object is prepared, the resource manager needs to call ITransactionEnlistmentAsync::PrepareRequestDone.

If fSinglePhase flag is TRUE, it indicates that the RM is the only resource manager enlisted on the transaction. Therefore the resource manager has the option to perform the single phase optimization. If the RM does choose to perform the single phase optimization, then it lets the Transaction Coordinator know of this optimization by providing XACT_S_SINGLEPHASE flag to the ITransactionEnlistmentAsync::PrepareRequestDone. If the resource manager chooses not to perform the single phase optimization then the transaction manager will perform the second phase of the two-phase commit protocol.

Requirements

To use the methods of this interface, you must include Txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface


ITransactionResourceAsync::TMDown

The MS DTC Proxy calls on this method if the connection to the transaction manager goes down and the resource manager's transaction object is prepared (that is, after the resource manager has called the ITransactionEnlistmentAsync::PrepareRequestDone method). In general, the proxy calls the ITransactionResourceAsync::TMDown method to inform the resource manager that it must perform recovery on that particular transaction.

If the resource manager has enlisted in the transaction as a Last Resource Manager (LRM), the proxy calls the ITransactionResourceAsync::TMDown method only if the connection goes down within a specific time interval. The time interval begins when the proxy delegates the commit decision to the LRM. The window ends either when the LRM informs the proxy that it has decided to abort the transaction or when the proxy calls the ITransactionLastResourceAsync::ForgetRequest method on the LRM. However, the semantics of the call are simple from the LRM perspective: If the proxy makes this call, the resource manager needs to perform recovery on that particular transaction.

If the connection between the MS DTC Proxy and the transaction manager fails, the MS DTC Proxy first calls the resource manager's ITransactionResourceAsync::TMDown method once for each transaction in which the resource manager is enlisted. The MS DTC Proxy then calls the resource manager's IResourceManagerSink::TMDown method. This ensures that the resource manager is informed of the failure even if it has no enlisted transactions. The above semantics remain exactly the same in the LRM scenario as well.

HRESULT TMDown(void);

Return Values

S_OK
Success.

Requirements

To use the methods of this interface, you must include Txdtc.h in your project.

See Also

ITransactionEnlistmentAsync Interface

IresourceManagerSink Interface


ITransactionPhase0Factory Interface

The interface contains a single method that creates a new phase0 enlistment object. The phase0 enlistment object implements the ITransactionPhase0EnlistmentAsync Interface. This interface is exported as a sink to the Phase0 participant; the phase0 participant uses it for controlling the Phase 0 enlistment.

Methods

When to Implement

You do not need to implement this interface. It is implemented by the Transaction object of the MS DTC Proxy.

When to Use

Use this interface to enlist for Phase 0 notification on a transaction.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionPhase0Factory Methods | Description
Create | Creates the Phase0 Enlistment object and exchanges the ITransactionPhase0NotifyAsync and ITransactionPhase0EnlistmentAsync sinks between the Phase0 participant and the MS DTC proxy.

Remarks

You obtain a pointer to this interface by calling QueryInterface on any ITransaction interface pointer with a riid of IID_ITransactionPhase0Factory. This returns a factory that is specialized for that particular transaction.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0EnlistmentAsync Interface and ITransactionPhase0NotifyAsync Interface.


ITransactionPhase0Factory::Create

This method creates the Phase0 Enlistment object and exchanges the ITransactionPhase0NotifyAsync and ITransactionPhase0EnlistmentAsync sinks between the Phase0 participant and the MS DTC proxy. A Phase0 participant invokes this method on the transaction object for any transaction on which it needs notification of phase0 events. The lifetime of a Phase0 Enlistment object matches that of the transaction with which it is associated, unless it is released sooner.

A Phase0 Enlistment object is considered a "single-shot" enlistment That is, a Phase0 enlistment object will produce one and only one Phase0 notification. If a Phase0 participant wishes to receive additional phase0 notifications (for example, if additional work were received after having completed one bout of Phase0 processing), additional Phase0 Enlistment objects should be created.

The enlistment object is created in the "disabled" state; no callbacks (either Phase0Request or EnlistCompleted) will be received on the Notify interface until the enlistment has been "enabled" via the Enable method. This avoids the race condition that otherwise results, wherein a callback arrives before the [out] parameter has been set on return from the Create method (so the participant has not received the Phase0 enlistment object pointer on which to respond).

The enlistment with the TM occurs asynchronously; a client application that prefers to use a synchronous-style interface (e.g. block until the enlistment has completed) should call WaitForEnlistment after Create. Note that the successful return of the Create method does not necessarily indicate that the enlistment will succeed. Successful enlistment can only be determined by checking the status parameter returned to WaitForEnlistment or passed to the Unenlist callback.

The last Release of the ITransactionPhase0Enlistment interface pointer returned via Create causes the Phase0 Enlistment object to be destructed. This may or may not cause the associated transaction to abort, depending on the state of the enlistment object. If the phase0 enlistment object is in a "done" state (e.g. the participant has already called Phase0Done, or Unenlist), then an abort is not implied. If the phase0 enlistment object is in a state that implies a phase0 notification is still pending (e.g. the "disabled" state, the "active" state, or the "phase0" state), then Releasing the object would imply an Abort.

C++ Syntax

HRESULT Create(
  ITransactionPhase0NotifyAsync* pITransactionPhase0Notify,
  ITransactionPhase0EnlistmentAsync** ppITransactionPhase0Enlistment
);

Parameters

pITransactionPhase0Notify
[in] Pointer to the ITransactionPhase0NotifyAsync sink exported by the participant.
ppITransactionPhase0Enlistment
[out] Pointer to a pointer of an ITransactionPhase0EnlistmentAsync interface via which the participant can indicate the completion of phase0 processing.

Return Values

S_OK
Success—the transaction completed.
E_INVALIDARG
Failure—one or more of the parameters are not valid.
E_OUTOFMEMORY
Failure—unable to allocate memory.
E_UNEXPECTED
Failure—an unexpected error occurred.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0EnlistmentAsync Interface and ITransactionPhase0NotifyAsync Interface.


ITransactionPhase0EnlistmentAsync Interface

ITransactionPhase0EnlistmentAsync is the interface a Phase0 participant uses to indicate that it is ready to receive phase0 notification, that phase0 processing has completed, or that phase0 notification is no longer desired.

When to Implement

You do not need to implement this interface. It is implemented by the Phase0 Enlistment object of the MS DTC Proxy.

When to Use

A Phase0 participant uses this interface to indicate that it is ready to receive phase0 notification, that phase0 processing has completed, or that phase0 notification is no longer desired.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionPhase0EnlistmentAsync Methods | Description
Enable | Indicates that it is prepared to accept Phase0 notifications and changes the enlistment object from the "disabled" state (in which it was created) to the "enabled" state.
WaitForEnlistment | Blocks the caller until the Phase0 enlistment completes.
Phase0Done | Indicates that the caller has completed Phase0 processing.
Unenlist | Indicates that receiving Phase0 notifications is no longer needed.
GetTransaction | Retrieves a pointer to the transaction that is associated with the Phase0 Enlistment object.

Remarks

You obtain a pointer to this interface by calling the ITransactionPhase0Factory::Create method.

All of the calls in this interface are asynchronous, with the exception of WaitForEnlistment and GetTransaction methods.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0EnlistmentAsync::Enable

An application invokes the Enable method to indicate that it is prepared to accept Phase0 notifications; which changes the phase0 enlistment object from the disabled state (in which it was created) to the enabled state. The phase0 participant must be prepared to receive its phase0 notification prior to the return from the Enable method.

C++ Syntax

HRESULT Enable(void);

Return Values

S_OK
Success—the transaction enable completed.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_PROTOCOL
Failure—Enable was called illegally.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0EnlistmentAsync::GetTransaction

An application invokes the GetTransaction method to retrieve a pointer to the transaction that is associated with the Phase0 Enlistment object. This allows a phase0 participant to perform operations on the associated transaction without being required to maintain a pointer to it.

C++ Syntax

HRESULT GetTransaction(
  ITransaction ** ppITransaction
);

Parameters

ppITransaction
[out] Pointer to an address at which the caller wishes to receive a pointer to the transaction interface that is associated with the Phase0 Enlistment.

Return Values

S_OK
Success.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_PROTOCOL
GetTransaction was called illegally.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0EnlistmentAsync::Phase0Done

An application invokes the Phase0Done method to indicate that it has completed Phase0 processing. The implication of making this call is that the Phase0 participant has no more work that would preclude the transaction from beginning the two-phase commit processing(though other participants may still have such work). When the last Phase0 participant has called Phase0Done, and there are no new Phase0 enlistments, the transaction can proceed with two-phase commit processing.

This method should be called only after receiving a Phase0Request notification.

C++ Syntax

HRESULT Phase0Done(void);

Return Values

S_OK
Success.
E_UNEXPECTED
Failure—Something unexpected happened.
XACT_E_PROTOCOL
Failure—Phase0Done was called illegally.
XACT_E_CONNECTION_DOWN
Failure Lost connection with the TM.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0EnlistmentAsync::Unenlist

An application invokes the Unenlist method to indicate that it is no longer interested in receiving Phase0 notifications. This call cancels an existing enlistment.

The implication of making this call is that the application has no further need to receive phase0 notifications; however, it is still possible that the application will receive a phase0 notification regardless. A phase0 participant who receives a phase0 notification after calling Unenlist may choose to call Phase0Done, but is not required to do so.

The only time at which the participant is guaranteed not to receive a phase0 notification is after its ITransactionPhase0NotifyAsync Interface pointer is released by the phase0 enlistment object.

C++ Syntax

HRESULT Unenlist(void);

Return Values

S_OK
Success.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_PROTOCOL
Failure—Unenlist was called illegally.
XACT_E_CONNECTION_DOWN
Failure—the connection to the local TM is down.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0EnlistmentAsync::WaitForEnlistment

An application invokes the WaitForEnlistment method if it wishes to block until the phase0 enlistment completes. A return from this method indicates that enlistment has either completed successfully or has failed, as indicated by the status parameter. Note that this is a synchronous call, in contrast to most of the methods in this interface.

C++ Syntax

HRESULT WaitForEnlistment(void);

Return Values

S_OK
Success—the asynchronous pull request was queued.
E_OUTOFMEMORY
Failure—out of resources.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_TMNOTAVAILABLE
Failure—unable to establish a connection with the transaction manager.
XACT_E_CONNECTION_REQUEST_DENIED
Failure—transaction manager refused to accept a connection.
XACT_E_CONNECTION_DOWN
Failure—connection with the transaction manager was lost.
XACT_E_PROTOCOL
WaitForEnlistment was called illegally.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0NotifyAsync Interface

The MS DTC Proxy calls the methods of this interface to deliver phase zero notification to a Phase0 participant, and to notify the participant that the asynchronous enlistment has completed.

When to Implement

An application wanting to receive phase 0 notification on a transaction implements this interface. Typically various cache managers would require phase 0 notification to trigger a flush on a cache that has been updated in a transaction.

When to Use

Use this interface to receive phase zero notification from the MSDTC Proxy.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionPhase0NotifyAsync Methods | Description
Phase0Request | Notifies a Phase0 participant that the transaction manager has issued the phase 0 notifications.
EnlistCompleted | Notifies a Phase0 participant that the process of enlisting with the TM is complete.

Remarks

You supply a pointer to this interface when calling the ITransactionPhase0Factory::Create method.

When processing a callback, there are a few restrictions on what can be performed. Since the callback is running on a DTC CM thread, which is a scarce resource, the callback should not make any blocking DTC calls, nor should it block on any user-level locks unless they are guaranteed to be available very shortly in spite of blocking. Failure to abide by these restrictions can result in deadlock situations.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0NotifyAsync::EnlistCompleted

The MS DTC Proxy calls this method to notify a Phase0 participant that the process of enlisting with the TM is complete. The status parameter indicates whether the phase0 enlistment succeeded or failed. A Phase0 participant who is not interested in receiving this event should simply return S_OK.

C++ Syntax

HRESULT EnlistCompleted(
  HRESULT * status,
);

Parameters

status
[in] Result code indicating the success or failure of the enlistment Create request.

Return Values

S_OK
Success—the transaction pull completed.
E_OUTOFMEMORY
Failure—out of resources.
E_UNEXPECTED
Failure—an unexpected error occurred.
XACT_E_TMNOTAVAILABLE
Failure—unable to connect to the transaction manager.
XACT_E_NOTRANSACTION
Failure—the transaction has already committed or aborted.
XACT_E_CONNECTION_DOWN
Failure—connection with the transaction manager was lost.
XACT_E_CONNECTION_REQUEST_DENIED
Failure—The transaction manager refused to accept a connection.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionPhase0NotifyAsync::Phase0Request

The MS DTC Proxy calls this method to notify a Phase0 participant that phase 0 processing has commenced. The Phase0 participant must perform any operations necessary to ensure the transaction is in a state where it is safe to begin two-phase commit (e.g. satisfies durability guarantees), and then signal completion using the ITransactionPhase0Enlistment::Phase0Done method.

A phase0 participant who receives a phase0 notification after calling Unenlist may choose to call Phase0Done, but is not required to do so.

C++ Syntax

HRESULT Phase0Request(
  BOOL fAbortHint
);

Parameters

fAbortHint
A value of TRUE provides the phase0 participant with an indication that further work on this transaction is not worth pursuing, since another participant has already aborted the transaction.

Note Certain Phase0 participants such as caches may choose to simply invalidate portions of the cache rather than flushing them to stable storage or other Resource Managers. The fact that the fAbortHint argument is FALSE does not in any way imply that the transaction will eventually commit (since other phase0 participants or Resource Managers may subsequently abort it)—it merely implies that at Phase0Request time, the eventual outcome is still uncertain.

Return Values

S_OK
Success—The Phase0 participant has been notified that the transaction is ready to enter phase one of 2PC.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

ITransactionPhase0Factory Interface


ITransactionEnlistmentAsync Interface

The resource manager uses this interface to notify the transaction manager that it has completed the prepare, abort, or commit request on the transaction object associated with this enlistment object.

When to Implement

You do not need to implement this interface. It is implemented by the Enlistment object of the MS DTC Proxy.

When to Use

Use this interface to notify the transaction manager that the resource manager has completed a request on the transaction object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionEnlistmentAsync Methods | Description
PrepareRequestDone | Informs the transaction manager that the resource manager has completed the prepare phase.
CommitRequestDone | Informs the transaction manager that the resource manager has successfully committed the transaction.
AbortRequestDone | Informs the transaction manager that the resource manager has successfully aborted the transaction.

Remarks

You obtain a pointer to this interface by calling the IResourceManager::Enlist method.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager Interface


ITransactionEnlistmentAsync::AbortRequestDone

The resource manager invokes this method to inform the transaction manager that it has successfully aborted the transaction.

HRESULT AbortRequestDone(
  HRESULT hr
);

Parameters

hr
[in] S_OK indicates that the transaction has been aborted.

Return Values

S_OK
Success. The enlistment has accepted the notification.
E_FAIL
AbortRequestDone was called illegally.
E_INVALIDARG
An invalid hr was specified.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager Interface


ITransactionEnlistmentAsync::CommitRequestDone

The resource manager invokes this method to inform the transaction manager that it has successfully committed the transaction.

HRESULT CommitRequestDone(
  HRESULT hr
);

Parameters

hr
[in] S_OK indicates that the transaction has committed.

Return Values

S_OK
Success.
E_INVALIDARG
An invalid hr was specified.
E_FAIL
CommitRequestDone was called illegally.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager Interface


ITransactionEnlistmentAsync::PrepareRequestDone

The resource manager invokes this method to inform the transaction manager that it has completed the prepare phase of the two-phase commit protocol.

HRESULT PrepareRequestDone(
  HRESULT hr,
  IMoniker * pmk,
  BOID * pboidReason
);

Parameters

hr
[in] The resource manager uses the hr parameter to inform the transaction manager of the outcome of the prepare phase.
Value of hr parameter | Meaning
S_OK | Success. The transaction is prepared.
XACT_S_READONLY | Success. The resource manager votes yes because the transaction was read-only. The resource manager will not be notified of the commit.
E_FAIL | Failure. The resource manager has aborted the transaction.
E_UNEXPECTED | Failure. An unknown error occurred. The resource is in an indeterminate state. The transaction will abort.
XACT_S_SINGLEPHASE | Success: The resource manager has committed the transaction and does not want commit notification. This HRESULT should be specified only if the fSinglePhase flag was TRUE in the call to ITransactionResourceAsync::PrepareRequest.
XACT_S_LASTRESOURCEMANAGER | Success: The resource manager has requested that the transaction manager treat it as a Last Resource Manager (LRM). If the transaction manager is incapable of treating this resource manager as an LRM, the transaction is aborted. This value is not supported in previous releases of MS DTC.
pmk
[in] Must be NULL.
pboidReason
[in] Pointer to a BOID explaining why the transaction could not be prepared. This parameter must be NULL if hr is S_OK, XACT_S_READONLY, XACT_S_SINGLEPHASE, or XACT_S_LASTRESOURCEMANAGER.

Return Values

S_OK
Success.
E_UNEXPECTED
An unexpected error occurred.
E_INVALIDARG
The value of pboidReason must be NULL for the specified hr, or an invalid hr was specified. If the resource manager specifies the hr value of XACT_S_LASTRESOURCEMANAGER to an older version of the proxy, this is the error it will receive. On receiving this error, the LRM should release the enlistment object, causing the transaction to be aborted.
E_FAIL
PrepareRequestDone was called illegally.
XACT_E_NOTSINGLEPHASE
Indicates that the fSinglePhase flag to the ITransactionResourceAsync call was FALSE, but the RM is trying to do the single-phase optimization.
XACT_E_NOTSUPPORTED
Indicates that the version of the associated transaction manager is such that it does not support the LRM functionality. On getting this error, the LRM should release the enlistment object, causing the transaction to be aborted.
XACT_E_NOLASTRESOURCEINTERFACE
Indicates that the proxy received an error when trying to do a QueryInterface on the LRM for the ITransactionLastResourceAsync interface.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.

See Also

IResourceManager Interface


ITransactionVoterFactory2 Interface

The interface contains a single method that is used to create a new transaction voter object. The transaction voter object implements the ITransactionVoterBallotAsync interface. This interface is exported as a sink to the transaction voter for vetoing distributed transaction commitment.

Note: the ITransactionVoterFactory2 interface is no longer supported and applications must instead use the ITransactionVoterFactory2 interface.

When to Implement

You do not need to implement this interface. It is implemented by the core object of the MS DTC Proxy.

When to Use

Use this interface to create a new transaction voter object. For non-durable participants in a transaction it is more advantageous to use a transaction voter object to control the outcome of a transaction as opposed to using an enlistment object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionVoterFactory2 Methods | Description
Create | Creates the transaction voter object and exchanges sinks between the transaction voter and the MS DTC proxy.

Remarks

Call QueryInterface on any interface on the MS DTC proxy core object with a riid of IID_ITransactionVoterFactory2.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.


ITransactionVoterFactory2::Create

This method creates the transaction voter object and exchanges the ITransactionVoterNotifyAsync2 and ITransactionVoterBallotAsync2 sinks between the transaction voter and the MS DTC proxy.

HRESULT Create(
  ITransaction * pITransaction,
  ITransactionVoterNotifyAsync2 * pVoterNotify,
  ITransactionVoterBallotAsync2 ** ppVoterBallot
);

Parameters

pITransaction
[in] Pointer to the ITransaction interface associated with the transaction object on which the transaction voter enlists.
pVoterNotify
[in] Pointer to the ITransactionVoterNotifyAsync sink exported by the transaction voter.
ppVoterBallot
[out] Pointer to a pointer of an ITransactionVoterBallotAsyncinterface supplied to vote on the outcome of a distributed transaction with which it is associated.

Return Values

S_OK
Success.
E_INVALIDARG
Invalid arguments.
E_OUTOFMEMORY
Unable to allocate memory.
XACT_E_NOTRANSACTION
No transaction corresponding to pITransaction.
XACT_E_TMNOTAVAILABLE
Unable to connect to the transaction manager.
XACT_E_CONNECTION_DOWN
Connection with the transaction manager was lost.
XACT_E_CONNECTION_REQUEST_DENIED
The transaction manager refused to accept a connection.
E_UNEXPECTED
An unexpected error has occurred.

Remarks

A transaction voter calls this method on the transaction object for any transaction for which it needs notification of outcome events or would like to veto. The lifetime of a transaction voter object matches that of the transaction with which it is employed.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.


ITransactionVoterBallotAsync Interface

ITransactionVoterBallotAsync is the interface transaction voters use to either sanction or veto a transaction during the prepare phase of the two-phase commit protocol. The interface has one method, VoteRequestDone, which relays a transaction voter's vote on the outcome of a distributed transaction. The transaction voter ballot object, in the MS DTC proxy, implements this interface and creates it on the method call ITransactionVoterFactory2::Create.

Note: the ITransactionVoterBallotAsync interface is no longer supported and applications must instead use the ITransactionVoterBallotAsync interface.

When to Implement

You do not need to implement this interface. It is implemented by the transaction voter ballot object of the MS DTC Proxy.

When to Use

Use this interface to either sanction or veto a transaction during the prepare phase of the two-phase commit protocol.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionVoterBallotAsync Methods | Description
VoteRequestDone | Application server uses this method to submit a vote during the prepare phase of a transaction.

Remarks

You obtain a pointer to this interface by calling the ITransactionVoterFactory2::Create method.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.


ITransactionVoterBallotAsync::VoteRequestDone

An application server invokes the VoteRequestDone method to submit a vote during the prepare phase of a transaction.

HRESULT VoteReqDone(
  HRESULT hr,
  BOID * pboidReason
);

Parameters

hr
[in] HRESULT returning a transaction voter's vote. An application sets this value to S_OK or XACT_OK_NONOTIFY to sanction the transaction. XACT_OK_NONOTIFY specifies that the voter does not want the transaction manager to return with an outcome notification. E_FAIL specifies that the MS DTC should abort the transaction.
pboidReason
[in]Pointer to a BOID returning a transaction abort reason code. This value should be NULL if the voter sanctioned the transaction. Otherwise, the voter can optionally set this value with an abort reason.

Return Values

S_OK
Success.
E_INVALIDARG
One or more parameters were invalid. For example, pboidReason must NULL if hr == S_OK.
E_UNEXPECTED
An unexpected error occurred.
E_FAIL
VoteRequestDone was called illegally.
XACT_E_CONNECTION_DOWN
Lost connection with the TM.

Remarks

The vote is submitted when the MS DTC sends it a vote request through the ITransactionVoterNotifyAsync interface. The voter can either sanction the transaction or vote against it. If a voter successfully votes to abort a transaction, it will not be notified of the transaction outcome.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.


ITransactionVoterNotifyAsync Interface

The ITransactionVoterNotifyAsync2 interface notifies a transaction voter of a vote request during the first phase of the two-phase commit protocol. The transaction voter returns a vote to either sanction a commit outcome or vote to abort the transaction through the ITransactionVoterBallotAsync2::VoteRequestDone method. The ITransactionVoterNotifyAsync2 interface also notifies the voter of commit, abort, heuristic, and in-doubt transaction outcomes during phase two through the inherited ITransactionOutcomeEvents Interface.

Note The ITransactionVoterNotifyAsync2 interface is no longer supported and applications must instead use the ITransactionVoterNotifyAsync2 interface.

When to Implement

An application implements this interface to vote on the outcome of a transaction.

When to Use

The MSDTC Proxy calls on this interface to notify a transaction voter of a vote request during the first phase of the two-phase commit protocol.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ITransactionVoterNotifyAsync Methods | Description
VoteRequest | Notifies a transaction voter that phase one of the two-phase commit protocol has started.

Remarks

You obtain a pointer to this interface from the transaction voter.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.


ITransactionVoterNotifyAsync::VoteRequest

The MS DTC proxy calls this method to notify a transaction voter that phase one of the two-phase commit protocol has started.

HRESULT VoteRequest();

Return Values

S_OK
Success. The transaction associated with this sink has entered phase one of the two-phase commit protocol.

Remarks

The transaction voter implements this method to perform phase one work and return its vote to the transaction manager.

Requirements

To use the methods of this interface, you must include txdtc.h in your project.


Compensating Resource Manager Interfaces

The Compensating Resource Managers (CRM) feature of Component services provides an quick and easy way to integrate application resources with Microsoft Distributed Transaction Coordinator (MS DTC) transactions. The following interfaces provide detailed reference information for developers of compensating resource managers. The interfaces include:

Interfaces | Description
ICrmCompensator | This interface delivers unstructured log records in VC and VJ.
ICrmCompensatorVariants | This interface delivers structured log records to the CRM Compensator when using VB.
ICrmLogControl | This interface is the means by which the CRM Worker and CRM Compensator write records to the log and make them durable.
ICrmMonitor | This interface captures a snapshot of the current state of the CRMs and holds a specific CRM clerk.
ICrmMonitorClerks | This interface obtains information about the state of clerks.
ICrmMonitorLogRecords | This interface monitors the individual log records maintained by a specific CRM clerk for a given transaction.
ICrmFormatLogRecords | This interface converts the log records to viewable format so they can be presented using a generic monitoring tool.


ICrmCompensator Interface

The ICrmCompensator interface delivers unstructured log records in VC.

When to Implement

This interface is implemented by the CRM Compensator.

When to Use

Use the ICrmCompensator interface to deliver unstructured log records to the CRM compensator.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICrmCompensator Methods | Description
SetLogControl | Delivers an ICrmLogControl Interface to the CRM Compensator so that it can write further log records during transaction completion.
BeginPrepare | Notifies the CRM Compensator of the prepare phase of the transaction completion and that records are about to be delivered.
PrepareRecord | Delivers a log record in forward order during the prepare phase.
EndPrepare | Notifies the CRM Compensator that it has had all the log records available during the prepare phase.
BeginCommit | Notifies the CRM Compensator of the commit phase of the transaction completion and that records are about to be delivered.
CommitRecord | Delivers a log record in forward order during the commit phase.
EndCommit | Notifies the CRM Compensator that it has delivered all the log records available during the commit phase.
BeginAbort | Notifies the CRM Compensator of the abort phase of the transaction completion, and that records are about to be delivered.
AbortRecord | Delivers a log record to the CRM Compensator during the abort phase.
EndAbort | Notifies the CRM Compensator that it has received all the log records available during the abort phase.

Remarks

The CRM clerk finds out the CLSID of the CRM Compensator with the ICrmLogControl::RegisterCompensator method. It then calls CoCreateInstance specifying the CLSID of this CRM Compensator, and then it does QueryInterface for both the ICrmCompensator Interface and the ICrmCompensatorVariants Interface.

Requirements

To implement the methods of this interface, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::AbortRecord

This method delivers a log record to the CRM Compensator during the abort phase. Log records are delivered in the reverse of the order in which they were originally written. This method may be received by the CRM Compensator multiple times, once for each log record that was written. If no log records were written, then the BeginAbort and EndAbort methods will be received but there will be no AbortRecord method calls.

The CRM Compensator can choose to forget the record that was delivered to it during this method by setting the forget flag on return from this method.

C++ Syntax

HRESULT Abortrecord(
[in] CrmLogRecordRead CrmLogRec,
[out, retval] BOOL * pfForget
);
CrmLogRec
[in] The log record.
pfForget
[out] A pointer to a flag which indicates whether the delivered record should be forgotten.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::BeginAbort

This method notifies the CRM Compensator of the abort phase (phase 2) of the transaction completion and that records are about to be delivered. Note that the abort phase can be received during normal processing without a prepare phase should the client decide to initiate abort.

The CRM Compensator should not depend on any state to be maintained between the prepare phase and this phase; the CRM infrastructure is free to release the CRM Compensator between these 2 phases should it need to do so. State is however maintained between the Begin-Record-End calls, and the CRM Compensator will always get the ICrmLogControl interface before delivery of any transaction outcome methods.

C++ Syntax

HRESULT BeginAbort(
[in] BOOL fRecovery
);
fRecovery
[in] This method is being called during recovery.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::BeginCommit

This method notifies the CRM Compensator of the commit phase (phase 2) of the transaction completion, and that records are about to be delivered. A flag indicates whether this method is being called during recovery or normal processing. Note that the commit or abort phases will be received by the compensator without a prepare phase during recovery. Note also that the abort phase can also be received during normal processing without a prepare phase should the client decide to initiate abort.

C++ Syntax

HRESULT BeginCommit(
[in] BOOL fRecovery
);
fRecovery
[in] Indicates whether this method is being called during recovery.

Remarks

The CRM Compensator should not depend on any state to be maintained between the prepare and commit/abort phases - the CRM infrastructure is free to release the CRM Compensator between these 2 phases should it need to do so. State is however maintained between the Begin-Record-End calls, and the CRM Compensator will always get the ICrmLogControl interface before delivery of any transaction outcome methods.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::BeginPrepare

This method notifies the CRM Compensator of prepare phase (phase 1) of the transaction completion, and that records are about to be delivered. Prepare notifications are never received during recovery, only during normal processing.

C++ Syntax

HRESULT BeginPrepare(
);

Return Values

If the CRM Compensator returns anything other than S_OK from this call it will be considered a CRM Compensator error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::CommitRecord

This method delivers a log record during the commit phase. Log records are delivered in the order they were originally written. This method may be received by the CRM Compensator multiple times, once for each log record that was written. If no log records were written, then the BeginCommit and EndCommit methods will be received but there will be no CommitRecord method calls.

The CRM Compensator can choose to forget the record that was delivered to it during this method by setting the forget flag on return from this method.

C++ Syntax

HRESULT CommitRecord(
  [in] CrmLogRecordRead crmLogRec,
  [out, retval] BOOL * pfForget
);
crmLogRec
[in] The log record.
pfForget
[out] A pointer to a flag which indicates whether the delivered record should be forgotten.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::EndAbort

This method notifies the CRM Compensator that it has received all the log records available during the abort phase. All log records for this transaction are free to be discarded from the log once this method has completed.

C++ Syntax

HRESULT EndAbort(
);

Return Values

If the CRM Compensator returns anything other than S_OK from this call it will be considered a CRM Compensator error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::EndCommit

This method notifies the CRM Compensator that it has delivered all the log records available during the commit phase. All log records for this transaction are free to be discarded from the log once this method has completed.

C++ Syntax

HRESULT EndCommit(
);

Return Values

If the CRM Compensator returns anything other than S_OK from this call it will be considered a CRM Compensator error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::EndPrepare

This method notifies the CRM Compensator that it has received all the log records available during the prepare phase. The CRM Compensator votes on the transaction outcome using the return parameter from this method.

C++ Syntax

HRESULT EndPrepare(
[out, retval] BOOL * pfOkToPrepare
);
pfOkToPrepare
[out] A pointer to a flag which indicates whether the prepare phase succeeded and it is OK to commit this transaction.

Return Values

If the CRM Compensator returns anything other than S_OK from this call it will be considered a CRM Compensator error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::PrepareRecord

This method delivers a log record during the prepare phase. Log records are delivered in forward order for this phase. This method may be received by the CRM Compensator multiple times, once for each log record that was written.

C++ Syntax

HRESULT PrepareRecord(
[in] CrmLogRecordRead crmLogRec,
[out, retval] BOOL * pfForget

typedef struct tagCrmLogRecordRead
{
  DWORD dwCrmFlags;
  DWORD dwSequenceNumber;
  BLOB blobUserData;

} CrmLogRecordRead;

typedef enum tagCRMFLAGS
{
  CRMFLAG_FORGETTARGET=0x00000001,
  CRMFLAG_WRITTENDURINGPREPARE=0x00000002,
  CRMFLAG_WRITTENDURINGCOMMIT=0x00000004,
  CRMFLAG_WRITTENDURINGABORT=0x00000008,
  CRMFLAG_WRITTENDURINGRECOVERY=0x00000010,
  CRMFLAG_WRITTENDURINGREPLAY=0x00000020,
  CRMFLAG_REPLAYINPROGRESS   =0x00000040,

} CRMFLAGS;
);
crmLogRec
[in] The log record.
pfForget
[out] A pointer to a flag which indicates whether the delivered record should be forgotten.
dwCrmFlags
[in] Bit field which provides further information about when this record was written.
dwSequenceNumber
[in] The sequence number of the log record. Sequence numbers might not necessarily be contiguous due to internal log records or forgotten log records which are not delivered to the CRM Compensator.
blobUserData
[in] User data information.

Return Values

If the CRM Compensator returns anything other S_OK from this call it will be considered a CRM Compensator error.

Remarks

Unstructured log records are delivered as a CrmLogRecordRead structure. In addition to the user data (as a single BLOB) this contains a couple of additional fields which might be useful for debugging or fault finding should human compensation be necessary. The dwCrmFlags field is a bit field which provides further information about whether this record was forgotten at some point, and when it was written. The dwSequenceNumber provides the sequence number of the log record. In most cases sequence numbers will be sequential but might not necessarily be contiguous due to internal log records which are not delivered to the CRM Compensator.

If no log records were written by the CRM Worker, then the BeginPrepare and EndPrepare methods will be received but there will be no PrepareRecord method calls. This is to allow for CRM Compensators which write log records at prepare time only.

The CRM Compensator can choose to forget the record that was delivered to it during this method by setting the forget flag on return from this method.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensator::SetLogControl

This method delivers an ICrmLogControl Interface to the CRM Compensator so that it can write further log records during transaction completion. This method is the first method called on the CRM Compensator once it has been created.

C++ Syntax

HRESULT SetLogControl(
[in] ICrmLogControl * pLogControl
);
pLogControl
[in] A pointer to the ICrmLogControl interface of the CRM clerk.

Return Values

If the CRM Compensator returns anything other than S_OK from this call it will be considered a CRM Compensator error. CRM Compensator errors will cause failfast of the server process, unless this has been specifically overriden (via a registry flag) for this particular CRM Compensator CLSID.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensatorVariants Interface


ICrmCompensatorVariants Interface

The ICrmCompensatorVariants interface delivers structured log records to the CRM Compensator when using Visual Basic.

When to Implement

This interface is implemented by the CRM Compensator.

When to Use

Use the ICrmCompensatorVariants interface is used to deliver unstructured log records.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICrmCompensatorVariants Methods | Description
SetLogControlVariants | Delivers an ICrmLogControl interface to the CRM Compensator.
BeginPrepareVariants | Notifies the CRM Compensator of the prepare phase of the transaction completion and that records are about to be delivered.
PrepareRecordVariants | Delivers a log record to the CRM Compensator during the prepare phase.
EndPrepareVariants | Notifies the CRM Compensator that it has had all the log records available during the prepare phase.
BeginCommitVariants | Notifies the CRM Compensator of the commit phase (phase 2) of the transaction completion, and that records are about to be delivered.
CommitRecordVariants | Delivers a log record to the CRM Compensator during the commit phase.
EndCommitVariants | Notifies the CRM Compensator that it has delivered all the log records available during the commit phase.
BeginAbortVariants | Notifies the CRM Compensator of the abort phase of the transaction completion, and that records are about to be delivered.
AbortRecordVariants | Delivers a log record to the CRM Compensator during the abort phase.
EndAbortVariants | Notifies the CRM Compensator that it has received all the log records available during the abort phase.

Remarks

The CRM clerk finds out the CLSID of the CRM Compensator with the ICrmLogControl::RegisterCompensator method. It then calls CoCreateInstance specifying the CLSID of this CRM Compensator, and then it does QueryInterface for both the ICrmCompensator Interface and the ICrmCompensatorVariants Interface

Requirements

To implement the methods of this interface, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::AbortRecordVariants

This method delivers a log record to the CRM Compensator during the abort phase. Log records are delivered in the reverse of the order in which they were originally written. This method may be received by the CRM Compensator multiple times, once for each log record that was written. If no log records were written, then the BeginAbortVariants and EndAbortVariants methods will be received but there will be no AbortRecordVariants method calls.

The CRM Compensator can choose to forget the record that was delivered to it during this method by setting the forget flag on return from this method.

C++ Syntax

HRESULT AbortRecordVariants (
[in] VARIENT * pLogRecord,
[out, retval] VARIANT_BOOL * pbForget
);
pLogRecord
[in] The log record (as a variant array of variants).
pbForget
[out] A pointer to a flag which indicates whether the delivered record should be forgotten.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::BeginAbortVariants

This method notifies the CRM Compensator of the abort phase (phase 2) of the transaction completion, and that records are about to be delivered. The abort phase can be received during normal processing without a prepare phase should the client decide to initiate abort.

The CRM Compensator should not depend on any state to be maintained between the prepare phase and this phase- the CRM infrastructure is free to release the CRM Compensator between these two phases should it need to do so. State is however maintained between the Begin-Record-End calls, and the CRM Compensator will always get the ICrmLogControl interface before delivery of any transaction outcome methods.

C++ Syntax

HRESULT BeginAbortVariants(
[in] VARIANT_BOOL * bRecovery
);
bRecovery
[in] A flag which indicates whether this method is being called during recovery.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::BeginCommitVariants

This method notifies the CRM Compensator of the commit phase (phase 2) of the transaction completion, and that records are about to be delivered.

The CRM Compensator should not depend on any state to be maintained between the prepare phase and this phase- the CRM infrastructure is free to release the CRM Compensator between these two phases should it need to do so. State is however maintained between the Begin-Record-End calls, and the CRM Compensator will always get the ICrmLogControl interface before delivery of any transaction outcome methods.

C++ Syntax

HRESULT BeginCommitVariants(
[in] VARIANT_BOOL * bRecovery,
);
bRecovery
[in] A flag which indicates whether this method is being called during recovery.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::BeginPrepareVariants

This method notifies the CRM Compensator of the prepare phase (phase 1) of the transaction completion, and that records are about to be delivered.

Prepare notifications are never received during recovery, only during normal processing.

C++ Syntax

HRESULT BeginPrepareVariants(
);

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::CommitRecordVariants

This method delivers a log record to the CRM Compensator during the commit phase. Log records are delivered in the order they were originally written. This method may be received by the CRM Compensator multiple times, once for each log record that was written. If no log records were written, then the BeginCommitVariants and EndCommitVariants methods will be received but there will be no CommitRecordVariants method calls.

The CRM Compensator can choose to forget the record that was delivered to it during this method by setting the forget flag on return from this method.

C++ Syntax

HRESULT CommitRecordVariants (
[in] VARIENT * pLogRecord,
[out, retval] VARIANT_BOOL * pbForget
);
pLogRecord
[in] The log record (as a variant array of variants).
pbForget
[out] A pointer to a flag which indicates whether the delivered record should be forgotten.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::EndAbortVariants

This method notifies the CRM Compensator that it has received all the log records available during the abort phase. All log records for this transaction are free to be discarded from the log once this method has completed.

C++ Syntax

HRESULT EndAbortVariants(
);

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmCompensatorVariants::EndCommitVariants

This method notifies the CRM Compensator that it has received all the log records available during the commit phase. All log records for this transaction are free to be discarded from the log once this method has completed.

C++ Syntax

HRESULT EndCommitVariants(
);

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::EndPrepareVariants

This method notifies the CRM Compensator that it has received all the log records available during the prepare phase.

C++ Syntax

HRESULT EndPrepareVariants (
[out, retval] VARIANT_BOOL * pbOkToPrepare
);
pbOkToPrepare
[out] A pointer to a flag which indicates whether the prepare phase succeeded and it is OK to commit this transaction.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::PrepareRecordVariants

This method delivers a log record to the CRM Compensator during the prepare phase. Log records are delivered in the order they were originally written. This method may be received by the CRM Compensator multiple times, once for each log record that was written.

For the ICrmCompensatorVariants interface, log records are delivered as a variant array of variants in the same way that they were written. The CRM flags and sequence number (see ICrmCompensator::PrepareRecord) are appended as the last two elements in the array.

If no log records were written by the CRM Worker, then the BeginPrepareVariants and EndPrepareVariants methods will be received by the CRM Compensator but there will be no PrepareRecordVariants method calls. This is to allow for CRM Compensators which write log records at prepare time only.

The CRM Compensator can choose to forget the record that was delivered to it during this method by setting the forget flag on return from this method.

C++ Syntax

HRESULT PrepareRecordVariants(
[in] VARIANT * pLogRecord,
[out, retval] VARIANT_BOOL * pbForget
);
pLogRecord
[in] The log record (as a variant array of variants).
pbForget
[out] A pointer to a flag which indicates whether the delivered record should be forgotten.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmCompensatorVariants::SetLogControlVariants

This method delivers an ICrmLogControl interface to the CRM Compensator. You can use the ICrmLogControl interface to write further log records if required. This method is the first method called on the CRM Compensator once it has been created.

C++ Syntax

HRESULT SetLogControlVariants(
[in] ICrmLogControl * pLogControl,
);
pLogControl
[in] A pointer to the ICrmLogControl interface of the CRM clerk.

Return Values

Any other return than S_OK is considered an error.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmCompensator Interface


ICrmLogControl Interface

The ICRMLogControl interface is the means by which the CRM Worker and CRM Compensator write records to the log and make them durable.

When to Implement

ICrmLogControl is implemented on the CRM clerk.

When to Use

A CRM Worker uses this interface to write log records to the log. The CRM Compensator can also use this interface.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICrmLogControl Methods | Description
TransactionUOW | Allows CRMs to obtain the transaction Unit Of Work (UOW), a GUID, as a BSTR without having to log the transaction UOW in the log record.
RegisterCompensator | The CRM Worker uses this method to register the CRM Compensator with the CRM infrastructure.
WriteLogRecordVariants | The CRM Worker and CRM Compensator use this method to write structured log records to the log.
ForceLog | Forces all log records to be durable on disk.
ForgetLogRecord | Forgets the last log record written by this instance of the interface.
ForceTransactionToAbort | Performs an immediate abort call on the transaction.
WriteLogRecord | The CRM Worker and CRM Compensator use this method to write unstructured log records to the log in VC.

Remarks

The CRM Worker obtains this interface by creating an instance of a CRM Clerk.

The CRM Worker calls CoCreateInstance specifying the CLSID of the CRM clerk and the IID of ICrmLogControl.

The CRM Compensator receives this interface after its instantiation via the ICrmCompensator::SetLogControl or ICrmCompensatorVariants::SetLogControlVariants methods.

In addition to the return values listed for each method, the methods may also pass back error codes from DTC (Distributed Transaction Coordinator) or other standard COM error codes.

Requirements

To implement the methods of this interface, you must include comsvcs.h in your project.


ICrmLogControl::ForceLog

This method forces all log records (that have been written so far) to disk. The CRM Worker and CRM Compensator use this method to write Log records lazily to the log, which means they are not made durable until they have been forced to the log. Calling ForceLog will make all log records that have been written durable on disk.

C++ Syntax

HRESULT ForceLog(
);

Return Values

S_OK
Success.
XACT_E_WRONGSTATE
This method was called in the wrong state; either before RegisterCompensator or when the transaction is completing (CRM Worker)
XACT_E_ABORTED
The transaction has aborted. Most likely this is because of a transaction timeout.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmLogControl::ForceTransactionToAbort

This method performs an immediate abort call on the transaction.

C++ Syntax

HRESULT ForceTransactionToAbort(
);

Return Values

S_OK
Success.
XACT_E_WRONGSTATE
This method was called in the wrong state; either before RegisterCompensator or when the transaction is completing (CRM Worker).
XACT_E_ABORTED
The transaction has aborted. Most likely this is because of a transaction timeout.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmLogControl::ForgetLogRecord

The CRM Worker and CRM Compensator use this method to forget the last log record that was written by this instance of this interface. It can only be used to forget the last record, there is no concept of nesting; that is, Write, Forget, Write, Forget is valid, but Write, Write, Forget, Forget is not. A log record that has been forgotten will not be delivered to the CRM Compensator during transaction outcome notifications.

C++ Syntax

HRESULT ForgetLogRecord(
);

Return Values

S_OK
Success.
E_FAIL
There is no valid log record to forget.
XACT_E_WRONGSTATE
This method was called in the wrong state; either before RegisterCompensator or when the transaction is completing (CRM Worker)
XACT_E_ABORTED
The transaction has aborted. Most likely this is because of a transaction timeout.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmLogControl::RegisterCompensator

The CRM Worker uses this method to register the CRM Compensator with the CRM infrastructure. It must be the first method called by the CRM Worker, and it can be called successfully only once. If the CRM Worker receives a "recovery in progress" error code on calling this method, it should call this method again until it receives success.

C++ Syntax

HRESULT RegisterCompensator(
LPCWSTR lpcwstrProgIdCompensator,
LPCWSTR lpcwstrDescription
LONG lCrmRegFlags
);

typedef enum tagCRMREGFLAGS
{
CRMREGFLAG_PREPAREPHASE=0x00000001,
CRMREGFLAG_COMMITPHASE=0x00000002,
CRMREGFLAG_ABORTPHASE=0x00000004,
CRMREGFLAG_ALLPHASES=0x00000007,
CRMREGFLAG_FAILIFINDOUBTSREMAIN=0x00000010,

} CRMREGFLAGS;
lpcwstrProgIdCompensator
[in] The ProgId of the CRM Compensator. The CLSID of the CRM Compensator in string form is also accepted.
lpcwstrDescription
[in] Description string to be used by the monitoring interfaces.
lCrmRegFlags
[in] Flags (see syntax above) that control which phases of transaction completion should be received by the CRM Compensator, and whether recovery should fail in-doubt transactions remain after recovery has been attempted.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_UNEXPECTED
An unexpected error has occurred.
XACT_E_NOTRANSACTION
The component creating the CRM clerk does not have a transaction.
XACT_E_RECOVERYINPROGRESS
Recovery of the CRM log file is still in progress.
XACT_E_RECOVERY_FAILED
Recovery of the CRM log file failed because in-doubt transactions remain.
XACT_E_WRONGSTATE
This method was called in the wrong state - RegisterCompensator was already successfully called by the CRM Worker.
E_OUTOFMEMORY
Out of memory.
E_NOINTERFACE
The CRM Compensator does not support at least one of the correct interfaces (ICrmCompensator or ICrmCompensatorVariants).

Remarks

The lCrmRegFlags parameter allows the implementor to decide which phases of transaction completion the CRM Compensator wants to receive. Some CRM Compensators might perform no work in the prepare phase, and so have no need to receive prepare notifications; it can improve performance to specify that no prepare phase is required in this case.

It is recommended that CRM Workers and CRM Compensators be developed as "Both" threaded components (Threading Model = Any Apartment). However, in some cases this might not be possible due to language contraints (for example, when developing CRMs with VB). Apartment threaded CRM Compensators (Threading Model = Single Thread Apartment) will deadlock in the prepare phase unless their synchronization property is set to "not supported". Another alternative for Apartment threaded CRM Compensators is to skip the prepare phase if it is not necessary.

The "fail if in-doubts remain" flag is used as follows. In scenarios with multiple Distributed Transaction Coordinators (DTCs), it is possible that a DTC transaction can go into the "in-doubt" state. Normally this is because an interruption occurred during a transaction, and the originator of the transaction cannot be contacted to find out the outcome of the transaction. In this case, the CRM infrastructure cannot determine the outcome of the transaction. A CRM implementor can decide whether new transactions should be allowed in this case, or not. By specifying the "fail if in-doubts remain" flag on RegisterCompensator, if in-doubts transactions remain after recovery, then the call to RegisterCompensator will fail with a "recovery failed" error code (see below). If the "fail if in-doubts remain" flag is not specified, then the recovery will succeed, new transactions will be allowed, and the in-doubt transactions will remain in the CRM log file. The CRM infrastructure will attempt to resolve these in-doubt transactions again on the next recovery (when the application server process is started again).

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmLogControl::TransactionUOW

This method allows CRMs to obtain the transaction Unit Of Work (UOW), a GUID, as a BSTR without having to log the transaction UOW in the log record.

C++ Syntax

HRESULT TransactionUOW(
[out, retval] BSTR * pVal
);
pVal
[out] A pointer to a string which returns the UOW of the transaction.

Return Values

S_OK
Success
E_POINTER
A NULL pointer was provided as an argument.
XACT_E_WRONGSTATE
This method was called in the wrong state - RegisterCompensator was not yet successfully called by the CRM Worker.
E_OUTOFMEMORY
Out of memory.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmLogControl::WriteLogRecord

The CRM Worker and CRM Compensator WriteLogRecord use this method to write unstructured log records to the log. This method would typically be used by CRM components written with VC. Records are written lazily to the log and must be forced before they become durable (see ICrmLogControl::ForceLog).

Unstructured records are simply a buffer of bytes. The method implements a gather capability by allowing sections of the CRM specific log record to be built up from an array of BLOBs, which is a structure containing a pointer to the data plus a count of the number of bytes. This reduces the copying of data, leading to only one copy directly from the CRM memory space into the buffer of the log manager.

Note, however, that you should not include pointer types within datastructures contained in BLOBs in a log record. Object references will no longer be valid during recovery phase, as the CRM Compensator runs in a different process than that of the CRM Worker that wrote the log record. Including pointer types within BLOBs in a log record may cause an application to crash or corrupt itself during recovery.

Unstructured and structured log records cannot be mixed - either WriteLogRecord or WriteLogRecordVariants can be called, but not both by the same CRM Worker or CRM Compensator.

C++ Syntax

HRESULT WriteLogRecord(
[in, size_is(cBlob)] BLOB rgBlob[],
[in] ULONG cBlob
);
rgBlob
[in] An array of blobs that form the log record.
cBlob
[in] The number of blobs in the array.

Return Values

S_OK
Success.
E_INVALIDARG
The count of the number of blobs is zero.
E_POINTER
A NULL pointer was provided as an argument.
XACT_E_WRONGSTATE
This method was called in the wrong state; either before RegisterCompensator or when the transaction is completing (CRM Worker)
XACT_E_ABORTED
The transaction has aborted. Most likely this is because of a transaction timeout.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmLogControl::WriteLogRecordVariants

The CRM Worker and CRM use this method to write structured log records to the log. Structured records are records made up as a variant array of variants. Typically this method would be used by CRM Workers and CRM Compensators that are written in VB or VJ. Records are written lazily to the log and must be forced before they become durable (see ICrmLogControl::ForceLog).

Unstructured and structured log records cannot be mixed - either WriteLogRecord or WriteLogRecordVariants can be called, but not both by the same CRM Worker or CRM Compensator.

C++ Syntax

HRESULT WriteLogRecordVariants(
[in] VARIANT * pLogRecord
);
pLogRecord
[in] Pointer to a variant array of variants.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
XACT_E_WRONGSTATE
This method was called in the wrong state; either before RegisterCompensator or when the transaction is completing (CRM Worker).
XACT_E_ABORTED
The transaction has aborted. Most likely this is because of a transaction timeout.
E_INVALIDARG
There are several reasons this error code could be returned:

Wrong variant type was provided – must be a variant array

Wrong dimension array – must be single dimension variant array

Wrong type of array – must be an array of variants

Wrong lower bound – lower bound of array must be zero

Unsupported variant type – only simple variants types are supported

Log record is too large

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmLogControl Interface


ICrmMonitor Interface

The ICrmMonitor interface captures a snapshot of the current state of the CRMs and holds a specific CRM clerk.

When to Implement

This interface is implemented by the CRM recovery clerk.

When to Use

Use this interface to obtain the current state of the CRMs, and to hold a specific CRM clerk.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICrmMonitor Methods | Description
GetClerks | Returns a clerk collection object, which is a snapshot of the current state of the clerks.
HoldClerk | Returns an IUnknown pointer on the specified clerk (as a variant IUnknown).

Remarks

Use CoCreateInstance for the CRM recovery clerk and specify the IID of ICrmMonitor.

Requirements

To implement the methods of this interface, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitor::GetClerks

This method returns a clerks collection object, which is a snapshot of the current state of the clerks.

C++ Syntax

HRESULT GetClerks(
[out, retval] ICrmMonitorClerks **pClerks
);
pClerks
[out] Pointer to a clerks collection object.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
XACT_E_RECOVERYINPROGRESS
Recovery of the CRM log file is still in progress.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitor Interface


ICrmMonitor::HoldClerk

This method returns an IUnknown pointer on the specified clerk and holds it in memory.

C++ Syntax

HRESULT HoldClerk(
[in] VARIANT Index,
[out, retval] LPVARIANT pItem
);
Index
[in] A VARIANT string containing the instance CLSID of the required CRM clerk.
pItem
[out] A VARIANT IUnknown pointer returning the interface to the specified CRM clerk.

Return Values

S_OK
Success.
E_INVALIDARG
There are several reasons this error code could be returned:

Index was not the correct variant type – must be a string.

Index variant string was incorrectly formatted – must be a CLSID.

XACT_E_CLERKNOTFOUND
The specified CRM clerk was not found. It may have completed before it could be held.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitor Interface


ICrmMonitorClerks Interface

The ICrmMonitorClerks interface obtains information about the state of clerks.

When to Implement

The clerks collection object implements the ICrmMonitorClerks interface.

When to Use

Use the clerks collection object to browse for information about the state of the clerks.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICrmMonitorClerks Methods | Description
Item | Returns the instance CLSID of the CRM clerk given a numeric index into the collection.
ICrmMonitorClerks::_NewEnum | Returns an IEnumVARIANT interface to enumerate the instance CLSIDs of the CRM clerks as variant strings.
Count | Returns the count of CRM clerks in the collection.
ProgIdCompensator | Returns the ProgId of the CRM Compensator given an index into the collection.
Description | Returns the description of the CRM Compensator given an index into the collection.
TransactionUOW | Returns the Unit Of Work (UOW) of the transaction given an index into the collection.
ActivityId | Returns the activity id of the CRM Worker given an index into the collection.

Remarks

The clerks collection information includes the number of clerks, the ProgId of the CRM Compensator used by the clerk, the description provided at the time the CRM Compensator was registered (using ICrmLogControl::RegisterCompensator), the transaction Unit Of Work (UOW) id, and the activity id. Individual clerks are uniquely identified by a "clerk instance CLSID.

Requirements

To implement the methods of this interface, you must include comsvcs.h in your project.


ICrmMonitorClerks::ActivityId

This method returns the activity id of the CRM Worker given an index into the collection. The index can be either numeric or the instance CLSID of the required CRM clerk.

C++ Syntax

HRESULT ActivityId (
[in] VARIANT Index,
[out, retval] LPVARIANT pItem
);
Index
[in] Index of the required CRM clerk as a numeric variant, or the instance CLSID as a variant string.
pItem
[out] The activity id of the CRM Worker.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_INVALIDARG
There are several reasons this error code could be returned:

Index was not the correct variant type – must be numeric or string

Index was out of range

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitorClerks::Count

This method returns the count of CRM clerks in the collection.

C++ Syntax

HRESULT Count(
[out, retval] long *pVal
);
pVal
[out] A pointer to the returned count of the number of CRM clerks.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitorClerks::Description

This method returns the description of the CRM Compensator given an index into the collection. The index can be either numeric or the instance CLSID of the required CRM clerk. The description string is the string that was provided by the ICrmLogControl::RegisterCompensator method.

C++ Syntax

HRESULT Description (
[in] VARIANT Index,
[out, retval] LPVARIANT pItem
);
Index
[in] Index of the required CRM clerk as a numeric variant, or the instance CLSID as a variant string.
pItem
[out] The description string originally provided by RegisterCompensator.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_INVALIDARG
There are several reasons this error code could be returned:

Index was not the correct variant type – must be numeric or string

Index was out of range

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitorClerks::Item

This method returns the instance CLSID of the CRM clerk given a numeric index into the collection.

C++ Syntax

HRESULT Item(
[in] VARIANT Index,
[out, retval] LPVARIANT pItem
);
Index
[in] A numeric varient index into the collection.
pItem
[out] A pointer to varient string returning the instance CLSID corresponding to this numeric index.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_INVALIDARG
There are several reasons this error code could be returned:

Index was not the correct variant type – must be numeric

Index was out of range

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitorClerks::_NewEnum

This method returns an IEnumVARIANT interface which can be used to enumerate the instance CLSIDs of the CRM clerks as variant strings.

C++ Syntax

HRESULT _NewEnum(
[out, retval] LPUNKNOWN *pVal
);
pVal
[out] A pointer to the returned enumerator.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitorClerks::ProgIdCompensator

This method returns the ProgId of the CRM Compensator given an index into the collection. The index can be either numeric or the instance CLSID of the required CRM clerk.

C++ Syntax

HRESULT ProgIdCompensator(
[in] VARIANT Index,
[out, retval] LPVARIANT pItem
);
Index
[in] Index of the required CRM clerk as a numeric variant, or the instance CLSID as a variant string.
pItem
[out] The ProgId of the CRM Compensator.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_INVALIDARG
There are several reasons this error code could be returned :

Index was not the correct variant type – must be numeric or string.

Index was out of range.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitorClerks::TransactionUOW

This method returns the Unit Of Work (UOW) of the transaction given an index into the collection. The index can be either numeric or the instance CLSID of the required CRM clerk.

C++ Syntax

HRESULT TransactionUOW (
[in] VARIANT Index,
[out, retval] LPVARIANT pItem
);
Index
[in] Index of the required CRM clerk as a numeric variant, or the instance CLSID as a variant string.
pItem
[out] The transaction UOW.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_INVALIDARG
There are several reasons this error code could be returned:

Index was not the correct variant type – must be numeric or string

Index was out of range

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorClerks Interface


ICrmMonitorLogRecords Interface

The ICrmMonitorLogRecords interface monitors the individual log records maintained by a specific CRM clerk for a given transaction.

When to Implement

ICrmMonitorLogRecords is implemented by the CRM clerk.

When to Use

Use the ICrmMonitorLogRecords interface to query the current state of the transaction, to find out how many log records this CRM clerk has written, and to obtain the actual log record data.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICrmMonitorLogRecords Methods | Description
Count | Returns the number of log records written by this CRM clerk.
TransactionState | Returns the current state of the transaction.
StructuredRecords | Returns a flag indicating whether the log records written by this CRM clerk were structured.
GetLogRecord | Returns an unstructured log record given its numeric index.
GetLogRecordVariants | Returns a structured log record given its numeric index.

Remarks

Because the ICrmMonitorLogRecords interface is implemented directly on the CRM clerk, you can QueryInterface for ICrmLogControl (also implemented on the CRM clerk). This can then be used to directly abort the transaction if required (ICrmLogControl::ForceTransactionToAbort).

Requirements

To implement the methods of this interface, you must include comsvcs.h in your project.


ICrmMonitorLogRecords::Count

This method returns the number of log records written by this CRM clerk.

C++ Syntax

HRESULT Count(
[out, retval] long *pVal
);
pVal
[out] Number of log records written by this CRM clerk.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorLogRecords Interface


ICrmMonitorLogRecords::GetLogRecord

This method returns an unstructured log record given its numeric index.

C++ Syntax

HRESULT GetLogRecord(
[in] DWORD dwIndex,
[in, out] CrmLogRecordRead *pCrmLogRec
);
dwIndex
[in] Index of the required log record.
pCrmLogRec
[in, out] The log record.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_INVALIDARG
Index is out of range.
XACT_E_WRONGSTATE
Attempting to read unstructured records, but structured records were written.
XACT_E_TRANSACTIONCLOSED
The transaction has completed and the log records have been discarded from the log file. They are no longer available.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorLogRecords Interface


ICrmMonitorLogRecords::GetLogRecordVariants

This method returns a structured log record given its numeric index.

C++ Syntax

HRESULT GetLogRecordVariants(
[in] VARIANT IndexNumber,
[out, retval] LPVARIANT pLogRecord
);
IndexNumber
[in] Index of the required log record.
pLogRecord
[out] The log record (see ICrmLogControl::PrepareRecordVariants for the format).

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_INVALIDARG
There are several reasons this error code could be returned:

Index was not the correct variant type – must be numeric

Index was out of range

XACT_E_WRONGSTATE
Attempting to read structured records, but unstructured records were written.
XACT_E_TRANSACTIONCLOSED
The transaction has completed and the log records have been discarded from the log file. They are no longer available.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorLogRecords Interface


ICrmMonitorLogRecords::StructuredRecords

This method returns a flag indicating whether the log records written by this CRM clerk were structured or not. If this method is called before any log records have been written it will return TRUE.

C++ Syntax

HRESULT StructuredRecords(
[out, retval] VARIANT_BOOL *pVal
);
pVal
[out] Flag indicating whether the log records are structured.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorLogRecords Interface


ICrmMonitorLogRecords::TransactionState

This method returns the current transaction state of the transaction.

C++ Syntax

typedef enum tagCrmTransactionState
{
   TxState_Active,
   TxState_Committed,
   TxState_Aborted,
   TxState_Indoubt,
} CrmTransactionState;

HRESULT TransactionState(
[out, retval] CrmTransactionState *pVal
);
pVal
[out] The current transaction state.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmMonitorLogRecords Interface


ICrmFormatLogRecords Interface

The ICrmFormatLogRecords interface converts the log records to viewable format so they can be presented using a generic monitoring tool.

When to Implement

This interface can be optionally implemented by a CRM Compensator.

When to Use

CRM Compensator can optionally implement this interface to format its log records into a viewable format.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
ICrmFormatLogRecords Methods | Description
GetColumnCount | Returns the number of fields (columns) in a log record of the type used by this CRM Compensator.
GetColumnHeaders | Returns the names of the fields (columns) as a variant array of variant strings.
GetColumn | Formats one unstructured log record into an array of viewable fields.
GetColumnVariants | Formats one structured log record into an array of viewable fields.

Remarks

The log records are provided from the ICrmMonitorLogRecords interface in the same format that they were originally written (using ICrmLogControl). ICrmFormat can be used to convert the log records to viewable format so they can be presented using a generic monitoring tool.

Requirements

To implement the methods of this interface, you must include comsvcs.h in your project.


ICrmFormatLogRecords::GetColumn

This method formats one unstructured log record into an array of viewable fields.

C++ Syntax

HRESULT GetColumn(
[in] CrmLogRecordRead CrmLogRec,
[out] LPVARIANT pFormattedLogRecord
);
CrmLogRec
[in] The unstructured log record to be formatted.
pFormattedLogRecord
[out] A variant array of the fields in this log record as variant strings.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_FAIL
The log record could not be formatted.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmFormatLogRecords Interface


ICrmFormatLogRecords::GetColumnCount

This method returns the number of fields (columns) in a log record of the type used by this CRM Compensator.

C++ Syntax

HRESULT GetColumnCount(
[out] long *plColumnCount
);
plColumnCount
[out] The number of fields (columns) in the log record.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmFormatLogRecords Interface


ICrmFormatLogRecords::GetColumnHeaders

This method returns the names of the fields (columns) as a variant array of variant strings. This is so the field names may be used as column headings when the information is presented.

C++ Syntax

HRESULT GetColumnHeaders(
[out] LPVARIANT pHeaders
);
pHeaders
[out] A variant array containing the field names as variant strings.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmFormatLogRecords Interface


ICrmFormatLogRecords::GetColumnVariants

This method formats one structured log record into an array of viewable fields.

C++ Syntax

HRESULT GetColumnVariants(
[in] VARIANT LogRecord,
[out] LPVARIANT pFormattedLogRecord
);
LogRecord
[in] The structured log record to be formatted.
pFormattedLogRecord
[out] A variant array of the fields in this log record as variant strings.

Return Values

S_OK
Success.
E_POINTER
A NULL pointer was provided as an argument.
E_FAIL
The log record could not be formatted.

Requirements

To implement this method, you must include comsvcs.h in your project.

See Also

ICrmFormatLogRecords Interface


Resource Dispenser Interfaces

Application components use resource dispensers to access shared information. The following interfaces provide detailed reference information for developers of resource dispensers. The interfaces include:

Interfaces | Description
IDispenserManager | Individual resource dispensers use this interface to connect to DispMan.
IDispenserDriver | This interface is called by the holder of the resource dispenser to create enlist, evaluate, and destroy a resource.
IHolder | This interface is used to prepare and handle resources.


IDispenserManager Interface

DispMan exposes IDispenserManager to resource dispensers.

When to Implement

You do not need to implement this interface. It is implemented in comsvcs.dll.

When to Use

Individual resource dispensers use this interface to connect to DispMan.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispenserManager Methods | Description
RegisterDispenser | Resource dispenser tells DispMan it has started and wants to be connected.
GetContext | Resource dispenser (or any caller) asks about current COM+ instance and transaction context.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserDriver Interface


IDispenserManager::GetContext

A resource dispenser (or any caller with a reference to IDispenserManager) can call this method to determine the current context.

HRESULT IDispenserManager::GetContext(
  INSTID *pInstId,
  TRANSID *pTransId
);

Parameters

pInstId
[out] An internal unique identifier of the current object, or 0 if no current object. This may not be interpreted as an (IUnknown *) of the current object.
pTransId
[out] The transaction that the current object is running in, or 0 if none. This may be cast to (ITransaction *).

Return Values

S_OK
Success.
E_FAIL
Failure.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager::RegisterDispenser


IDispenserManager::RegisterDispenser

A resource dispenser calls this method to register with DispMan.

HRESULT IDispenserManager::RegisterDispenser(
  const IDispenserDriver *pDispenserDriver,
  const WCHAR *szDispenserName,
  IHolder **ppIHolder
);

Parameters

pDispenserDriver
[in] Specifies the interface the resource dispenser offers to DispMan to use later to notify the resource dispenser.
szDispenserName
[in] A friendly name of the resource dispenser for administrator display.
ppIHolder
[out] The IHolder Interface that has been instantiated for the resource dispenser.

Return Values

S_OK
Success.
E_FAIL
Failure.

Remarks

The resource dispenser notifies DispMan that it has started and is prepared to accept notifications on this IDispenserDriver Interface. Then DispMan creates the holder for this new resource dispenser and returns it to the resource dispenser.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager::GetContext


IDispenserDriver Interface

This interface is called by the holder of the resource dispenser to create enlist, evaluate, and destroy a resource.

When to Implement

Any resource dispenser can implement this interface.

When to Use

Use this interface to prepare and handle resources.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IDispenserDriver Methods | Description
CreateResource | Create a resource.
RateResource | Evaluate how well a candidate resource matches.
EnlistResource | Enlist a resource in a transaction.
ResetResource | Prepare a resource to be returned to inventory.
DestroyResource | Destroy a resource.
DestroyResourceS | String SRESID version of DestroyResource.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface


IDispenserDriver::CreateResource

Holder asks resource dispenser to create a resource.

HRESULT IDispenserDriver::CreateResource(
  const RESTYPID ResTypId,
  RESID *pResId,
  TIMEINSECS *pSecsFreeBeforeDestroy
);

Parameters

ResTypId
[in] The type of resource to create.
pResId
[out] The handle to the newly created resource.
pSecsFreeBeforeDestroy
[out] The timeout of the new resource. This is the number of seconds that this resource is allowed to remain idle in the pool before it is destroyed.

Return Values

S_OK
Success.
E_FAIL
Failure.

Remarks

Called by DispMan in two cases: when a resource is needed and there is no inventory to either satisfy an AllocResource call when none were found in inventory, or when DispMan is setting up initial inventory.

The resource dispenser assigns ResId as the handle to identify this resource.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface


IDispenserDriver::DestroyResource

Holder asks resource dispenser to destroy a resource.

HRESULT IDispenserDriver::DestroyResource(
  const RESID ResId
);

Parameters

ResId
[in] The resource that DispMan is asking resource dispenser to destroy.

Return Values

S_OK
Success.
E_NOTIMPL
For resource dispensers which do not support numeric RESIDs.
E_FAIL
Failure.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface


IDispenserDriver::DestroyResourceS

This is same as DestroyResource, except that it takes a string SRESID.

HRESULT IDispenserDriver::DestroyResource(
  constSRESID SResId
);

Parameters

SResId
[in] The resource that DispMan is asking resource dispenser to destroy.

Return Values

S_OK
Success.
E_NOTIMPL
For resource dispensers which do not support string SRESIDs.
E_FAIL
Failure.


IDispenserDriver::EnlistResource

Holder asks resource dispenser to enlist a resource in a transaction.

HRESULT IDispenserDriver::EnlistResource(
  const RESID ResId,
  const TRANSID TransId
);

Parameters

ResId
[in] The resource that DispMan is asking to be enlisted in transaction TransId.
TransId
[in] The transaction that DispMan wants the resource dispenser to enlist resource ResId in. DispMan will pass 0 to indicate that the resource dispenser should ensure that the resource is not enlisted in any transaction.

Return Values

S_OK
Successfully enlisted.
S_FALSE
The resource is not enlistable (not transaction capable).
E_INVALIDARG
ResId or TransId is not a valid handle.
E_FAIL
Failure. Enlistment failed.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface


IDispenserDriver::RateResource

Holder asks resource dispenser to evaluate how well a candidate resource matches.

HRESULT IDispenserDriver::RateResource(
  const RESTYPID ResTypId,
  const RESID ResId,
  const BOOL fRequiresTransactionEnlistment,
  RESOURCERATING *pRating
);

Parameters

ResTypId
[in] The type of resource that DispMan is looking to match.
ResId
[in] The candidate resource that DispMan is considering.
fRequiresTransactionEnlistment
[in] If TRUE, the candidate resource (ResId) if chosen, will require transaction enlistment. If enlistment is expensive, RateResource may want to rate such a resource lower than one which is already enlisted in the correct transaction.
pRating
[out] The Dispenser's rating of this candidate:

0 = Candidate resource is unuseable for this request. Resource is not or cannot be changed to be of type ResTypId.

1 = Bad fit, but a useable candidate. DispMan will continue to suggest candidates.

2 = Better than 1. DispMan will continue to suggest candidates.

100 = Perfect fit. DispMan stops suggesting candidates when resource dispenser gives a "100" rating to a candidate.

Return Values

S_OK
Successfully rated. Resource dispenser must set *pRating before returning S_OK.
E_FAIL
Failure.

Remarks

If fRequiresTransactionEnlistment is FALSE, then an object was dispensed this resource in this transaction, the object used and then freed the resource (explicitly or implicitly at end of object lifetime). A second object in the same transaction asks for a similar resource, and the resource that the first object used is considered. This resource is a good candidate because it is already enlisted in the correct transaction.

If a particular type of resource can only be used once per transaction, then a resource which has already been used once in the transaction may be identified by an fRequiresTransactionEnlistment of FALSE and may be rejected for further use by returning *pRating=0.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface


IDispenserDriver::ResetResource

Prepares the resource to be put back into general or enlisted inventory.

HRESULT IDispenserDriver::ResetResource(
  const RESID ResId
);

Parameters

ResId
[in] The resource to be reset.

Return Values

S_OK
Success.
E_INVALIDARG
ResId is not a valid resource handle.
E_FAIL
Failure. Resource ResId has not been reset.

Remarks

Note The resource may still be enlisted at this time, so ResetResource can't disrupt the enlistment.

Example

ODBC Resource Dispenser calls SQLFreeStmt with SQL_DROP for the hstmts still allocated on the hdbc.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface


IHolder Interface

DispMan exposes a different IHolder to each installed resource dispenser. A resource dispenser calls one of the following methods to allocate or free resources.

When to Implement

Any resource dispenser can implement this interface.

When to Use

Use this interface to prepare and handle resources.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IHolder Methods | Description
AllocResource | Asks the holder to allocate a resource from inventory.
FreeResource | Returns a resource to inventory.
TrackResource | Asks the holder to track life of resource.
TrackResourceS | Same as TrackResource with string SRESID.
UntrackResource | Asks the holder to stop tracking a resource.
UntrackResourceS | Same as UntrackResource with string SRESID.
Close | Asks the holder to close down.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


IHolder::AllocResource

Allocates a resource from the inventory.

HRESULT IHolder::AllocResource(
  RESTYPID ResTypId,
  RESID *pResId
);

Parameters

ResTypId
[in] The type of resource to be allocated.
pResId
[out] Points to the location where the handle of the resource allocated is returned.

Return Values

S_OK
Success.
E_INVALIDARG
ResTypId is NULL or "", or the resource dispenser's CreateResource generated empty or duplicate RESID.
E_FAIL
Failure. *pResId has not been set. Likely cause is that the caller's transaction is aborting.

Remarks

DispMan takes the following steps to locate a resource:

  1. Searches the pool for a free resource of this RESTYPID, which is already enlisted in the caller's current transaction.
  2. Searches the pool for a free unenlisted resource of this RESTYPID, and then enlists it in the caller's current transaction.
  3. Creates the resource by calling back to the resource dispenser's IDispenserDriver::CreateResource, and then enlisting it.

If the caller does not have a current transaction, then the enlistment is skipped. Or if the resource dispenser rejects the enlistment (meaning the resource is not transaction capable), then the enlistment is skipped.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


IHolder::Close

Closes the holder.

HRESULT IHolder::Close();

Remarks

This closes a resource dispenser's holder, after which the resource dispenser will probably be released.

Before closing, any remaining inventory is destroyed by calling back to the resource dispenser's DestroyResource.

The following sequence describes how to close down a resource dispenser.

  1. You must hold a reference to the resource dispenser (the object which exposes IDispenserDriver).
  2. Call a method in resource dispenser whose implementation calls IHolder::Close.
  3. IHolder::Close destroys any remaining inventory by calling back to resource dispenser's DestroyResource.
  4. IHolder::Close calls DispMan to remove this holder from the holder list. (If there are now no holders left, the DispMan object deletes itself.)
  5. IHolder::Close releases its reference to resource dispenser's IDispenserDriver. Note that this is the reason you need a reference in step 1; otherwise, the resource dispenser would delete itself prematurely before the subsequent steps can be completed.
  6. IHolder::Close returns to resource dispenser.
  7. The resource dispenser calls IDispenserDriver::DestroyResource. The holder now deletes itself.
  8. The method called in step 2 now returns.
  9. Release your final reference to the resource dispenser, which now deletes itself.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


IHolder::FreeResource

Returns a resource to the inventory.

HRESULT IHolder::FreeResource(
  const RESID ResId
);

Parameters

ResId
[in] The handle of the resource to free.

Return Values

S_OK
Success.
E_INVALIDARG
ResId is not a valid resource handle.
E_FAIL
Failure. Resource ResId has not been freed.

Remarks

A resource originally returned by AllocResource is returned to the pool. This will notify the resource dispenser via IDispenserDriver::ResetResource, which is the resource dispenser's opportunity to prepare the resource before it is returned to the pool.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


IHolder::TrackResource

Tracks the resource.

HRESULT IHolder::TrackResource(
  const RESID ResId
);

Parameters

ResId
[in] The handle of the resource to track. The resource dispenser has already created this resource before calling TrackResource.

Return Values

S_OK
Success.
E_INVALIDARG
ResId is not a valid resource handle; is NULL or "" or duplicate.
E_FAIL
Failure. Resource ResId has not been tracked. Likely cause is that the caller's transaction is aborting.

Remarks

Some resources are not kept in inventory; they are always manufactured on demand, for example, memory allocation through Malloc. The holder is used only as a mechanism to automatically free the resources left at end of an object's lifetime.

TrackResource tells the holder that a resource should be tracked until it is freed by calling UntrackResource, or until the object which called TrackResource is released, at which time DispMan automatically frees the resource.

If TrackResource is called from a transactional object, it calls back to the resource dispenser's EnlistResource method. The EnlistResource method may enlist the resource in the transaction, or it may return S_FALSE, indicating that the resource is not transaction capable and has not been enlisted.

This resource will eventually be destroyed after both of the following are true:

  • The resource dispenser calls UntrackResource (most likely at the component's request) or the object's lifetime ends.
  • The transaction that the resource was enlisted in (if any) is done.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


IHolder::TrackResourceS

This is same as TrackResource except that it takes a string.

HRESULT IHolder::TrackResourceS(
  constSRESID SResId
);

Parameters

SResId
[in] The handle of the resource to track. The resource dispenser has already created this resource before calling TrackResourceS.

Return Values

S_OK
Success.
E_INVALIDARG
SResId is not a valid resource handle; is NULL or "" or duplicate.
E_FAIL
Failure. Resource SResId has not been tracked. Likely cause is that the caller's transaction is aborting.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


IHolder::UntrackResource

Stops tracking this resource.

HRESULT IHolder::UntrackResource(
  const RESID ResId,
  const BOOL fDestroy
);

Parameters

ResId
[in] The handle of the resource to stop tracking.
fDestroy
[in] If TRUE, caller is requesting the resource be destroyed, by calling IDispenserDriver::DestroyResource. If FALSE, caller will destroy the resource.

Return Values

S_OK
Success.
E_INVALIDARG
ResId is not a valid resource handle.
E_FAIL
Failure. Resource ResId has not been freed.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


IHolder::UntrackResourceS

This is same as UntrackResource except that it takes a string.

HRESULT IHolder::UntrackResource(
  constSRESID SResId,
  const BOOL fDestroy
);

Parameters

SResId
[in] The handle of the resource to stop tracking.
fDestroy
[in] If TRUE, caller is requesting the resource be destroyed, by calling IDispenserDriver::DestroyResource. If FALSE, caller will destroy the resource.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IDispenserManager Interface and IDispenserDriver Interface


COM+ Instrumentation Interfaces

The following COM+ instrumentation interfaces allow clients to receive notifications for a variety of COM+ metrics.

Interfaces | Description
IComActivityEvents | This interface notifies the subscriber if an activity is created, destroyed, or timed out.
IComAdmAppEvents | This interface notifies the subscriber if an application is created, deleted, updated, paused, or installed from an MSI file.
IComAdmCompEvents | This interface notifies the subscriber when a component property has been changed, installed, imported, or deleted.
IComAdmItfEvents | This interface notifies the subscriber when an interface property has been changed.
IComAdmMashEvents | This interface notifies the subscriber when a computer has been added, deleted or updated.
IComAdmMetEvents | This interface notifies the subscriber when a method property has been changed.
IComAdmPartEvents | This interface notifies the subscriber when a single partition or a set of partitions has been added or deleted.
IComAdmSecEvents | This interface notifies the subscriber if a role has been added or deleted from an application, component, or interface. The subscriber is also notified if a user has been added or deleted from a role.
IComAdmSubscrEvents | This interface notifies the subscriber when a permanent or transient subscription has been added, changed, or deleted.
IComAppEvents | This interface notifies the subscriber if a COM+ server application is started, shut down, or forced to shut down.
IComApp2Events | This interface notifies the subscriber if a COM+ server application is loaded, shut down, or paused. The subscriber is also notified if the application is marked for recycling.
IComCRMEvents | This interface notifies the subscriber about the activities of the Compensating Resource Manager (CRM). Activities such as the recovery start, recovery done, and checkpoints occurred are included.
IComExceptionEvents | This interface notifies the subscriber when a user exception occurs.
IComIdentityEvents | This interface notifies the subscriber of an activity that is part of an Internet Information Services (IIS) Active Server Pages (ASP) page.
IComInstanceEvents | This interface notifies the subscriber of an object's creation or release.
IComInstance2Events | This interface notifies the subscriber if an object has been created or released by a client.
IComMethodEvents | This interface notifies the subscriber if an object's method has been called, returned, or has generated an exception.
IComObjectConstructionEvents | This interface notifies the subscriber if a constructed object is created in an object pool.
IComObjectConstruction2Events | This interface notifies the subscriber if a constructed object is created.
IComObjectEvents | This interface notifies the subscriber if an instance of a just-in-time (JIT) activated object has been created or freed. These events also provide notification when IObjectContext::DisableCommit, IObjectContext::EnableCommit, and IObjectContext::SetComplete are called.
IComObjectPoolEvents | This interface notifies the subscriber if a new object is added to the pool. The subscriber is also notified if a transactional or nontransactional object is obtained or returned to the pool.
IComObjectPoolEvents2 | This interface notifies the subscriber if a new object is created for or removed from the pool. The subscriber is also notified when a new object pool is created or when the request for a pooled object times out.
IComObjectPool2Events | This interface notifies the subscriber if a transactional or nontransactional object is added to or obtained from the object pool.
IComQCEvents | This interface notifies the subscriber if a queued message is created, de-queued, or moved to a retry or Dead Letter queue.
IComResourceEvents | This interface notifies the subscriber if a resource is created, allocated, tracked, or destroyed.
IComSecurityEvents | This interface notifies the subscriber if the authentication of a method call succeeded or failed.
IComThreadEvents | This interface notifies the subscriber if a single-threaded apartment (STA) is created or terminated, and when an apartment thread is allocated. The subscriber is also notified if an activity is assigned or unassigned to an apartment thread.
IComTransactionEvents | This interface notifies the subscriber if a Microsoft Distributed Transaction Coordinator (DTC) transaction starts, commits, or aborts. The subscriber is also notified when the resource manager retrieves prepare information from the transaction manager.
IComTransaction2Events | This interface notifies the subscriber if a Microsoft Distributed Transaction Coordinator (DTC) transaction starts, commits, or aborts. The subscriber is also notified when the transaction is in the prepare phase of the two-phase commit protocol.
IComUserEvent | This interface notifies the subscriber of the specified user-defined metrics.


IComActivityEvents

The IComActivityEvents interface notifies the subscriber if an activity is created, destroyed, or timed out.

When to Implement

The activity event is published to the subscriber using COM+ Events, a loosely coupled events (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. The subscriber must implement this interface in order to receive the activity events. The subscriber will subscribe to the events publisher, which publishes the events. The subscriber can also choose which event to fire by registering an Event Class. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComActivityEvents when you want to be notified about events related to activities.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComActivityEvents Methods | Description
OnActivityCreate | Generated when an activity starts.
OnActivityDestroy | Generated when an activity is finished.
OnActivityTimeout | Generated when a call into an activity times out.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model, COM+ Instrumentation


IComActivityEvents::OnActivityCreate

Generated when an activity starts.

HRESULT OnActivityCreate(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidActivity
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The GUID associated with the current activity.

See Also

IComActivityEvents


IComActivityEvents::OnActivityDestroy

Generated when an activity is finished.

HRESULT OnActivityDestroy(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidActivity
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The GUID associated with the current activity.

See Also

IComActivityEvents, COM+ Events Model, COM+ Instrumentation


IComActivityEvents::OnActivityTimeout

Generated when a call into an activity times out.

HRESULT OnActivityTimeout(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidCurrent,
   REFGUID guidEntered,
   DWORD dwThread,
   DWORD dwTimeout
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidCurrent
[in] The GUID associated with the current activity.
guidEntered
[in] Causality ID for the caller.
dwThread
[in] Windows 2000 thread ID executing the call.
dwTimeout
[in] Timeout period.

See Also

IComActivityEvents, COM+ Events Model, COM+ Instrumentation


IComAdmAppEvents

The IComAdmAppEvents interface notifies the subscriber if an application is installed from an MSI file. The subscriber is also notified if a new application is created or when an existing application is deleted or updated.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComAdmAppEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComAdmAppEvents when you want to be notified about events related to a COM+ application.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmAppEvents Methods | Description
OnAdmAppInstall | Generated when an application is installed from an .msi or MSI file.
OnAdmAppCreate | Generated when a new application is created.
OnAdmAppDelete | Generated when an application is deleted.
OnAdmAppUpdate | Generated when an application property is changed.

Note The user verifies the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmAppEvents::OnAdmAppCreate

Generated when a new application is created.

HRESULT OnAdmAppCreate(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application.
pszName
[in] Name of the new application.
hresult
[in] The result of the creation.


IComAdmAppEvents::OnAdmAppDelete

Generated when an application is deleted.

HRESULT OnAdmAppDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
hresult
[in] The result of the deletion.


IComAdmAppEvents::OnAdmAppInstall

Generated when an application is installed from an .msi or MSI file.

HRESULT OnAdmAppInstall(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszMSIName,
   LPCOLESTR pszDestPath,
   LPCOLESTR pszUserName,
   BOOL bWithUsers,
   BOOL bSecurity,
   BOOL bQueued,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application to install.
pszMSIName
[in] Path to the MSI file containing the application to install.
pszDestPath
[in] The destination path to the directory where the application is to be installed.
pszUserName
[in] The user name.
bWithUsers
[in] Indicates whether or not the client requested that users should be installed in roles.
bSecurity
[in] If the security is on, value is set to TRUE.
bQueued
[in] If the application is queued, value is set to TRUE.
hresult
[in] The result of the installation.


IComAdmAppEvents::OnAdmAppUpdate

Generated when an application property is changed.

HRESULT OnAdmAppUpdate(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszPropName,
   LPCOLESTR pszNewName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
pszPropName
[in] The name of the property.
pszNewName
[in] The new value of the property.
hresult
[in] The result of the update.


IComAdmCompEvents

The IComAdmCompEvents interface notifies the subscriber when a component property has been changed, installed, imported, or deleted.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement this interface to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComAdmCompEvents when you want to be notified about events related to component properties.

Methods in Vtable Order

Iunknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmCompEvents Methods | Description
OnAdmCompInstall | Generated when a component is installed in an application.
OnAdmCompImport | Generated when a component is imported in an application.
OnAdmCompDelete | Generated when a component is deleted.
OnAdmCompUpdate | Generated when a component property changes.

Note The user verifies the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmCompEvents::OnAdmCompDelete

Generated when a component is deleted.

HRESULT OnAdmCompDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID compClsid,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application from which the component is deleted.
compClsid
[in] CLSID of the component.
hresult
[in] The result of the deletion.


IComAdmCompEvents::OnAdmCompImport

Generated when a component is imported in an application.

HRESULT OnAdmCompImport(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID compClsid,
   LPCOLESTR pszProgId,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application where the component is imported.
compClsid
[in] The CLSID of the component.
pszProgId
[in] The programmatic ID of the new component.
hresult
[in] The result of the installation.


IComAdmCompEvents::OnAdmCompInstall

Generated when a component is installed in an application.

HRESULT OnAdmCompInstall(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszDllPath,
   LPCOLESTR pszTlbPath,
   LPCOLESTR pszPSDLLPath,
   REFCLSID compClsid,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application where the component is installed.
pszDllPath
[in] Path of the DLL from which the component is installed.
pszTlbPath
[in] Path of the type library associated with the component.
pszPSDLLPath
[in] Path of the proxy/stub DLL associated with the component.
compClsid
[in] The CLSID of the component.
hresult
[in] The result of the installation.

Comment

If the user provides an invalid application ID or application name as the bstrApplIdOrName argument to the IComAdminCatalog::InstallComponent method, the complementary guidApp parameter will also be an invalid value and the hresult parameter will indicate the error.


IComAdmCompEvents::OnAdmCompUpdate

Generated when a component property changes.

HRESULT OnAdmCompUpdate(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID compClsid,
   LPCOLESTR pszPropName,
   LPCOLESTR pszNewValue,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application where the component property is updated.
compClsid
[in] CLSID of the component.
pszPropName
[in] The name of the property.
pszNewValue
[in] The new value of the property.
hresult
[in] The result of the update.


IComAdmItfEvents

The IComAdmItfEvents interface notifies the subscriber when an interface property has been changed.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement this interface to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComAdmItfEvents when you want to be notified about events related to interface properties.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmItfEvents Methods | Description
OnAdmItfUpdate | Generated when an interface property is changed.

Note The user verifies the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmIftEvents::OnAdmItfUpdate

Generated when an interface property is changed.

HRESULT OnAdmItfUpdate(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID itfClsid,
   REFIID guidItf,
   LPCOLESTR pszPropName,
   LPCOLESTR pszNewValue,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application where the interface property is updated.
itfClsid
[in] The CLSID of the component whose interface property is updated.
guidItf
[in] The IID of the interface.
pszPropName
[in] The name of the property.
pszNewValue
[in] The new value of the property.
hresult
[in] The result of the update.


IComAdmMashEvents

The IComAdmMashEvents interface notifies the subscriber when a computer has been added, deleted from the ComputerList collection, or when some properties of the My Computer object are updated.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement this interface to catch events. The system events publisher publishes these events, and you will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComAdmMashEvents when you want to be notified about events related to computer properties.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmMashEvents Methods | Description
OnAdmMashAdd | Generated when a computer is added to the ComputerList collection.
OnAdmMashDelete | Generated when a computer is deleted from the ComputerList collection.
OnAdmMashUpdate | Generated when properties of the My Computer object are updated.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmMashEvents::OnAdmMashAdd

Generated when a new computer is added to the ComputerList collection.

HRESULT OnAdmMashAdd(
   COMSVCSEVENTINFO * pInfo,
   LPCOLESTR pszMachineName,,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
pszMachineName
[in] Computer name.
hresult
[in] The result of the addition.


IComAdmMashEvents::OnAdmMashDelete

Generated when a computer is deleted from the ComputerList collection.

HRESULT OnAdmMashDelete(
   COMSVCSEVENTINFO * pInfo,
   LPCOLESTR pszMachineName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
pszMachineName
[in] Computer name.
hresult
[in] The result of the deletion.


IComAdmMashEvents::OnAdmMashUpdate

Generated when properties of the My Computer object are updated.

HRESULT OnAdmMashUpdate(
   COMSVCSEVENTINFO * pInfo,
   LPCOLESTR pszMachineName,
   LPCOLESTR pszPropName,
   LPCOLESTR pszNewValue,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
pszMachineName
[in] The computer name.
pszPropName
[in] The name of the property.
pszNewValue
[in] The new value of the property.
hresult
[in] The result of the update.


IComAdmMetEvents

The IComAdmMetEvents interface notifies the subscriber when a method property has been changed.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComAdmMetEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComAdmMetEvents when you want to be notified about events related to method properties.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmMetEvents Methods | Description
OnAdmMetUpdate | Generated when a method property has changed.

Note The user verifies the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmMetEvents::OnAdmMetUpdate

Generated when a method property has changed.

HRESULT OnAdmMetUpdate(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID itfClsid,
   REFIID guidItf,
   ULONG iMeth,
   LPCOLESTR pszPropName,
   LPCOLESTR pszNewValue,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application where the method property is updated.
itfClsid
[in] The CLSID of the component whose method property is updated.
guidItf
[in] The IID of the interface whose method property is updated.
iMeth
[in] The vtable index of the method.
pszPropName
[in] The name of the property.
pszNewValue
[in] The new value of the property.
hresult
[in] The result of the update.


IComAdmPartEvents

The IComAdmPartEvents interface notifies the subscriber when a single partition or a set of partitions is added or deleted.

When to Implement

To use this interface, you must know how to use loosely coupled events. You will implement this interface to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComAdmPartEvents when you want to be notified about events related to partitions and partition sets.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmPartEvents Methods | Description
OnAdmPartitionAdd | Generated when a partition is added.
OnAdmPartitionDelete | Generated when a partition is deleted.
OnAdmPartitionSetAdd | Generated when a partition set is added.
OnAdmPartitionSetDelete | Generated when a partition set is deleted.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmPartEvents::OnAdmPartitionAdd

Generated when a partition is added.

HRESULT OnAdmPartitionAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidPartition,
   LPCOLESTR pszPartitionName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidPartition
[in] GUID of the partition.
pszPartitionName
[in] The partition name.
hresult
[in] The result of the addition of the partition.


IComAdmPartEvents::OnAdmPartitionDelete

Generated when a partition is deleted.

HRESULT OnAdmPartitionDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidPartition,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidPartition
[in] The GUID of the partition.
hresult
[in] The result of the deletion.


IComAdmPartEvents::OnAdmPartitionSetAdd

Generated when a partition set has been added.

HRESULT OnAdmPartitionSetAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidPartitionSet,
   LPCOLESTR pszPartitionSetName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidPartitionSet
[in] The GUID of the partition.
pszPartitionSetName
[in] The partition set name.
hresult
[in] The result of the update.


IComAdmPartEvents::OnAdmPartitionSetDelete

Generated when a partition set is deleted.

HRESULT OnAdmPartitionSetDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidPartitionSet,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidPartitionSet
[in] GUID of the partition set.
hresult
[in] The result of the addition of the subscription.


IComAdmSecEvents

The IComAdmSecEvents interface notifies the subscriber if a role is added or deleted from an application, component, or interface. The subscriber is also notified if a user has been added or deleted from a role.

When to Implement

To use this interface, you must know how to use loosely coupled events. You will implement this interface to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComAdmSecEvents when you want to be notified about events related to user roles in applications, components, and interfaces.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmSecEvents Methods | Description
OnAdmRoleAdd | Generated when a new role is added to an application.
OnAdmRoleDelete | Generated when a role is deleted from an application.
OnAdmUserAdd | Generated when a new user is added to a role.
OnAdmUserDelete | Generated when a user is deleted from a role.
OnAdmCompRoleAdd | Generated when a role is assigned to a component.
OnAdmCompRoleDelete | Generated when a role is deleted from a component.
OnAdmItfRoleAdd | Generated when a role is assigned to an interface.
OnAdmItfRoleDelete | Generated when a role is deleted from an interface.
OnAdmMetRoleAdd | Generated when a role is assigned to a method.
OnAdmMetRoleDelete | Generated when a role is removed from an interface.

Note The user verifies the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmSecEvents::OnAdmCompRoleAdd

Generated when a role is assigned to a component.

HRESULT OnAdmCompRoleAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID clsid,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
clsid
[in] The CLSID of the component.
pszRoleName
[in] The role name.
hresult
[in] The result of the addition of the role.


IComAdmSecEvents::OnAdmCompRoleDelete

Generated when a role assigned to a component is deleted.

HRESULT OnAdmCompRoleDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID clsid,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
clsid
[in] CLSID of the component.
pszRoleName
[in] The role name.
hresult
[in] The result of the deletion of the role.


IComAdmSecEvents::OnAdmItfRoleAdd

Generated when a role is assigned to an interface.

HRESULT OnAdmItfRoleAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID clsid,
   REFIID guidItf,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
clsid
[in] The CLSID of the component containing the interface.
guidItf
[in] The IID of the interface that will have the role assigned.
pszRoleName
[in] The role name.
hresult
[in] The result of the addition of the role.


IComAdmSecEvents::OnAdmItfRoleDelete

Generated when a role assigned to an interface is deleted.

HRESULT OnAdmItfRoleDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID clsid,
   REFIID guidItf,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
clsid
[in] The CLSID of the component containing the interface.
guidItf
[in] The IID of the interface that will have the role assigned.
pszRoleName
[in] The role name.
hresult
[in] The result of the deletion of the role.


IComAdmSecEvents::OnAdmMetRoleAdd

Generated when a role is assigned to a method.

HRESULT OnAdmMetRoleAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID clsid,
   REFIID guidItf,
   ULONG iMeth,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
clsid
[in] The CLSID of the component containing the interface.
guidItf
[in] The IID of the interface that will have the role assigned.
iMeth
[in] The vtable index of the method that will have the role assigned.
pszRoleName
[in] The role name.
hresult
[in] The result of the addition of the role.


IComAdmSecEvents::OnAdmMetRoleDelete

Generated when a role assigned to a method is deleted.

HRESULT OnAdmMetRoleDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   REFCLSID clsid,
   REFIID guidItf,
   ULONG iMeth,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
clsid
[in] The CLSID of the component containing the interface.
guidItf
[in] The IID of the interface that will have the role assigned.
iMeth
[in] The vtable index of the method that will have the role assigned.
pszRoleName
[in] The role name.
hresult
[in] The result of the deletion of the role.


IComAdmSecEvents::OnAdmRoleAdd

Generated when a new role is added to an application.

HRESULT OnAdmRoleAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application to which the role is added.
pszRoleName
[in] The role name.
hresult
[in] The result of the addition.

Comments

If the user provides an invalid application ID or application name then the complementary guidApp parameter from this method will also be an invalid value, and the hresult parameter will indicate the error.


IComAdmSecEvents::OnAdmRoleDelete

Generated when a role assigned to an application is deleted.

HRESULT OnAdmRoleDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszRoleName,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application from which the role is deleted.
pszRoleName
[in] The role name.
hresult
[in] The result of the deletion.


IComAdmSecEvents::OnAdmUserAdd

Generated when a new user is added to a role.

HRESULT OnAdmUserAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszRoleName,
   ULONG cbBytes,
   BYTE * pUserSid,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
pszRoleName
[in] The role name.
cbBytes
[in] Account of bytes.
pUserSid
[in, size_is(cbBytes)] The user’s Service ID (SID).
hresult
[in] The result of the addition of the user.


IComAdmSecEvents::OnAdmUserDelete

Generated when a user is deleted from a role.

HRESULT OnAdmUserDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   LPCOLESTR pszRoleName,
   ULONG cbBytes,
   BYTE * pUserSid,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
pszRoleName
[in] The role name.
cbBytes
[in] Account of bytes.
pUserSid
[in, size_is(cbBytes)] The user’s Service ID (SID).
hresult
[in] The result of the deletion of the user.


IComAdmSubscrEvents

The IComAdmSubscrEvents interface notifies the subscriber when a permanent or transient subscription has been added, changed, or deleted. Permanent subscriptions are saved in the administration catalog and are persistent. Transient subscriptions are not saved in the administration catalog.

When to Implement

To use this interface, you must know how to use loosely coupled events. You will implement this interface to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComAdmSubscrEvents when you want to be notified about events related to transient and permanent subscriptions.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAdmSubscrEvents Methods | Description
OnAdmPermSubsAdd | Generated when a permanent subscription is added.
OnAdmPermSubsDelete | Generated when a permanent subscription is deleted.
OnAdmPermSubsUpdate | Generated when a permanent subscription has changed.
OnAdmTransSubsAdd | Generated when a transient subscription is added.
OnAdmTransSubsDelete | Generated when a transient subscription is deleted.
OnAdmTransSubsUpdate | Generated when a transient subscription has changed.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComAdmSubscrEvents::OnAdmPermSubsAdd

Generated when a permanent subscription is added.

HRESULT OnAdmPermSubsAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   GUID guidSubs,
   REFCLSID ECclsid,
   REFIID guidItf,
   LPCOLESTR pszMethodName,
   BOOL bEnabled,
   REFCLSID subscriberCLSID,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
guidSubs
[in] The subscription ID.
ECclsid
[in] The CLSID of the Event Class.
guidItf
[in] IID of the interface in case a user has subscribed to an interface.
pszMethodName
[in] The name of the method in case a user has subscribed to a method.
bEnabled
[in] TRUE if enabled; else FALSE.
subscriberCLSID
[in] The CLSID for the subscriber to this event.
hresult
[in] The result of the addition of the subscription.


IComAdmSubscrEvents::OnAdmPermSubsDelete

Generated when a permanent subscription is deleted.

HRESULT OnAdmPermSubsDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   GUID guidSubs,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
guidSubs
[in] The subscription ID.
hresult
[in] The result of the deletion.


IComAdmSubscrEvents::OnAdmPermSubsUpdate

Generated when a permanent subscription has changed.

HRESULT OnAdmPermSubsUpdate(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   GUID guidSubs,
   LPCOLESTR pszPropName,
   LPCOLESTR pszNewValue,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.
guidSubs
[in] The subscription ID.
pszPropName
[in] Name of the property.
pszNewValue
[in] Name of the new property
hresult
[in] The result of the update.


IComAdmSubscrEvents::OnAdmTransSubsAdd

Generated when a transient subscription is added.

HRESULT OnAdmTransSubsAdd(
   COMSVCSEVENTINFO * pInfo,
   GUID guidSubs,
   REFCLSID ECclsid,
   REFIID guidItf,
   LPCOLESTR pszMethodName,
   BOOL bEnabled,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidSubs
[in] The subscription ID.
ECclsid
[in] The CLSID of the event class.
guidItf
[in] The IID of the interface in case a user has subscribed to an interface.
pszMethodName
[in] The name of the method in case a user has subscribed to a method.
bEnabled
[in] TRUE if enabled; else FALSE.
hresult
[in] The result of the addition of the subscription.


IComAdmSubscrEvents::OnAdmTransSubsDelete

Generated when a transient subscription is deleted.

HRESULT OnAdmTransSubsDelete(
   COMSVCSEVENTINFO * pInfo,
   GUID guidSubs,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidSubs
[in] The subscription ID.
hresult
[in] The result of the deletion.


IComAdmSubscrEvents::OnAdmTransSubsUpdate

Generated when a transient subscription has changed.

HRESULT OnAdmTransSubsUpdate(
   COMSVCSEVENTINFO * pInfo,
   GUID guidSubs,
   LPCOLESTR pszPropName,
   LPCOLESTR pszNewValue,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidSubs
[in] The subscription ID.
pszPropName
[in] Name of the property.
pszNewValue
[in] Name of the new property
hresult
[in] The result of the update.


IComAppEvents

The IComAppEvents interface notifies the subscriber if a COM+ server application is started, shut down, or forced to shut down. The latter is initiated by the user calling a catalog method, such as ShutdownApplication, to shut down the server.

When to Implement

The events are published to the subscriber using COM+ Events, a loosely coupled events (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. The subscriber must implement the IComAppEvents interface in order to receive the events. The subscriber will subscribe to the events publisher, which publishes the events. The subscriber can also choose which event to fire by registering an Event Class. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComAppEvents when you want to be notified about events related to a COM+ server application.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComAppEvents Methods | Description
OnAppActivation | Generated when an application server starts.
OnAppShutdown | Generated when an application server shuts down.
OnAppForceShutdown | Generated when an application server is forced to shut down.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model, COM+ Instrumentation


IComAppEvents::OnAppActivation

Generated when an application server starts.

HRESULT OnAppActivation(
    COMSVCSEVENTINFO __RPC_FAR *pInfo,
    GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The globally unique identifier (GUID) of the application.

See Also

IComAppEvents, COM+ Events Model, COM+ Instrumentation


IComAppEvents::OnAppForceShutdown

Generated when the user has shut down an application server. This is usually initiated by the user calling a catalog method, such as ShutdownApplication, to shut down the server.

HRESULT OnAppForceShutdown(
    COMSVCSEVENTINFO __RPC_FAR *pInfo,
    GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The globally unique identifier (GUID) of the application.

See Also

IComAppEvents, COM+ Events Model, COM+ Instrumentation


IComAppEvents::OnAppShutdown

Generated when an application server shuts down.

HRESULT OnAppShutdown(
    COMSVCSEVENTINFO __RPC_FAR *pInfo,
    GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The globally unique identifier (GUID) of the application.

See Also

IComAppEvents, COM+ Events Model, COM+ Instrumentation


IComApp2Events

The IComApp2Events interface notifies the subscriber if a COM+ server application is loaded, shut down, or paused. The subscriber is also notified if the application is marked for recycling.

When to Implement

To use this interface, you must know how to use loosely coupled events. You will implement this interface to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComApp2Events when you want to be notified about events related to server applications.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComApp2Events Methods | Description
OnAppActivation2 | Generated when the server application process is loaded.
OnAppShutdown2 | Generated when the server application shuts down.
OnAppForceShutdown2 | Generated when the server application is forced to shut down.
OnAppPaused2 | Generated when the server application is paused or resumed to its initial state.
OnAppRecycle2 | Generated when the server application process is marked for recycling termination.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComApp2Events::OnAppActivation2

Generated when the server application process is loaded.

HRESULT OnAppActivation2(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   GUID guidProcess
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application.
guidProcess
[in] The process ID.


IComApp2Events::OnAppForceShutdown2

Generated when the server application is forced to shut down.

HRESULT OnAppForceShutdown2(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.


IComApp2Events::OnAppPaused2

Generated when the server application is paused or resumed to its initial state.

HRESULT OnAppPaused2(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp,
   BOOL bPaused
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] GUID of the application.
bPaused
[in] If the server application is paused, value is set to TRUE. If the application has resumed to its original state, value is set to FALSE.


IComApp2Events::OnAppRecycle2

Generated when the server application process is marked for recycling termination.

HRESULT OnAppRecycle2(
   COMSVCSEVENTINFO * pInfo,
   GUID guidProcess
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidProcess
[in] The process ID.


IComApp2Events::OnAppShutdown2

Generated when the server application shuts down.

HRESULT OnAppShutdown2(
   COMSVCSEVENTINFO * pInfo,
   GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The GUID of the application.


IComCRMEvents

The IComCRMEvents interface notifies the subscriber about activities of the Compensating Resource Manager (CRM) feature of Component Services.

When to Implement

To use these you have to know how to use loosely coupled events. The system events publisher publishes these events. You will be a subscriber and you will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComCRMEvents when you want to be notified about events related to the CRM.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComCRMEvents Methods | Description
OnCRMRecoveryStart | Generated when CRM recovery has started.
OnCRMRecoveryDone | Generated when CRM recovery is done.
OnCRMCheckpoint | Generated when a CRM checkpoint occurs.
OnCRMBegin | Generated when a CRM clerk is starting, either due to a client registering a compensator, or during recovery.
OnCRMPrepare | Generated when CRM clerk receives a prepare notification to pass on to the CRM compensator.
OnCRMCommit | Generated when CRM clerk receives a commit notification to pass on to the CRM compensator.
OnCRMAbort | Generated when CRM clerk receives an abort notification to pass on to the CRM compensator.
OnCRMIndoubt | Generated when CRM clerk receives an in-doubt notification to pass on to the CRM compensator.
OnCRMDone | Generated when CRM clerk is done processing transaction outcome notifications.
OnCRMAnalyze | Generated when a CRM clerk receives a record during the analysis phase of recovery.
OnCRMWrite | Generated when a CRM clerk receives a request to write a log record, either from the CRM Worker or CRM compensator.
OnCRMForget | Generated when a CRM clerk receives a request to forget a log record, either from the CRM Worker or CRM compensator.
OnCRMForce | Generated when a CRM clerk receives a request to force log records to disk, either from the CRM Worker or CRM compensator.
OnCRMDeliver | Generated when a CRM clerk delivers a record to a CRM compensator.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComCRMEvents::OnCRMAbort

Generated when a CRM clerk receives an abort notification to pass on to the CRM compensator.

HRESULT OnCRMAbort(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.


IComCRMEvents::OnCRMAnalyze

Generated when a CRM clerk receives a record during the analysis phase of recovery.

HRESULT OnCRMAnalyze
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID,
   DWORD dwCrmRecordType,
   DWORD dwRecordSize
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.
dwCrmRecordType
[in] CRM log record type (internal).
dwRecordSize
[in] Log record size (approximate).


IComCRMEvents::OnCRMBegin

Generated when a CRM clerk is starting, either due to a client registering a compensator, or during recovery.

HRESULT OnCRMBegin(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID,
   GUID guidActivity,
   GUID guidTx,
   WCHAR RPC_FAR szProgIdCompensator[64],
   WCHAR RPC_FAR szDescription[64]
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.
guidActivity
[in] Activity ID (NULL if recovery).
guidTx
[in] Transaction Unit Of Work (UOW) ID.
szProgIdCompensator
[in] Prog ID of the CRM compensator.
szDescription
[in] Description (blank if recovery).


IComCRMEvents::OnCRMCheckpoint

Generated when a CRM checkpoint occurs.

HRESULT OnCRMCheckpoint(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidApp
[in] The globally unique identifier (GUID) of the application.


IComCRMEvents::OnCRMCommit

Generated when a CRM clerk receives a commit notification to pass on to the CRM compensator.

HRESULT OnCRMCommit(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.


IComCRMEvents::OnCRMDeliver

Generated when a CRM clerk delivers a record to a CRM compensator.

RESULT OnCRMDeliver
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID,
   BOOL fVariants,
   DWORD dwRecordSize
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.
fVariants
[in] Log record is being written as variant array.
dwRecordSize
[in] Log record size (approximate).


IComCRMEvents::OnCRMDone

Generated when a CRM clerk is done processing transaction outcome notifications.

HRESULT OnCRMDone
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.


IComCRMEvents::OnCRMForce

Generated when a CRM clerk receives a request to force log records to disk, either from the CRM Worker or CRM compensator.

HRESULT OnCRMForce
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.


IComCRMEvents::OnCRMForget

Generated when a CRM clerk receives a request to forget a log record, either from the CRM Worker or CRM compensator.

HRESULT OnCRMForget
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.


IComCRMEvents::OnCRMIndoubt

Generated when a CRM clerk receives an in-doubt notification to pass on to the CRM compensator.

HRESULT OnCRMIndoubt
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.


IComCRMEvents::OnCRMPrepare

Generated when a CRM clerk receives a prepare notification to pass on to the CRM compensator.

HRESULT OnCRMPrepare(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.


IComCRMEvents::OnCRMRecoveryDone

Generated when CRM recovery is done.

HRESULT OnCRMRecoveryDone(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure see Event Structure.
guidApp
[in] The globally unique identifier (GUID) of the application.


IComCRMEvents::OnCRMRecoveryStart

Generated when CRM recovery has started.

HRESULT OnCRMRecoveryStart(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidApp
) = 0;

Parameters

pInfo
[in] For more information on this structure see Event Structure.
guidApp
[in] The GUID of the application.


IComCRMEvents::OnCRMWrite

Generated when a CRM clerk receives a request to write a log record, either from the CRM Worker or CRM compensator.

HRESULT OnCRMWrite
   COMSVCSEVENTINFO RPC FAR *pInfo,
   GUID guidClerkCLSID,
   BOOL fVariants,
   DWORD dwRecordSize
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidClerkCLSID
[in] Identity of the CRM clerk.
fVariants
[in] Log record is being written as variant array.
dwRecordSize
[in] Log record size (approximate).


IComExceptionEvents

The IComExceptionEvents interface notifies the subscriber when an un-handled exception occurred in the user's code.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComExceptionEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComExceptionEvents when you want to be notified of a user exception.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComExceptionEvents Methods | Description
OnExceptionUser | Generated for transactional components when a user exception occurs.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComExceptionEvents::OnExceptionUser

Generated for transactional components when an un-handled exception occurred in the user's code.

HRESULT OnExceptionUser(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG code,
   ULONG64 address,
   LPCOLESTR pszStackTrace
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
code
[in] Exception code.
address
[in] Address of exception.
pszStackTrace
[in] Stack trace.


IComIdentityEvents

The IComIdentityEvents interface notifies the subscriber if an activity that is part of an Internet Information Services (IIS) Active Server Pages (ASP) page. For example, if a COM+ object is invoked in an ASP page the user would be notified of this activity.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComIdentityEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComIdentityEvents when you want to be notified about events related to an activity that is part of an IIS ASP.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComIdentityEvents Methods | Description
OnIISRequestInfo | Generated when an activity is part of an IIS ASP.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComIdentityEvents::OnIISRequestInfo

Generated when an activity is part of an Internet Information Services (IIS) Active Server Pages (ASP) page.

HRESULT OnIISRequestInfo(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 ObjId,
   LPCOLESTR pszClientIP,
   LPCOLESTR pszServerIP,
   LPCOLESTR pszURL
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ObjId
[in] The unique identifier for this object.
pszClientIP
[in] The Internet Protocol (IP) address of the IIS client.
pszServerIP
[in] The IP address of the IIS server.
pszURL
[in] URL on IIS server generating object reference.


IComInstanceEvents

The IComInstanceEvents interface notifies the subscriber of an object's creation or release.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComInstanceEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComInstanceEvents when you want to receive notification about events related to an object's creation and release.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComInstanceEvents Methods | Description
OnObjectCreate | Generated when an object is created by a client.
OnObjectDestroy | Generated when an object is released by a client.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComInstanceEvents::OnObjectCreate

Generated when an object is created by a client.

HRESULT OnObjectCreate(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   REFGUID guidActivity,
   REFCLSID clsid,
   REFGUID tsid,
   ULONG64 CtxtID,
   ULONG64 ObjectID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The identifier of the activity in which the object is created.
clsid
[in] CLSID for the object being created.
tsid
[in] The Transaction stream ID. Unique identifier for correlation to objects.
CtxtID
[in] Context ID for this object.
ObjectID
[in] Initial just-in-time (JIT) activated object.


IComInstanceEvents::OnObjectDestroy

Generated when a client releases an object.

HRESULT OnObjectDestroy(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 CtxtID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
CtxtID
[in] Context ID for this object.


IComInstance2Events

The IComInstance2Events interface notifies the subscriber if an object is created or released by a client.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComInstance2Events to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComInstance2Events when you want to be notified about an object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComInstance2Events Methods | Description
OnObjectCreate2 | Generated when a client creates an object.
OnObjectDestroy2 | Generated when a client releases an object.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComInstance2Events::OnObjectCreate2

Generated when a client creates an object.

HRESULT OnObjectCreate2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidActivity,
   REFCLSID clsid,
   REFGUID tsid,
   ULONG64 CtxtID,
   ULONG64 ObjectID,
   REFGUID guidPartition
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] Identifies the activity.
clsid
[in] CLSID for the object being created.
tsid
[in] Transaction stream ID. Unique identifier for correlation to objects.
CtxtID
[in] The context ID for this object.
ObjectID
[in] Initial JIT activated object.
guidPartition
[in] The partition ID that this instance is created for.


IComInstance2Events::OnObjectDestroy2

Generated when a client releases an object.

HRESULT OnObjectDestroy2(
   COMSVCSEVENTINFO *pInfo,
   ULONG64 CtxtID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
CtxtID
[in] The context ID for this object.

See Also

IComInstance2Events::OnObjectCreate2


IComMethodEvents

The IComMethodEvents interface notifies the subscriber if an object's method has been called, returned, or generated an exception.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComMethodEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComMethodEvents when you want to be notified about events related to an object's method.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComMethodEvents Methods | Description
OnMethodCall | Generated when an object’s method is called.
OnMethodReturn | Generated when an object’s method returns.
OnMethodException | Generated when an object’s method generates an exception.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComMethodEvents::OnMethodCall

Generated when an object’s method is called.

HRESULT OnMethodCall(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 oid,
   REFCLSID guidCid,
   REFIID guidRid,
   ULONG iMeth
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
oid
[in] Just-in-time (JIT) activated object.
guidCid
[in] CLSID for the object being called.
guidRid
[in] The IID of the method being called.
iMeth
[in] V-table index of method.


IComMethodEvents::OnMethodException

Generated when an object’s method generates an exception.

HRESULT OnMethodException(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 oid,
   REFCLSID guidCid,
   REFIID guidRid,
   ULONG iMeth
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
oid
[in] Just-in-time (JIT) activated object.
guidCid
[in] CLSID for the object being called.
guidRid
[in] The IID of the method being called.
iMeth
[in] V-table index of method.


IComMethodEvents::OnMethodReturn

Generated when an object’s method returns.

HRESULT OnMethodReturn(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 oid,
   REFCLSID guidCid,
   REFIID guidRid,
   ULONG iMeth,
   HRESULT hresult
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
oid
[in] Just-in-time (JIT) activated object.
guidCid
[in] CLSID for the object being called.
guidRid
[in] The IID of the method being called.
iMeth
[in] V-table index of method.
hresult
[in] The result of the method call.


IComObjectConstructionEvents

The IComObjectConstructionEvents interface notifies the subscriber if a constructed object is created in an object pool. A constructed object is derived from the IObjectConstruct interface. Constructed objects can inherit parameter names from within other objects or libraries.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComObjectConstructionEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComObjectConstructionEvents to be notified of when an object is constructed. When object construction is administratively enabled for a component, COM+ will call the IObjectConstruct::Construct method that it implements. This interface also notifies you if an object constructor is created in an object pool.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComObjectConstructionEvents Methods | Description
OnObjectConstruct | Generated for when a constructed object is created.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComObjectConstructionEvents::OnObjectConstruct

Generated for when a constructed object is created.

HRESULT OnObjectConstruct(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidObject,
   LPCOLESTR sConstructString,
   ULONG64 oid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
sConstructString
[in] Object construction string.
oid
[in] Unique constructed object ID.


IComObjectConstruction2Events

The IComObjectConstruction2Events interface notifies the subscriber if a constructed object is created.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComObjectConstruction2Events to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComObjectConstruction2Events when you want to be notified of the creation of a constructed object.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComObjectConstruction2Events Methods | Description
OnObjectConstruct2 | Generated when a constructed object is created.

Note The user verifies the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComObjectConstruction2Events::OnObjectConstruct2

Generated when a constructed object is created.

HRESULT OnObjectConstruct2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidObject,
   LPCOLESTR sConstructString,
   ULONG64 oid,
   REFGUID guidPartition
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
sConstructString
[in] Object construction string.
oid
[in] Unique constructed Object ID.
guidPartition
[in] The partition ID that this instance is created for.


IComObjectEvents

The IComObjectEvents interface notifies the subscriber if an instance of a Just-in-Time (JIT) activated object has been created or freed. The subscriber is notified if IObjectContext::DisableCommit, IObjectContext::EnableCommit, IObjectContext::SetComplete or IObjectContext::SetAbort are called.

When to Implement

These events are published to the subscriber using COM+ Events, a loosely coupled events (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. The subscriber must implement the IComObjectEvents interface in order to receive the events. The subscriber will subscribe to the events publisher, which publishes the events. The subscriber can also choose which event to fire by registering an Event Class. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComObjectEvents when you want to be notified about events related to JIT activated objects. If the transaction in which the object is executing commits or aborts, and the object deactivated on returning from the currently executing method call. The user is notified if the current object's work is not finished, but that its transactional updates are consistent and could be committed in their present form. As well as, if the object's transactional updates are inconsistent and can't be committed in their present state.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComObjectEvents Methods | Description
OnObjectActivate | Generated when an object gets an instance of a new JIT activated object.
OnObjectDeactivate | Generated when the JIT activated object is freed by SetComplete or SetAbort.
OnDisableCommit | Generated when the client calls DisableCommit on a context.
OnEnableCommit | Generated when the client calls EnableCommit on a context.
OnSetComplete | Generated when the client calls SetComplete on a context.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model, COM+ Instrumentation


IComObjectEvents::OnDisableCommit

Generated when the client calls IObjectContext::DisableCommit on a context.

HRESULT OnDisableCommit(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 CtxtID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
CtxtID
[in] The GUID of the current context.

See Also

IComObjectEvents, COM+ Events Model, COM+ Instrumentation


IComObjectEvents::OnEnableCommit

Generated when the client calls IObjectContext::EnableCommit on a context.

HRESULT OnEnableCommit(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 CtxtID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
CtxtID
[in] The GUID of the current context.

See Also

IComObjectEvents, COM+ Events Model, COM+ Instrumentation


IComObjectEvents::OnObjectActivate

Generated when an object gets an instance of a new just-in-time (JIT) activated object.

HRESULT OnObjectActivate(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 CtxtID,
   ULONG64 ObjectID
) = 0;

Parameters

pInfo
[in] For more information on this structure see Event Structure.
CtxtID
[in] The GUID of the current context.
ObjectID
[in] The JIT activated object.

See Also

IComObjectEvents, COM+ Events Model, COM+ Instrumentation


IComObjectEvents::OnObjectDeactivate

Generated when the just-in-time (JIT) activated object is freed by IObjectContext::SetComplete or IObjectContext::SetAbort.

HRESULT OnObjectDeactivate(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 CtxtID,
   ULONG64 ObjectID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
CtxtID
[in] The GUID of the current context.
ObjectID
[in] The JIT activated object.

See Also

IComObjectEvents, COM+ Events Model, COM+ Instrumentation


IComObjectEvents::OnSetComplete

Generated when the client calls IObjectContext::SetComplete on a context.

HRESULT OnSetComplete(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 CtxtID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
CtxtID
[in] The GUID of the current context.

See Also

IComObjectEvents, COM+ Events Model, COM+ Instrumentation


IComObjectPoolEvents

The IComObjectPoolEvents interface notifies the subscriber if a new object is added to the pool. The subscriber is also notified if a transactional and non-transactional object is obtained or returned to the pool.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComObjectPoolEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComObjectPoolEvents when you want to be notified about events related to COM+ object pooling.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComObjectPoolEvents Methods | Description
OnObjPoolPutObject | Generated when a new object is added to the pool.
OnObjPoolGetObject | Generated when a non-transactional object is obtained from the pool.
OnObjPoolRecycleToTx | Generated when a transactional object is returned to the pool.
OnObjPoolGetFromTx | Generated when a transactional object is obtained from the pool.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComObjectPoolEvents::OnObjPoolGetFromTx

Generated when a transactional object is obtained from the pool.

HRESULT OnObjPoolGetFromTx(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   EFGUID guidActivity,
   REFGUID guidObject,
   REFGUID guidTx,
   ULONG64 objid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The activity ID for which the object is created.
guidObject
[in] CLSID for the objects in the pool.
guidTx
[in] GUID representing the transaction ID.
objid
[in] The unique identifier for this object.


IComObjectPoolEvents::OnObjPoolGetObject

Generated when a non-transactional object is obtained from the pool.

HRESULT OnObjPoolGetObject(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidActivity,
   REFGUID guidObject,
   DWORD dwAvailable,
   ULONG64 oid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The activity ID for which the object is created.
guidObject
[in] CLSID for the objects in the pool.
dwAvailable
[in] Number of objects in the pool.
oid
[in] The unique identifier for this object.


IComObjectPoolEvents::OnObjPoolPutObject

Generated when a new object is added to the pool.

HRESULT OnObjPoolPutObject(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidObject,
   int nReason,
   DWORD dwAvailable,
   ULONG64 oid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
nReason
[in] Reserved. This parameter is always 0.
dwAvailable
[in] Number of objects in the pool.
oid
[in] The unique identifier for this object.


IComObjectPoolEvents::OnObjPoolRecycleToTx

Generated when a transactional object is returned to the pool.

HRESULT OnObjPoolRecycleToTx(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   EFGUID guidActivity,
   REFGUID guidObject,
   REFGUID guidTx,
   ULONG64 objid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The activity ID for which the object is created.
guidObject
[in] CLSID for the objects in the pool.
guidTx
[in] GUID representing the transaction ID.
objid
[in] The unique identifier for this object.


IComObjectPool2Events

The IComObjectPool2Events interface notifies the subscriber if a transactional or nontransactional object is added to or obtained from the object pool.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComObjectPool2Events to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComObjectPool2Events when you want to be notified about object pooling events.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComObjectPool2Events Methods | Description
OnObjPoolPutObject2 | Generated when an object is added to the pool.
OnObjPoolGetObject2 | Generated when a nontransactional object is obtained from the pool.
OnObjPoolRecycleToTx2 | Generated when a transactional object is returned to the pool.
OnObjPoolGetFromTx2 | Generated when a transactional object is obtained from the pool.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComObjectPool2Events::OnObjPoolGetFromTx2

Generated when a transactional object is obtained from the pool.

HRESULT OnObjPoolGetFromTx2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidActivity,
   REFGUID guidObject,
   REFGUID guidTx,
   ULONG64 objid,
   REFGUID guidPartition
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The activity ID for which the object is created.
guidObject
[in] CLSID for the objects in the pool.
guidTx
[in] The GUID representing the transaction ID.
objid
[in] The unique identifier for this object.
guidPartition
[in] The partition ID that this instance is obtained from.


IComObjectPool2Events::OnObjPoolGetObject2

Generated when a nontransactional object is obtained from the pool.

HRESULT OnObjPoolGetObject2(
   COMSVCSEVENTINFO *pInfo,
   REFGUID guidActivity,
   REFGUID guidObject,
   DWORD dwAvailable,
   ULONG64 oid,
   REFGUID guidPartition
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The activity ID for which the object is created.
guidObject
[in] CLSID for the objects in the pool.
dwAvailable
[in] Number of objects in the pool.
oid
[in] The unique identifier for this object.
guidPartition
[in] The Partition ID that this instance is obtained from.


IComObjectPool2Events::OnObjPoolPutObject2

Generated when an object is added to the pool.

HRESULT OnObjPoolPutObject2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidObject,
   int nReason,
   DWORD dwAvailable,
   ULONG64 oid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
nReason
[in] Reserved.
dwAvailable
[in] Number of objects in the pool.
oid
[in] The unique identifier for this object.


IComObjectPool2Events::OnObjPoolRecycleToTx2

Generated when a transactional object is returned to the pool.

HRESULT OnObjPoolRecycleToTx2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidActivity,
   REFGUID guidObject,
   REFGUID guidTx,
   ULONG64 objid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The activity ID for which the object is created.
guidObject
[in] CLSID for the objects in the pool.
guidTx
[in] The GUID representing the transaction ID.
objid
[in] The unique identifier for this object.


IComObjectPoolEvents2

The IComObjectPoolEvents2 interface notifies the subscriber if a new object is created for or removed from the pool. The subscriber is also notified when a new object pool is created or when the request for a pooled object times out.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComObjectPoolEvents2 to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComObjectPoolEvents2 to be notified about events related to object pooling.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComObjectPoolEvents2 Methods | Description
OnObjPoolCreateObject | Generated when an object is created for the pool.
OnObjPoolDestroyObject | Generated when an object is permanently removed from the pool.
OnObjPoolCreateDecision | Generated when a pool decides to give out an existing object or create a new one.
OnObjPoolTimeout | Generated when the request for a pooled object times out.
OnObjPoolCreatePool | Generated when a new pool is created.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComObjectPoolEvents2::OnObjPoolCreateDecision

When a component is configured for object pooling, the pool is populated with objects up to the specified minimum level. As client requests for the component come in, they are satisfied on a first-come first-served basis from the pool. If no pooled objects are available, and the pool is not yet at its specified maximum level, a new object is created and activated for the client. This method is generated when the pool decides to give out an existing object or create a new one.

HRESULT OnObjPoolCreateDecision(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   DWORD dwThreadsWaiting,
   DWORD dwAvail,
   DWORD dwCreated,
   DWORD dwMin,
   DWORD dwMax
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
dwThreadsWaiting
[in] Number of threads waiting for an object.
dwAvail
[in] Number of free objects in the pool.
dwCreated
[in] Number of total objects in the pool.
dwMin
[in] The pool's minimum object value.
dwMax
[in] The pool's maximum object value.


IComObjectPoolEvents2::OnObjPoolCreateObject

Generated when an object is created for the pool.

HRESULT OnObjPoolCreateObject(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidObject,
   DWORD dwObjsCreated,
   ULONG64 oid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
dwObjsCreated
[in] Number of objects in the pool.
oid
[in] Unique pooled object ID.


IComObjectPoolEvents2::OnObjPoolCreatePool

Generated when a new pool is created.

HRESULT OnObjPoolCreatePool(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidObject,
   DWORD dwMin,
   DWORD dwMax,
   DWORD dwTimeout
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
dwMin
[in] The pool's minimum object value.
dwMax
[in] The pool's maximum object value.
dwTimeout
[in] The pool’s timeout value.


IComObjectPoolEvents2::OnObjPoolDestroyObject

Generated when an object is permanently removed from the pool.

HRESULT OnObjPoolDestroyObject(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidObject,
   DWORD dwObjsCreated,
   ULONG64 oid
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
dwObjsCreated
[in] Number of objects in the pool.
oid
[in] Unique pooled object ID.


IComObjectPoolEvents2::OnObjPoolTimeout

Generated when the request for a pooled object times out.

HRESULT OnObjPoolTimeout(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidObject,
   EFGUID guidActivity,
   DWORD dwTimeout
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidObject
[in] CLSID for the objects in the pool.
guidActivity
[in] The identifier of the activity in which the object is created.
dwTimeout
[in] The pool’s timeout value.


IComQCEvents

The IComQCEvents interface notifies the subscriber if a queued message is created, de-queued, or moved to a retry or Dead Letter queue.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement this interface to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComQCEvents when you want to be notified about events related to Queued Components.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComQCEvents Methods | Description
OnQCRecord | Generated when the Queued Components (QC) recorder creates the queued message.
OnQCQueueOpen | Generated when the queue for a QC queue is opened.
OnQCReceive | Generated when a message is successfully de-queued even though QC might find something wrong with the contents.
OnQCReceiveFail | Generated when the receive message fails.
OnQCMoveToReTryQueue | Generated when a message is moved to a QC retry queue.
OnQCMoveToDeadQueue | Generated when a message is moved to the Dead Letter queue and cannot be delivered.
OnQCPlayback | Generated when a message’s contents are replayed.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComQCEvents::OnQCMoveToDeadQueue

Generated when a message is moved to the Dead Letter queue and cannot be delivered.

HRESULT OnQCMoveToDeadQueue(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidMsgId,
   REFGUID guidWorkFlowId
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidMsgId
[in] Unique identifier for queue.
guidWorkFlowId
[in] Reserved.


IComQCEvents::OnQCMoveToReTryQueue

Generated when a message is moved to a Queued Components (QC) retry queue.

HRESULT OnQCMoveToReTryQueue(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidMsgId,
   REFGUID guidWorkFlowId,
   ULONG RetryIndex
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidMsgId
[in] Unique identifier for queue.
guidWorkFlowId
[in] Reserved.
RetryIndex
[in] The index number of the retry queue where the message moved.


IComQCEvents::OnQCPlayback

Generated when a message’s contents are replayed.

HRESULT OnQCPlayback(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 objid,
   REFGUID guidMsgId,
   REFGUID guidWorkFlowId,
   HRESULT hr
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
objid
[in] The Just-In-Time activated object.
guidMsgId
[in] Unique identifier for queue.
guidWorkFlowId
[in] Reserved.
hr
[in] Status from Message Queuing receive message.


IComQCEvents::OnQCQueueOpen

Generated when the queue for a Queued Components (QC) queue is opened. This method is used to generate the QueueID parameter.

HRESULT OnQCQueueOpen(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   WCHAR RPC_FAR szQueue[60],
   ULONG64 QueueID,
   HRESULT hr
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
szQueue
[in] Message Queuing queue name.
QueueID
[in] Unique identifier for queue.
hr
[in] Status from Message Queuing queue open.


IComQCEvents::OnQCReceive

Generated when a message has successfully been de-queued.

HRESULT OnQCReceive(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 QueueID,
   REFGUID guidMsgId,
   REFGUID guidWorkFlowId,
   HRESULT hr
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
QueueID
[in] Unique identifier for queue.
guidMsgId
[in] Unique message ID for this queued message.
guidWorkFlowId
[in] Reserved
hr
[in] Status from Queued Components (QC) processing of received message.


IComQCEvents::OnQCReceiveFail

Generated when the receive message fails.

HRESULT OnQCReceiveFail(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 QueueID,
   HRESULT msmqhr
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
QueueID
[in] Unique identifier for queue.
msmqhr
[in] Status from Message Queuing receive message.


IComQCEvents::OnQCRecord

Generated when the Queued Components (QC) recorder creates the queued message.

HRESULT OnQCRecord(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 ObjId,
   WCHAR RPC_FAR szQueue[60],
   REFGUID guidMsgId,
   REFGUID guidWorkFlowId,
   HRESULT msmqhr
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ObjId
[in] The Just-In-Time activated object.
szQueue
[in] Message Queuing queue name.
guidMsgId
[in] Unique message ID for this queued message.
guidWorkFlowId
[in] Reserved.
msmqhr
[in] Message Queuing return status for queue message.


IComResourceEvents

The IComResourceEvents interface notifies the subscriber if a resource is created, allocated, tracked, or destroyed.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComResourceEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComResourceEvents when you want to be notified about events related to the resource dispenser management.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComResourceEvents Methods | Description
OnResourceCreate | Generated when a new resource is created and allocated.
OnResourceAllocate | Generated when an existing resource is allocated.
OnResourceRecycle | Generated when an object is finished with a resource.
OnResourceDestroy | Generated when a resource is destroyed.
OnResourceTrack | Generated when a resource is tracked.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComResourceEvents::OnResourceAllocate

Generated when an existing resource is allocated.

HRESULT OnResourceAllocate(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 ObjectID,
   LPCOLESTR pszType,
   ULONG64 resId,
   BOOL enlisted,
   DWORD NumRated,
   DWORD Rating
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ObjectID
[in] The Just-In-Time activated object.
pszType
[in] String describing resource being created.
resId
[in] Unique identifier for resource.
enlisted
[in] If TRUE, the resource is enlisted in a transaction.
NumRated
[in] Number of possible resources evaluated for match.
Rating
[in] The rating of the resource actually selected.


IComResourceEvents::OnResourceCreate

Generated when a new resource is created and allocated.

HRESULT OnResourceCreate(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 ObjectID,
   LPCOLESTR pszType,
   ULONG64 resId,
   BOOL enlisted
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ObjectID
[in] The Just-In-Time activated object.
pszType
[in] String describing the resource being created.
resId
[in] Unique identifier for resource.
enlisted
[in] If TRUE, the resource is enlisted in a transaction.


IComResourceEvents::OnResourceDestroy

Generated when a resource is destroyed.

HRESULT OnResourceDestroy(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 ObjectID,
   HRESULT hr,
   LPCOLESTR pszType,
   ULONG64 resId
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ObjectID
[in] The Just-In-Time activated object.
hr
[in] Result from Resource Dispenser’s Destroy.
pszType
[in] String describing resource being created.
resId
[in] Reference Unique identifier for resource.


IComResourceEvents::OnResourceRecycle

Generated when an object is finished with a resource.

HRESULT OnResourceRecycle(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 ObjectID,
   LPCOLESTR pszType,
   ULONG64 resId
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ObjectID
[in] The Just-In-Time activated object.
pszType
[in] String describing resource being created.
resId
[in] Unique identifier for resource.


IComResourceEvents::OnResourceTrack

Generated when the dispenser manager tracks a resource. When a tracked resource is freed, it is destroyed and therefore not returned to inventory.

HRESULT OnResourceTrack(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   ULONG64 ObjectID,
   LPCOLESTR pszType,
   ULONG64 resId,
   BOOL enlisted
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ObjectID
[in] The Just-In-Time activated object.
pszType
[in] String describing resource being created.
resId
[in] Reference Unique identifier for resource.
enlisted
[in] If TRUE, the resource is enlisted in a transaction.

See Also

Tracking Resources


IComSecurityEvents

The IComSecurityEvents interface notifies the subscriber if the authentication of a method call succeeded or failed.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComSecurityEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComSecurityEvents when you want to be notified about events related to security and authentication.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComSecurityEvents Methods | Description
OnAuthenticate | Generated when a method call level authentication succeeds.
OnAuthenticateFail | Generated when a method call level authentication fails.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComSecurityEvents::OnAuthenticate

When you set an authentication level for an application, you determine what degree of authentication is performed when clients call into the application. This method is generated when a method call level authentication succeeds.

HRESULT OnAuthenticate(
   COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidActivity,
   ULONG64 ObjectID,
   REFGUID guidIID,
   ULONG iMeth,
   ULONG cbByteOrig,
   BYTE __RPC_FAR *pSidOriginalUser,
   ULONG cbByteCur,
   BYTE __RPC_FAR *pSidCurrentUser,
   BOOL bCurrentUserInpersonatingInProc
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The identifier of the activity in which the object is created.
ObjectID
[in] The Just-In-Time activated object.
guidIID
[in] The IID of the method.
iMeth
[in] The v-table index of the method.
cbByteOrig
[in] Number of bytes in the security identifier for the original caller.
pSidOriginalUser
[in] The security identifier for the original caller.
cbByteCur
[in] Number of bytes in the security identifier for the current caller.
pSidCurrentUser
[in] The security identifier for the current caller.
bCurrentUserInpersonatingInProc
[in] If TRUE, the current user is impersonating.


IComSecurityEvents::OnAuthenticateFail

Generated when a method call level authentication fails.

HRESULT OnAuthenticateFail(
COMSVCSEVENTINFO RPC FAR *pInfo,
   REFGUID guidActivity,
   ULONG64 ObjectID,
   REFGUID guidIID,
   ULONG iMeth,
   ULONG cbByteOrig,
   BYTE __RPC_FAR *pSidOriginalUser,
   ULONG cbByteCur,
   BYTE __RPC_FAR *pSidCurrentUser,
   BOOL bCurrentUserInpersonatingInProc
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The identifier of the activity in which the object is created.
ObjectID
[in] The Just-In-Time activated object.
guidIID
[in] The IID of the method.
iMeth
[in] The v-table index of the method.
cbByteOrig
[in] Number of bytes in the security identifier for the original caller.
pSidOriginalUser
[in] The security identifier for the original caller.
cbByteCur
[in] Number of bytes in the security identifier for the current caller.
pSidCurrentUser
[in] The security identifier for the current caller.
bCurrentUserInpersonatingInProc
[in] If TRUE, the current user is impersonating.


IComThreadEvents

The IComThreadEvents interface notifies the subscriber if a single-threaded apartment (STA) is created or terminated, and when an apartment thread is allocated. The subscriber is also notified if an activity is assigned or unassigned to an apartment thread.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComThreadEvents to catch events that are published by the system events publisher. You will be a subscriber, and you will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComThreadEvents when you want to be notified about single-threaded apartment (STA) thread pool metrics.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComThreadEvents Methods | Description
OnThreadStart | Generated when a new STA is created.
OnThreadTerminate | Generated when an STA is terminated.
OnThreadBindToApartment | Generated when an apartment has to bind to a new context.
OnThreadUnBind | Generated when the lifetime of the configured component is over and the activity count on the apartment thread can be decremented.
OnThreadAssignApartment | Generated when an activity is assigned to an apartment thread.
OnThreadUnassignApartment | Generated when an activity is unassigned from an apartment thread.

Note The user verifes the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComThreadEvents::OnThreadAssignApartment

Generated when an activity is assigned to an apartment thread.

HRESULT OnThreadAssignApartment(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   REFGUID guidActivity,
   ULONG64 AptID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidActivity
[in] The activity ID for which the object is created.
AptID
[in] Apartment ID.


IComThreadEvents::OnThreadBindToApartment

Generated when an apartment thread is allocated for a single-thread apartment (STA) thread that does not have an apartment thread to run in. An apartment thread is created or allocated from the pool.

HRESULT OnThreadBindToApartment(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 ThreadID,
   ULONG64 AptID,
   DWORD dwActCnt,
   DWORD dwLowCnt
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ThreadID
[in] Unique thread identifier.
AptID
[in] Apartment ID.
dwActCnt
[in] Number of activities bound to this apartment.
dwLowCnt
[in] Reserved. Currently equal to 0.


IComThreadEvents::OnThreadStart

Generated when a single-threaded apartment (STA) thread is started.

HRESULT OnThreadStart(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 ThreadID,
   DWORD dwThread,
   DWORD dwThreadCnt
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ThreadID
[in] Unique thread identifier.
dwThread
[in] Windows® 2000 thread ID.
dwThreadCnt
[in] Number of threads in STA thread pool.


IComThreadEvents::OnThreadTerminate

Generated when a single-threaded apartment (STA) thread is terminated.

HRESULT OnThreadTerminate(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 ThreadID,
   DWORD dwThread,
   DWORD dwThreadCnt
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ThreadID
[in] Unique thread identifier.
dwThread
[in] Windows® 2000 thread ID.
dwThreadCnt
[in] Number of threads in STA thread pool.


IComThreadEvents::OnThreadUnassignApartment

Generated when an activity is assigned to an apartment thread.

HRESULT OnThreadUnassignApartment(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 AptID
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
AptID
[in] Apartment ID.


IComThreadEvents::OnThreadUnBind

Generated when the apartment thread is no longer needed.

HRESULT OnThreadUnBind(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   ULONG64 ThreadID,
   ULONG64 AptID,
   DWORD dwActCnt
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
ThreadID
[in] Unique thread identifier.
AptID
[in] Apartment ID.
dwActCnt
[in] Number of current activities on the apartment thread.


IComTransactionEvents

The IComTransactionEvents interface notifies the subscriber if a Microsoft Distributed Transaction Coordinator (MS DTC) transaction starts, commits, or aborts. The subscriber is also notified when the resource manager retrieves prepare information from the transaction manager.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComTransactionEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComTransactionEvents when you want to be notified of events related to MS DTC.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComTransactionEvents Methods | Description
OnTransactionStart | Generated when a transaction starts.
OnTransactionPrepare | Generated when the prepare phase of the two-phase commit protocol of the transaction is completed.
OnTransactionAbort | Generated when a transaction aborts.
OnTransactionCommit | Generated when a transaction commits.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComTransactionEvents::OnTransactionAbort

Generated when a transaction aborts.

HRESULT OnTransactionAbort(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   REFGUID guidTx
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.

See Also

ITransaction::Abort, IComTransactionEvents::OnTransactionStart


IComTransactionEvents::OnTransactionCommit

Generated when a transaction commits.

HRESULT OnTransactionCommit(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   REFGUID guidTx
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.

See Also

ITransaction::Commit, IComTransactionEvents::OnTransactionStart


IComTransactionEvents::OnTransactionPrepare

Generated when the resource manager retrieves prepare information from the transaction manager. This information is gathered during the prepare phase of the two-phase commit protocol of the transaction.

HRESULT OnTransactionPrepare(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   REFGUID guidTx,
   BOOL fVoteYes
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.
fVoteYes
[in] The resource manager’s result concerning the outcome of the prepare phase.

See Also

Transaction Commit Phase 1–Prepare II, IComTransactionEvents::OnTransactionStart


IComTransactionEvents::OnTransactionStart

Generated when a Microsoft Distributed Transaction Coordinator (MS DTC) transaction starts.

HRESULT OnTransactionStart(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   REFGUID guidTx,
   REFGUID tsid,
   BOOL fRoot
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.
tsid
[in] Transaction stream ID. Unique identifier for correlation to objects.
fRoot
[in] TRUE if this is a root transaction.


IComTransaction2Events

The IComTransaction2Events interface notifies the subscriber if a Microsoft Distributed Transaction Coordinator (DTC) transaction starts, commits, or aborts. The subscriber is also notified when the transaction is in the prepare phase of the two-phase commit protocol.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComTransaction2Events to catch events that are published by the system events publisher. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

You use IComTransaction2Events when you want to be notified about the outcome of a transaction.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComTransaction2Events Methods | Description
OnTransactionStart2 | Generated when a Microsoft Distributed Transaction Coordinator (DTC) transaction starts.
OnTransactionPrepare2 | Generated when the transaction is in the prepare phase of the commit protocol.
OnTransactionAbort2 | Generated when a transaction aborts.
OnTransactionCommit2 | Generated when a transaction commits.

Note The user verifies the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComTransaction2Events::OnTransactionAbort2

Generated when a transaction aborts.

HRESULT OnTransactionAbort2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidTx
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.

See Also

IComTransaction2Events::OnTransactionStart2


IComTransaction2Events::OnTransactionCommit2

Generated when a transaction commits.

HRESULT OnTransactionCommit2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidTx
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.

See Also

IComTransaction2Events::OnTransactionStart2


IComTransaction2Events::OnTransactionPrepare2

Generated when the resource manager retrieves prepare information from the transaction manager. This information is gathered during the prepare phase of the two-phase commit protocol of the transaction.

HRESULT OnTransactionPrepare2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidTx,
   BOOL fVoteYes
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.
fVoteYes
[in] The resource manager's result concerning the outcome of the prepare phase.

See Also

IComTransaction2Events::OnTransactionStart2


IComTransaction2Events::OnTransactionStart2

Generated when a Microsoft Distributed Transaction Coordinator (DTC) transaction starts.

HRESULT OnTransactionStart2(
   COMSVCSEVENTINFO * pInfo,
   REFGUID guidTx,
   REFGUID tsid,
   BOOL fRoot,
   int nIsolationLevel
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
guidTx
[in] GUID representing the transaction ID.
tsid
[in] Transaction stream ID for the correlation to objects.
fRoot
[in] If the transaction is a root transaction, this parameter is set to TRUE. Otherwise, this parameter is set to FALSE.
nIsolationLevel
[in] The isolation level of the transaction.

Comment

The nIsolationLevel argument representing the transaction isolation level is the only differentiating factor between the IComTransaction2Events and IComTransactionEvents interfaces.


IComUserEvent

The IComUserEvent interface notifies the subscriber of the specified user-defined metrics.

When to Implement

To use this interface, you have to know how to use loosely coupled events. You will implement IComUserEvents to catch events. The system events publisher publishes these events. You will need to subscribe to the system events publisher. The class ID is CLSID_ComServiceEvents.

When to Use

Use IComUserEvent when you want to be notified of user-specific events.

For a sample application specific to IComUserEvent see the UserEvents sample or COM+ Instrumentation Samples.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IComUserEvent Methods | Description
OnUserEvent | Provided for user components to generate user-defined metrics.

Note The user will be the one to verify the return values from these methods.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Events Model


IComUserEvent::OnUserEvent

Provided for user components to generate user-specific metrics.

HRESULT OnUserEvent(
   COMSVCSEVENTINFO __RPC_FAR *pInfo,
   VARIANT __RPC_FAR *pvarEvent
) = 0;

Parameters

pInfo
[in] For more information on this structure, see Event Structure.
pvarEvent
[in] User-defined content.


Event Structure

Each COM+ Instrumentation interface provides a standard event structure as its first value. The structure contains contextual information about the metric; such as the time it was generated and which process server and COM+ application generated it.

typedef struct COMSVCSEVENTINFO{
DWORD cbSize;
DWORD dwPid;
LONG ITime;
LONG IMicroTime;
LONGLONG perfCount;
GUID guidApp;
LPOLESTR sMachineName
};

Members

cbSize
The size of this structure.
dwPid
The process ID of the server application that the event was originated from.
ITime
The coordinated universal time of event as seconds elapsed since midnight, January 1, 1970.
IMicroTime
Microseconds added to the ITime argument for time to microsecond resolution.
perfCount
The value of the high-resolution performance counter when the event originated.
guidApp
The application’s globally unique identifier (GUID) for the first component instantiated in the dwPid argument. If you are subscribing to an administration interface or event and the event is not generated from a COM+ application, the guidApp parameter will be set to zero.
sMachineName
The fully qualified name of the computer where the event originated.

Comments

When the application ID (guidApp) is specified, the user will receive only the metrics from the specified application. If the process ID (dwPid) is specified, the user will receive metrics from the specified server application and library applications that are loaded in that process (because the server app calls them). The user can specify both the application ID and process ID. However, the application ID has to be that of the server application running in the process with the specified process ID. If neither is specified, the user will receive metrics from all the server and library applications.


MTS Support Interfaces

The following table lists the MTS support interfaces.

Interfaces | Description
IMtsEventInfo | This interface describes methods for describing user-defined events.
IMtsEvents | This interface describes methods for obtaining information about the running package and establishing event sinks.
IMtsGrp | This interface describes methods for enumerating through running packages.
IMtsLocator | This interface describes a single event that provides access to the IMTsEvents interface of the event dispatcher for the current process.


IMtsEventInfo Interface

This interface describes methods for describing user-defined events.

When to Implement

These events are published by the system events publisher. To use these you have to know how to use loosely-coupled events (LCE). You will implement this interface to catch events. You will be a subscriber and you will need to subscribe to the system events publisher. The ID of the ComEvents class is CLSID_ComEvents.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IMtsEventInfo Methods | Description
Names | Gets the names of the data values in an enumerator.
DisplayName | Gets the display name of the object.
EventID | Gets the event ID of the object (a GUID converted to a string).
Count | Gets the number of data values from the object.
Value | Given the name (or ordinal) returns the value of the user-defined event.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Instrumentation Interfaces


IMtsEventInfo::Count

Gets the number of data values from the object.

HRESULT Count(
  long *lCount
);
lCount
[out] The number of data values from the object.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEventInfo::DisplayName

Gets the display name of the object.

HRESULT DisplayName(
  BSTR *sDisplayName
);
sDisplayName
[out] Display name of the object.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEventInfo::EventID

Gets the event ID of the object (a GUID converted to a string).

HRESULT EventID(
  BSTR *sGuidEventID
);
sGuidEventID
[out] Event ID of the object

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEventInfo::Names

Gets the names of the data values in an enumerator.

HRESULT Names(
  IUnknown **pUnk
);
pUnk
[out] Interface pointer to the enumerator.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEventInfo::Value

Given the name (or ordinal), returns the value of the user-defined event.

HRESULT Value(
  BSTR sKey,
  VARIANT *pVal
);
sKey
[in] The name or ordinal of the value.
pVal
[out] The value of the user-defined event.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEvents Interface

This interface describes methods for obtaining information about the running package and establishing event sinks.

When to Implement

These events are published by the system events publisher. To use these you have to know how to use loosely-coupled events (LCE). You will implement this interface to catch events. You will be a subscriber and you will need to subscribe to the system events publisher. The ID of the ComEvents class is CLSID_ComEvents.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IMtsEvents Methods | Description
PackageName | Indicates the name of the package where the instance of the object that implements IMtsEvent is running.
PackageGuid | Indicates the globally unique identifier (GUID) for the package in which the event occurred.
PostEvent | Allows a component to post a user-defined event to an event sink.
get_FireEvents | Indicates if events are enabled or disabled for an event sink.
GetProcessID | Indicates the process identification for the package in which an event occurred.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Instrumentation Interfaces


IMtsEvents::get_FireEvents

Indicates if events are enabled or disabled for an event sink.

HRESULT get_FireEvents(
  VARIANT_BOOL *pVal
);
pVal
[out] Pointer to global variable indicating if events are enabled or disabled for an event sink.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEvents::GetProcessID

Indicates the process identification for the process in which the event occurred.

HRESULT GetProcessID(
  long *id
);
id
[out] Pointer to the process identification for the event.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEvents::PackageGuid

Indicates the globally unique identifier (GUID) for the package in which the event occurred.

HRESULT PackageGuid(
  BSTR *pVal
);
pVal
[out] Pointer to the package GUID.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEvents::PackageName

Indicates the name of the package where the instance of the object that implements the IMtsEvent interface is running.

HRESULT PackageName(
  BSTR *pVal
);
pVal
[out] Pointer to the package name string.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsEvents::PostEvent

Allows a component to post a user-defined event to an event sink.

HRESULT PostEvent(
  VARIANT *vEvent
);
vEvent
[in] Pointer to the name of the event.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsEvents Interface


IMtsGrp Interface

The IMtsGrp interface describes methods for enumerating through running packages.

When to Implement

These events are published by the system events publisher. To use these you have to know how to use loosely-coupled events (LCE). You will implement this interface to catch events. You will be a subscriber and you will need to subscribe to the system events publisher. The ID of the MtsGrp class is CLSID_MtsGrp.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IMtsGrp Methods | Description
get_Count | Indicates the number of running packages.
Item | Retrieves an IUnknown pointer that can be queried to access IMtsEvents.
Refresh | Updates the list of IUnknown pointers that is populated upon the creation of the object.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Instrumentation Interfaces


IMtsGrp::get_Count

Indicates the number of running packages in the catalog.

HRESULT get_Count(
  Long *pVal
);
pVal
[in] Pointer to the number of running packages.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsGrp Interface


IMtsGrp::Item

Retreives an IUnknown pointer that can be queried to access IMtsEvents.

HRESULT Item(
  Long lIndex,
  IUnknown **ppUnkDispatcher
);
lIndex
[in] Index containing running packages.
ppUnkDispatcher
[out] Points to a pointer to an IUnknown interface, which can be used to access IMtsEvents.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsGrp Interface


IMtsGrp::Refresh

Updates the list of IUnknown pointers that is populated upon the creation of the object.

HRESULT Refresh( );

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsGrp Interface


IMtsLocator Interface

The IMtsLocator interface describes a single event that provides access to the IMTsEvents interface of the event dispatcher for the current process.

When to Implement

These events are published by the system events publisher. To use these you have to know how to use loosely-coupled events (LCE). You will implement this interface to catch events. You will be a subscriber and you will need to subscribe to the system events publisher. The ID of the CoMTSLocator class is CLSID_MtsLocator.

Methods in Vtable Order

IUnknown Methods | Description
QueryInterface | Returns pointers to supported interfaces.
AddRef | Increments reference count.
Release | Decrements reference count.
IMtsLocator Methods | Description
GetEventDispatcher | Returns the IUnknown of the event dispatcher for the current process. Used with in-process event sinks.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

COM+ Instrumentation Interfaces


IMtsLocator::GetEventDispatcher

Provides access to the IUnknown interface of the event dispatcher for the current process.

HRESULT GetEventDispatcher(
  IUnknown **pUnk
);
pUnk
[out] Pointer to the IUnknown interface of the event dispatcher for the current process.

Requirements

To use the methods of this interface, you must include comsvcs.h in your project.

See Also

IMtsLocator Interface


Functions

This section describes special functions that developers use to create transaction managers, to dispense transactions, and to implement the data structure used by the resource manager proxy. The topics are:

Topic | Description
DtcGetTransactionManager Function | Establishes the initial connection to MS DTC. It returns an interface pointer to one of the interfaces on the MS DTC proxy core object.
DtcGetTransactionManagerEx Function | Establishes the initial connection to MS DTC. It returns an interface pointer to one of the interfaces on the MS DTC proxy core object and helps reduce the boot time. It also minimizes resource consumption for Windows 2000 and adds the ability to demand start DTC on Windows 2000 to compensate for removing boot start.
GetDispenserManager Function | A resource dispenser calls this function to get the IDispenserManager Interface.
GetXaSwitch Function | The DTC transaction manager calls this function to obtain the address of the XA switch data structure implemented by the RM Proxy.


DtcGetTransactionManager Function

This is typically the first MS DTC call that application programs and resource managers make when using MS DTC. This helper function establishes the initial connection to MS DTC. It returns an interface pointer to one of the interfaces on the MS DTC proxy core object.

Implemented by: | MS DTC proxy
Object | This is a helper function, not a method on an object
Interface Source | N/A
Called by: | Application programs and resource managers
HRESULT __cdecl DtcGetTransactionManager(
  char *pszHost,
  char *pszTmName,
  REFIID riid,
  DWORD dwReserved1,
  WORD wcbVarLenReserved2,
  void *pvVarDataReserved2,
  void **ppv
);

Parameters

pszHost
[in] Name of the host system which will serve as the transaction commit coordinator.
pszTmName
[in] String Name of the transaction manager which will serve as the transaction commit coordinator. Must be NULL.
riid
[in] IID of the requested interface.
dwReserved1
[in] See remarks below.
wcbVarLenReserved2
[in] See remarks below.
pvVarDataReserved2
[in] See remarks below.
ppv
[out] Pointer to the pointer to the requested interface.

Return Values

S_OK
Success.
E_NOINTERFACE
Unable to provide the requested interface.
E_UNEXPECTED
Unexpected error encountered.
E_INVALIDARG
One or more arguments are invalid.
E_FAIL
Failed to carry out the operation.

Remarks

Calls to DtcGetTransactionManager can specify a server host name in the pszHost parameter. This lets the transaction to be started and coordinated on a specific computer on the network.

However, if the caller supplies a valid machine name as the pszHost parameter, DTC completely ignores it and acts as if it was NULL, thus using rules 1 and 2 below.

  1. If the workstation making the call has a locally installed MS DTC, the local MS DTC is used.
  2. If the workstation making the call is a Windows 95 computer or a Windows 2000 computer which does not have a local MS DTC installed, the default MS DTC is used. The default MS DTC is specified as the “Remote Host” field on the MSDTC tab of the Component Services administrative tool.

Currently there are only two acceptable combinations for values for dwReserver1, wcbReserved2 and pvReservered2. They are:

  1. dwReserver1 = 0, wcbReserved2 = 0 and pvReservered2 = NULL
  2. dwReserver1 = dwUSER_MS_SQLSERVER, wcbReserved2 = sizeof (PROXY_CONFIG_PARAMS) and pvReservered2 = pparamsProxy, where pparamsProxy is a pointer to a structure of type PROXY_CONFIG_PARAMS

    The wcThreadsMax field in the PROXY_CONFIG_PARAMS structure hints at the maximum number of threads to use on behalf of the calling application. This combination of values is usually only used by resource managers or clients that require high concurrency.


DtcGetTransactionManagerEx Function

The DtcGetTransactionManagerEx function is typically the first MS DTC call that application programs and resource managers make when using MS DTC. This helper function establishes the initial connection to MS DTC. It returns an interface pointer to one of the interfaces on the MS DTC proxy core object. This function helps reduce the boot time and minimize resource consumption for Windows 2000 and adds the ability to demand start DTC on Windows 2000 to compensate for removing boot start.

Implemented by: | MS DTC proxy
Object | This is a helper function, not a method on an object
Interface Source | N/A
Called by: | Application programs and resource managers
EXTERN_C EXPORTAPI __cdecl DtcGetTransactionManagerEx(
   tchar * i_pszHost,
   tchar * i_pszTmName,
   REFIID i_riid,
   DWORD i_grfOptions,
   void * i_pvConfigParams,
   void ** o_ppvObject
);

Note This API should not be called without the OLE_TM_FLAG_NO_DEMANDSTART during service startup.

Parameters

i_pszHost
[in] Name of the host system which will serve as the transaction commit coordinator.
i_pszTmName
[in] String Name of the transaction manager which will serve as the transaction commit coordinator. Must be NULL.
i_riid
[in] IID of the requested interface.
i_grfOptions
[in] Specifies any configuration or startup options for the transaction manager object. Currently the supported flags are:

OLE_TM_FLAG_NODEMANDSTART (Value = 0x00000001)

Callers can specify this option if they do not want demand start of MS DTC.

OLE_TM_FLAG_NONE (Value = 0x00000000)

External callers should use this flag if they want the default behavior (which is to demand start MS DTC). This approach provides meaningful text and is preferable to directly using the value 0 for i_grfOptions.

OLE_TM_FLAG_INTERNAL_TO_TM (Internal only)

Only components internal to the Transaction manager (such as XATM) should use this flag. This flag should not be used by external callers.

OLE_TM_FLAG_QUERY_SERVICE_LOCKSTATUS (Internal only)

Specifying this flag will cause DTC to query the lock status and fail demand start if someone else is holding SCM lock. This flag should not be used by external callers.

i_pvConfigParams
[in] Pointer to a self-describing structure. You can use the structure to pass various configuration parameters into the TM object. Must be null.
o_ppvObject
[out] Pointer to the pointer to the requested interface.

Return Values

S_OK
Success.
E_NOINTERFACE
Unable to provide the requested interface.
E_UNEXPECTED
Unexpected error encountered.
E_INVALIDARG
One or more arguments are invalid.
E_FAIL
Failed to carry out the operation.

Remarks

Calls to DtcGetTransactionManagerEx can specify a server host name in the pszHost parameter. This lets the transaction to be started and coordinated on a specific computer on the network. If a value of NULL is supplied, the following rules determine where the transaction is started and coordinated:

  1. If the workstation making the call has a locally installed MS DTC, the local MS DTC is used.
  2. If the workstation making the call is a Windows 95 computer or a Windows 2000 computer which does not have a local MS DTC installed, the default MS DTC is used. The default MS DTC is specified as the “Remote Host” field on the MSDTC tab of the Component Services administrative tool.

The DtcGetTransactionManagerEx function helps reduce the boot time and minimize resource consumption for Windows 2000. The function also adds the ability to demand start DTC on Windows 2000 to compensate for removing boot start. In general, clients of DTC call this function DTC is not running. It demand starts the transaction manager (TM) for the caller. The caller specify OLE_TM_FLAG_NODEMANDSTART to explicitly disable demand start. The semantics for demand start are as follows:

  1. Calls into DtcGetTransactionManagerEx will demand start the TM if required. DtcGetTransactionManagerEx can still return XACT_E_TM_NOTAVAILABLE.
  2. This behavior is the same for local and remote clients.
  3. If clients want to restart DTC without shutting down and restarting their executables, they should release all references and call on DtcGetTransactionManagerEx again.


GetDispenserManager Function

A resource dispenser calls this function to get DispMan's IDispenserManager Interface.

HRESULT GetDispenserManager(
  IDispenserManager **ppIDispenserManager
);

Parameters

ppIDispenserManager
[out] Points to the location where the IDispenserManager Interface is returned.

Return Values

S_OK
Success.
E_FAIL
Failure. Interface was not returned.


GetXaSwitch Function

This function must be implemented and exported by the RM proxy. The DTC transaction manager calls this function to obtain the address of the XA switch data structure implemented by the RM Proxy.

Implemented by: | RM proxy
Object | This is a helper function, not a method on an object
Interface Source | N/A
Called by: | DTC transaction manager
HRESULT __cdecl   GetXaSwitch (
XA_SWITCH_FLAGS  XaSwitchFlags,
xa_switch_t **  ppXaSwitch
);

Parameters

XaSwitchFlags
[in] Flags providing information about the transaction manager making the call. Currently XA_SWITCH_F_DTC is the only defined flag
   typedef DWORD XA_SWITCH_FLAGS
   #define XA_SWITCH_F_DTC 0x00000001
ppXaSwitch
[out] Pointer to the pointer to the xa_switch_t data structure implemented by the RM proxy.
 #define RMNAMESIZE   32
 struct xa_switch_t {
   CHAR     name[RMNAMESIZE];
   LONG     flags;
   LONG     version; /* must be 0 */
   INT (__cdecl *xa_open_entry)(char *, int, long);
   INT (__cdecl *xa_close_entry)(char *, int, long);
   INT (__cdecl *xa_start_entry)(XID *, int, long);
   INT (__cdecl *xa_end_entry)(XID *, int, long);
   INT (__cdecl *xa_rollback_entry)(XID *, int, long);
   INT (__cdecl *xa_prepare_entry)(XID *, int, long);
   INT (__cdecl *xa_commit_entry)(XID *, int, long);
   INT (__cdecl *xa_recover_entry)(XID *, long, int, long);
   INT (__cdecl *xa_forget_entry)(XID *, int, long);
   INT (__cdecl *xa_complete_entry)(int *, int *, int, long);
 };

Return Values

S_OK
Success.
E_FAIL
Unable to provide the address of the XA switch function.

Remarks

All XA compliant resource managers must provide an XA switch. This XA switch makes it possible for transaction managers to call the resource managers xa_ routines. The format of the XA switch is described in the X/Open specification xa_switch_t structure. The XA switch contains the resource manager’s name, non-null pointers to the resource manager’s xa_ entry points, a flag, and a version number.

When the DTC transaction manager loads the RM proxy DLL, it calls GetProcAddress to obtain the address of the GetXaSwitch function. The DTC transaction manager then calls the GetXaSwitch function to obtain the address of the resource manager’s xa_switch_t structure. The RM proxy must implement both the GetXaSwitch function and the XA Switch structure, and both must be implemented using the __cdecl calling convention.


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

GetSecurityCallContext Example

Public Function FindDirectCallerProp(ByVal propName as String) as Variant

  Dim directCaller as SecurityIdentity
  Set directCaller = GetSecurityCallContext(“DirectCaller”)
  FindDirectCallerProp = directCaller(propName)

End Function


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

GetDirectCallerSID Method Example

#include <mtx.h>

IObjectContext* pIObjectContext = NULL;
ISecurityProperty* pISecurityProperty = NULL;
PSID pSid = NULL;
HRESULT hr;

// Get a reference to the ISecurityProperty interface.
pIObjectContext->QueryInterface(IID_ISecurityProperty,
    (void**)&pISecurityProperty);

// Obtain the caller's security ID.
hr = pISecurityProperty->GetDirectCallerSID(&pSid)

// Do some security checking here.

// Release the security ID.
pISecurityProperty->ReleaseSID(pSid);


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

GetOriginalCallerSID Method Example

#include <mtx.h>

IObjectContext* pIObjectContext = NULL;
ISecurityProperty* pISecurityProperty = NULL;
PSID pSid = NULL;
HRESULT hr;

// Get a reference to the ISecurityProperty interface.
pIObjectContext->QueryInterface(IID_ISecurityProperty,
    (void**)&pISecurityProperty);

// Obtain the original caller's security ID.
hr = pISecurityProp->GetOriginalCallerSID(&pSid)

// Do some security checking here.

// Release the security ID.
pISecurityProperty->ReleaseSID(pSid);


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

CreateInstance Method Example

#include <Txctx.h>

ITransactionContextEx* pTransactionContext = NULL;
IMyObject* pMyObject = NULL;
HRESULT hr;

// Get TransactionContextEx.
hr = CoCreateInstance(CLSID_ITransactionContextEx,
     NULL, CLSCTX_INPROC, IID_ITransactionContextEx,
     (void**) &pTransactionContext);

// Create an instance of MyObject.
hr = pTransactionContext->CreateInstance
     (CLSID_CMyObject, IID_IMyObject,
     (void**) &pMyObject);


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

Abort and Commit Methods Example

[C/C++]
#include <Txctx.h>

ITransactionContextEx* pTransactionContext = NULL;
IMyObject* pMyObject = NULL;
boolean bUserCanceled = FALSE;
HRESULT hr;

// Get TransactionContextEx.
hr = CoCreateInstance(CLSID_ITransactionContextEx,
     NULL, CLSCTX_INPROC, IID_ITransactionContextEx,
     (void**) &pTransactionContext);

// Create an instance of MyObject.
hr = pTransactionContext->CreateInstance
     (CLSID_CMyObject, IID_IMyObject,
     (void**) &pMyObject);

// Do some work here.

// If something goes wrong, abort the transaction.
if (bUserCanceled)
     pTransactionContext->Abort();

// Otherwise, commit it.
else
     pTransactionContext->Commit();

[Visual Basic]
Dim objTxCtx As TransactionContext
Dim objMyObject As MyCompany.MyObject
Dim userCanceled As Boolean

' Get TransactionContext.
Set objTxCtx = _
    CreateObject("TxCtx.TransactionContext")

' Create an instance of some component.
Set objMyObject= _
    objTxCtx.CreateInstance("MyCompany.MyObject")

' Do some work here.

' If something goes wrong, abort the transaction.
If userCanceled Then
    objTxCtx.Abort

' Otherwise, commit it.
Else
    objTxCtx.Commit
End If


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

Count, Item Methods Example

Dim x as Integer

' Get the context object
Dim secCallCtx As SecurityCallContext
Set secCallCtx = GetSecurityCallContext()

Dim dc As SecurityIdentity
Set dc = secCallCtx.Item("DirectCaller")

' Find out how many properties exist for the
' direct caller
x = dc.Count


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

GetOriginalCallerName Method Example

Public Function ComponentOriginalCaller() As String

    Dim objCtx As ObjectContext

    Set objCtx = GetObjectContext()
    ComponentOriginalCaller = objCtx.Security.GetOriginalCallerName()

End Function


Platform SDK: COM+ (Component Services)

[This is preliminary documentation and subject to change]

GetDirectCallerName Method Example

Public Function ComponentDirectCaller() As String

    Dim objCtx As ObjectContext

    Set objCtx = GetObjectContext()
    ComponentDirectCaller = objCtx.Security.GetDirectCallerName()

End Function