Microsoft Outlook and Exchange Client Extensions

Sharon Lloyd

March 1998

Introduction

Microsoft® Outlook™ is Microsoft Office's premier messaging and collaboration client for the Internet and Microsoft Exchange.

Outlook helps users communicate with others through e-mail, telephone, group scheduling and real-time Microsoft NetMeeting™ conferencing software. It allows users to share information with others via Internet connectivity, Microsoft Exchange Server, and electronic forms, and as a component of customized collaborative solutions. Outlook also integrates and organizes all this communication and shared information in one application.

The ability of developers to extend the Outlook application greatly enhances its usefulness. Adding custom features, overriding default behaviors, using existing Outlook features, and integrating existing Exchange client extensions make it possible to fully customize the already fabulous potential of Outlook.

This article will provide you with a brief introduction to the Messaging Application Programming Interface (MAPI) and a high-level understanding of its role in scenarios that include Microsoft Exchange Server. Following an explanation of the Exchange and Outlook clients is a discussion of client extensions and information about the hosting of Exchange client extensions by Outlook.

Helpful, but not required to comprehend this article, is an intermediate-level knowledge of C++ object-oriented programming techniques, Component Object Model (COM), and the Microsoft Win32® application programming interface (API). Although an introduction to MAPI is included, it is helpful if you already have some messaging-development experience.

To create a client extension, you should thoroughly understand and be able to implement the Microsoft Exchange IExchExt extensibility interfaces. You should have access to reference material for C++ object-oriented programming techniques, COM, and MAPI. To write an extension for Outlook, you should have a complete understanding of the Outlook object model.

Background Information

An explanation of Exchange client extensions must begin with a brief introduction to the MAPI, and how it interacts with the Exchange Server.

MAPI is not just a library of functions, but a specification for an entire messaging subsystem and all its interacting components. MAPI is designed to fulfill three principle requirements:

MAPI was created to provide a standardized application-level interface that allowed messaging components to communicate with widely incompatible messaging systems. Simple MAPI, or MAPI version 0, is a very limited library of only 12 functions written by Microsoft, which enabled the Microsoft Mail client to communicate with Microsoft Mail post offices. The extended MAPI, or MAPI version 1, specification was written by Microsoft in collaboration with more than 100 software vendors, and is thus an open specification that allows MAPI-compliant systems to communicate freely with other MAPI-compliant systems. It completely supersedes the older version.

The extended MAPI specification includes definitions of various external components, descriptions of what they do, and a list of the interfaces they expose. The interfaces between components are not APIs, but COM interfaces. COM components are bound together to form applications and can be extended to develop custom-application extensions. All MAPI components use or implement MAPI objects, and all MAPI objects are COM objects.

MAPI is available on all Microsoft Windows®–based desktops. The Windows Messaging Subsystem (WMS) is the MAPI standard user interface. WMS originally was referred to as the Exchange client, but was renamed to alleviate confusion. As a complicated structure, MAPI offers a number of different architectural perspectives:

Microsoft Exchange Server embraces Internet standards and is a MAPI service provider. It utilizes MAPI notification to register events and includes three types of services: message transport, message store, and address book or address list. When a new message is detected on the system, the transport provider alerts the MAPI spooler, which processes the message and copies it to the default message store. The address book freely provides client access to directory information—a list of known recipients that may be either single users or distribution lists.

When Microsoft Exchange Server sends a message, it relies on the MAPI subsystem to direct client requests to one or more transport-service providers. Microsoft Windows dynamic-link libraries (DLLs) serve as drivers for each transport provider. They also provide the interface between the MAPI spooler and the underlying messaging system or services.

Exchange Server will continue to support the widest possible array of network protocols (such as RPC, IMAP4, POP3, NNTP, HTTP, and so on), and it will continue to support MAPI as a programming interface.

What is the Exchange Client?

The Microsoft Exchange client, shipped with Microsoft Exchange Server through version 5.0, is an application (exchng32.exe) that employs Microsoft Exchange Server as its service provider. It offers a user interface that provides a method for browsing and manipulating the universal Inbox. There is a folder hierarchy table in the left pane and a folder contents list in the right pane. The Exchange client offers the user an opportunity to request different views of these tables, create and send messages, and use many other features. It is limited in its capabilities, but because it was designed for flexibility and extensibility, it allows developers to build systems that more accurately reflect the needs of their users.

