Legal Information

Microsoft Exchange Client Extensions Programmer's Reference

Information in this document is subject to change without notice. This document is provided for informational purposes only and Microsoft Corporation makes no warranties, either express or implied, in this document. The entire risk of the use or the results of the use of this document remains with the user. The names of companies, products, people, characters, and/or data mentioned herein are fictitious and are in no way intended to represent any real individual, company, product, or event, unless otherwise noted. Complying with all applicable copyright laws is the responsibility of the user. No part of this document may be reproduced or transmitted in any form or by any means, electronic or mechanical, without the express written permission of Microsoft Corporation. If, however, your only means of access is electronic, permission to print one copy is hereby granted.

Microsoft may have patents or pending patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. The furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property rights except as expressly provided in any written license agreement from Microsoft.

© 1996-1998 Microsoft Corporation. All rights reserved.

Microsoft, Windows, Win32, and Windows NT are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

Macintosh is a registered trademark of Apple Computer, Inc.

Other product and company names mentioned herein may be the trademarks of their respective owners.


About Client Extensions

Using the Client Extensions Programmer's Reference, it is possible to develop a wide variety of custom client applications that access Microsoft Exchange services such as the information store. These custom client applications can provide different views of data in the information store, data searching and sorting capabilities, security, custom mail or messaging features, forms, workgroup capabilities, and many other capabilities.

This documentation describes the four types of Microsoft Exchange client extensions in the following topics:

  • Command Extensions
  • Event Extensions
  • Property Sheet Extensions
  • Advanced Criteria Extensions

You can also develop multi-purpose extensions that span two or more of these categories. For example, you can develop an extension that adds menus to the Microsoft Exchange Viewer window and also provides custom property sheets.

This section provides detailed information on how the Microsoft Exchange client interacts with the major categories of extensions. Information is also provided on how to write modeless extensions, how to register extensions depending on your operating system, and how to optimize performance.

Note For sample code illustrating some of the concepts covered in this section, see the Code Samples section in the Platform SDK.


Advantages of Extending Microsoft Exchange

Before planning the development of a client application, you might want to consider extending the Microsoft Exchange client application. Microsoft Exchange provides a large number of features that enable users to view, search and sort information in the information store. It also provides a development platform for electronic mail, messaging, and workgroup applications that can handle a broad spectrum of information sharing tasks.

Instead of recreating features that are already provided in Microsoft Exchange, you can leverage the existing features and user interface of Microsoft Exchange and add your own custom features, also known as "extensions." You can override the default behavior of almost any feature of Microsoft Exchange. The use of extensions can save a considerable amount of development effort that would otherwise be devoted to creating a custom user interface and custom features.

Additionally, extending the Microsoft Exchange client benefits users by integrating capabilities from many different ISVs into a single user interface, rather than having multiple interfaces through which users accomplish their information sharing tasks.

Microsoft Exchange client extensions can run on any platform that is running the Microsoft Exchange client. This includes Microsoft® Windows® 3.1, Windows® for Workgroups 3.1, Windows NT®, and Windows® 95 operating systems. Since the Microsoft Exchange client is included with Windows 95, any extension you develop can run on any computer running Windows 95 — it is not necessary for the user to purchase a separate product to use your extension on Windows 95.


How Extensions Work

When Microsoft Exchange is started on 16-bit versions of Windows, it reads a list of extensions from the .INI file. On 32-bit Windows NT or Windows 95, each extension registers a DLL name, an ordinal, and a map indicating in which contexts it wants to be called in the registry database. Next, it activates all the extensions that are registered to participate within the EECONTEXT_TASK context. Later, extensions that participate in other contexts are activated as needed when those contexts become current.

After Microsoft Exchange and its initial extensions have been loaded into memory, the interaction between Microsoft Exchange and its extensions is determined mostly by the user's interaction with Microsoft Exchange, but it can also be determined by events such as the arrival of a new message.

The following steps give an overview of how Microsoft Exchange interacts with its extensions:

  1. A context activation occurs.
  2. In the order in which they are listed in the .INI file or registry, Microsoft Exchange invokes the IExchExt::Install method on each extension object that has registered to participate in the new context. One of the parameters passed to each extension through Install is a pointer to a callback object that supports the IExchExtCallback : IUnknown interface.
  3. Each extension that was called in step 2 uses IExchExtCallback to retrieve information about the environment, including the active menu, the active toolbar, the number of objects selected in the current window, and the entry identifier of the selected item. Extensions can also use MAPI and Windows API functions to retrieve information. Extensions use this information to determine if they will participate in the new context.
  4. If an extension determines that it will participate in the context, it will return S_OK from IExchExt::Install. For example, an extension might need to participate in a context only if a certain folder is open. Otherwise, it returns S_FALSE.
  5. In the order in which they are listed in the .INI file or registry, Microsoft Exchange invokes appropriate methods on all extensions that returned S_OK. The methods that are invoked depend on the context. For example, if the context is EECONTEXT_SENDNOTEMESSAGE, Microsoft Exchange first invokes the IExchExtCommands::InstallCommands method on all extensions that are registered to participate in this context and which implement the IExchExtCommands : IUnknown interface. Extensions can then add menu items to an existing menu and enable or disable them using Windows API calls.


Extension Contexts

Before implementing interfaces within an extension object, it is important to know the extension's associated context or contexts. A context corresponds to a user interface, particular window, or a related set of windows, within the Microsoft Exchange client. For example, the search viewer is one context and the main viewer is another. Two exceptions, the first two described in the following chart, are the contexts that last the duration of a task or the duration of a session. Most extension objects are designed to operate only within a particular context or set of contexts, but some can operate in all contexts.

The following contexts are defined within the Microsoft Exchange client:

EECONTEXT_TASK
The duration of the Microsoft Exchange task, from program start to program exit. This may span several logons. This context does not correspond to a Microsoft Exchange window. In this context, an extension can abort Exchange startup by returning an error.
EECONTEXT_SESSION
The duration of a Microsoft Exchange session from logon to logoff. Multiple logons can occur during a single execution of Microsoft Exchange, but they might not overlap. This context does not correspond to a Microsoft Exchange window.
EECONTEXT_VIEWER
The main Viewer window that displays the folder hierarchy in the left pane and folder contents in the right pane.
EECONTEXT_REMOTEVIEWER
The Remote Mail window that is displayed when the user chooses the Remote Mail command.
EECONTEXT_SEARCHVIEWER
The Find window that is displayed when the user chooses the Find command.
EECONTEXT_ADDRBOOK
The Address Book window that is displayed when the user chooses the Address Book command. This context only applies to a modeless address book.
EECONTEXT_SENDNOTEMESSAGE
The standard Compose, New Message window in which messages of class IPM.Note are composed.
EECONTEXT_READNOTEMESSAGE
The standard read note window in which messages of class IPM.Note are read after they are received.
EECONTEXT_READREPORTMESSAGE
The read report message window in which report messages (Read, Delivery, Non-Read, Non-Delivery) are read after they are received.
EECONTEXT_SENDRESENDMESSAGE
The send resend message window that is displayed when the user chooses the Send Again command on the non-delivery report.
EECONTEXT_SENDPOSTMESSAGE
The standard posting window in which existing posting messages are composed.
EECONTEXT_READPOSTMESSAGE
The standard posting window in which existing posting messages are read.
EECONTEXT_PROPERTYSHEETS
A property sheet window.
EECONTEXT_ADVANCEDCRITERIA
The dialog box in which the user specifies advanced search criteria.

Extensions register their "interest" in one or more of these contexts by placing entries in the EXCHNG.INI file on 16-bit versions of Microsoft Windows or in the registry on 32-bit Windows NT or Windows 95. When an extension registers for a context, it means that events associated with this context will cause the extension to be notified of the event. For example, if an extension registers for the EECONTEXT_VIEWER context, and the user selects an object, such as a folder or message, in the Viewer window, the extension will be called by Microsoft Exchange to notify it of the event.

If an extension does not register in specific contexts, it will be loaded and prompted to install itself in all contexts. Since loading extensions may reduce the performance of the Microsoft Exchange client, it is strongly recommended that all extensions specifically include context information as part of their registration.

Note If the standard Compose Message or Compose New Post has been replaced by a custom form, extensions that are normally called from the standard Compose Message and Compose New Post will not be called unless the replacement IPM.Note form supports extensibility. This means that the form must do all the same work that the Microsoft Exchange client does when activating a form. Extensions are never called for message types other than the standard note, unless the form author has specifically put in calls to extensions.


Context Lifetimes

Some contexts last only a short time; others can exist for the entire time that Microsoft Exchange is running. The EECONTEXT_TASK context, for example, exists continuously after Microsoft Exchange has logged on because this context refers to the running Microsoft Exchange client application. In contrast, the EECONTEXT_SEARCHVIEWER context exists only during display of the Find dialog box.

An extension is loaded into memory the first time a context for which it is registered is created. Once an extension is loaded into memory, it remains in memory for the duration of the Microsoft Exchange session. For example, consider three extensions E1, E2, and E3. If E1 and E2 are both registered for EECONTEXT_SESSION and E3 is registered for EECONTEXT_ADDRBOOK, then E1 and E2 will be loaded when Microsoft Exchange logs on, but E3 will not be loaded until the Address Book is opened. After the Address Book is opened, all three extensions will remain loaded until Microsoft Exchange is closed.

More than one context can exist at the same time. For example, EECONTEXT_VIEWER and EECONTEXT_ADDRBOOK exist simultaneously when the Viewer and the Address Book are active. Additionally, more than one instance of the same context can be active at one time, such as when two Find windows are open or two Compose Note windows are open. In these cases, two instances of the same context are active. When a context is destroyed, all extensions that are instantiated in that context are released but the extension DLLs remain in memory.


Context Interface Mappings

The following table shows which of the event interfaces can be called in each of the Microsoft Exchange contexts.

Context Interfaces
EECONTEXT_TASK IExchExt::Install
IUnknown::Release
EECONTEXT_SESSION IExchExt
IExchExtSessionEvents
EECONTEXT_VIEWER EECONTEXT_REMOTEVIEWER EECONTEXT_SEARCHVIEWER IExchExt
IExchExtCommands
IExchExtUserEvents
IExchExtPropertySheets
EECONTEXT_ADDRBOOK IExchExt
IExchExtCommands
IExchExtUserEvents
IExchExtPropertySheets
EECONTEXT_SENDNOTEMESSAGE EECONTEXT_READNOTEMESSAGE EECONTEXT_READREPORTMESSAGE EECONTEXT_SENDRESENDMESSAGE EECONTEXT_READPOSTMESSAGE EECONTEXT_SENDPOSTMESSAGE IExchExt
IExchExtCommands
IExchExtUserEvents
IExchExtMessageEvents
IExchExtAttachedFileEvents
IExchExtPropertySheets
EECONTEXT_PROPERTYSHEETS IExchExt
IExchExtPropertySheets
EECONTEXT_ADVANCEDCRITERIA IExchExt
IExchExtAdvancedCriteria


Extension Interfaces

To implement any of the extension types supported by Microsoft Exchange, you create a single dynamic link library (DLL) that contains one or more extension object. An extension object complies with the Microsoft Windows Component Object Model and implements a set of Microsoft Exchange extensibility interfaces. Each extension type has more than one interface associated with it, but some of these interfaces are optional.

If you implement an interface, you must implement all of its methods, even if your extension does not use them. For those methods that your extension doesn't use, a default response can usually be implemented with little effort. All extension objects must implement the IExchExt : IUnknown interface.

The interaction between Microsoft Exchange and an extension object is bidirectional and involves more than simply calling an extension object's methods. To operate correctly, extension objects must gather information about the version of Microsoft Exchange, the MAPI session, and menu, toolbar and window handles. In most cases, they must also retrieve information from Microsoft Exchange about which objects, such as messages and folders, are currently selected within Microsoft Exchange windows. Retrieving this information is achieved with the IExchExtCallback : IUnknown interface, which is passed to many extension object methods.

The following are the four types of extensions and the corresponding interfaces:

Extension type Interfaces to implement
Command extensions IExchExt (required).

IExchExtCommands (required).

IExchExtUserEvents (optional). Implement if you want to handle changes to the currently-selected list box item, text, or object.
Event extensions IExchExt (required).

IExchExtSessionEvents (optional). Implement if you want to customize the behavior when new messages are delivered.

IExchExtUserEvents (optional). Implement if you want to handle changes to the currently-selected list box item, text, or object.

IExchExtMessageEvents (optional). Implement if you want to customize the way Microsoft Exchange manipulates messages.

IExchExtAttachedFileEvents (optional). Implement if you want to customize the handling of message file attachments.
Property sheet extensions IExchExt (required).

IExchExtPropertySheets (required).
Advanced criteria extensions IExchExt (required).

IExchExtAdvancedCriteria (required).


Registering Extensions

Before an extension can be used within the Microsoft Exchange client, it must be registered. Registering an extension lets Microsoft Exchange know about its existence and provides other information about the extension so that Microsoft Exchange can work with it in an efficient manner.

On 16-bit versions of Windows, extensions are registered by adding entries to the [Extensions] section of the EXCHNG.INI file. These 16-bit clients include Windows 3.1 and Windows for Workgroups 3.x. Information on shared extensions is read from the [Extensions] section of the SHARED.INI file on 16-bit versions of Windows.

On 32-bit versions of Windows, Microsoft Exchange obtains extension-specific information from HKEY_LOCAL_MACHINE\Software\Microsoft\Exchange\Client\Extensions in the Windows NT or Windows 95 registry.

Information on shared extensions is read from the SHARED32.INI file on these 32-bit versions of Windows. The location of the SHARED.INI file is specified by the SharedExtsDir entry in the [Exchange] section of the EXCHNG.INI file. The location of the SHARED32.INI file is specified in the SharedExtsDir entry in HKEY_LOCAL_MACHINE\Software\Microsoft\Exchange\Client\Extensions.

If the directory is on a network drive, the SharedExtsServer entry can contain the name of the server and the SharedExtsPassword entry contains an unencrypted password. If this is the case, a connection to the server is made without redirecting a local device name.

The 32-bit clients cannot use 16-bit extensions, nor can 16-bit clients use 32-bit extensions.

When registering an extension, a specific syntax places your entry in the .INI file or registry. This syntax is as follows:

Tag=Version;<ExtsDir>DllName;[Ordinal];[ContextMap];[InterfaceMap];[Provider]

The following table shows the parameters used in the syntax line.

Parameter | Description
Tag | An extension identifier that uniquely identifies the .INI entry from other .INI entries.
Version | The version number of the Microsoft Exchange client; for example '4.0'.
DLLName | The path to the DLL containing the extension.
Ordinal | An optional field that specifies the entry point in the DLL to retrieve the extension object. If this field is empty, the default value is 1.
ContextMap | An optional string made up of '0' and '1' characters which indicates the contexts in which the extension should be loaded. Any unspecified values after the end of the string are assumed to be zero. If no context map is provided, the extension will be loaded in all contexts. For more information on context map bit positions, see the table later in this section.
InterfaceMap | An optional string made up of '0' and '1' characters that indicates the interfaces the extension supports. Although supported interfaces can be obtained through IUnknown::QueryInterface, registering which interfaces your extension supports can increase system performance. For more information on interface map bit positions, see the table later in this section.
Message Service | An optional string containing the PR_SERVICE_NAME, not the display name, of a message service that your extension is designed to work with. For example, if your extension is designed to work with a custom address book, place the PR_SERVICE_NAME of the address book in this parameter. If your extension is not provider-specific, this parameter should be omitted.

An example of this syntax is:

MyExtension=4.0;<ExtsDir>MYEXT.DLL;2;010001;1100000

In this example, EECONTEXT_VIEWER=0x00000002 and EECONTEXT_SENDNOTEMESSAGE =0x00000006 so the ContextMap string '010001' indicates that the extension located at MYEXT.DLL;2 should be loaded only for these two contexts. The interface map, specified by the string 1100000, indicates that the extension implements only the IExchExtCommands : IUnknown and IExchExtUserEvents : IUnknown interfaces.

Throughout the string, all occurrences of the string '<ExtsDir>' are replaced with the value of the SharedExtsDir entry described below. Extensions that are not shared should not use this.

The following tables indicate which positions in the Context Map and Interface Map correspond to which contexts and interfaces, respectively.

Context Map Bit Positions

Position | Context
1 | EECONTEXT_SESSION
2 | EECONTEXT_VIEWER
3 | EECONTEXT_REMOTEVIEWER
4 | EECONTEXT_SEARCHVIEWER
5 | EECONTEXT_ADDRBOOK
6 | EECONTEXT_SENDNOTEMESSAGE
7 | EECONTEXT_READNOTEMESSAGE
8 | EECONTEXT_SENDPOSTMESSAGE
9 | EECONTEXT_READPOSTMESSAGE
10 | EECONTEXT_READREPORTMESSAGE
11 | EECONTEXT_SENDRESENDMESSAGE
12 | EECONTEXT_PROPERTYSHEETS
13 | EECONTEXT_ADVANCEDCRITERIA
14 | EECONTEXT_TASK

Interface Map Bit Positions

Position | Interface
1 | IExchExtCommands
2 | IExchExtUserEvents
3 | IExchExtSessionEvents
4 | IExchExtMessageEvents
5 | IExchExtAttachedFileEvents
6 | IExchExtPropertySheets
7 | IExchExtAdvancedCriteria


Extension Ordering

Microsoft Exchange calls extensions in the order in which they are listed in the .INI file or registry. This can often affect the execution of the extension. For example, given two extensions that are registered within the same context, the first extension that is registered to participate in the context might handle an event or a command and not give the other extension a chance to respond. It is therefore important to plan how your extension will be entered into the registry or .INI file.

On Windows NT, extensions are ordered alphabetically within the registry. On Windows 95, the ordering of extensions is the order in which they are inserted.

To register your extension so that it appears in the correct position whether it is installed on Windows NT or Windows 95
  1. Identify the existing extension that you want your extension to be placed before and give your extension a name that alphabetically comes before that extension.
  2. Read the registry entry for the existing extension you want your extension to be placed before, store it, and delete the entry for that extension.
  3. Write the entry for your extension in place of the deleted extension entry.
  4. Re-insert the entry for the extension that was deleted in Step 2.

Although it is always possible to insert your extension at the top of the list to guarantee that it is called, this might cause contention between extensions.


Message Service Parameter

In some cases, your extension might be designed to work only with a particular provider and this information should be included in the registration entry. For example, your extension might only work with a custom address book provider that replaces or supplements the default address book provider of Microsoft Exchange. Under these circumstances, your extension should be prevented from loading if its associated provider is not loaded.

This situation is handled by specifying the name of the extension's associated provider in the [Provider] parameter of your extension's registration line. If you specify the provider, your extension will not be loaded unless the provider has been loaded. This can save some programming effort because it might be difficult for your extension to determine whether a specific provider has been loaded. Frequently, but not as a requirement, these extensions are in the same DLL as the message service.

When Microsoft Exchange starts, it reads the current profile and attempts to start all providers listed there. After attempting to load all providers specified in the profile, it reads the extension registration lines of its .INI file or registry and omits all extensions that specify a provider that was not in the profile or failed to load.


Using Client Extensions

There are many possible extensions that you can program to work with Microsoft Exchange. These extensions generally fall into four categories:

Extension type | Description
Command extensions | Add new commands to the client's menus and toolbar, or replace the behavior of existing commands and toolbar buttons. For example, you can add commands that are specific to certain folders or selected message types. See Command Extensions.
Event extensions | Invoke custom behavior to handle events such as the arrival of new messages, reading and writing messages, sending messages, reading and writing attached files and selection changes in a window. See Event Extensions.
Property sheet extensions | Add custom property sheet pages to an object's properties dialog box, enabling users or administrators to view or edit custom message properties. See Property Sheet Extensions.
Advanced criteria extensions | Implement your own custom advanced criteria dialog boxes to be used when searching for messages in the information store. This is useful when you want to enable users to search for custom message properties. See Advanced Criteria Extensions.


