Overview of ExchangeRPC

There are (at least) two conceptual models of ExchangeRPC:
  • the store, folders and messages model
  • the table / rows / columns / properties model

You need to understand both to make sense out of what is happening.

Store, Folders and Messages

Each user has a private mailbox "store", which is accessed using ExchangeRPC Remote Operations (often abbreviated as "ROPs"). Within that store, there is a hierarchy of folders, which can contain messages. In this context, a message might be a mail message, but it could also be a "Contact" (private address book entry), a "todo" task list entry, or some other item held on the server store. Folders may also contain Folder Associated Information (FAI) messages, which are basically metadata for the folder, and are not intended to be viewed directly by a user.

In addition to the per-user store, the server also has a public folder store, which is common to all users. This has a similar arrangement of folders and messages, divided into two sub-trees. One sub-tree within the public folder store has folders and messages that are intended to be viewed by users, and is known as the InterPersonal Message folders (often abbreviated to just IPM folders). The other sub-tree has additional information, not intended to be viewed directly by viewers, and is known as the NonInterPersonalMessage subtree (or NonIPM folders). The NonIPM folders provide support for functionality like per-user Free/Busy information, and a copy of the Global Address List (known as the Offline Address Book) that can be downloaded for use when the client is not connected to the server

Folders are identified by a 64 bit identifier, known as the Folder ID or FID.

Similarly, messages are identified by a 64 bit identifier, known as the Message ID or MID.

Tables / Rows / Columns / Properties

To actually work within a particular store, the main data structure that is used is a table, consisting of rows and columns. There are several types of tables, including:
  • contents table
  • hierarchy table
  • attachment table
  • rules table

Conceptually, the client sets the columns header of the table, and requests the server to fill in the rows with data that corresponds to that table. See the MS-OXCTABL specification for more details on how these remote operations work.

[TODO: much more information required here]

A property is used to describe something about an entity. Examples of properties are the name of a folder, the date an email was sent, whether a message has been read or the HTML version of a message body. Each property consists of a tag and a value. The tag is made up of an identifier (16 bits) and a property type (16 bits). The property identifiers and types are provided by Microsoft in the MS-OXPROPS specification, and are made available in OpenChange using a combination of IDL (especially the top level exchange.idl file) and custom generation (using the mparse.pl script and a list in libmapi/conf/mapi-properties).

As an example of a property, take the subject of an email. The property tag is PR_SUBJECT or PidTagSubject which is a name for 0x0037001f (or 0x0037001e if not using Unicode). 0x0037 is the identifier and 0x001f is a property type of Unicode string. The value could be something like "Re: Funniest joke".

Remote operations

There are three main sets of operations that are used in Exchange RPC:
  1. referral service (RFR)
  2. name service (NSPI), described in the MS-NSPI specification
  3. mailbox service (EMSMDB), described in the MS-OXCROPS specification.

The EMSMDB operations are transported "over the wire" using RPC calls that are described in MS-OXCRPC. You should be aware that MS-OXCRPC does not provide a full list of operations - some of the operations described as "reserved for local use" will be used by Exchange and Outlook (depending on version, protocol negotiation and server configuration). See exchange.idl in the OpenChange source tree for more information on the operations, but it is important to know that EcDoConnect (0x00) and EcDoRpc (0x02) are the earlier alternatives to EcDoConnectEx (0x0A) and EcDoRpcExt2 (0x0B) calls.

Handles and objects

The ExchangeRPC protocols end up with a significant amount of state information shared between the client and the server, referenced using "handles" or "context handles". For example, when the client asks for a folder to be opened (RopOpenFolder), the client provides the folder ID (FID), and the server returns a 1 byte handle index (OutputHandleIndex in this case) - there is a little bit more information exchanged by RopOpenFolder, but its not too important at this stage. Then when the client wants to perform some operation on the Folder (e.g. to set the columns in the content table corresponding to the folder details, using RopSetColumns), the client refers to the folder using that handle index.

On the openchange side, these handles (and other some other data) are managed using an opaque data structure (mapi_object). Every mapi_object must be initialised (using mapi_object_init()) before it is used, and it should be released (using mapi_object_release) after it is used. Note that mapi_object_release() cleans up both the client side memory, and the state on the server corresponding to the handles (using RopRelease), so you should be careful that exit / failure paths contain appropriate calls to mapi_object_release(). There is some protection from using all the server resources, in that the server will clean up the handles when the session ends.

mapi_object      obj_store;
enum MAPISTATUS  retval;

mapi_object_init( &obj_store );

retval = OpenMessageStore( &obj_store );
if ( retval != MAPI_E_SUCCESS ) {
    mapi_errstr( "OpenMsgStore", retval );
    mapi_object_release( &obj_store );
    exit( 1 );
}

/* ... use the store as required */

mapi_object_release( &obj_store );

Also available in: HTML TXT