The Exchange client is supported by, but not shipped with, Microsoft Exchange Server 5.5. Future changes to the code base will be limited to customer-requested, quick-fix engineering modifications for issues that affect use, interoperability, and/or deployment.

What is the Outlook Client?

Outlook is the client fully optimized for Microsoft Exchange Server 5.0 and later. Released with version 5.0 of Microsoft Exchange Server and included in Microsoft Office 97, Outlook 97 combines e-mail, calendar and scheduling features, contact and task management, journalizing, and custom forms-based applications in a single interface. Outlook 98 also includes complete, native support for major Internet mail, news, and directory standards, such as IMAP4, LDAP, HTML, NNTP, MIME, and S/MIME, and also supports these Internet calendar and contact standards: vCard, vCalendar, and iCalendar Free-Busy lookup. Outlook is designed for use with Internet protocols (SMTP/POP3 and IMAP4), Microsoft Exchange Server, or any other standards-based communication system that supports MAPI, including voice mail.

Outlook enables complete access to its data by other Microsoft Office applications. With its object library, you can enable access by other applications to Outlook e-mail, appointments, tasks, journal items, and notes. The Outlook object library, because of its integration with the Microsoft Office product family, allows programmatic access to Office command bars and the Office Assistant. The object library supports separation of the user interface and data; the root Application object enables you to create a new mail message with a single line of code. For example, in Microsoft Visual Basic® Scripting Edition (VBScript):

Set newItem = Application.CreateItem(0)

The Application object is also the main entry point into the rest of the data store. Using the MAPI NameSpace object, you can access all the information stored on the Exchange server.

You can extend the functionality of Outlook Forms by using VBScript, which is a subset of Visual Basic for Applications (VBA). Outlook does not host VBA.

You can access an information store by using Outlook objects through Automation. You do this by writing Visual Basic or Visual Basic for Applications code in Visual, Microsoft Excel, Microsoft Access, Microsoft Word, or Microsoft PowerPoint®.

Outlook is a platform for extensibility and third-party solutions that enables enterprise developers, solution providers, and third-party software developers to build add-on applications that extend the functionality of Outlook. Outlook is the premier e-mail client for Microsoft Office and the upgrade to the Microsoft Exchange Client and Schedule+.

Outlook 98 builds on the role of Outlook 97 as the client fully optimized for the fast-growing number of companies that rely on the scalable and advanced e-mail capabilities of Microsoft Exchange Server, and its group calendar and collaboration features, for their business-critical intranets. Outlook 98 interoperates with Outlook 97 and earlier versions of Microsoft Mail, Microsoft Exchange client, or Schedule+, without requiring a Microsoft Exchange Server upgrade.

What is an Exchange Client Extension?

An Exchange client extension is a component object that implements the Exchange IExchExt interface and complies with the Microsoft Windows Component Object Model. This interface is defined in the Win32 Software Development Kit (SDK) header file exchext.h, and allows the client to load extension objects in all contexts. The client loads the object server and then creates an instance of the extension object for every extensible context of the client. Search for the title "About Client Extensions" in the MSDN™ Library, Platform SDK documentation for more information about interface contexts.

Client extensions are created to take advantage of the existing abilities of the client. These inherent abilities are used and custom interfaces are added by the extension. Instead of developing an entirely new user interface and messaging service, the extension expands and utilizes existing features.

An Exchange client extension differs from a standard COM in-process server in that it does not identify its class with a CLSID and does not register its server under the HKEY_CLASSES_ROOT key of the system registry. Instead, an extension class identifies itself with a printable string that serves to tag its registration string under the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Client\Extensions. The extension server exports an entry point that returns a new instance of an extension object. The client queries additional interfaces off this object as needed.