Command Extensions

You can add new commands to the client's menus or toolbar, or completely replace the behavior of existing commands and toolbar buttons. Adding commands allows you to customize in several ways. For example:

  • Integrated proofing tools

    Custom spelling and grammar tools can be added to the Microsoft Exchange menu. If a user has composed a message, choosing a custom Spelling or Grammar command could invoke an ISV-supplied spell-checker or grammar-checker. It is also possible to add a thesaurus, text formatting tools, and other functionality provided by many word processors.

  • Public folder commands

    When a specific public folder has the focus, menu items or toolbar buttons can be enabled that are specific to that folder. For example, if the public folder is associated with an on-line service, you might want to include a Retrieve Latest command that prompts the on-line service to download the most current information into the selected topic area of the public folder.

  • Message class commands

    When messages of a specific class are selected, new application behavior can be added to handle messages of that class in a specific way. For example, you might want to replace the default behavior of the Microsoft Exchange Delete command when a message of a specific class is selected. The new behavior might simply move the message into a certain folder where it is processed at a later time.


Implementing Command Extensions

To implement a command extension
  1. Create a DLL that contains one or more extension objects.
  2. Implement the following interfaces as noted:
    • IExchExt is required.
    • IExchExtCommands is required.
    • IExchExtUserEvents if you want to handle changes to the currently-selected list box item, text, or object.
  3. Register for the EECONTEXT_SENDNOTEMESSAGE context by placing an entry in the EXCHNG.INI file on 16-bit versions of Microsoft Windows or in the registry on Windows NT or Windows 95.

The sequence of events that should occur when Microsoft Exchange interacts with your extension object, to add new commands to the menu bar or new toolbar buttons in the EECONTEXT_SENDNOTEMESSAGE context, is as follows:

  1. When the standard send form is activated, but not yet displayed, the Microsoft Exchange client calls the IExchExt::Install method on all extensions registered to participate in that context and passes each extension a pointer to an IExchExtCallback interface along with the active context, which in this case is EECONTEXT_SENDNOTEMESSAGE.
  2. All extensions that are registered to participate in the EECONTEXT_SENDNOTEMESSAGE context and have determined they will participate return S_OK to Microsoft Exchange.
  3. After the New Message window is created, Microsoft Exchange invokes the IExchExtCommands::InstallCommands method on all extension objects that returned S_OK to IExchExt::Install. These extension objects then add their menu commands or toolbar buttons to the New Message window using Windows API calls for adding menu commands and toolbar buttons. After the commands and buttons are added, Microsoft Exchange displays the New Message window, and the new commands are available to the user.
  4. As the user interacts with the New Message window, Microsoft Exchange will frequently receive WM_INITMENU messages. Each time this happens, Microsoft Exchange calls the IExchExtCommands::InitMenu method for each extension to give that extension an opportunity to enable, disable, or update its menu items before they are seen by the user. Microsoft Exchange then calls the IExchExtCommands::QueryButtonInfo method for both standard Microsoft Exchange toolbar buttons and any buttons installed by extensions.
  5. When the user chooses a menu command or a toolbar button, the window receives a WM_COMMAND message with the command identifier of the menu item or toolbar button that was selected. Microsoft Exchange sequentially calls the IExchExtCommands::DoCommand method on all extensions that have registered for that context and have implemented the IExchExtCommands : IUnknown interface, passing the command identifier as an argument. Even native Microsoft Exchange commands are passed to the extensions, enabling them to replace or enhance these native commands. When an extension is called, it examines the command identifier and determines if it should handle that command. If an extension isn't programmed to handle the command identifier, it should return S_FALSE, and Microsoft Exchange will pass the command identifier to the next extension. If an extension is programmed to handle the command, it should return S_OK. In most cases, extensions will only handle commands that they added to the menu or toolbar with the IExchExtCommands::InstallCommands method. If no extension handles the command, Microsoft Exchange will handle the command if it recognizes it. If Microsoft Exchange does not recognize a command, it is ignored.

The following table provides a summary of the interaction between a user, Microsoft Exchange and an extension object following a series of user actions performed by a user with a custom command. It also shows which component — Microsoft Exchange or the client extension — performs the step and in the case of the client extension, what method is invoked.

You can install commands on the Microsoft Exchange system menu using the same general process as described in the section "Command Extensions," but instead of using the Windows GetMenu function, you'll use GetSystemMenu. Once a custom command is installed, Microsoft Exchange passes the command identifier of the system menu command to the extension when the user chooses that command. Handling system commands enables an extension to override default Microsoft Exchange behavior. For example, you might want your extension to override the system menu's Close command and perform a few cleanup operations before terminating the application.

It is also possible to specify menu accelerators — by placing an ampersand in the command string — that can be used with menu items. These menu accelerators can be invoked by users in the usual way by pressing Alt plus the access key of the menu or command.

Note In accordance with standard user interface conventions, the Services and Options commands on the Microsoft Exchange Tools menu should remain at the bottom of the menu. If your extension adds commands to the Tools menu, it should add them above the Microsoft Exchange Services and Options commands.


Event Extensions

Event extensions enable developers to add to or override behavior such as the arrival of new messages, reading and writing messages, sending messages, reading and writing attached files and tracking selection changes in a window. For example:

  • Attachment virus detection

    You can write an extension that transparently scans message attachments for viruses. When a message is received in a user's Inbox, the "message received" event would trigger the virus detection program and the user could be prompted to take action if a virus was found. This is especially useful in environments where users routinely attach executable programs to messages.

  • Message and attachment compression

    You can write an extension that compresses and decompresses messages when certain messaging events are detected. This can be especially useful in an environment where large messages, such as attached documents containing bitmaps, are routinely sent.


Implementing Event Extensions

To implement an event extension
  1. Create a DLL that contains one or more extension objects.
  2. Implement the following interfaces as noted:
    • IExchExt is required.
    • IExchExtSessionEvents if you want to customize the behavior when new messages are delivered.
    • IExchExtUserEvents if you want to handle changes to the currently-selected list box item, text, or object.
    • IExchExtMessageEvents if you want to customize the way Microsoft Exchange manipulates messages.
    • IExchExtAttachedFileEvents if you want to customize the handling of message file attachments.
  3. Register for the appropriate context by placing an entry in the EXCHNG.INI file on 16-bit versions of Microsoft Windows or in the registry on Windows NT.

Extensions that handle events can be installed in the following contexts:

Window | Context
Main Viewer window | EECONTEXT_VIEWER
Remote Mail window | EECONTEXT_REMOTEVIEWER
Find window | EECONTEXT_SEARCHVIEWER
Address Book window | EECONTEXT_ADDRBOOK
Session context | EECONTEXT_SESSION

Additionally, user events, such as an object selection in a container, occur in the various message windows.

These events, divided into four categories and described in the following sections, are passed to the Microsoft Exchange client when they occur.


User Events

When a Microsoft Exchange user changes the selection within a window or changes which object's contents are being displayed in a window, a user event is sent to Microsoft Exchange extensions. Within the main Viewer window, the selection can be a message store, a folder, or a message. Within the Find window or the Remote Mail window, the selection is always a message. Within the Address Book, it is an address entry.

Extensions that should be notified whenever a selection or object changes must implement the IExchExtUserEvents : IUnknown interface. This interface includes two methods: IExchExtUserEvents::OnSelectionChange and IExchExtUserEvents::OnObjectChange. Whenever a selection or object changes, Microsoft Exchange calls these methods on all extensions that were installed for that context.

The two IExchExtUserEvents methods only pass the extension a pointer to the IExchExtCallBack : IUnknown interface, which provides information about the current selection. Using this information, the extension can then act appropriately. For example, it can enable or disable a toolbar button.


Message Events

The Microsoft Exchange client enables extensions to control various details of how a message is handled when certain events occur. This is done with the IExchExtMessageEvents : IUnknown interface, which allows extensions to intercept message events:

  • Immediately before OnRead and immediately after OnRead Complete, a message's properties are read from the message store. For example, when an extension displays a message in a form.
  • Immediately before OnWrite and immediately after OnWriteComplete a message's properties are written to the message store.
  • Immediately before and immediately after Microsoft Exchange resolves unresolved addresses. For example, when a user chooses the Check Names button.
  • Immediately before and immediately after Microsoft Exchange submits an open message for delivery.

For example, an extension might want to check spelling or validate data before it is written to the properties of the message in the store and sent to another user.

Each one of the events in the preceeding list is associated with a method that is a member of IExchExtMessageEvents. For example, the IExchExtMessageEvents::OnWrite method is invoked whenever Microsoft Exchange is about to save the message properties.


Session Events

When a new message arrives in a user's Inbox, a session event is sent to Microsoft Exchange. Extensions can be notified when a new message arrives by installing themselves in the EECONTEXT_SESSION context and by implementing the IExchExtSessionEvents : IUnknown interface, which supports only one method: IExchExtSessionEvents::OnDelivery. Whenever a session event occurs, Microsoft Exchange calls this method on all extensions that are registered to handle these events.

OnDelivery passes a pointer to the IExchExtCallBack : IUnknown interface to the extension, which uses the pointer to obtain details about the current context. The extension returns S_OK from OnDelivery if it will handle the event. For example, an extension might use the IExchExtCallBack pointer to determine the class of the newly arrived message. If the message class is of a specific type, the extension might want to perform a custom operation on that message, such as extracting its properties and storing them in a database.

Note IExchExtSessionEvents::OnDelivery is called after the Microsoft Exchange Server has processed the rules attached to the folder. Therefore, OnDelivery will not be called if it was previously handled; for example, if a rule deleted the message. Because this is a server process, rules processing is performed prior to all extensions.


Attachment Events

Attachment events occur when an attached file is being read, written, or opened. These events enable extensions to control access to attachments and provide custom handling behavior. Attachment extensions are useful for providing virus detection and compression of attached files. These extensions are called from the context of the message containing the attachment.

Note Not all attachments are files. Attachment events apply only to attached files. Because attachments can themselves be other messages — that is, messages can contain messages — another context corresponding to the attached message might be created when an attached message is opened.

Sending a Note with an Attachment

The following table shows the steps involved in sending a standard message with an attachment. It also shows which component — Microsoft Exchange client or the extension — performs the step and in the case of the client extension, what method is invoked.

Reading a Note and Opening its Attachment

The following table shows the steps involved in reading a message and opening its attachment. It also shows which component — the Microsoft Exchange client or the extension — performs the step, and in the case of the extension, shows what method is invoked.


Property Sheet Extensions

Property sheet extensions are useful for displaying custom properties for messages of a particular message class or for adding your own Microsoft Exchange options. For example:

  • Custom form property sheets

    If your application provides a custom form with custom properties, you can display those properties in one or more property sheet pages. For example, the property sheet of a custom routing form might display the name of the person who initiated the routing process or the routing path of the form.

  • Custom document property sheets

    Your application can supply a custom property sheet that is displayed for certain types of documents. For example, if your extension provides a document archiving system, you might want to provide a property sheet that enables users to select archiving options for documents.


Implementing Property Sheet Extensions

To implement a property sheet extension
  1. Create a single DLL that contains one or more extension objects.
  2. Implement the following interfaces:
    • IExchExt
    • IExchExtPropertySheets
  3. Register for the appropriate context by placing an entry in the EXCHNG.INI file on 16-bit versions of Microsoft Windows or in the registry on Windows NT or Windows 95.

Property sheet extensions enable you to add custom property sheet pages for information stores, folders, and messages. These pages can be added to property sheets that are displayed in a variety of contexts. For example, you can add a page to the folder property sheet that is displayed when a user chooses the Properties command from the File menu in the main Viewer window when a folder is selected.

Property sheet extensions are useful for displaying custom properties for messages of a particular message class or for adding your own Microsoft Exchange options. For example, if you wrote an application that created and managed a specific public folder, you could add a property sheet page that would enable users to set various application-specific properties for the folder.

The sequence of events that should occur when Microsoft Exchange interacts with your extension object to install and use custom property sheet pages is as follows:

  1. When the user chooses Properties from the File menu to view the property sheet, Microsoft Exchange sequentially calls the IExchExt::Install method on all extensions registered to participate in the EECONTEXT_PROPERTYSHEETS context and passes each extension a pointer to an IExchExtCallback interface. These extensions, along with extensions that have registered for the context in which the property sheet is displayed, will be called to add property sheet pages. For example, if a property sheet is displayed in the Viewer window, extensions registered for the EECONTEXT_PROPERTYSHEETS or EECONTEXT_VIEWER context will be called.
  2. Microsoft Exchange calls the IExchExtPropertySheets::GetMaxPageCount method on each extension that returned S_OK from Install. This enables Microsoft Exchange to allocate sufficient memory for the property sheet page array.
  3. When Microsoft Exchange is ready to build the property sheet, it calls the IExchExtPropertySheets::GetPages method so that the extension can specify a pointer to the pages it will append. GetPages is called immediately before the property sheet is displayed and enables the extension to fill in the pages it wants appended to the Microsoft Exchange Properties dialog box. The standard Microsoft Exchange pages are added first, followed by pages from each extension in the order the extensions are installed. GetPages uses the IExchExtCallback::GetObject method to retrieve the object for which the information should be displayed and the store which contains that object. The extension must use the standard property sheet structures specified by the Windows API. One of the parameters passed to the extension in GetPages is the type of property sheet being displayed — for example, message, folder, or store property sheet.
  4. When the user closes the property sheet, Microsoft Exchange calls the IExchExtPropertySheets::FreePages method which instructs the extension to free any resources associated with the property sheet pages that were specified in GetPages.

The following table summarizes the interaction between a user, Microsoft Exchange and an extension object when a custom property sheet is being added to the Microsoft Exchange client. It also shows which component — the Microsoft Exchange client or the extension — performs the step and in the case of the extension, what method is invoked. To simplify this table, the installation of command extensions is not included. Command extensions are called in the context of a user choosing the Properties command from the File menu.


Advanced Criteria Extensions

Advanced criteria extensions enable you to create your own advanced criteria dialog box that can be used to provide custom search capabilities, allowing users to search for custom message properties. For example:

  • Custom property searching

    You can display a custom advanced criteria dialog box that enables users to specify search criteria for custom properties. For example, in a public folder that receives custom messages from an on-line service, there might be custom properties such as "Company" or "Industry" that are defined for each of the messages. With a custom search dialog box, you can supply criteria fields for these custom properties that enable users to perform custom searches. For instance, a user could search for all messages with an Industry property equal to "Biomedical."


Implementing Advanced Criteria Extensions

To implement advanced criteria extensions
  1. Create a single DLL that contains one or more extension objects.
  2. Implement the following interfaces:
    • IExchExt
    • IExchExtAdvancedCriteria
  3. Register for the EECONTEXT_ADVANCED_CRITERIA context by placing an entry in the EXCHNG.INI file or 16-bit versions of Microsoft Windows or in the registry on Windows NT or Windows 95.

Advanced criteria extensions enable you to create your own advanced criteria window that can be used when searching for messages. This is especially useful when you want to enable users to search for custom message properties.

Although several extensions that supply advanced criteria dialog boxes might be available, only one advanced criteria window at a time can be displayed from a single context. Multiple advanced criteria contexts can be active at the same time; for example, when more than one Find window is open. Extensions are called in the order in which they were installed.

Because more than one advanced criteria extension might be installed, it is important to ensure that your advanced criteria is as selective as possible before choosing to install extensions into an advanced criteria context. For instance, a public folder application should only choose to install its advanced criteria interface when its public folder is open or highlighted.

Advanced criteria extensions that are more selective should be listed ahead of more general ones in the EXCHNG.INI file or the registry. Because Microsoft Exchange itself uses very general advanced criteria, most extensions should register themselves before Microsoft Exchange. If two or more such general advanced criteria extensions are present, the first one installed will always be used. The ordering of extensions is determined by their entry order in the EXCHNG.INI file or in the registry. For more information on creating extension entries, see Registering Extensions.

The sequence of events that should occur when Microsoft Exchange interacts with your extension object to add a custom advanced criteria dialog box to the Microsoft Exchange client is as follows:

  1. When the user chooses the Find command from the Tools menu, Microsoft Exchange calls the IExchExt::Install method on all extension objects with the EECONTEXT_ADVANCEDCRITERIA bit set in the context map. During the call, it passes each extension a pointer to an IExchExtCallback interface along with the context, which in this case is EECONTEXT_ADVANCEDCRITERIA. The IExchExtCallBack pointer enables the extension to retrieve information about the current context. In this case, the current message store and folder will probably be useful. If it is the right context for you, return S_OK; otherwise, S_FALSE.
  2. Microsoft Exchange calls the IExchExtAdvancedCriteria::InstallAdvancedCriteria method on the first extension to return S_OK from Install. Microsoft Exchange uses InstallAdvancedCriteria to pass information to the extension, including the window handle of the Find dialog box, the current advanced criteria restriction, and an array of folder entry identifiers to which the criteria will be applied. If the extension returns S_OK from InstallAdvancedCriteria, Microsoft Exchange will call the IExchExtAdvancedCriteria::DoDialog method when the user selects the Advanced button in the Find dialog box.

    If S_FALSE is returned from InstallAdvancedCriteria, remaining extensions will be given the opportunity to examine the current search restriction and display a custom search dialog box. If no extension returns S_OK, Microsoft Exchange will display the standard default advanced criteria dialog box.

  3. If the user chooses the New Search button, changes folders, or closes the Find dialog box after Microsoft Exchange calls InstallAdvancedCriteria, Microsoft Exchange calls the IExchExtAdvancedCriteria::Clear, IExchExtAdvancedCriteria::SetFolders, or IExchExtAdvancedCriteria::QueryRestriction methods respectively to inform the extension of the changes.
  4. When the user closes the advanced criteria window, Microsoft Exchange calls the IExchExtAdvancedCriteria::UninstallAdvancedCriteria method, which allows the extension to free any resources associated with the advanced criteria window that it displayed.

The following table summarizes the interaction between a user, Microsoft Exchange and an extension object when using a custom advanced criteria dialog box. It also shows which component — Microsoft Exchange or the client extension — performs the step and in the case of the client extension, what method is invoked.


Task and Session Extensions

In some cases, an extension runs when the user starts Microsoft Exchange or right after the user logs on. For example, an extension that connects to a corporate database may be set up to establish a connection to the database as part of the logon process.


Implementing Task and Session Extensions

As shown in the following table, the client extension implements the TASK, SESSION, and VIEWER contexts with only the IExchExt : IUnknown interface using the IExchExt:Install method (and the IUnknown::Release method).

The following table summarizes the interaction between a user, Microsoft Exchange and an extension object when a user launches Microsoft Exchange or logs on to a MAPI session. It also shows which component — Microsoft Exchange or the client extension — performs the step and in the case of the client extension, what method is invoked.


Modal and Modeless Extension Windows

You can create extensions that use either modal or modeless windows. When a modal window is displayed, users can only interact with the extension and not with Microsoft Exchange. For example, an extension might display a modal Folder Backup dialog box that enables a user to choose a specific folder to back up.

In contrast, some extensions can run modelessly, displaying windows that allow the user to switch their input back and forth between Microsoft Exchange windows and the extension's windows. For example, a Stock Quote extension could display a modeless window that displays dynamically changing stock data while the user interacts with Microsoft Exchange windows.

For simplicity, an extension that displays only modal windows is referred to as a modal extension while an extension that displays at least one modeless window is referred to as a modeless extension.

Some extensions can involve a combination of modeless and modal windows; that is, modeless extensions might display modal windows at certain times. For example, the Stock Quote extension mentioned previously might display a modal Options dialog box.

When writing modeless extensions, it is important to coordinate the actions of your extension's windows with the windows of Microsoft Exchange. For example, if Microsoft Exchange displays a modal window, modeless extensions should disable their windows. Interfaces that enable this cooperation are implemented by Microsoft Exchange and extensions.


Writing Modeless Extensions

When writing extensions that use modeless windows, it is a good idea to design your code to cooperate with Microsoft Exchange. The most common scenario for this cooperation is enabling or disabling modeless windows when the user switches between Microsoft Exchange windows and the windows of your extension.

Coordination between Microsoft Exchange and modeless extensions is achieved using two interfaces: IExchExtModeless : IUnknown and IExchExtModelessCallback : IUnknown. Microsoft Exchange implements IExchExtModelessCallback and client extensions implement IExchExtModeless.


Initializing a Modeless Extension

A modeless extension must first indicate to Microsoft Exchange that it will be modeless. This is done by calling the IExchExtCallback::RegisterModeless method. If an extension does not call this method, Microsoft Exchange, by default, detects a modal extension window. This results in the inability of the extension to coordinate its actions with those of Microsoft Exchange.

When calling RegisterModeless, the extension must pass to Microsoft Exchange a modeless object that implements the IExchExtModeless interface. This interface enables Microsoft Exchange to communicate with the extension object about the state of its windows.


How Modeless Coordination Works

When Microsoft Exchange runs, it creates a modeless callback object with which extensions can communicate. This callback object implements the IExchExtModelessCallback : IUnknown interface.

Before displaying a modal window, Microsoft Exchange invokes the IExchExtModeless::EnableModeless method on all modeless objects. In this case, the fEnable parameter of EnableModeless is set to FALSE, indicating that the extension should disable its modeless windows. When Microsoft Exchange removes its modal window, it calls EnableModeless with the fEnable parameter set to TRUE. The extension can then re-enable its modeless windows.

Similary, if a modeless extension displays a modal window, it should call the IExchExtModelessCallback::EnableModeless method with the fEnable parameter set to FALSE. Microsoft Exchange then disables its modeless windows. When the extension removes its modal window, it should call IExchExtModeless::EnableModeless with the fEnable parameter set to TRUE, enabling Microsoft Exchange to re-enable its modeless windows.


Additional Programming Considerations

When creating extensions for the Microsoft Exchange client, there are a number of programming considerations you will want to keep in mind beyond the basic technique of implementing extension interfaces. These considerations generally fall into the following categories:

  • Optimizing Performance
  • Handling Error Values
  • Cooperating with Other Extensions
  • Programming Tips and Suggestions


Optimizing Performance

Because the Microsoft Exchange client polls installed extensions every time a context change occurs, Microsoft Exchange can exhibit decreased performance or response time if several extensions are installed. In particular, performance can be affected when displaying menus, sending and receiving messages, or selecting different messages and folders. This performance degradation can be caused by extensions that respond to events that are not applicable to the functionality they provide. It can also be caused by extensions that take a long time to respond when Microsoft Exchange invokes their methods.

When developing an extension, you can reduce the impact on the performance of Microsoft Exchange by keeping the following programming guidelines in mind:

  • Register your extension only for contexts that are applicable to it. This can be done by placing the appropriate values in the context map in the EXCHNG.INI file or the registry. The context map designates contexts in which an extension will participate. Although specifying a context map is optional, it is highly recommended. If you don't specify a context map, an attempt will be made to install your extension in all contexts and it will be loaded at all times. For more information about context maps, see Registering Extensions.
  • Register your extension only for interfaces that are applicable to it. This can be done by placing the appropriate values in the interface map in the EXCHNG.INI file or the registry. Although specifying an interface map is optional, it is highly recommended. The interface map prevents Microsoft Exchange from making calls to IUnknown::QueryInterface for interfaces that are not supported. This can improve the performance of context creation and application startup.
  • Optimize functions that handle various events received by your extension. For example, event-handling functions should minimize the use of any time-consuming calculations, loops, lookups, and file input and output.


Handling Error Values

Extensions are responsible for handling and displaying their own errors. Microsoft Exchange handles error return values by not continuing with the current operation. Microsoft Exchange does not display error messages because the extension is usually better aware of what caused the error and what steps should be taken to correct it.


Cooperating with Other Extensions

Extensions that you distribute to customers might be installed alongside extensions developed by other programmers. Therefore, it is useful to design your extensions to cooperate with other extensions. Cooperation among extensions is important because the order in which extensions are listed in the EXCHNG.INI file or the registry determines the order in which extensions are called to respond to context changes in Microsoft Exchange. Extensions are called sequentially; extensions that are not designed to cooperate can block the execution of other extensions.

For example, suppose a user double clicks on a folder to display its messages. When this happens, Microsoft Exchange will call each extension to determine if it wants to participate in the event. If a extension handles the event without being selective about the context in which it has been installed, it will block the execution of other extensions that fall after it in the calling sequence. One of these other extensions might be programmed specifically to handle that event, but it will not be given a chance.

To avoid blocking other extensions, your extension should be highly selective in determining when it runs. When Microsoft Exchange passes your extension a pointer to the IExchExtCallback : IUnknown interface, your extension should use the methods of this interface to thoroughly examine the current context. An extension should run only if it determines that the current context is specific to it — for example, if the current selection is a custom message type understood only by your extension.

To avoid collisions, consider the following guidelines:

  • Avoid programming extensions that provide broad or general behavior for features such as the advanced criteria dialog box that can only have one active extension. Most extensions should operate only in contexts that can be considered extension-specific.
  • Extensions that are selective and highly context-specific should be registered at the beginning of the [Extensions] section of the .INI file. Those that exhibit more general behavior should be entered at the end of the [Extensions] section. For example, the standard Microsoft Exchange extension that handles the advanced criteria dialog box always returns S_OK to the IExchExtAdvancedCriteria::InstallAdvancedCriteria method. More selective advanced criteria dialog boxes must come before this entry or they will never be called.

Extensions can selectively install themselves in different contexts in the Exchange client, such as: EECONTEXT_TASK and EECONTEXT_VIEWER. By installing in a particular context, the extension needs to instantiate a new set of interface objects, such as IExchExtCommands, to handle the methods in that particular object. For example, if an extension is installed into EECONTEXT_VIEWER and EECONTEXT_SENDNOTEMESSAGE, it needs to remember which commands it has installed into which context so that it can respond to the IExchExtCommands::DoCommand method.


Programming Tips and Suggestions

When writing an extension, you can reduce the number of bugs and other problems by observing the following:

  • Pointers can become invalid shortly after they are used within the scope of a single function. Do not store pointers to callback functions for later use outside of the current function. The same advice applies for pointers returned from callback functions.
  • Creative use of the hMenu or hWnd pointers may cause problems in future versions of Microsoft Exchange. Avoid performing special "tricks" with these pointers.
  • Avoid adding menus to Microsoft Exchange outside the scope of the IExchExtCommands::InstallCommands method.
  • When adding menu commands for your provider extension, place these menu commands underneath the Find command on the Tools menu.
  • When adding your provider-specific Help command, place it underneath the Microsoft Exchange Help Topics command on the Help menu.


About Samples

The sample code for extending the Microsoft Exchange Client is included in the Code Samples section of the Platform SDK. More information about these samples can be found in the README.TXT files in this section.


Sample Command Extension

This sample adds a simple command to the messaging client's menu. This sample demonstrates adding a menu command, adding a toolbar button, disabling and enabling the menu item and toolbar item depending on what object is selected in the viewer, making MAPI calls from an extension, extending a command in the Main Viewer and the Search Viewer dialog boxes, F1 response for context help on the menu item, and implementing custom ToolTip and Status Bar text.

Quick Info

Executable: | CMDEXT.DLL
Directory for source code: | COMMAND.EXT
Written in: | C++
Supports: | Win32 platforms only

Remarks

The custom command displays the number of subfolders, read messages, and unread messages in a selected folder.

This sample implements the IExchExt : IUnknown, IExchExtCommands : IUnknown, and IExchExtUserEvents : IUnknown interfaces.


Sample Event Extension

This sample adds a new-mail event handler to the messaging client.

Quick Info

Executable: | EVEXT.DLL
Directory for source code: | EVENTS.EXT
Written in: | C++
Supports: | Win32 platforms only

Supported Features

  • Reading message text before being displayed in the read note form
  • Reading message text as it is submitted to MAPI
  • Reply to Sender context

Remarks

This sample uses a very basic form of signing a message. A checksum on the message as it is written is stored as a custom property. Upon reading the message, the extension verifies the checksum and displays one of two possible outcomes: the message has been verified with correct contents, or the message text has been altered.


Sample Property Sheet Extension

This sample adds to the messaging client's standard message property sheets, for messages belonging to the IPM.Document class. The new property sheet displays the document's summary properties which include information such as author, title and date. .

Quick Info

Executable: | PRSHEXT.DLL
Directory for source code: | PROPSH.EXT
Written in: | C++
Supports: | Win32 platforms only

Remarks

This sample implements the IExchExt : IUnknown and IExchExtPropertySheets : IUnknown interfaces.


Interfaces for Extending the Microsoft Exchange Client

The Microsoft Exchange client is an extensible program containing a number of interfaces that independent software vendors can use to extend or enhance its functionality. Two of those interfaces are implemented by Microsoft Exchange and called by extension objects. All the other interfaces for client extensibility are implemented by extension objects and are called by Microsoft Exchange. Both sets of interfaces are described in this chapter.

An extension object is an object that complies with the Microsoft Windows Component Object Model and implements a set of Microsoft Exchange interfaces. Some of the interfaces described in this chapter are optional, but if an extension object implements an interface, it must implement all the functions of that interface.

The IUnknown interface provides object management functions from the OLE 2 component object model. Since all extension objects inherit from this interface, all extension interfaces include the three IUnknown methods in addition to their own methods.

For more information on the IUnknown interface, see the OLE Programmer's Reference.


IExchExt : IUnknown

Microsoft Exchange uses the IExchExt interface to load extension objects in all contexts. Most extension objects are designed to operate only within a particular context or set of contexts, but some can operate in all contexts.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXT

Vtable Order

Install Enables an extension object to determine the context into which it is being loaded, along with information about that context.

Note Custom form developers are responsible for supporting extension objects in their custom forms. That is, replacement IPM.Note forms and other custom forms supplied by form developers might choose to load extension objects and call them the same way that Microsoft Exchange does with its native forms. In this documentation, all references to forms refer to the standard forms supplied by Microsoft Exchange, such as the standard IPM.Note.


IExchExt::Install

Enables an extension object to determine the context into which it is being loaded, along with information about that context. The MAPI and user interface information that can be retrieved by the extension includes session, store, viewer, note form, and address book information.

Quick Info

See IExchExt : IUnknown.

HRESULT Install(
  LPEXCHEXTCALLBACK lpeecb,
  ULONG eecontext,
  ULONG ulFlags
);

Parameters

lpeecb
[in] Pointer to an IExchExtCallback interface.
eecontext
[in] Indicates the currently active Microsoft Exchange context. This parameter can have the following values:
EECONTEXT_TASK
The context where the Microsoft Exchange client application has started but has not yet logged in. This context begins when the Microsoft Exchange application starts, and ends when the Microsoft Exchange application exits. This context does not correspond to a window. This is the first context in which extensions are loaded.
EECONTEXT_SESSION
The duration of a Microsoft Exchange session. This context and EECONTEXT_TASK are the only contexts that do not correspond to a specific window.
EECONTEXT_VIEWER
The main Viewer window that displays the folder hierarchy in the left pane and folder contents in the right pane.
EECONTEXT_REMOTEVIEWER
The remote Viewer window that is displayed when the user chooses the Remote Mail command from the Tools menu in the Microsoft Exchange client.
EECONTEXT_SEARCHVIEWER
The search Viewer window that is displayed when the user chooses the Find button from the Tools menu in the Microsoft Exchange client.
EECONTEXT_ADDRBOOK
The Address Book dialog box that is displayed when the user chooses the Address Book button from the Tools menu in the Microsoft Exchange client.
EECONTEXT_SENDNOTEMESSAGE
The standard send note window in which messages of the IPM.Note class are composed.
EECONTEXT_READNOTEMESSAGE
The standard read note window in which messages of the IPM.Note class are read after they are received.
EECONTEXT_SENDPOSTMESSAGE
The standard posting window in which new IPM.Post posting messages are composed.
EECONTEXT_READPOSTMESSAGE
The standard posting window in which existing posting messages are read.
EECONTEXT_READREPORTMESSAGE
The read report message window in which the Read, Delivery, Non-Read, and Non-Delivery report messages are read after they are received.
EECONTEXT_SENDRESENDMESSAGE
The send-resend message window that is displayed when the user chooses the Send Again button from the nondelivery report.
EECONTEXT_PROPERTYSHEETS
A property sheet window.
EECONTEXT_ADVANCEDCRITERIA
Any window in which the user specifies advanced search criteria. In Microsoft Exchange, this is a window brought up by the Find button from the Tools menu, or the dialog box brought up by the Filter button.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EE_MODAL
The extension is being installed into a context where modal windows are displayed. Extensions that are loaded into modal contexts should only display modal windows.

Return Values

S_OK
The extension object elects to run in this context.
S_FALSE
The extension object does not elect to run in this context and will be released immediately.

Remarks

Microsoft Exchange calls the IExchExt::Install method to enable an extension object to determine the context into which it is being loaded, along with information about that context. The context is determined using the callback object returned in the lpeecb parameter. The user interface context is described by the value of the eecontext parameter.

IExchExtCallback::GetVersion is often called during Install to ensure that the version of the Microsoft Exchange client is compatible with your extension object.

IExchExtCallback::GetObject is often called during Install to determine whether the currently selected object in the Microsoft Exchange user interface is the type your extension object supports. When Install is called with the property sheet's context, your extension object should make sure the selected object matches the type of property sheet that is provided to the extension.

HRESULT return values other than S_OK and S_FALSE indicate that the extension object has encountered an error and Microsoft Exchange will not load the extension object.

See Also

IExchExtCallback::GetVersion, IExchExtCallback::GetObject


IExchExtAdvancedCriteria : IUnknown

The IExchExtAdvancedCriteria interface is used to enable extension objects to replace or enhance the functionality of the Advanced dialog box that appears when the user selects the Advanced button from the Find dialog box.

Only one advanced criteria interface is used by a single context, although different extension objects can implement advanced criteria dialog boxes used by different contexts, potentially at the same time. The first extension object to be called with the IExchExtAdvancedCriteria::InstallAdvancedCriteria method is given precedence in determining the situations in which to install its advanced criteria dialog box. This ordering depends on the order in which extensions are listed in the registry database. Advanced criteria implementers can choose whether to take responsibility for advanced criteria based on the selected folder or on the existing restriction.

IExchExtAdvancedCriteria is used by Microsoft Exchange only in the EECONTEXT_VIEWER and EECONTEXT_SEARCHVIEWER contexts.

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTADVANCEDCRITERIA

Vtable Order

InstallAdvancedCriteria | Enables an extension to install its advanced criteria dialog box.
DoDialog | Displays an extension's advanced criteria dialog box.
Clear | Prompts an extension to clear all of its advanced criteria.
SetFolders | Called when the folders have been changed.
QueryRestriction | Returns a restriction object and a text representation of the restriction.
UninstallAdvancedCriteria | Called when the criteria user interface is closed and enables extensions to release resources.


IExchExtAdvancedCriteria::Clear

Clears the advanced criteria associated with the extension object. This method is called by Microsoft Exchange when the user chooses the Clear All button in the Advanced dialog box.

Quick Info

See IExchExtAdvancedCriteria : IUnknown.

VOID Clear()


IExchExtAdvancedCriteria::DoDialog

Displays an extension object's advanced criteria dialog box.

Quick Info

See IExchExtAdvancedCriteria : IUnknown.

HRESULT DoDialog()

Return Values

S_OK
Advanced criteria, including the fNot parameter, were set after the user chose the dialog box's OK button, unless an error occurs.
EXCHEXT_S_NOCHANGE
No change was made to the dialog box, or the user chose the Cancel button.
EXCHEXT_S_NOCRITERIA
No criteria were specified in the dialog box. That is, the user changed the criteria to be empty.

Remarks

Microsoft Exchange calls the IExchExtAdvancedCriteria::DoDialog method when the user selects the Advanced button in the Find dialog box. The extension object should display a dialog box that enables the user to specify search criteria. The dialog box should be modal to the window specified in the hwnd parameter of IExchExtAdvancedCriteria::InstallAdvancedCriteria.


IExchExtAdvancedCriteria::InstallAdvancedCriteria

Enables an extension object to install its advanced criteria dialog box.

Quick Info

See IExchExtAdvancedCriteria : IUnknown.

HRESULT InstallAdvancedCriteria(
  HWND hwnd,
  LPSRestriction lpres,
  BOOL fNot,
  LPENTRYLIST lpeidl,
  ULONG ulFlags
);

Parameters

hwnd
[in] Window handle containing the advanced criteria user interface.
lpres
[in] Pointer to a MAPI SRestriction structure containing the advanced criteria restriction. NULL if none exists.
fNot
[in] TRUE if the user wants only messages that do not meet the criteria specified in the structure pointed to by the lpres parameter.
lpeidl
[in] Pointer to an array of folder entry identifiers to which the criteria will be applied.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EEAC_INCLUDESUBFOLDERS
Subfolders of the lpeidl parameter are to be included in the search.

Return Values

S_OK
The extension object will display its advanced criteria user interface.
S_FALSE
The extension object will not display its advanced criteria user interface.

Remarks

Microsoft Exchange calls the IExchExtAdvancedCriteria::InstallAdvancedCriteria method when the user chooses the Advanced button in the Find dialog box. The first extension that returns S_OK is the only IExchExtAdvancedCriteria interface implementation used for the criteria dialog box instance. Implementations of this method should examine the lpres parameter to see if the restriction's format is recognizable. If not, S_FALSE should be returned and other extensions will be given the opportunity to handle the restriction. Extensions should use comment fields in restrictions to identify their particular formats.

Calls to InstallAdvancedCriteria will not be nested within a single context; that is, they will not be prompted to install their advanced criteria dialog box a second time before an existing installation has been uninstalled (with the exception of multiple instances of Microsoft Exchange Find windows and advanced criteria objects). Specifically, separate contexts which use IExchExtAdvancedCriteria can have overlapping lifespans.

To determine whether your extension should participate in the current advanced criteria context, you can obtain information about the context during the last call to the IExchExt::Install method. You might want to save information about the advanced criteria context for later use. You cannot save the pointer to the callback object during the call to Install.

If S_FALSE is returned, remaining extension objects will be given the opportunity to recognize the restriction and display the user interface. If no extension object returns S_OK, the Advanced button will be disabled. Microsoft Exchange will provide default advanced criteria functionality.

See Also

IExchExtCallback::GetObject


IExchExtAdvancedCriteria::QueryRestriction

Returns a restriction object and a text version of the restriction.

Quick Info

See IExchExtAdvancedCriteria : IUnknown.

HRESULT QueryRestriction(
  LPVOID lpvAllocBase,
  LPSRestriction FAR * lppres,
  LPSPropTagArray FAR * lppPropTags,
  LPMAPINAMEID FAR * FAR * lppPropNames,
  BOOL * lpfNot,
  LPTSTR lpszDesc,
  ULONG cchDesc,
  ULONG ulFlags
);

Parameters

lpvAllocBase
[in] Pointer to the memory allocation base to be used when allocating memory for the restriction data. For more information on allocating memory, see Managing Memory in the MAPI Programmer's Reference.
lppres
[out] Pointer to where to return a pointer to the advanced criteria restriction.
lppPropTags
[out] Pointer to where to return a pointer to a MAPI property tag array containing the property tags of any named properties involved in the restriction. This parameter is used by Microsoft Exchange to find property tags which need to be remapped should the restriction be applied to a different store.
lppPropNames
[out] Pointer to where to return an array of MAPI property NAMEID structures that define the properties whose tags are given in the lppPropTags parameter. This value is used by Microsoft Exchange to obtain the appropriate new property tags should the restriction be applied to a different store.
lpfNot
[out] Pointer to a variable that returns TRUE if the user only wants messages that do not meet the criteria specified in the structure pointed to by the lpres parameter.
lpszDesc
[out] Pointer to a buffer which the extension should fill with a string containing a text description of the restriction.
cchDesc
[in] Maximum length of the lpszDesc parameter.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EXCHEXT_UNICODE
Microsoft Exchange sets the ulFlags parameter to this value if it wants the extension to fill the lpszDesc parameter with a Unicode string.