There are four main types of extensions:

  1. Command extensions are the most common extension interfaces. They either replace existing behavior or add new commands to the client's menus and toolbars by utilizing the IExchExtCommands interface. A custom spelling tool, text-formatting tool, public-folder command, or message-class command can be implemented with a command extension.

  2. Event extensions use the IExchExt event interfaces to invoke custom behavior to handle events such as the arrival of new messages; reading, writing, and sending messages; reading and writing attached files, and selection changes in a window. By overriding the behavior associated with certain events, you can transparently scan message attachments for viruses, or compress and decompress messages with an event extension.

  3. Property sheet extensions utilize the IExchExtPropertySheets interface that allows an extension to define additional pages on the client property sheets. This enables users or administrators to view or edit custom message properties. If your application provides a custom form with custom properties, you can display those properties with a property sheet extension.

  4. Advanced criteria extensions are the least common extension interfaces. By using the IExchExtAdvancedCriteria interface, you can implement your own custom advanced criteria dialog boxes to be used when searching for items in the information store. You can display a custom advanced criteria dialog box that enables users to specify search criteria for custom properties with an advanced criteria extension.

How to Make an Exchange Client Extension Work in Outlook

While Outlook recognizes, loads, and runs extensions that conform to specifications for Microsoft Exchange client extensions, methods exist for improving performance and creating added functionality.

A client extension registry entry is a string value consisting of a series of semicolon-separated fields. The entry is identified with a unique tag name that differentiates the entry from other values beneath the registry key. The entry consists of six fields. The first two are required, and identify the version number of the registry entry and the path to the extension's DLL. The next four fields are optional, identifying the ordinal entry point, context map, interface map, and service name of a service provider accompanying the client extension. If these four fields are empty, the client supplies a suitable default value for each empty field.

Client extensions export their names and entry points in their registry entries in HKEY_LOCAL_MACHINE\Software\Microsoft\Exchange\Client\Extensions. Each string value within this key constitutes a single client extension. When the client starts, it reads the contents of the key to find all the extensions available to the client.

By default, the Exchange client reads the extension registry key when it starts, and loads every extension having an entry in this key. After loading every extension library, the client creates an extension object from each of these libraries for every extensibility context that it encounters, unless the extension library has specified in its context map that it does not handle a particular context.

Outlook uses the same profile and other configuration information as the Exchange client and can use all Microsoft Exchange Client extensions and custom forms. While Outlook recognizes, loads, and runs extensions that conform to specifications for Microsoft Exchange client extensions, you can improve an extension's performance and increase its functionality under Outlook by providing an Extension Configuration File (ECF). Using an ECF, Outlook knows ahead of time the contexts under which an extension needs to be loaded, which commands the extension contributes, the Outlook modules to which the extension applies, and so on. This enables Outlook to delay loading the extension until it is needed.

Without an ECF, an extension registers itself in the registry only. In the registry entry, the information an extension can specify is limited to a DLL, an entry point, a binary context map, a binary interface map, and a provider if applicable. An ECF, however, allows an extension to register itself with much more complete and detailed data. If an ECF is loaded for an extension, registry entries for the extension are not used. Therefore, the ECF must contain a complete description of the extension. The ECF provides textual information, using the standard INI file format. There is only one ECF per extension, and only one extension per ECF. For more information about writing an ECF, search for the topic, "Outlook Extension Configuration File Document," in the MSDN Library, Microsoft Office Development documentation.

The Outlook client reads the registry information only once for an extension, and for performance reasons, transfers it to an internal cache. This internal cache is the extend.dat file, located in the Windows directory. Outlook uses the extend.dat file to record paths to DLLs for all extensions loaded into Outlook.

The first time you begin an Outlook session, or any time after an extension is installed, uninstalled, or upgraded, extend.dat will be rewritten with the new DLL paths. Deleted extensions will no longer have an entry in the extend.dat file. If unwanted extensions have been loaded into Outlook, you will need to manually remove them using the Add-In Manager. In Outlook 97, the Add-In Manager is accessible from the Tools menu by clicking Options, selecting the General tab, and clicking on Add-In Manager. To remove an extension, simply scroll down until you locate the extension, clear the check box next to its name, click Remove, and then click OK. In Outlook 98, the Add-In Manager is accessed from the Tools menu by clinking Options, then selecting the Other tab, clicking on Advanced Options, and selecting Add-In Manager.

The Exchange client does not have an extend.dat file, nor does it have an Add-In Manager that utilizes ECFs.

Note   One of the major differences between the two clients is the fact that Outlook does not enable an extension to access the product's user interface; that is, to directly manipulate HWNDs. If the Exchange client extension manipulates the window handles in Exchange, it is likely that this extension will not work properly in Outlook.