Remarks

Microsoft Exchange calls the IExchExtAdvancedCriteria::QueryRestriction method when the criteria which the user has specified must be instantiated as a restriction. For example, when the user closes the Advanced dialog box, Microsoft Exchange prompts the extension object to return the current restriction. The restriction is a MAPI construct specifying a query. Memory for the returned restriction object must be allocated with the MAPIAllocateMore function using the pvAllocBase parameter as the base. QueryRestriction can be called zero, one, or multiple times depending on the context and the user's choices.

The text version this method returns is a user-readable representation of the query that the user composed in the Advanced dialog box. The format of the text version depends on the complexity of the criteria. For example, it could be a description in plain text English or in SQL language.

If no restriction is defined, the function should return S_OK with a null restriction in lppres. If EXCHEXT_S_NOCRITERIA is returned, the operation will be stopped. Extensions can selectively install themselves in different contexts in the Exchange client, such as: EECONTEXT_TASK, EECONTEXT_VIEWER, etc. By installing in a particular context, the extension needs to instantiate a new set of interface objects, such as IExchExtCommands, to handle the methods in that particular object. For example, if an extension is installed into EECONTEXT_VIEWER and EECONTEXT_SENDNOTEMESSAGE, it needs to remember which commands it has installed into which context so that it can respond to the IExchExtCommands::DoCommand method.


IExchExtAdvancedCriteria::SetFolders

Notifies an extension object when the folders to which the search criteria apply have been changed.

Quick Info

See IExchExtAdvancedCriteria : IUnknown.

VOID SetFolders(
  LPENTRYLIST lpeidl,
  ULONG ulFlags
);

Parameters

lpeidl
[in] Pointer to an array of folder entry identifiers to which the search criteria will be applied.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EEAC_INCLUDESUBFOLDERS
Microsoft Exchange sets the ulFlags parameter to this value to specify that subfolders of the lpeidl parameter are to be included in the search.

Remarks

Microsoft Exchange calls the IExchExtAdvancedCriteria::SetFolders method when the user changes the folders to which the search criteria will be applied. This enables extensions to take additional actions, depending on the newly selected folder.


IExchExtAdvancedCriteria::UninstallAdvancedCriteria

Notifies an extension object when the search criteria dialog box is closed.

Quick Info

See IExchExtAdvancedCriteria : IUnknown.

VOID UninstallAdvancedCriteria()

Remarks

Microsoft Exchange calls the IExchExtAdvancedCriteria::UninstallAdvancedCriteria method when the search criteria dialog box is closed. The effect of this method is similar to what is expected during the IExchExtMessageEvents::OnReadComplete, OnWriteComplete, OnSubmitComplete, and OnCheckNamesComplete methods. When UninstallAdvancedCriteria is invoked, the extension object can release interfaces previously claimed with the AddRef method and release any other resources used while the criteria dialog box was displayed.

The extension object can discard any state information it is maintaining, such as memory allocations and the current state of the dialog box. The extension should not free any memory returned by the IExchExtAdvancedCriteria::QueryRestriction method.


IExchExtAttachedFileEvents : IUnknown

The IExchExtAttachedFileEvents interface is used to enable extension objects to replace or enhance the default attachment-handling behavior of Microsoft Exchange.

The IExchExtAttachedFileEvents interface is used only in the following contexts:

EECONTEXT_SENDNOTEMESSAGE

EECONTEXT_READNOTEMESSAGE

EECONTEXT_SENDPOSTMESSAGE

EECONTEXT_READPOSTMESSAGE

EECONTEXT_READREPORTMESSAGE

EECONTEXT_SENDRESENDMESSAGE

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTATTACHEDFILEEVENTS

Vtable Order

OnReadPattFromSzFile | Replaces or enhances the behavior of Microsoft Exchange when adding attachments to a message from a file.
OnWritePattToSzFile | Replaces or enhances the behavior of Microsoft Exchange when writing attachments from a message to a file (such as when responding to the Save command.)
QueryDisallowOpenPatt | Prevents a document file attachment from being opened directly without writing it first to an intermediate file.
OnOpenPatt | Replaces or enhances the behavior of Microsoft Exchange when opening a file attachment directly from the message.
OnOpenSzFile | Replaces or enhances the behavior of Microsoft Exchange when opening an attachment from a temporary file.


IExchExtAttachedFileEvents::OnReadPattFromSzFile

Replaces or enhances the behavior of Microsoft Exchange when adding attachments to a message from a file.

Quick Info

See IExchExtAttachedFileEvents : IUnknown.

HRESULT OnReadPattFromSzFile(
  LPATTACH lpAtt,
  LPTSTR lpszFile,
  ULONG ulFlags
);

Parameters

lpAtt
[in] Pointer to the MAPI IAttach : IMAPIProp interface on the attachment.
lpszFile
[in] Pointer to a string containing the name and path of the file being attached.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EXCHEXT_UNICODE
The lpszFile parameter is a unicode string.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and handled attaching the file on its own. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extensions or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtAttachedFileEvents::OnReadPattFromSzFile method when it is about to read an attached file's data. This can occur on initial attachment and when the contents of the attachment are being updated from a temporary file. If an error occurs, OnReadPattFromSzFile should display an error message and return an error. Microsoft Exchange will not continue to attach the file, nor will it display an additional error message, but will stop the user action that requested the attachment.


IExchExtAttachedFileEvents::OnWritePattToSzFile

Replaces or enhances the behavior of Microsoft Exchange when writing attachments from a message to a file.

Quick Info

See IExchExtAttachedFileEvents : IUnknown.

HRESULT OnWritePattToSzFile(
  LPATTACH lpAtt,
  LPTSTR lpszFile,
  ULONG ulFlags
);

Parameters

lpAtt
[in] Pointer to the MAPI IAttach : IMAPIProp interface on the attachment.
lpszFile
[in] Pointer to a string containing the name and path of the intermediate file being written.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EXCHEXT_UNICODE
The lpszFile parameter is a unicode string.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and wrote out the file on its own. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extension objects or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtAttachedFileEvents::OnWritePattToSzFile method when it is about to write an attachment to a file, such as when the user chooses the Save or Open button. If an error occurs, OnWritePattToSzFile should display an error message and return an error. Microsoft Exchange will not continue to try and write out the file, nor will it display an error message, but will stop the user action that requested the file be written.


IExchExtAttachedFileEvents::OnOpenPatt

Replaces or enhances the behavior of Microsoft Exchange when opening a document file attachment directly from a message.

Quick Info

See IExchExtAttachedFileEvents : IUnknown.

HRESULT OnOpenPatt(
  LPATTACH lpAtt
);

Parameters

lpAtt
[in] Pointer to the MAPI IAttach : IMAPIProp interface on the attachment.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and opened the file on its own. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extensions or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtAttachedFileEvents::OnOpenPatt method when it is about to open an attachment directly from the message. Before writing it to an intermediate file, Microsoft Exchange allows extension objects to open directly from the attachment. File viewers might use this method to display the content of the attachment without writing an intermediate file to the file system.

Microsoft Exchange attempts to find an application that is registered to handle the attached file's class. If no such application can be found, Microsoft Exchange writes the attachment to a temporary file and prompts Microsoft® Windows® operating system to start the application that is registered to handle files with the given file extension (such as .XLS for Microsoft Excel).

It then calls the IExchExtAttachedFileEvents::OnOpenSzFile method on extension objects instantiated in the context that supports the IExchExtAttachedFileEvents : IUnknown interface. Microsoft Exchange may try to open an attachment from a file after learning from IExchExtAttachedFileEvents::QueryDisallowOpenPatt that it is allowed to do so. At this point, Microsoft Exchange prompts the extension object if it wants to do special handling of the file, such as replacing the open-attachment behavior or by doing other work such as detecting viruses.

If an error occurs, OnOpenPatt should display an error message and return an error. Microsoft Exchange will not continue to try and open the attachment, nor will it display an error message, but will stop the user action that requested the attachment be opened.


IExchExtAttachedFileEvents::OnOpenSzFile

Replaces or enhances the behavior of Microsoft Exchange when opening an attachment from a temporary file.

Quick Info

See IExchExtAttachedFileEvents : IUnknown.

HRESULT OnOpenSzFile(
  LPTSTR lpszFile,
  ULONG ulFlags
);

Parameters

lpszFile
[in] Pointer to a string containing the name and path of the temporary file being opened.
ulFlags
[in] Bitmask of flags. Set this parameter to one of the following values:
EXCHEXT_UNICODE
The lpszFile parameter is a unicode string.
EEAFE_OPEN
The attachment is being opened.
EEAFE_PRINT
The attachment is being printed.
EEAFE_QUICKPREVIEW
The attachment is being quickviewed.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and opened the file on its own. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extensions or, if necessary, open the file attachment itself.

Remarks

Microsoft Exchange calls the IExchExtAttachedFileEvents::OnOpenSzFile method when it is about to open an attachment, but was not able to open it directly from the data in the attachment in the message. When this occurs, the attachment data is written to an intermediate file. Microsoft Exchange attempts to find an application that is registered to handle the attached file's class. If it finds it, the application is started and prompted to open the attachment.

If an error occurs, OnOpenSzFile should display an error message and return an error. Microsoft Exchange will not continue to try and open the attachment, nor will it display an error message, but will stop the user action that requested the attachment be opened.


IExchExtAttachedFileEvents::QueryDisallowOpenPatt

Prevents a file attachment from being opened directly without writing it first to an intermediate file.

Quick Info

See IExchExtAttachedFileEvents : IUnknown.

HRESULT QueryDisallowOpenPatt(
  LPATTACH lpAtt
);

Parameters

lpAtt
[in] Pointer to the MAPI IAttach : IMAPIProp interface on the attachment.

Return Values

S_OK
The extension object will prevent other extensions or Microsoft Exchange from opening the attachment directly without writing it to a file first.
S_FALSE
The extension object did nothing. Microsoft Exchange will call other extension objects if opening the attachment directly ought to be disallowed.

Remarks

Microsoft Exchange calls the IExchExtAttachedFileEvents::QueryDisallowOpenPatt method when it is about to open the attachment directly without writing it first to an intermediate file. An extension object might elect to disallow opening attachments directly if it has encrypted or modified the attachment and should decrypt or restore it to an intermediate file.

If an error occurs, QueryDisallowOpenPatt should display an error message and return an error. Microsoft Exchange will not continue to try to open the file, nor will it display an error message, but will stop the user action that requested the attachment be opened.


IExchExtCallback : IUnknown

The IExchExtCallback interface enables extension objects to retrieve information about the current context, including the objects that are currently selected in the Microsoft Exchange window. IExchExtCallback uses the methods of the IUnknown interface for reference management.

IExchExtCallback is implemented by a callback object supplied by Microsoft Exchange. A pointer to this interface is passed as a parameter to many methods of the Microsoft Exchange extensibility API. This interface and any interfaces it might return are valid only for the time of the call to one of its methods and might not be retained when the extension object's method returns. The called method does not need to release the callback object unless it has completed a corresponding call to AddRef.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Microsoft Exchange
Called by: | Extension objects
Corresponding pointer type: | LPEXCHEXTCALLBACK

Vtable Order

GetVersion | Returns the version number of the Microsoft Exchange application.
GetWindow | Returns a window handle corresponding to the specified flag.
GetMenu | Returns the Microsoft Exchange menu handle for the current window.
GetToolbar | Returns a toolbar's window handle.
GetSession | Returns an interface to the current open MAPI session and associated address book.
GetObject | Returns an interface and store for a particular object.
GetSelectionCount | Returns the number of objects selected in the window.
GetSelectionItem | Returns the entry identifier of a selected item in a Microsoft Exchange window.
GetMenuPos | Returns the position of a command or set of commands on the Microsoft Exchange menu.
GetSharedExtsDir | Returns the Microsoft Exchange shared-extensions directory.
GetRecipients | Returns a pointer to the recipient list of the currently selected item.
SetRecipients | Sets the recipient list for the currently selected item.
GetNewMessageSite | Returns interface pointers to the message site and view context of the selected message.
RegisterModeless | Enables extension objects that display modeless windows to coordinate with windows displayed by the Microsoft Exchange client.
ChooseFolder | Displays a dialog box that enables users to choose a specific message store and folder.


IExchExtCallback::ChooseFolder

Displays a dialog box that enables users to choose a specific message store and folder.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT ChooseFolder(
  LPEXCHEXTCHOOSEFOLDER peecf
);

Parameters

peecf
[in] Pointer to a structure that describes the Choose Folder dialog box. The structure also includes output members that provide information about the selections made by the user when the user chooses the OK button. The structure has the following members:
UINT cbLength
Input member indicating the size of the structure.
HWND hwnd
Input member indicating the parent window of the Choose Folder dialog box.
LPTSTR szCaption
Input member indicating the caption that is displayed in the dialog box's title bar.
LPTSTR szLabel
Input member indicating a label that is displayed at the top of the list box of folders.
LPTSTR szHelpFile
Input member specifying which Help file should be launched when the user chooses the Help button.
ULONG ulHelpID
Input member indicating the topic that should be referenced in the Help file.
HINSTANCE hinst
Input member indicating the instance handle containing the resource of a custom dialog box. Set this value only if you want to supply your own dialog box template.
UINT uiDlgID
Input member indicating the resource identifier of the instance of the custom dialog box template. Set this value only if you set the hinst parameter.
LPEECFHOOKPROC lpeecfhp
Input member indicating a hook proc pointer. Set this value only if you want to do special processing of messages within the dialog box.
DWORD dwHookData
Input member used to cache additional information about events that occur while the dialog box is displayed. Use this member if you are providing a hook process for handling dialog box messages.
ULONG ulFlags
Input member containing a bitmask of flags. The following flags can be set:
EECBCF_GETNAME | The name of the folder selected by the user is returned. This name must be freed using the MAPIFreeBuffer function.
EECBCF_HIDENEW | Hides the New button on the Choose Folder dialog box. This button enables users to create a new folder.
EECBCF_PREVENTROOT | Disables the OK button when the root is the currently selected folder. In most cases, this flag should be specified because the root folder is not a valid container of messages.

LPMDB pmdb
Output member that is an interface pointer to the message store object selected in the Choose Folder dialog box.
LPMAPIFOLDER pfld
Output member that is an interface pointer to the folder object selected in the Choose Folder dialog box.
LPTSTR szName
Output member indicating the name of the folder the user selected. This value enables you to get the name of the folder without using a MAPI GetProps method. This value is only provided if the EECBCF_GETNAME flag is set.
DWORD dwReserved1 - dwReserved3
These three members are reserved for future use and should be set to NULL by extensions.

Return Values

S_OK
No errors occurred.

Remarks

Extension objects call the IExchExtCallback::ChooseFolder method to enable users to select a specific message store or folder. For example, if your application provides a backup command, you might want to prompt the user to specify which folder in which message store should be backed up.


IExchExtCallback::GetMenu

Returns the menu handle for the current Microsoft Exchange window.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetMenu(
  HMENU FAR * lphMenu
);

Parameters

lphMenu
[out] Pointer to the Microsoft Exchange menu handle.

Return Values

S_OK
The lphMenu parameter returned a non-null HMENU.
S_FALSE
The lphMenu parameter returned a NULL HMENU.
E_INVALIDARG
The lphMenu parameter is NULL or no HWND is associated with the context where the extension is installed.


IExchExtCallback::GetMenuPos

Returns the position of a command, menu, or set of commands on the Microsoft Exchange menu for the current context.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetMenuPos(
  UINT cmdid,
  HMENU FAR * lphmenu,
  ULONG FAR * lpmposMin,
  ULONG FAR * lpmposMax,
  ULONG ulFlags
);

Parameters

cmdid
[in] The command identifier of interest.
lphMenu
[out] Pointer to the menu handle where the cmdid parameter can be found.
lpmposMin
[out] Pointer to the menu position above the command.
lpmposMax
[out] Pointer to the menu position below the command.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EECBGMP_RANGE
The returned positions should correspond to the separator-delimited range of the menu containing the command.

Return Values

S_OK
No errors occurred.
E_FAIL
Microsoft Exchange cannot find the menu associated with the cmdid parameter.
E_INVALIDARG
The command identifier does not correspond to a menu item or the lphmenu parameter is NULL, or there is no HMENU associated with the context where the extension is installed.


IExchExtCallback::GetNewMessageSite

Returns interface pointers to the message, message site, and view context for a new message that is being composed. Using these interface pointers, an extension object can display a form for the new message.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetNewMessageSite(
  ULONG fComposeInFolder,
  LPMAPIFOLDER pfldFocus,
  LPPERSISTMESSAGE ppermsg,
  LPMESSAGE FAR * ppmsg,
  LPMAPIMESSAGESITE FAR * ppmms,
  LPMAPIVIEWCONTEXT FAR * ppmvc,
  ULONG ulFlags
);

Parameters

fComposeInFolder
[in] Indicates whether the message is being composed in the same folder from which it was activated. If this flag is TRUE, the message site supports default behavior for posting messages, which means that the message always remains in the same folder in which it was created. If this flag is FALSE, the message site supports default behavior for sending messages, which means that messages are automatically moved to the Outbox or Inbox when the user sends or saves the message.
pfldFocus
[in] Pointer to the folder in which the message is to be composed.
ppermsg
[in] Pointer to a pointer to the IPersistMessage interface on the form for which the new message site is being obtained.
ppmsg
[out] Pointer to a pointer to the message being composed.
ppmms
[out] Pointer to a pointer to the MAPI message site for the new message.
ppmvc
[out] Pointer to a pointer to the MAPI view context for the new message.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EECBGNMS_MODAL
The new form should be modal.

Return Values

S_OK
No error occurred.
E_INVALIDARG
No session is associated with the context where the extension is installed or the ulFlags parameter has EECBGNMS_MODAL set.

Remarks

Extension objects call the IExchExtCallback::GetNewMessageSite method to display a form for a new message that the user has created. For example, an extension that performs scheduling functions might have a New Meeting menu command which results in the creation of a new message and the display of a custom form that enables users to fill in the fields of the message.


IExchExtCallback::GetObject

Returns interfaces for a particular object and the object's containing store. The interfaces returned depend on the context of the caller. For a list of possible interfaces returned, see the "Remarks" section.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetObject(
  LPMDB FAR * lppmdb,
  LPMAPIPROP FAR * lppmp
);

Parameters

lppmdb
[out] Pointer to a pointer to the store object containing the lppmp parameter.
lppmp
[out] Pointer to a pointer to a MAPI object.

Return Values

S_OK
Either the lppmdb or lppmp parameter returned non-null values.
S_FALSE
Both the lppmdb and lppmp parameters returned NULL values.
E_INVALIDARG
Both the lppmdb and lppmp parameters are NULL.

Remarks

The IExchExtCallback::GetObject method is used to return an interface and message store for a particular object. The interface returned depends on the context or the caller. When called by the IExchExtPropertySheets::GetPages method, the object is the object for which information should be displayed, and the store is the store containing that object.

The interfaces must be released before the call which was given the lpeecb parameter returns. The following list describes the interfaces that are returned when GetObject is called from various contexts.

EECONTEXT_SESSION, EECONTEXT_TASK
Both interfaces returned are NULL.
EECONTEXT_VIEWER
The interfaces returned by GetObject are NULL when called from the IExchExt::Install or IExchExtCommands::InstallCommands methods because the Viewer is not necessarily permanently associated with the same store or object.

When called from the IExchExtCommands::InitMenu or IExchExtCommands::DoCommand methods, the object is the open folder being displayed and the store is the store that contains that folder. When the root of a store is displayed, the object is the IPM_SUBTREE folder. Both pointers are NULL when the list of stores is displayed in the content pane.

EECONTEXT_REMOTEVIEWER
Both interfaces are NULL.
EECONTEXT_SEARCHVIEWER
The object is the search folder being displayed, and the store is the store which contains that search folder.
EECONTEXT_ADDRBOOK
The interfaces are generally NULL when called from Install or InstallCommands because the address book is not always necessarily associated with the same container.

When called from InitMenu and DoCommand, the object is the ABContainer being displayed and the store is NULL. GetObject is called in the following contexts:

EECONTEXT_SENDNOTEMESSAGE

EECONTEXT_READNOTEMESSAGE

EECONTEXT_SENDPOSTMESSAGE

EECONTEXT_READPOSTMESSAGE

EECONTEXT_READREPORTMESSAGE

EECONTEXT_SENDRESENDMESSAGE

The object is the message being displayed and the store is the store which contains that message.

The object interface returned in the lppmp parameter supports the IMAPIProp : IUnknown interface as well as the additional interface methods specific to its type.

Object | Interface type
Folder | IMAPIFolder
Message | IMessage
Store | IMsgStore
Address Book | IABContainer

See Also

IExchExt::Install, IExchExtAdvancedCriteria::InstallAdvancedCriteria


IExchExtCallback::GetRecipients

Returns a pointer to the recipient list for the currently open item.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetRecipients(
  LPADRLIST FAR * lppal
);

Parameters

lppal
[out] Pointer to the location where the address list is returned.

Return Values

S_OK
No error occurred.
E_INVALIDARG
The function was called from a context that does not support recipients or there is no recipients list.

Remarks

The recipient list is returned in a MAPI ADRLIST structure.

This method is called in the following contexts:

EECONTEXT_SENDNOTEMESSAGE

EECONTEXT_READNOTEMESSAGE

EECONTEXT_SENDPOSTMESSAGE

EECONTEXT_READPOSTMESSAGE

EECONTEXT_READREPORTMESSAGE

EECONTEXT_SENDRESENDMESSAGE

See Also

IExchExtCallback::SetRecipients


IExchExtCallback::GetSelectionCount

Returns the number of objects selected in the active window. Selections can only be made in windows that display containers.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetSelectionCount(
  ULONG FAR * lpceid
);

Parameters

lpceid
[out] Pointer to a variable containing the number of objects selected in the window.

Return Values

S_OK
The lpceid parameter returned the count of the current selection.
E_INVALIDARG
The lpceid parameter is NULL or GetSelectionCount was called from an invalid context (EECONTEXT_SESSION, EECONTEXT_TASK, EECONTEXT_MESSAGE).

Remarks

The IExchExtCallback::GetSelectionCount method is used to return the number of objects selected in the active window. The window is determined by the context in which the extension object is installed.

See Also

IExchExtCommands::InitMenu


IExchExtCallback::GetSelectionItem

Returns the entry identifier and other information of the currently selected item in a Microsoft Exchange window.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetSelectionItem(
  ULONG ieid,
  ULONG FAR * lpcbeid,
  LPENTRYID FAR * lppeid,
  ULONG FAR * lpulType,
  LPTSTR lpszMsgClass,
  ULONG cbMsgClass,
  ULONG FAR * lpulMsgFlags,
  ULONG ulFlags
);

Parameters

ieid
[in] Index of the entry identifier to be retrieved. Valid values for this parameter are 0 to lpceid -1 where lpceid is returned in the IExchExtCallback::GetSelectionCount method.
lpcbeid
[out] Pointer to the number of bytes returned in the lppeid parameter.
lppeid
[out] Pointer to a pointer to the entry identifier of the selection.
lpulType
[out] Pointer to the type of entry identifier returned in the lppeid parameter. This parameter can have the following values:

MAPI_STORE = 1, if lppeid refers to a message store.

MAPI_ADDRBOOK = 2, if lppeid refers to an address book.

MAPI_FOLDER = 3, if lppeid refers to a folder.

MAPI_MESSAGE = 5, if lppeid refers to a message.

lpszMsgClass
[in, out] Pointer to a buffer into which Microsoft Exchange will copy the message class of the selected message.
cbMsgClass
[out] Size of the message class.
lpulMsgFlags
[out] Pointer to the message flags returned. See the MAPI PR_MESSAGE_FLAGS property.
ulFlags
Reserved; must be zero.

Return Values

S_OK
No errors occurred.
S_FAIL
Microsoft Exchange failed to access the selected item.
E_INVALIDARG
The ulFlags parameter is not fMapiUnicode or it is called from an invalid context that does not support the selected item.

Remarks

The IExchExtCallback::GetSelectionItem method is used to return the entry identifier of the currently selected item in a Microsoft Exchange Window. For example, if a custom form is installed and the user selects this form, extension objects that implement the IExchExtUserEvents::OnSelectionChange method can use GetSelectionItem to determine the message class of the selected message. If the extension object is programmed to handle messages of this class, it might display or enable menu items specific to the message class.

If a parameter is not used in this method, pass NULL for that parameter.

See Also

IExchExtCommands::InitMenu


IExchExtCallback::GetSession

Returns interfaces to the current open MAPI session and associated address book.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetSession(
  LPMAPISESSION FAR * lppses,
  LPADRBOOK FAR * lppab
);

Parameters

lppses
[out] Pointer to a pointer to the current MAPI session object.
lppab
[out] Pointer to a pointer to the address book object associated with the lppses parameter.

Return Values

S_OK
Either the lppses or lppab parameter returned a non-null value.
S_FALSE
Both the lppses and lppab parameters returned NULL values.
E_INVALIDARG
Both the lppses and lppab parameters are NULL.

Remarks

The lppses and lppab parameters might be NULL. Both interfaces must be released before the method which was passed the lpeecb parameter returns a value.


IExchExtCallback::GetSharedExtsDir

Returns the location of the Microsoft Exchange shared extensions directory.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetSharedExtsDir(
  LPTSTR lpszDir,
  ULONG cchDir,
  ULONG ulFlags
);

Parameters

lpszDir
[in, out] Pointer to a buffer to be filled with the location of the shared directory.
cchDir
[in] Size of the lpszDir parameter.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EXCHEXT_UNICODE
The lpszDir parameter is a unicode string.

Return Values

S_OK
No error occurred.
S_FALSE
There is no SharedExtsDir.
E_INVALIDARG
The lpszDir parameter is NULL, the cchDir parameter is zero, or the ulFlags parameter is not fMapiUnicode.


IExchExtCallback::GetToolbar

Returns a toolbar window handle.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetToolbar(
  ULONG tbid,
  HWND FAR * lphwndTb
);

Parameters

tbid
[in] Toolbar identifier.
lphwndTb
[out] Pointer to the Microsoft Exchange toolbar window handle.

Return Values

S_OK
The lphWnd parameter returned a non-null HWND.
S_FALSE
The lphWnd parameter returned a null HWND.
E_INVALIDARD
The tbid parameter is not EETB_STANDARD or the lphWnd parameter is NULL.

Remarks

Currently, only the standard toolbar defined by EETB_STANDARD is supported. It is therefore not possible to add toolbar buttons to other toolbars such as the formatting toolbar.

See Also

IExchExtCommands::ResetToolbar


IExchExtCallback::GetVersion

Returns the version number of the Microsoft Exchange client.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetVersion(
  ULONG FAR * lpulVersion,
  ULONG ulFlags
);

Parameters

lpulVersion
[out] Pointer to the location where the version of Microsoft Exchange is returned. The format of the returned version is determined by the value of the ulFlags parameter.
ulFlags
[in] Bitmask of flags used to specify the type and format of the version information that is returned. These flags can have the following values:
EECBGV_GETBUILDVERSION
Requests that the major version is returned in the HIWORD and the minor version in the LOWORD. Extension objects should verify that the major version matches the EECBGV_BUILDVERSION_MAJOR with which they were compiled, and that the minor version is at least the minor version with which the extension object was tested.
EECBGV_GETACTUALVERSION
Requests that the version returned corresponds to the actual version of the calling client.
EECBGV_GETVIRTUALVERSION
Requests that the version returned is the version which the client wants the extension to base its decisions on. For example, if an application named Zippypost 5.0 implements Microsoft Exchange extensibility to exactly match that implemented in Microsoft Exchange, the actual version would be Zippypost 5.0 but the virtual version would be Microsoft Exchange.

Return Values

S_OK
No error occurred.

Remarks

Extension objects should test against the virtual version and should reserve actual version checking for determination of additional features specific to a particular kind of client or version.

The actual and virtual versions are made up of four bytes, which represent in order from most significant to least the product, the platform, the major version, and the minor version. For example, Microsoft Exchange 4.0 for Microsoft® Windows NT® operating system is 0x01030400. Microsoft Exchange for the Macintosh would be 0x0104052A. Zippypost 3.2 for Microsoft® Windows® operating system (version 3.1) might be 0x13010320.

See Also

IExchExt::Install


IExchExtCallback::GetWindow

Returns the window handle for the current Microsoft Exchange window.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT GetWindow(
  HWND FAR * lphwnd
);

Parameters

lphwnd
[out] Pointer to the Microsoft Exchange window handle.

Return Values

S_OK
The lphwnd parameter returned a non-null HWND.
S_FALSE
The lphwnd parameter returned a null HWND.
E_INVALIDARG
The lphwnd parameter is null.


IExchExtCallback::RegisterModeless

Ensures coordination between the modeless windows and modal windows displayed by the Microsoft Exchange client.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT RegisterModeless(
  LPEXCHEXTMODELESS peem,
  LPEXCHEXTMODELESSCALLBACK FAR * ppeemcb
);

Parameters

peem
[in] Pointer to an IExchExtModeless interface implemented by the extension. This interface should be implemented as another object with separate reference counts from the main extension object.
ppeemcb
[out] Pointer to an IExchExtModelessCallback interface implemented by Microsoft Exchange.

Return Values

S_OK
No errors occurred.
S_FALSE
It was not possible to register a modeless window for the extension.
E_INVALIDARG
The peemObj or ppeemcb parameter is NULL.

Remarks

Extension objects that run in the process space of the Microsoft Exchange client and display modeless windows use the IExchExtCallback::RegisterModeless method primarily to enable and disable Microsoft Exchange windows and extension object windows in a coordinated manner. If an extension object has registered for modeless behavior by calling this method and has called IExchExtModelessCallBack::AddWindow, Microsoft Exchange invokes IExchExtModeless::EnableModeless (with its fEnable parameter set to FALSE) before displaying a modal window. The extension object can then disable its modeless windows. When Microsoft Exchange removes its modal window, it invokes EnableModeless (with its fEnable parameter set to TRUE). The extension object can then re-enable its modeless windows.

Similarly, if a modeless extension object needs to display a modal window, it should call IExchExtModelessCallback::EnableModeless (with its fEnable parameter set to FALSE). Microsoft Exchange will then disable its modeless windows. When the extension object removes its modal window, it should invoke IExchExtModeless::EnableModeless (with its fEnable parameter set to TRUE), enabling Microsoft Exchange to re-enable its modeless windows.

When an extension registers itself as modeless, it supplies a modeless object that enables Microsoft Exchange to communicate with the extension object about the state of its windows.

See Also

IExchExtModeless


IExchExtCallback::SetRecipients

Sets the recipient list for the currently selected item.

Quick Info

See IExchExtCallback : IUnknown.

HRESULT SetRecipients(
  LPADRLIST lpal
);

Parameters

lpal
[in] Pointer to the location of the new address list.

Return Values

S_OK
No error occurred.
E_INVALIDARG
The method was called from a context that does not support recipients.

Remarks

Use MAPI functions to fill a MAPI ADRLIST structure with the appropriate information.

This method is called in the following contexts:

EECONTEXT_SENDNOTEMESSAGE

EECONTEXT_READNOTEMESSAGE

EECONTEXT_SENDPOSTMESSAGE

EECONTEXT_READPOSTMESSAGE

EECONTEXT_READREPORTMESSAGE

EECONTEXT_SENDRESENDMESSAGE

See Also

IExchExtCallback::GetRecipients


IExchExtCommands : IUnknown

The IExchExtCommands interface is implemented by extension objects to add and execute custom menu or toolbar command buttons. Extension objects can also replace existing Microsoft Exchange commands or enhance their behavior before Microsoft Exchange carries them out.

Use the operating system's native API to implement the methods given in the following table. For example, when implementing the IExchExtCommands::InstallCommands method for an extension object that will run in the Microsoft Windows 95 environment, the extension object must use the Microsoft® Win32® API structures, messages, and function calls for Windows 95 to manipulate menu or toolbar commands. IExchExtCommands is used in all contexts except EECONTEXT_SESSION, EECONTEXT_TASK, and EECONTEXT_PROPERTYSHEETS.

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTCOMMANDS

Vtable Order

InstallCommands | Enables an extension to install its menu commands or toolbar buttons.
InitMenu | Enables an extension to update its menu items when the user begins using the menus.
DoCommand | Carries out a menu or toolbar command chosen by the user.
Help | Provides user Help for a command.
QueryHelpText | Provides status bar or tool tip Help text for a command.
QueryButtonInfo | Provides information about the extension's toolbar buttons.
ResetToolbar | Enables an extension to restore its toolbar buttons to their default positions.


IExchExtCommands::DoCommand

Carries out a menu or toolbar command chosen by the user.

Quick Info

See IExchExtCommands : IUnknown.

HRESULT DoCommand(
  LPEXCHEXTCALLBACK lpeecb,
  UINT cmdid
);

Parameters

lpeecb
[in] Pointer to an IExchExtCallback interface.
cmdid
[in] Command identifier of the command to be carried out.

Return Values

S_OK
The extension object recognized the cmdid parameter and carried out the command. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did not recognize the cmdid parameter. Microsoft Exchange will continue prompting extension objects to carry out the command and, if necessary, carry out the command itself. In some cases, an extension object might perform some action but still return S_FALSE to give other extensions the opportunity to handle the command.

Remarks

Microsoft Exchange calls the IExchExtCommands::DoCommand method when it receives a WM_COMMAND or WM_SYSCOMMAND message corresponding to a menu command, system menu command, or toolbar button so that the extension object can carry out any commands it implements or supersede the Microsoft Exchange implementation of a command. The command identifier passed to WM_COMMAND is mapped to the published set of Microsoft Exchange commands. It is this published command identifier that is passed to DoCommand in the cmdid parameter. The command identifier in WM_COMMAND maps to, but is different than, the command identifier specified in the cmdid parameter. Extension objects should therefore not rely on this mapping.

If an error occurs, DoCommand should display a message and return an error value. Microsoft Exchange will not continue trying to perform the command nor will it display a message.

The system command identifiers that extensions can override include:

SC_CLOSE
SC_MAXIMIZE
SC_MINIMIZE
SC_MOVE
SC_RESTORE
SC_SIZE
SC_TASKLIST

These commands are standard wparam values for the WM_SYSCOMMAND message.


IExchExtCommands::Help

Provides user Help for a command.

Quick Info

See IExchExtCommands : IUnknown.

HRESULT Help(
  LPEXCHEXTCALLBACK lpeecb,
  UINT cmdid
);

Parameters

lpeecb
[in] Pointer to an IExchExtCallback interface.
cmdid
[in] Command identifier selected by the user.

Return Values

S_OK
The extension object recognized the cmdid parameter and provided Help. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did not recognize the cmdid parameter. Microsoft Exchange will continue prompting extension objects and, if necessary, provide Help itself.

Remarks

Microsoft Exchange calls the IExchExtCommands::Help method when the user requests Help on a command. If the extension object has added a menu, the cmdid parameter corresponding to that menu is the cmdid parameter of the first command on the menu minus one.

The extension object can provide Help for any command it implements or supersede Microsoft Exchange Help text for an existing command.


IExchExtCommands::InitMenu

Enables an extension object to update its menu items when the user begins to use the menu.

Quick Info

See IExchExtCommands : IUnknown.