The method of installing extensions differs in Exchange and Outlook. In Exchange, you simply add a new registry entry for the extension in: HKEY_LOCAL_MACHINE\Software\Microsoft\Exchange\Client\Extensions

In Outlook, in addition to the traditional registry entry for the extension, you must add an entry called "Outlook Setup Extension" (do not localize this string).

The value must be:

4.0;Outxxx.dll;7;000000000000000;0000000000;OutXXX

It must be in:

HKEY_LOCAL_MACHINE\Software\Microsoft\Exchange\Client\Extensions

This entry signals Outlook that new extensions have been added or removed. Outlook will remove this entry the next time it is launched.

How to Access the Outlook Object Model

If you want to access the Outlook object model from within an extension, Microsoft publishes an interface called IOutlookExtCallback for this purpose. The following code is the header file:

#ifndef _OUTLOOK_H
#define _OUTLOOK_H

#if defined(WIN32) && !defined(MAC)

#ifndef __IOutlookExtCallback_FWD_DEFINED__
#define __IOutlookExtCallback_FWD_DEFINED__
typedef interface IOutlookExtCallback IOutlookExtCallback;
#endif    /* __IOutlookExtCallback_FWD_DEFINED__ */

// Outlook defines this interface as an alternate to IExchExtCallback.
#ifndef __IOutlookExtCallback_INTERFACE_DEFINED__
#define __IOutlookExtCallback_INTERFACE_DEFINED__

EXTERN_C const IID IID_IOutlookExtCallback;

    interface DECLSPEC_UUID("0006720D-0000-0000-C000-000000000046")
    IOutlookExtCallback : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE GetObject( 
            /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetOfficeCharacter( 
            /* [out] */ void __RPC_FAR *__RPC_FAR *ppmsotfc) = 0;
    };

DEFINE_GUID(IID_IOutlookExtCallback,
    0x0006720d,
    0x0000,
    0x0000,
    0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

#endif    /* __IOutlookExtCallback_INTERFACE_DEFINED__ */

#endif // defined(WIN32) && !defined(MAC)

#endif // _OUTLOOK_H

In the header file for the extension, you must include the following code:

#ifndef __IOutlookExtCallback_INTERFACE_DEFINED__
#define __IOutlookExtCallback_INTERFACE_DEFINED__

EXTERN_C const IID IID_IOutlookExtCallback;
    interface DECLSPEC_UUID("0006720D-0000-0000-C000-000000000046")
    IOutlookExtCallback : public IUnknown
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE GetObject( 
            /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk) = 0;       
        virtual HRESULT STDMETHODCALLTYPE GetOfficeCharacter( 
            /* [out] */ void __RPC_FAR *__RPC_FAR *ppmsotfc) = 0;
};
 #endif  /* __IOutlookExtCallback_INTERFACE_DEFINED__ */

The following code fragment obtains access to an IDispatch for the current context:

void GetRenDispatch(
   IExchExtCallback *lpeecb,
   IOutlookExtCallback **pprGetObj,
   IDispatch **ppdisp)
{
   IUnknown punk;
   lpeecb->QueryInterface(IID_IOutlookExtCallback,
      (void **) pprGetObj);
   // If you're running Outlook, then prGetObj will not be NULL.
   if (*pprGetObj != NULL)
   {
      (*pprGetObj)->GetObject(&punk);
      if (punk != NULL)
      {
         punk->QueryInterface(IID_IDispatch, (void **) ppdisp);
      }
   }
   if ( punk != NULL )
      punk->Release();
}

This function returns two pointers—the pointer to IOutlookExtCallback and the pointer to IDispatch. The first is returned in case the user wants to perform other functions. Microsoft provides only the GetOfficeCharacter function. If this function returns NULL in ppdisp, the extension is not running in Outlook. This is an acceptable method of determining if the client that is running the extension is indeed Outlook and not Exchange. The caller is responsible for releasing the returned pointers.

Recommended Reading

The best resource for learning about the Outlook object model is the Microsoft Outlook Visual Basic Reference. This help file is available as part of the Development Tools Add-In that also includes the Outlook Object Browser and Script Debugger.

Also take a look at the following:

Note   All books available from the Microsoft Press can be ordered from the Microsoft Press Web site at http://mspress.microsoft.com/.