VOID InitMenu(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to an IExchExtCallback interface. The lpeech parameter is used to determine information about the selection if this is appropriate to the context.

Remarks

Microsoft Exchange calls the IExchExtCommands::InitMenu method when it receives a WM_INITMENU message, allowing the extension object to enable, disable, or update its menu commands before the user sees them. This method is called frequently and should be written in a very efficient manner.

If your command extension needs to be enabled when specific message classes or folders are selected, use the IExchExtCallback::GetSelectionCount method to determine whether there currently is a selection, and use the GetSelectionItem method to traverse the selection. You would traverse the selection to see whether the selected objects are of interest to your command extension.

Microsoft Exchange intercepts the EnableMenuItem message and applies the same enabled or disabled state to the associated toolbar button. These menu items and toolbar buttons do not have to be set independently.

See Also

IExchExtCallback::GetSelectionCount, IExchExtCallback::GetSelectionItem


IExchExtCommands::InstallCommands

Enables an extension object to install its menu commands and toolbar command buttons into a Microsoft Exchange window.

Quick Info

See IExchExtCommands : IUnknown.

HRESULT InstallCommands(
  LPEXCHEXTCALLBACK lpeecb,
  HWND hwnd,
  HMENU hmenu; UINT FAR * lpcmdidBase,
  LPTBENTRY lptbeArray,
  UINT ctbe,
  ULONG ulFlags
);

Parameters

lpeecb
[in] Pointer to an IExchExtCallback interface.
hwnd
[in] Handle of the top-level Microsoft Exchange window.
hmenu
[in] Microsoft Exchange menu handle.
lpcmdidBase
[in, out] Pointer to the first command identifier the extension object can use. This is also the command identifier for a menu item or toolbar button.
lptbeArray
[in] Pointer to an array of toolbars.
ctbe
[in] Count of toolbars in the lptbeArray parameter.
ulFlags
Reserved; must be zero.

The following members are used with the TBENTRY structure, which is defined in the EXCHEXT.H header file:

hwnd
Input member indicating the window handle of the toolbar.
tbid
Input member indicating the toolbar identifier. A toolbar identifier distinguishes between multiple toolbars, such as the standard toolbar and the format toolbar. Currently, only the standard toolbar is defined with the EETB_STANDARD value identifier.
ulFlags
Reserved; must be zero.
itbbBase
Input-output member indicating the index of the extension's first toolbar button in the set of available buttons.

Return Values

S_OK
No error occurred.

Remarks

Microsoft Exchange calls the IExchExtCommands::InstallCommands method to enable an extension object to install its menu commands and toolbar command buttons into a Microsoft Exchange window. Microsoft Exchange invokes InstallCommands before a top level Microsoft Exchange window, such as the Viewer, is made visible.

To prevent identifier collisions, the lpcmdidBase parameter points to the first identifier the extension object can use for a command identifier. The extension must update the contents of the lpcmdidBase parameter, so that on return it contains the first identifier the next extension can use. The lptbeArray parameter contains a list of toolbars with the number of toolbars in the ctbe parameter.

To prevent identifier collisions, the itbbBase parameter contains the index of the extension's first toolbar button in the set of available buttons. This index is not the same as the position of the extension's first button displayed in the toolbar.

The extension object must use the Windows API to add menus, popup menus, and top-level menus. Windows 95 toolbar messages are used on all platforms to register and add toolbar buttons. If an extension object elects to place its toolbar buttons on the toolbar by default, the extension object must add them to the toolbar's set of available buttons when InstallCommands is called and then position those buttons on the toolbar when the IExchExtCommands::ResetToolbar method is called.

If an error is returned, Microsoft Exchange will not try to install another extension and will fail to create the window associated with the context.


IExchExtCommands::QueryButtonInfo

Provides information about the extension object's toolbar buttons.

Quick Info

See IExchExtCommands : IUnknown.

HRESULT QueryButtonInfo(
  ULONG tbid,
  UINT itbb,
  LPTBBUTTON ptbb,
  LPTSTR lpsz,
  UINT cch,
  ULONG ulFlags
);

Parameters

tbid
[in] Toolbar identifier.
itbb
[in] Index into the list of available buttons.
ptbb
[in, out] Pointer to a TBBUTTON toolbar button structure, which can be found in the EXCHEXT.H header file.
lpsz
[in] Pointer to a buffer in which text describing the button should be returned. This description text appears in the Customize Toolbar dialog box. This parameter can be NULL to indicate that text is not required.
cch
[in] Size of the buffer pointed to by the lpsz parameter.
ulFlags
[in] Bitmask of flags. The following flag can be set:
EXCHEXT_UNICODE
The lpsz parameter is a unicode string.

Return Values

S_OK
The extension object recognized the itbb parameter and provided information.
S_FALSE
The extension object did not recognize the itbb parameter. Microsoft Exchange will continue to call extension objects, and if necessary, provide information itself.

Remarks

Microsoft Exchange calls the IExchExtCommands::QueryButtonInfo method when it needs information about a toolbar button. Currently only one toolbar is defined, EETB_STANDARD.

If an error is returned, Microsoft Exchange will not call other extensions and will use default or null information.


IExchExtCommands::QueryHelpText

Provides status bar or tool tip Help text for a command.

Quick Info

See IExchExtCommands : IUnknown.

HRESULT QueryHelpText(
  UINT cmdid,
  ULONG ulFlags,
  LPTSTR lpsz,
  UINT cch
);

Parameters

cmdid
[in] Command identifier selected by the user.
ulFlags
[in] Bitmask of flags. The following flags can be set:
EECQHT_STATUS
Microsoft Exchange requests a string to be displayed in the status bar.
EECQHT_TOOLTIP
Microsoft Exchange requests a string to be displayed in a tool tip.
lpsz
[in, out] Buffer to be filled with Help text.
cch
[in] Size of the lpsz parameter's buffer.

Return Values

S_OK
The extension object recognized the cmdid parameter and returned text in the lpsz parameter.
S_FALSE
The extension object did not recognize the cmdid parameter. Microsoft Exchange will continue to call extension objects, and if necessary, provide text itself.

Remarks

Microsoft Exchange calls the IExchExtCommands::QueryHelpText method when the user chooses a menu command or selects and holds the mouse down over a toolbar button. The extension object can provide Help text for any commands it implements or supersede Microsoft Exchange Help text for an existing command.

If an error is returned, Microsoft Exchange will not call other extensions and will use a default or blank string.


IExchExtCommands::ResetToolbar

Enables an extension to restore its toolbar buttons to their default positions.

Quick Info

See IExchExtCommands : IUnknown.

HRESULT ResetToolbar(
  UINT tbid,
  ULONG ulFlags
);

Parameters

tbid
[in, out] Toolbar identifier. Currently, only the EETB_STANDARD toolbar is defined.
ulFlags
Reserved; must be zero.

Return Values

S_OK
No error occurred.

Remarks

Microsoft Exchange calls the IExchExtCommands::ResetToolbar method when the user chooses the Reset button from the Customize Toolbar dialog box, which means that the toolbar has been reset to its default state. The extension object should place its default toolbar buttons into their default locations.

See Also

IExchExtCallback::GetToolbar


IExchExtMessageEvents : IUnknown

The IExchExtMessageEvents interface is implemented by extension objects and gives them the ability to replace or enhance the default message-handling behavior of Microsoft Exchange. Microsoft Exchange always calls these methods in pairs. For example, if it calls the IExchExtMessageEvents::OnRead method, it also calls the IExchExtMessageEvents::OnReadComplete method; if it calls the IExchExtMessageEvents::OnWrite method, it also calls the IExchExtMessageEvents::OnWriteComplete method, and so forth. The OnReadComplete, OnWriteComplete, IExchExtMessageEvents::OnSubmitComplete, and IExchExtMessageEvents::OnCheckNamesComplete methods are used to undo operations whenever an error occurs. They are also used to release resources that are allocated during calls to the OnRead, OnWrite, IExchExtMessageEvents::OnSubmit, and IExchExtMessageEvents::OnCheckNames methods. For example, an extension object can allocate buffers to validate text during a call to the OnRead method, and deallocate these buffers during a call to the OnReadComplete method.

There is a specific set of steps followed by Microsoft Exhange to handle errors during a call to these functions. This is best illustrated with a specific example that applies to all other methods in this interface. Suppose Microsoft Exchange calls OnCheckNames to notify extensions that it is about to check names and give extensions an opportunity to resolve names. If no extensions return S_OK, Microsoft Exchange performs the name resolution itself. After the resolution is completed or if it failed, Microsoft Exchange calls the OnCheckNamesComplete method of all the extensions whose OnCheckNames method it called, passing in EEME_FAILED if the operation failed. If any extension returns an error from OnCheckNamesComplete, Microsoft Exchange calls each of those extensions again, passing in EEME_COMPLETE_FAILED as the value for the ulFlags parameter. The same series of steps applies to other methods in this interface.

IExchExtMessageEvents is used only in the following contexts:

EECONTEXT_SENDNOTEMESSAGE

EECONTEXT_READNOTEMESSAGE

EECONTEXT_SENDPOSTMESSAGE

EECONTEXT_READPOSTMESSAGE

EECONTEXT_READREPORTMESSAGE

EECONTEXT_SENDRESENDMESSAGE

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTMESSAGEEVENTS

Vtable Order

OnRead | Replaces or enhances the behavior of Microsoft Exchange when reading information from a message.
OnReadComplete | Enables extension objects to roll back their implementation of the OnRead method in case of an error or to release resources allocated by OnRead.
OnWrite | Replaces or enhances the behavior of Microsoft Exchange when writing information to a message.
OnWriteComplete | Enables extension objects to roll back their implementation of the OnWrite method in case of an error or to release resources allocated by OnWrite.
OnCheckNames | Replaces or enhances the behavior of Microsoft Exchange when recipient names typed by the user are being resolved to their address book entries.
OnCheckNamesComplete | Enables extension objects to roll back their implementation of the OnCheckNames method in case of an error or to release resources allocated by OnCheckNames.
OnSubmit | Replaces or enhances the behavior of Microsoft Exchange when a message has been submitted.
OnSubmitComplete | Enables extension objects to roll back their implementation of the OnSubmit method in case of an error or to release resources allocated by OnSubmit.


IExchExtMessageEvents::OnCheckNames

Replaces or enhances the behavior of Microsoft Exchange when recipient names typed by the user are being resolved to their address book entries.

Quick Info

See IExchExtMessageEvents : IUnknown.

HRESULT OnCheckNames(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message and the window containing the unresolved names.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and handled the name resolution on its own. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. See the text provided in the definition of the IExchExtMessageEvents interface in this reference.

Remarks

Microsoft Exchange calls the IExchExtMessageEvents::OnCheckNames method when it is about to resolve unresolved names.

If an error occurs, OnCheckNames should display an error message and return an error. Microsoft Exchange will not continue to check names, nor will it display an error message, but will stop the user action that caused the check names operation. This method should call the IExchExtCallback::GetObject method to determine the message identifier of the item being displayed and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtMessageEvents::OnCheckNamesComplete

Enables extension objects to roll back their implementation of the IExchExtMessageEvents::OnCheckNames method in case of an error or to release resources allocated by OnCheckNames.

Quick Info

See IExchExtMessageEvents : IUnknown.

HRESULT OnCheckNamesComplete(
  LPEXCHEXTCALLBACK lpeecb,
  ULONG ulFlags
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message and the window containing the unresolved names.
ulFlags
[in] Bitmask of flags. The following flags can be set:
EEME_FAILED
The check names operation could not be completed successfully. See the text provided in the definition of the IExchExtMessageEvents interface in this reference.
EEME_COMPLETE_FAILED
See the text provided in the definition of the IExchExtMessageEvents interface in this reference.

Return Values

S_OK
The extension object handled the event. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extensions or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtMessageEvents::OnCheckNamesComplete method after it has resolved the addresses. This method should call the IExchExtCallback::GetObject method to determine the message identifier of the item being displayed and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtMessageEvents::OnRead

Replaces or enhances the behavior of Microsoft Exchange when reading information from a message.

Quick Info

See IExchExtMessageEvents : IUnknown.

HRESULT OnRead(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message being read and the window whose controls are to be populated.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and populated the window used to display the message. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extension objects or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtMessageEvents::OnRead method when it is about to read the properties of a message so that they can be displayed to the user in a standard form. If an error occurs, OnRead should display an error message and return an error. Microsoft Exchange will not continue to read the message, nor will it display an error message, but will stop the user action that caused the read operation to occur.

This method should call the IExchExtCallback::GetObject method to determine the message identifier of the item being read and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtMessageEvents::OnReadComplete

Enables extension objects to roll back their implementation of the IExchExtMessageEvents::OnRead method in case of an error or to release resources allocated by the OnRead method.

Quick Info

See IExchExtMessageEvents : IUnknown.

HRESULT OnReadComplete(
  LPEXCHEXTCALLBACK lpeecb,
  ULONG ulFlags
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message being read and the window whose controls are to be populated.
ulFlags
EEME_FAILED
The check names operation could not be completed successfully. See the text provided in the definition of the IExchExtMessageEvents interface in this reference.
EEME_COMPLETE_FAILED
See the text provided in the definition of the IExchExtMessageEvents interface in this reference.

Return Values

S_OK
The extension object handled the event. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extensions or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtMessageEvents::OnReadComplete method when it has finished reading the properties of a message for display to the user in a standard form.

If an error occurs, OnReadComplete should display an error message and return an error. Microsoft Exchange will then call each extension object again with OnReadComplete with ulFlags = EEME_FAILED to indicate that the read operation failed. Microsoft Exchange will not continue to read the message, nor will it display an error message, but will stop the user action that caused the read operation.

OnReadComplete should call the IExchExtCallback::GetObject method to determine the message identifier of the item being read and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtMessageEvents::OnSubmit

Replaces or enhances the behavior of Microsoft Exchange when a message has been submitted.

Quick Info

See IExchExtMessageEvents : IUnknown.

HRESULT OnSubmit(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message being submitted and the window whose controls were saved.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and handled the submission on its own. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extensions or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtMessageEvents::OnSubmit method when it is about to submit an open message. At this point, the information will have been written to the message.

If an error occurs, OnSubmit should display an error message and return an error. Microsoft Exchange will not submit the message, nor will it display an error message, but will stop the user action that caused the submit.

This method should call the IExchExtCallback::GetObject method to determine the message identifier of the item being submitted and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtMessageEvents::OnSubmitComplete

Enables extension objects to roll back their implementation of the IExchExtMessageEvents::OnSubmit method in case of an error or to release resources allocated by OnSubmit.

Quick Info

See IExchExtMessageEvents : IUnknown.

VOID OnSubmitComplete(
  LPEXCHEXTCALLBACK lpeecb,
  ULONG ulFlags
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message and the window containing the displayed information.
ulFlags
EEME_FAILED
The check names operation could not be completed successfully. See the text provided in the definition of the IExchExtMessageEvents interface in this reference.
EEME_COMPLETE_FAILED
See the text provided in the definition of the IExchExtMessageEvents interface in this reference.

Remarks

The IExchExtMessageEvents::OnSubmitComplete method is used to enable extension objects to roll back the Microsoft Exchange default implementation of the IExchExtMessageEvents::OnSubmit method. OnSubmitComplete should call the IExchExtCallback::GetObject method to determine the message identifier of the item being submitted and its container. The container is usually a folder, but it can also be a message or an information store.

This method returns VOID because at this point the message should have already been submitted, so it is too late to cancel the operation.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtMessageEvents::OnWrite

Replaces or enhances the behavior of Microsoft Exchange when writing information to a message.

Quick Info

See IExchExtMessageEvents : IUnknown.

HRESULT OnWrite(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message being written and the window whose controls are to be saved.

Return Values

S_OK
The extension object replaced Microsoft Exchange behavior and handled writing out the information on its own. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extension objects or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtMessageEvents::OnWrite method when it is about to write the contents of a standard form to the properties of a message. If an error occurs, the extension object should display an error message and return an error. Microsoft Exchange will not continue to write the message, call another extension object's OnWrite method, or display an error message. However, it will stop the user action that caused the write operation.

This method should call the IExchExtCallback::GetObject method to determine the message identifier of the item being written and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtMessageEvents::OnWriteComplete

Enables extension objects to roll back the Microsoft Exchange default implementation of the IExchExtMessageEvents::OnWrite method in case of an error or to release resources allocated by OnWrite.

Quick Info

See IExchExtMessageEvents : IUnknown.

HRESULT OnWriteComplete(
  LPEXCHEXTCALLBACK lpeecb,
  ULONG ulFlags
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message that was written and the window whose controls are to be saved.
ulFlags
EEME_FAILED
The check names operation could not be completed successfully. See the text provided in the definition of the IExchExtMessageEvents interface in this reference.
EEME_COMPLETE_FAILED
See the text provided in the definition of the IExchExtMessageEvents interface in this reference.

Return Values

S_OK
The extension object successfully rolled back the write operation and freed resources.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extensions or complete the work itself.

Remarks

Microsoft Exchange calls the IExchExtMessageEvents::OnWriteComplete method after it has finished writing the contents of a standard form to the properties of a message. If an error occurs, the extension object should display an error message and return an error. Microsoft Exchange will then call each extension object again with OnWriteComplete with ulFlags = EEME_FAILED to indicate that the write operation failed.

The extension object should free resources used for the write operation.

This method should call the IExchExtCallback::GetObject method to determine the message identifier of the item being written and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject, IExchExtMessageEvents : IUnknown


IExchExtModeless : IUnknown

The IExchExtModeless interface enables modeless extensions to coordinate their actions with Microsoft Exchange.

IExchExtModeless should not be implemented by extensions as another interface on their main extension interface, but should instead be implemented on a separate object with its own independent set of reference counts.

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTMODELESS

Vtable Order

TranslateAccelerator | Enables an extension object to intercept messages before they are processed by the Microsoft Exchange client.
EnableModeless | Notifies an extension object to disable its modeless windows.


IExchExtModeless::EnableModeless

Enables extension objects to enable or disable their modeless windows.

Quick Info

See IExchExtModeless : IUnknown.

HRESULT EnableModeless(
  HWND hwnd,
  BOOL fEnable
);

Parameters

hwnd
[in] Pointer to the handle of the parent window of the modal window being displayed or removed.
fEnable
[in] TRUE when Microsoft Exchange should enable its modeless windows (that is, when the extension has removed a modal window). Set to FALSE when Microsoft Exchange should disable its modeless windows (that is, when the extension is about to display a modal window).

Return Values

S_OK
No error occurred.

Remarks

Microsoft Exchange uses the IExchExtModeless::EnableModeless method to notify extension objects that they should enable or disable their modeless windows. If an extension has registered for modeless behavior using the IExchExtCallback::RegisterModeless method and has called the IExchExtModelessCallBack::AddWindow method, Microsoft Exchange calls the extension's EnableModeless method when it displays or removes a modal window. In the case of creation, the extension object should disable its modeless windows; in the case of removal, the extension object should enable its modeless windows.


IExchExtModeless::TranslateAccelerator

Enables modeless extensions to intercept and handle messages.

Quick Info

See IExchExtModeless : IUnknown.

HRESULT TranslateAccelerator(
  LPMSG pmsg
);

Parameters

pmsg
[in] Pointer to the message.

Return Values

S_OK
The message was handled by the extension object.
S_FALSE
The message was not handled by the extension object.

Remarks

The IExchExtModeless::TranslateAccelerator method is used to enable modeless extension objects to intercept and handle messages. While running in-process, an extension object might need to intercept and handle various messages that would otherwise be handled by Microsoft Exchange. If the extension object has registered for modeless behavior using the IExchExtCallback::RegisterModeless method and has called the IExchExtModelessCallBack::AddWindow method, the Microsoft Exchange client will call TranslateAccelerator whenever it receives a Windows message. If the extension object handles the message, it should return S_OK to prevent Microsoft Exchange from handling the same message.


IExchExtModelessCallback : IUnknown

The IExchExtModelessCallback interface is implemented by the Microsoft Exchange client to coordinate with extension objects using a modeless user interface.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Microsoft Exchange
Called by: | Extension objects
Corresponding pointer type: | LPEXCHEXTMODELESSCALLBACK

Vtable Order

EnableModeless | Enables the Microsoft Exchange client to enable or disable its modeless windows.
AddWindow | Enables Microsoft Exchange to keep track of modeless windows displayed by extension objects.
ReleaseWindow | Enables the Microsoft Exchange client to keep track of modeless windows displayed by extension objects.


IExchExtModelessCallback::AddWindow

Enables Microsoft Exchange to keep track of modeless windows that are displayed by extensions.

Quick Info

See IExchExtModelessCallback : IUnknown.

HRESULT AddWindow()

Return Values

S_OK
No error occurred.

Remarks

Extension objects should call the IExchExtModelessCallback::AddWindow method when they display a modeless window. This method, along with the IExchExtModelessCallback::ReleaseWindow method, enables Microsoft Exchange to keep track of modeless windows that are displayed by extensions. Microsoft Exchange will not terminate until all extension windows have been closed. It is not necessary to call this method multiple times when multiple modeless windows are displayed.

To enable users to exit Microsoft Exchange with one command, modeless extensions should intercept the Microsoft Exchange Exit and Exit and Log off commands on the File menu. By doing so, extensions can prompt the user to save any changes that have been made and then close the user's modeless windows, returning S_FALSE to enable other extensions to close their windows as well. In this way, extensions can cooperate with Microsoft Exchange when a user wants to close all windows and exit.

See Also

IExchExtModelessCallback::ReleaseWindow


IExchExtModelessCallback::EnableModeless

Extension objects should call this method just before they display or remove a modal dialog box, allowing the Microsoft Exchange client to enable or disable its modeless windows.

Quick Info

See IExchExtModelessCallback : IUnknown.

HRESULT EnableModeless(
  HWND hwnd,
  BOOL fEnable
);

Parameters

hwnd
[in] Handle of the parent window of the modal window being displayed or removed.
fEnable
[in] FALSE when your extension is going to display a modal window. Set to TRUE when your extension has removed its modal window.

Return Values

S_OK
No error occurred.

Remarks

If an extension object calls the IExchExtModelessCallback::EnableModeless method when it creates or removes a modal window, the Microsoft Exchange client will disable or enable its modeless windows as appropriate.


IExchExtModelessCallback::ReleaseWindow

Enables the Microsoft Exchange client to be notified when an extension object's modeless windows have been removed.

Quick Info

See IExchExtModelessCallback : IUnknown.

HRESULT ReleaseWindow()

Return Values

S_OK
No error occurred.

Remarks

Extension objects should call the IExchExtModelessCallback::ReleaseWindow method when they release all their modeless windows. This method, along with the IExchExtModelessCallback::AddWindow method, enables the Microsoft Exchange client to keep track of modeless windows displayed by extensions. Microsoft Exchange cannot be closed until all extension windows have been closed.

Extensions are expected to make an equal number of calls to AddWindow and ReleaseWindow. For example, if an extension calls AddWindow for every modeless window it displays, it should call ReleaseWindow for each modeless window it closes. Similarly, if an extension calls AddWindow only once for its modeless windows, it should call ReleaseWindow only once when the last of the extension's modeless windows is closed.

To enable users to exit Microsoft Exchange with one command, modeless extensions should intercept the Exit and Exit and Log off commands on the Microsoft Exchange File menu. By doing so, extensions can prompt the user to save any changes that have been made and then close the user's modeless windows, returning S_FALSE to enable other extensions to close their windows as well. In this way, extensions can cooperate with Microsoft Exchange when a user wants to close all windows and exit.

See Also

IExchExtModelessCallback::AddWindow


IExchExtPropertySheets : IUnknown

The IExchExtPropertySheets interface is used to enable extension objects to append pages to Microsoft Exchange property sheets. IExchExtPropertySheets is used only in the EECONTEXT_PROPERTYSHEETS context.

For more information on property sheets, see the Win32 documentation.

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTPROPERTYSHEETS

Vtable Order

GetMaxPageCount | Returns the maximum number of pages an extension will add to the property sheet.
GetPages | Adds property sheet pages to the current list of pages.
FreePages | Frees any resources allocated by the GetPages method.


IExchExtPropertySheets::FreePages

Frees all resources allocated by the IExchExtPropertSheets::GetPages method.

Quick Info

See IExchExtPropertySheets : IUnknown.

VOID FreePages(
  LPPROPSHEETPAGE lppsp,
  ULONG ulFlags,
  ULONG cpsp
);

Parameters

lppsp
[in] Pointer to a pointer to the first page of a list of property sheet pages previously added. The extension object should not free the memory associated with the lppsp parameter because this parameter points to an element of an array allocated by Microsoft Exchange.
cpsp
Input parameter containing the number of property sheet pages added to the lppsp parameter by the extension object.
ulFlags
[in] Bitmask of flags used to indicate the type of property sheet whose pages are being freed. The following flags can be set:
EEPS_MESSAGE
A message's property sheet.
EEPS_FOLDER
A folder's property sheet.
EEPS_STORE
A store's property sheet.
EEPS_TOOLSOPTIONS
The Tools.Options property sheet.

Remarks

Microsoft Exchange calls the IExchExtPropertySheets::FreePages method when the user closes the properties dialog box and Microsoft Exchange prompts the extension objects to free their pages and other associated resources and interfaces.


IExchExtPropertySheets::GetMaxPageCount

Returns a value for the maximum number of pages an extension object will add to the property sheet.

Quick Info

See IExchExtPropertySheets : IUnknown.

ULONG GetMaxPageCount(
  ULONG ulFlags
);

Parameters

ulFlags
[in] Bitmask of flags used to indicate the type of property sheet being displayed. The following flags can be set:
EEPS_MESSAGE
A message's property sheet.
EEPS_FOLDER
A folder's property sheet.
EEPS_STORE
A store's property sheet.
EEPS_TOOLSOPTIONS
The Tools.Options property sheet.

Remarks

Microsoft Exchange calls the IExchExtPropertySheets::GetMaxPageCount method when it is allocating memory for the property sheet page array. The value returned by this method represents the maximum number of pages to be shown at any one time, not the sum of all property sheet pages for all objects.


IExchExtPropertySheets::GetPages

Adds property sheet pages to the current list of pages.

Quick Info

See IExchExtPropertySheets : IUnknown.

HRESULT GetPages(
  LPEXCHEXTCALLBACK lpeecb,
  ULONG ulFlags,
  LPPROPSHEETPAGE lppsp,
  ULONG FAR * lpcpsp
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface.
ulFlags
[in] Bitmask of flags used to indicate the type of property sheet being displayed. The following flags can be set:
EEPS_MESSAGE
A message's property sheet.
EEPS_FOLDER
A folder's property sheet.
EEPS_STORE
A store's property sheet.
EEPS_TOOLSOPTIONS
The Tools.Options property sheet.
lppsp
[out] Pointer to a pointer to a list of property sheet pages the extension will fill.
lpcpsp
[out] Pointer to a variable containing the number of property sheet pages actually filled in by the extension object. The number must be less than or equal to the maximum requested by the IExchExtPropertySheets::GetMaxPageCount method.

Return Values

S_OK
No error occurred.

Remarks

Microsoft Exchange calls the IExchExtPropertySheets::GetPages method when it is building a property sheet and needs each extension object to fill in any pages that will be appended. Microsoft Exchange, not the extension object, handles the allocation of the page array pointed to by the lppsp parameter. Microsoft Exchange allocates this array after it calls the extension object and gets the value returned by the IExchExtPropertySheets::GetMaxPageCount method. The extension object should not allocate its own pages in the lppsp parameter, nor should it free them when the IExchExtPropertySheets::FreePages method is called. Instead, it should free the additional resources added during the call to GetPages.

The Windows 95 property sheet structures are used to describe the pages.


IExchExtSessionEvents : IUnknown

The IExchExtSessionEvents interface is used to enable an extension object to respond to the arrival of new messages. This interface can be used to create rules-based inbox processing and other custom handling of new messages. IExchExtSessionEvents is used only in the EECONTEXT_SESSION context.

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTSESSIONEVENTS

Vtable Order

OnDelivery Replaces or enhances the behavior of Microsoft Exchange when a new message arrives.


IExchExtSessionEvents::OnDelivery

Replaces or enhances the behavior of Microsoft Exchange when a new message arrives.

Quick Info

See IExchExtSessionEvents : IUnknown.

HRESULT OnDelivery(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeecb parameter is used to determine information about the message or messages which have arrived.

Return Values

S_OK
The extension object replaced Microsoft Exchange default behavior with its own behavior. Microsoft Exchange will consider the task handled.
S_FALSE
The extension object did nothing or added additional behavior. Microsoft Exchange will continue to call extension objects or complete the work itself.

Remarks

The IExchExtSessionEvents::OnDelivery method is used to replace or enhance the behavior of Microsoft Exchange when a new message arrives. If an error occurs, OnDelivery should display an error message and return an error value. Microsoft Exchange will not notify the user about the new message, nor will it display an error message or continue to call extension objects in response to the new message.

When a new message arrives, the extension object obtains its message identifier by calling the IExchExtCallback::GetObject method.

See Also

IExchExtCallback::GetObject


IExchExtUserEvents : IUnknown

The IExchExtUserEvents interface is used to enable an extension object to handle changes to the currently-selected list box item, text, or object. IExchExtUserEvents is used in all contexts except EECONTEXT_TASK and EECONTEXT_SESSION.

This interface is optional.

Quick Info

Header file: | EXCHEXT.H
Exposed by: | Extension objects
Implemented by: | Extension objects
Called by: | Microsoft Exchange
Corresponding pointer type: | LPEXCHEXTUSEREVENTS

Vtable Order

OnSelectionChange | Enables the extension object to enable, disable, or update visual elements.
OnObjectChange | Enables the extension object to enable, disable, or update visual elements in an object.


IExchExtUserEvents::OnObjectChange

Enables the extension object to enable, disable, or update visual elements in an object displayed in the window.

Quick Info

See IExchExtUserEvents : IUnknown.

VOID OnObjectChange(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to the IExchExtCallback interface. The lpeech parameter is used to determine information about the selection.

Remarks

Microsoft Exchange calls the IExchExtUserEvents::OnObjectChange method when the object within the container displayed by the Microsoft Exchange window changes. For example, this method is called when a user changes a folder whose contents are displayed in the Viewer, or when the user moves to the next message in cases where the message's class permits the same window to be used.

OnObjectChange should call the IExchExtCallback::GetObject method to determine the identifier of the changed object and its container. The container is usually a folder, but it can also be a message or an information store.

See Also

IExchExtCallback::GetObject


IExchExtUserEvents::OnSelectionChange

Enables the extension object to enable, disable, or update visual elements.

Quick Info

See IExchExtUserEvents : IUnknown.

VOID OnSelectionChange(
  LPEXCHEXTCALLBACK lpeecb
);

Parameters

lpeecb
[in] Pointer to an IExchExtCallback interface that is used to determine information about the currently selected item.

Remarks

Microsoft Exchange calls the IExchExtUserEvents::OnSelectionChange method when the currently selected message, folder or store changes in a Microsoft Exchange window. This method is also called when a selection in a list box changes or when the current selection of text in a form changes. For example, this method is called when an item is selected in a Viewer list box, or when text is selected in a note form. It is also called when the user changes the currently selected message or folder.

This method might be called very frequently and should therefore be implemented efficiently.

This method should call the IExchExtCallback::GetObject method to determine the identifier of the newly selected object and its container.

See Also

IExchExtCallback::GetObject


Microsoft Exchange Client View Descriptor Data Format

Many applications written for Microsoft Exchange are designed to manipulate views. An application may, for example, programmatically create views for its folder application, or an application may simply include functionality to read or modify existing view definitions. The following information provides developers with the information necessary to create, read, modify, and delete any of the views used by Microsoft Exchange.

Successful implementation of code designed to manipulate views requires proficiency in the C language and a good understanding of the Win32 Messaging Application Programming Interface (MAPI).

Disclaimer

This information on the Microsoft Exchange Client View Descriptor Data Format applies only to the Microsoft Exchange client version 4.0. This is not a part of the MAPI specification. Other MAPI clients, as well as future versions of the Microsoft Exchange client, may not be compatible with the view descriptor functionality built according to the information supplied here.


Elements of Views

Element | Description
Display name | The view's display name identifies the view in the Microsoft Exchange client. The display name is used on the View menu to identify the named views that are available and it is used in the View dialog box to identify the view being modified.
Version | The version of the view descriptor format shipped with Windows 95 is currently 0x00000008 and is likely to change in future releases of Microsoft Exchange. This is the version documented in this guide. Your application should not read or write view descriptors with version numbers greater than eight unless you know the format. If the view descriptor format is changed, the version number will be incremented so that your application will not attempt to read these views.
Message class | The message class is used to find views among messages in a folder. All views must have the message class IPM.Microsoft.FolderDesign.NamedView to be recognized by Microsoft Exchange.
Columns | Views consist of a collection of columns where each column represents a MAPI property such as the display name and the column width.
Categorization | Messages in a view can be categorized, or grouped, so that messages with the same property values appear together in the viewer. The view descriptor maintains a count of the number of categorized columns and the sort order of those groupings. The categorized columns are always the leftmost columns in the viewer.
Conversation threading | Conversation threading is used to indent the responses to items posted into a folder. Each response is indented to the right of the item that it is responding to. This is important for discussion public folder applications. Conversation threading is displayed when the PR_CONVERSATION_INDEX property is added to the view descriptor and sorted on.
Sorting | View descriptors specify a particular column to sort on and also whether the sort direction is ascending or descending. The sort column must be a column that is displayed in the view.
Filtering | View descriptors support filters, in the form of MAPI row restrictions, so that the right pane of the Microsoft Exchange viewer can show a subset of all the messages in a folder.
State | Microsoft Exchange supports views with groupings so that messages with properties of the same value are grouped together in the viewer. This is important for categorizing information. Groups can be expanded or collapsed to show the messages within the group. The expand or collapse state is saved in a view descriptor so that the state can be returned when the view is used again. For new views, the collapse state will be NULL.


Locating View Descriptors Using MAPI

View descriptors are stored as hidden messages in many locations within a MAPI message store. View descriptors are messages known as associated information. These messages are not visible to the user; they are accessible using MAPI.

There are four types of view descriptors: common, personal, folder, and current.


Common Views

Common views are global in usage, available no matter what folder the user is looking in. Common views are located in the top bin of the Views.Personal Views cascade menu. Common views, although stored in a private message store, are common to all users as they are installed during setup of the client and cannot be modified. Common views are stored in the default message store.

To locate common view messages using MAPI
  1. Determine the default store.
  2. Read the PR_VALID_FOLDER_MASK property on the store object. This property indicates the validity of the entry identifiers of special folders in the store. If the FOLDER_COMMON_VIEWS_VALID flag is set, the common views are located in this store.
  3. Read the PR_COMMON_VIEWS_ENTRYID property on the store object to get the entry identifier of the hidden common views folder.
  4. Read the messages from the folder specified above. All views have the message class IPM.Microsoft.FolderDesign.NamedView.


Personal Views

Personal views are defined by the user, and like common views, are global in usage. That is, they are available no matter what folder the user is looking in. Personal views are located in the bottom bin of the View.Personal Views cascade menu. Personal views are stored in a private message store and are only available to the user who created them. Personal view descriptors are stored in the default message store.

To locate personal view messages using MAPI
  1. Determine the default store.
  2. Read the PR_VALID_FOLDER_MASK property on the store object. This property indicates the validity of the entry identifiers of special folders in the store. If the FOLDER_VIEWS_ENTRYID flag is set, the personal views are located in this store.
  3. The user's personal views will be stored in the Views folder directly under the root of the message store.
  4. Read the messages from the folder specified above. Views all have the message class IPM.Microsoft.FolderDesign.NamedView.


Folder Views

Folder views are defined on a folder by folder basis. They are only accessible when the folder is the current folder and its messages are displayed in the right pane. Folder views are located in the View.Folder Views cascade menu. Folder views are stored as hidden messages in the folder and are accessible by anyone having read access to the folder. Users can only create views on public folders for which they have owner permissions. Users cannot create private views on public folders.

To locate folder view messages
  • Locate the messages in the folder with the message class IPM.Microsoft.FolderDesign.NamedView.


Current Views

Current — or unnamed — views are derived from named views but have been modified through the Microsoft Exchange viewer or the view design commands on the View menu.

When a user modifies a view by dragging the column header, using the View menu commands or by other means, the view will no longer be the same as a named view. In order to retain this new view for later uses of the folder, the view is saved as the current view on the folder. These current views are used when a view is saved and recalled automatically at the time the user selects something else and then returns to the folder. Current views, especially useful for public folders, allow every user to have a custom view on the folder that is saved between uses of the folder.

Each folder, whether private or public, retains a view message in the IPM.Microsoft.FolderDesign.NamedView hidden folder. Whenever a folder is accessed for the first time, a view is created in this folder with a property PR_VD_VIEW_FOLDER, which is a MAPI record key, linking it to the folder being used. This view will initially have a link pointing to the named view that is the current view, but, if the current view is modified, this view will contain the view descriptor used to render the view. If a current view doesn't exist, Microsoft Exchange will use the initial view. If an initial view is not defined, Microsoft Exchange will use the normal view.


Reading View Descriptors

The subtopics in this section discuss the details of reading the various components of a view descriptor. Saving a view descriptor is not covered in this document as it is simply the reverse of reading.

Before reading the view descriptor, you will need to open two properties to read as a stream. These properties are PR_VD_STRINGS and PR_VD_BINARY. These are referred to as the string and binary stream, respectively.


Reading a View's Display Name

The display name (PT_STRING8) is read from the view message using property ID = 0x7006.


Reading a View's Version

The version number is read from the PR_VD_VERSION property on the view.


Reading a View's Flags

The view descriptor flags are read from the view message by reading the PR_VD_FLAGS property. Currently, there is only one flag which defines the sort order of the messages in the folder. The sort order is applied to the messages after they are grouped (optional). Each group of messages will be grouped in ascending or descending order based on this flag. The flag VDF_SORTDESCENDING should be set for descending order or cleared for ascending order. The sort order of the grouped columns is defined separately in ulCatSort. All other bits are reserved and must be cleared.


Reading a View's Folder Record Key

For current views stored in the Views folder of the default store it is useful to know which folder they apply to. All view descriptor messages have a PR_VD_VIEW_FOLDER property, which is a record key that points to the folder.


Reading a View's Columns

The columns are read from the binary stream immediately after the VD structure is read. The VD structure is the first block of data in this stream.

The cvcd member of the VD structure contains the number of columns. The number of columns in the view will be stored in pvd->cvcd, where pvd is a pointer to a VD. You will need to declare a pointer to the pvcd parameter in the VCD structure to hold the view column descriptors. With this information, the following steps are necessary to read in the view's column descriptors.

  1. Allocate memory for the array of VCD structures. The size of the allocation must be the number of the columns in the view (cvcd) plus one, times the size of the VCD structure. There is one extra element to hold the parent display column which is appended on the end.
  2. For each VCD structure,
    1. Read the structure from the stream.
    2. If the VCD structure has a named property (that is, VCDF_NAMEDPROP set in pvcd->ulFlags), you must read it in. To read the named property, allocate a pointer to hold a GUID structure, and read the GUID from the binary stream. The pointer to the GUID structure should be saved in
    16. pvcd->mnid->lpguid.

      If the named property has a string (that is, pvcd->mnid->ulKind == MNID_STRING), read it from the binary stream. The first DWORD is the length of the string, the string immediately follows in the stream. The pointer to the string should be saved in

      pvcd->mnid-> lpwstrName.

    17. Read the column display name from the string stream and store the pointer with the column descriptor.

Because named property identifiers are imbedded between VCD structures in the stream, you cannot read all VCD structures at once.

The 'drag column' must be the first column in the view descriptor. This column is used to drag-select a number of messages without invoking the move message operation. This column can be seen in the heading of the main viewer as a narrow rectangle.

The 'action icon' column is added to a view column descriptor for the remote views. This column indicates whether the message is to be downloaded or not.

The 'parent display' column is a column added to the end of views defined in the Finder. This column is labeled 'In Folder' in the finder's viewer.


Reading a View's Linked Entry Identifier

If linked, the PR_VD_LINK_TO property will contain the entry identifier of the folder this link applies to. You must then read the VD structure and get the entry identifier of the view descriptor this view is linked to. If PR_VD_LINK_TO is set, the current view descriptor is not used.


Reading a View's State

The expand or collapse state is read from a PT_BINARY property on the view message with property tag PR_VD_COLLAPSE_STATE (0x7003). The binary bytes are then simply set into the current MAPI table using the IMAPITable::SetCollapseState method. For a newly created view, this property should be set to NULL.


Reading a View's Row Restriction

The following steps are necessary to read in the view's row restriction. The restriction's data in the two streams comes immediately after the VCD structures. Therefore, the VCD structures must be read before the restriction.

  1. Declare a pointer to an SRestriction (presRoot) to retain the root level of the restriction. Set the pointer to NULL.
  2. Read the restriction's main data structure into a temporary SRestriction (resT) by reading sizeof (SRestriction) bytes into this structure from the binary stream.
  3. Allocate sizeof (SRestriction) bytes for another SRestriction (pres) by either calling the MAPI function MAPIAllocateBuffer or MAPIAllocateMore, depending on whether presRoot has previously been allocated.
  4. Set a variable (ppres) to point to this block of memory.
  5. Set pres->rt to resT->rt and then do the following:
  6. Allocate a property value pointer: LPSPropValue * ppval.

Depending on the value for the restriction type (rt), process as follows:

switch (pres->rt)

case RES_CONTENT:
ppval = &pres->res.resContent.lpProp
//Read the property values from the streams.//
break;

case RES_PROPERTY:
ppval = &pres->res.resProperty.lpProp
//Read the property values from the streams.//
break;

case RES_SUBRESTRICTION:
ppres = &pres->res.resSub.lpRes;
*ppres = NULL;
//Forces the following recursive call to allocate memory for ppres.//
//Call to step 2 to read the subrestriction.//
//Then, ppres should be passed in to point to the next restriction in the stream.//
break;

case RES_NOT:
ppres = &pres->res.resNot.lpRes;
*ppres = NULL;
//Recursively call to step 2 to read the negated sub-restriction. //

case RES_AND:
  case RES_OR:
ppres = &pres->res.resAnd.lpRes
//Declare an unsigned long variable: ULONG cres//
cres = pres->res.resAnd.cRes

// Remember the number of restrictions being AND'd or OR'd. Append ppres onto the end of presRoot by calling MAPIAllocateMore.//

presNext (LPSRestriction * presNext)
//Point to the next restriction.//

(pres->res.resAnd.lpRes)

presLast (LPSRestriction * presLast)
//Point to the last restriction. //

(pres->res.resAnd.lpRes)

//For each AND or OR'd restriction, recursively call to step 2 to read the AND/OR clauses. //
//Then, ppresNext should be passed in to point to the next restriction in the stream.//

case RES_COMMENT:
//Read the property values from the stream into pres.//
pres->res.resComment.lpRes = NULL
//To force the recursive call below to allocate memory for pres. This pointer was saved but is no longer valid.//

pres->res.resComment.cValues = resT ->res.resComment.cValues
pres->res.resComment.lpRes = resT ->res.resComment.lpRes
pres->res.resComment.lpProp = resT->res.resComment.lpProp

//Recursively call to step 2 to read the sub-restriction. //

pres->res.resComment.lpRes

//Then, ppresNext should be passed in to point to the next restriction in the stream.//

At the end of this algorithm, the restriction has been read completely.


Reading a View's Restriction Property Values

When reading a restriction from the view description streams, there are cases where you must read the property values. For more information, see Reading a View's Row Restriction.

The procedure for reading the property values for a view restriction assumes that the following parameters were passed to this function:

Pstm
A stream on the PR_VD_BINARY property.
pstmSz
A stream on the PR_VD_STRINGS property.
pib
An input buffer.
presRoot
The root of the restriction being read.
pcval
Pointer to the number of property values to read.
ppval
Pointer to an array of pointers to property values to read.
To read the property values for a view restriction
  1. Read a ULONG from the binary stream to get the count of the number of property values to read. If the count is zero, the view descriptor is invalid.
  2. Use MAPIAllocateMore to enlarge the memory allocated to presRoot by the number of properties to be read times the size of SPropValue.
  3. Declare a pointer to a property value (SPropValue * pval)
  4. Read the properties into the end of the presRoot. This can be done all at once because they are packed in the binary stream and point pval to the first property read in.
  5. For each property value read in:

    If pval->ulPropTag == PT_BINARY, append the binary bytes onto the end of presRoot by using MAPIAllocateMore to allocate the number of bytes specified in pval->Value.bin.cb and then reading the bytes from the binary stream into the newly allocated space.

    If pval->ulPropTag == PT_TSTRING, read the string from the string stream. Allocate sufficient memory to the end of presRoot by using MAPIAllocateMore, and then copy the string into the newly allocated space.

For all other properties, there is no additional information to read.


View Data Types and Structures

The following are C language data types and structures used by Microsoft Exchange. They are provided to help you when writing your code that reads and writes views. Many of the members of these structures are relevant only during run time, but for performance reasons the whole structure is written into the PR_VD_BINARY property. Run-time specific values are reset by Microsoft Exchange when reading views. Although your application can read, manipulate, and write views in whichever way you choose, these structures make development and compatibility easier.


VD

The VD structure is used to specify a view during run time. The structure is the first block of data written to the PR_VD_BINARY property when a view is saved. Data specified by pointers in this structure is appended after this structure in the PR_VD_BINARY property. When the VD structure is read in, the pointers are invalid.

typedef struct VD
{
    ULONG ulReserved1;
    ULONG ulReserved2;
    ULONG ulVersion;
    ULONG ulReserved3;
    ULONG ulReserved4;
    ULONG cvcd;
    ULONG ivcdSort;
    ULONG cCat;
    ULONG ulCatSort;
    ULONG ulReserved5;
    ULONG ulReserved6;
    ULONG ulReserved7;
    ULONG ulReserved8;
    ULONG ulReserved9;
    ULONG ulReserved10;
} VD;

Members

ulVersion
Version of the view descriptor format.
cvcd
Number of view column descriptors.
ivcdSort
Index into the array of view column descriptors indicating the primary sort column. This column is indicated in the viewer's column header by a upward or downward pointing triangle corresponding to ascending and descending sort order, respectively.
cCat
Number of categorized columns in the view. Microsoft Exchange allows up to four levels of categorization. This is zero if the view is not categorized.
ulCatSort
Sort order flag for the categorized columns. The most significant bit is the sort order flag for the highest level (leftmost) grouping in the viewer; the second most significant bit is the sort order for the second highest level grouping, etc. The following flag can be set:
VDF_SORTDESCENDING
Indicates descending sort orders; if cleared indicates ascending sort orders.
cbCollapseState
Number of bytes in lpbCollapseState.
lpbCollapseState
Pointer to bytes containing the saved expand or collapse state for categorized views.
ulReserved1…ulReserved10
These are reserved and must be NULL.


VCD

The VCD structure holds data used for defining a column in a view.

typedef struct VCD
{
    ULONG vcds;
    ULONG cx;
    ULONG ulReserved1;
    ULONG ulFlags;
    ULONG ulReserved2;
    ULONG ulReserved3;
    MAPINAMEID mnid;
} VCD;

Members

vcds
The view column descriptor selector (vcds) contains constants identifying the property in the column. The property values are list in remarks following.
cx
Column width in characters or pixels. Whenever possible the column width should be specified in character widths to avoid problems with views appearing distorted on machines with different font sizes.
ulFlags
Bitmask of flags associated with a view column descriptor. Corresponding properties are listed in remarks following. These flags can be set:
VCDF_NOT_SORTABLE
Indicates the column cannot be sorted.
VCDF_SORTDESCENDING
Indicates a column whose default is to sort in descending order and cleared when the default is in ascending order.
VCDF_BITMAP
Indicates the column width value is measured in pixels.
VCDF_MOVABLE
Indicates whether the column can be moved relative to other columns in the view.
VCDF_COLUMNSDLG
Indicates the column is to be displayed in the column dialog box.
VCDF_SORTDLG
Indicates the column is to be displayed in the sort dialog box.
VCDF_GROUPDLG
Indicates the column is to be displayed in the group dialog box.
VCDF_RCOLUMNSDLG
Indicates the column is to be displayed in the remote columns dialog box.
VCDF_MULTIVALUED
Indicates the column is multivalued.
VCDF_NAMEDPROP
Indicates when the mnid member of the VCD structure contains a named MAPI property to be displayed in the column. This also requires reading the named property information from the binary stream.

All other flags are reserved and must be cleared.

mnid
MAPI name identifier for the column.
ulReserved1…ulReserved10
These are reserved and must be NULL.

Remarks

The following chart lists the vcds value and the corresponding MAPI property.

vcds value | Corresponding property to display
VCDS_HASATTACH | PR_HASATTACH
VCDS_MESSAGE_CLASS | PR_MESSAGE_CLASS
VCDS_IMPORTANCE | PR_IMPORTANCE
VCDS_SENSITIVITY | PR_SENSITIVITY
VCDS_SENDER_NAME | PR_SENT_REPRESENTING_NAME
VCDS_DISPLAY_TO | PR_DISPLAY_TO
VCDS_SUBJECT | PR_SUBJECT
VCDS_RECEIVED_TIME | PR_MESSAGE_DELIVERY_TIME
VCDS_SUBMIT_TIME | PR_CLIENT_SUBMIT_TIME
VCDS_MESSAGE_SIZE | PR_MESSAGE_SIZE
VCDS_DISPLAY_NAME | PR_DISPLAY_NAME
VCDS_COMMENT | PR_COMMENT
VCDS_PROVIDER_DISPLAY | PR_PROVIDER_DISPLAY
VCDS_BODY | PR_BODY
VCDS_PARENT_DISPLAY | PR_PARENT_DISPLAY
VCDS_CONVERSATION_TOPIC | PR_CONVERSATION_TOPIC
VCDS_CONVERSATION_INDEX | PR_CONVERSATION_INDEX
VCDS_COUNT_TIME | PR_MESSAGE_DOWNLOAD_TIME

The following chart shows the view column descriptor selector (vcds), column width required, and the applicable view column descriptor flag (vcdf):

vcds Corresponding Flags

VCDS_… | cx | VCDF_
BLANK | 7 | BITMAP, NO_CUSTOM, NOT_SORTABLE
ACTION_ICON | 20 | BITMAP, CENTER_JUSTIFY, SORTDESCENDING, SORTDLG, RCOLUMNSDLG
IMPORTANCE | 10 | BITMAP, CENTER_JUSTIFY, SORTDESCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
SENSITIVITY | 20 | LEFT_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
MESSAGE_CLASS | 20 | BITMAP, CENTER_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
HASATTACH | 13 | BITMAP, CENTER_JUSTIFY, SORTDESCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
SENDER_NAME | 23 | LEFT_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, RCOLUMNSDLG, SORTDLG, GROUPDLG
DISPLAY_TO | 20 | LEFT_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
SUBJECT | 39 | LEFT_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
RECEIVED_TIME | 26 | LEFT_JUSTIFY, SORTDESCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
SUBMIT_TIME | 26 | LEFT_JUSTIFY, SORTDESCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG
MESSAGE_SIZE | 9 | RIGHT_JUSTIFY, SORTDESCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG, RCOLUMNSDLG
MSGSTORE_ICON | 20 | CENTER_JUSTIFY, BITMAP, NOT_SORTABLE, NO_CUSTOM
FOLDER_ICON | 20 | CENTER_JUSTIFY, BITMAP, NOT_SORTABLE, NO_CUSTOM
DISPLAY_NAME | 60 | LEFT_JUSTIFY, SORTASCENDING
COUNT_TIME | 18 | RIGHT_JUSTIFY, SORTDESCENDING, SORTDLG, RCOLUMNSDLG
BODY | 20 | LEFT_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG
PARENT_DISPLAY | 20 | LEFT_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG
CONVERSATION_TOPIC | 20 | LEFT_JUSTIFY, SORTASCENDING, MOVEABLE, COLUMNSDLG, SORTDLG, GROUPDLG
CONVERSATION_INDEX | 1 | BITMAP, NO_CUSTOM, SORTDLG


Setting the Initial View

Folders allow for an initial view to be chosen for display when a user selects a folder not previously used. The initial view is saved by storing the entry identifier of the view descriptor message into the PR_DEFAULT_VIEW_ENTRYID property on the folder. If no default view is specified, the normal view is used as the default. There is always a normal view.


Limitations

There are restrictions in the way that views can be manipulated. When Microsoft Exchange is running, it is not possible to determine what the current view is nor is it possible to set the current view programmatically.


Programming Microsoft Exchange Message and Folder Links

Disclaimer

The following information on links to messages applies only to the Microsoft Exchange Client version 4.0. Other MAPI clients, as well as future versions of the Microsoft Exchange Client, may not be compatible with links built according to the information supplied here.


Overview

MAPI defines methods for attaching messages, links to files, and files to other messages. It does not define methods for attaching folders or for attaching links to messages. The Microsoft Exchange Client has defined its own methods for attaching links to folders and links to messages. This document explains how to create attachments in a message that the Microsoft Exchange Client version 4.0 will recognize as links to folders or messages. Other MAPI clients, as well as future versions of the Microsoft Exchange Client, may not be compatible with links built according to the information supplied here.

A folder link is an attached file in a specific format; its name must end with the extension .XNK. Microsoft Exchange designates itself as the handler for this file extension when it is installed. An .XNK file contains two kinds of information. First, there is the path to the folder, which is a list of entry identifiers: the entry identifiers of the folder, all its parent folders, and the message store in which it resides. Then there is display information: the position, size, and display elements present in a Microsoft Exchange viewer. Together, this gives Microsoft Exchange all the information needed to display the folder. Folder links may be placed in the filesystem, or attached to a message by value like any file. The exact structure of the attachment is defined in _LINKS.H.

A message link is a structured storage object. Message links can be attached to other messages, but not placed in the filesystem. Within the structured storage are four or five streams, each containing one piece of information, including: the entry identifiers of the message, its parent folder, and the message store in which it resides; the subject of the message; and a metafile used to portray the link in the outer message (this one is optional). The storage also contains the CLSID of an OLE server implemented by Microsoft Exchange, that can interpret the storage and launch a viewer on the linked message. The stream names and CLSID are defined in MSGLINK.CPP; in summary:

MailMsgAttMdb
MailMsgAttFld
MailMsgAttMsg
MailMsgAttSubject
MailMsgAttIcon


Using Folder and Message Links

Links are most useful when you have a shared message store, such as the Microsoft® Exchange Server public folders, Lotus Notes, or the Microsoft Mail Server shared folders. One common use of links is to inform people, through the use of e-mail, of the presence of a new shared folder or message. Other people will not generally be able to follow links to your own personal messages or folders. (Links within a personal folder store may still be very useful, for instance, if you are compiling information for distribution and wish to cross-link items.)

The Microsoft Exchange Client can both create and read folder links (.XNK files). To create a folder link in the filesystem, select the folder in the scope (left) pane of the Microsoft Exchange viewer, choose Create Shortcut from the File menu, and enter the path of the file you want. To open a Microsoft Exchange viewer on the folder named in the link, use the /t command line option. On Windows NT or Windows 95,

exchng32 /t foo.xnk

and on Windows 3.1 or Windows for Workgroups,

exchng /t foo.xnk

This command always creates a new viewer window; if Microsoft Exchange is already running, it does not replace the folder currently being viewed with the linked folder.

Folder links can also be attached to messages as ordinary attached files. Double-clicking on an attached folder link also causes Microsoft Exchange to open a new window for viewing the linked folder.

The Microsoft Exchange Client can create and read message links in other messages. To create a message link in another message, choose the Message command from the Insert menu. In the Insert as radio button group of the resulting dialog box, select Link attachment to original item, then choose a message from the listbox. To activate a linked message, simply double-click it; Microsoft Exchange displays the message in a new window, using the appropriate form.


Sample Programs

Three separate command-line programs illustrate embedding a link to an existing message in a new message (LinkMM.exe); embedding a link to a folder in a message (LinkFM.exe); and creating a folder link in a file (LinkFF.exe).

The sample code is available for downloading from the MAPI FTP site: ftp://ftp.microsoft.com/developr/mapi/samples/links.cli/links.zip.


Building the Sample Programs

To build the sample programs, you must have the Platform SDK installed. It is not necessary to install the MAPI samples, although you may find that useful. The PATH, INCLUDE, and LIB environment variables must be set up according to SETENV.BAT in the SDK. Copy all the sample files (listed below) to an empty directory, change to that directory, and use NMAKE.EXE to build the sample programs. Some command examples follow.

To build debug versions of all three programs, type:

nmake

To build retail versions of all three programs, use the NODEBUG flag:

nmake NODEBUG=1

To build the debug version of one program, use its name:

nmake linkmm.exe

To build the retail versions of two programs, use their names:

nmake NODEBUG=1 linkmm.exe linkfm.exe


File List

File | Description
_links.h | Defines structures and internal functions.
fldlink.cpp | Reusable functions for creating folder links.
msglink.cpp | Reusable functions for creating message links.
linkutl.cpp | Common code for both types of links.
linkff.cpp | Creates a .XNK file, given a folder path.
linkfm.cpp | Creates a message with a folder link attachment, given a folder path.
linkmm.cpp | Creates a message with a message link attachment, given a folder path and partial message subject.
makefile | Builds all three samples.
fldlink.ico | Suggested icon for folder links.
msglink.ico | Suggested icon for message links.
links.rc | Resource file used for all three samples.
_resrc.h | Resource identifiers used for all three samples.
readme.txt |


Link Message to Message (linkmm.exe)

This command-line program creates a new message in the default Inbox, and embeds a link to another message there. The folder path and partial subject of the linked message are taken from the command line. Assume for a moment that you have a message entitled "Hi, Mom" in your Inbox, and another message entitled "Lincoln project status summary" in a top-level Microsoft Exchange Server public folder named Projects. You would type

linkmm Inbox/Hi

to create a new message with a link to the first, and

linkmm Public Folders/All Public Folders/Projects/Lincoln project status

to create another new message with a link to the second message. (No quotes are necessary on the command line for linkmm, and it is not necessary to name the message store if you want the default store.)


Link Folder to Message (linkfm.exe)

This command-line program creates a new message in the default Inbox, and embeds a link to a folder there. The folder path is taken from the command line. Assume for a moment that you have a top-level Microsoft Exchange server public folder named Projects. You would type

linkmm Inbox

to create a new message with a link to your Inbox, and

linkmm Public Folders/All Public Folders/Projects

to create another new message with a link to your public folder. (No quotes are necessary on the command line for linkfm, and it is not necessary to name the message store if you want the default store.)


Link Folder to File (linkff.exe)

This command-line program creates an .XNK file containing a link to a folder. The folder path and the file path are both taken from the command line. Assume for a moment that you have a top-level Microsoft Exchange Server public folder named Projects. You would type

linkff Inbox inbox.xnk

to place a link to your Inbox in INBOX.XNK, and

linkff "Public Folders/All Public Folders/Projects" c:\temp\proj.xnk

to place a link to your public folder in c:\temp\pproj.xnk. (Quotes are necessary on the command line for linkff; it is not necessary to name the message store if you want the default store.)


Reusable Code

In general, the source files with the same names as the executable files contain throwaway wrapper code, and the others have functions you may be able to use "as is." Even if you cannot just reuse them, they are what you'll have to read in order to write your own. Here is a quick list of the most interesting functions. All return S_OK if successful, and a fatal HRESULT otherwise; there are no warnings.


WriteFolderLink

The WriteFolderLink function takes a list of entry identifiers leading to the linked folder, formats the folder link, and writes it to pstream.

STDAPI WriteFolderLink(
  LPENTRYLIST pel,
  LPSTREAM pstream
);

Parameters

pel
[in] List of entry identifiers leading to the linked folder: message store, IPM root, . . ., parent folder, then the linked folder.
pstream
[in] Stream to which the link is written.


LinkFolderToNewMessage

The LinkFolderToNewMessage function takes a list of entry identifiers leading to the linked folder, formats the folder link, and places it in an attachment to pmsg, along with rendering and positioning information.

STDAPI LinkFolderToNewMessage(
  LPMESSAGE pmsg,
  LPENTRYLIST pel,
  LPSTR szFileName,
  LPSTR szFolder,
  HICON hicon,
  ULONG ulPos
);

Parameters

pmsg
[in] Outer message to place the link into.
pel
[in] List of entry identifiers leading to the linked folder: message store, IPM root, . . ., parent folder, then the linked folder.
szFileName
[in] Attached filename, must end in .XNK.
szFolder
[in] Folder name, for display purposes.
hicon
[in] If nonzero, an icon for display purposes.
ulPos
[in] Position of the link in the outer message's text; pass 0xffffffff if not to be displayed.


WriteMessageLink

The WriteMessageLink function takes the three entry identifiers leading to the linked message, formats the message link, and places it in an attachment to pmsg, along with rendering and positioning information.

STDAPI WriteMessageLink(
  LPMESSAGE pmsg,
  LPSBinary pbinStore,
  LPSBinary pbinFolder,
  LPSBinary pbinMessage,
  LPSTR szSubject,
  HANDLE hicon,
  ULONG ulPos
);

Parameters

pmsg
[in] Outer message to place the link into.
pbinStore
[in] Entry identifier of the message store for the linked message.
pbinFolder
[in] Entry identifier of the message store for the linked message.
pbinMessage
[in] Entry identifier of the linked message.
szSubject
[in] Subject of the linked message.
hicon
[in] If nonzero, icon used to render the link in the outer message.
ulPos
[in] Position of the link in the outer message's text; pass 0xffffffff if not to be displayed.


LinkMessageToMessage

The LinkMessageToMessage function extracts the necessary properties (PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID, PR_SUBJECT) from one message and uses them to create a link to that message in a second message.

STDAPI LinkMessageToMessage(
  LPMESSAGE pmsgLink,
  LPMESSAGE pmsgOuter,
  HANDLE hicon,
  ULNOG ulPos
);

Parameters

pmsgLink
[in] The message the link should point to.
pmsgOuter
[in] The message the link should be placed into.
hicon
[in] Icon for rendering the link.
ulPos
[in] Position of the link in pmsgOuter's text.


Topic Not Found

No matching topic was found. Some possible reasons and remedies are as follows:

  • The file (.chm) that contains the destination topic is not in the expected location.

Remedy: Rerun the MSDN Library Setup.

  • The file (.chm) that contains the current topic or destination topic is out-of-date and the link is no longer valid.

Remedy: Install the latest version of the MSDN Library.

  • The MSDN Library CD is not in the CD-ROM drive.

Remedy: Insert the MSDN Library CD into the CD-ROM drive.