Rebase This: Introducing the Calendar Rebasing Library

[This is now documented here: https://msdn2.microsoft.com/en-us/library/bb820976.aspx

We're getting near DST time again. Last time around, we had both an Outlook based tool and an Exchange based tool for rebasing appointments. The idea was the Outlook based tool could be used by end users to update their calendars, while the Exchange based tool could be used by corporate administrators to update their users' calendars en masse.

For the most part, this worked well. One problem with the Exchange tool was that it was essentially a wrapper around the Outlook tool. That is, the Exchange tool gathered parameters and passed them to the Outlook tool to do the work. The reason this was a problem was that, in addition to the overhead of starting and stopping an external process, we also had to incur the cost of a MAPI logon and logoff for each mailbox being processed. And as any MAPI developer knows, MAPI logon and logoff is expensive and slow.

So, this time around, we've split all the code that does the rebasing work into a redistributable DLL, tzmovelib.dll. Both Outlook and Exchange rewrote their tools to use this DLL. For the Outlook tool, the effect is negligible. But for the Exchange tool, this allows us to log on to MAPI just one time and then iterate through all the mailboxes which need to be processed. This should allow the Exchange tool to run significantly faster.

As an added bonus, we now have an API that third party developers can use to perform the rebasing themselves without potentially corrupting calendars by trying to work directly in MAPI. And I got the honor of writing the documentation and a sample for it. We're putting it up here on my blog for now. MSDN documentation based on this blog entry will come later.

BTW - This DLL will ship with the updated Outlook and Exchange tools when they're released. We've also produced an MSI that can be included with third party rebasing tools. If you are writing a calendar rebasing tool and would like to use the functionality this DLL provides, drop me a note through the contact link below and I'll send you the installer. Please note that for the DLL to work, it must be installed with it's own installer.

Update (9/12/07):

Both Exchange and Outlook have shipped their updated tools.

Exchange's tool can be found here: https://support.microsoft.com/kb/941018. It uses tzmovelib.dll to do the rebasing.

Outlook's tool can be found here: https://support.microsoft.com/kb/931667. It does NOT use tzmovelib.dll (this is contrary to what I said above - I misunderstood the developer). It does use the same core logic as the Exchange tool though - it's just linked directly into the binary instead of called through a DLL.

Resources

  Name Location
DLL: tzmovelib.dll https://blogs.msdn.com/stephen_griffin/contact.aspx
Header: tzmovelib.h https://stephengriffin.members.winisp.net/TzMoveLib/tzmovelib.h
Sample: TzTest https://stephengriffin.members.winisp.net/TzMoveLib/tztest.zip

 

Documentation

HrCreateApptRebaser

The HrCreateApptRebaser function initializes a IOlkApptRebaser object for use in rebasing appointments.

Quick Info

Header file: tzmovelib.h
Implemented by: tzmovelib.dll
Called by: Client applications
Pointer type: LPHRCREATEAPPTREBASER
DLL Entry Point: HrCreateApptRebaser@44

Syntax

 HRESULT HrCreateApptRebaser( 
    ULONG ulFlags,
    IMAPISession *pSession,
    IMsgStore *pCalendarMsgStore,
    IMAPIFolder *pCalendarFolder,
    LPCWSTR pwszUpdatePrefix,
    const FILETIME *pftInstallDateUTC,
    LONG lExpansionDepth,
    const TZDEFINITION *pTZTo,
    const TZDEFINITION *pTZMissing,
    MAPIERROR **ppError,
    IOlkApptRebaser **ppApptRebase);

Parameters
ulFlags [in] Bitmask of flags used to control how rebasing is performed. The following flags can be set:

REBASE_FLAG_UPDATE_ORGANIZED_MEETINGS
Items in which the user is the meeting organizer will be rebased. Note that by default this will cause meeting updates to be sent out to all attendees of any meeting being rebased. Combine this flag with either REBASE_FLAG_FORCE_NO_EX_UPDATES or REBASE_FLAG_FORCE_NO_UPDATES to change the behavior of how meeting updates are handled.
REBASE_FLAG_UPDATE_UNMARKED
Update items that aren't marked with a time zone. If this flag is specified, the pTZMissing value passed to HrCreateApptRebaser will be used as created-in time zone for all items that do not have time zone data.
REBASE_FLAG_UPDATE_ONLYRECURRING
Update only recurring items.
REBASE_FLAG_NO_UI
Do not show any UI (prevents the display of any logon dialog boxes when opening the message store).
REBASE_FLAG_UPDATE_MINIMIZEAPPTS
Do not rebase items that will only have changes which occur in the past.
REBASE_FLAG_FORCE_REBASE
Do not check the organizer for rebasing decisions (enables items in which the user is the attendee to be rebased).
REBASE_FLAG_FORCE_NO_EX_UPDATES
Only send updates if the user is the organizer and recipient is non-EX.
REBASE_FLAG_FORCE_NO_UPDATES
Never send updates.
REBASE_FLAG_ONLY_CREATED_PRE_PATCH
Only rebase single instance items created before the patch was applied.
REBASE_FLAG_REPORTING_MODE
Do not actually rebase, just report items that would be rebased.
REBASE_FLAG_SEND_RESOURCE_UPDATES
Send meeting updates to resources (attendees explicitly specified on the "Resource" line of a meeting).

 

pSession [in] Required. Pointer to a MAPI session interface.

pCalendarMsgStore [in] Required. Pointer to a message store containing items to be rebased.

pCalendarFolder [in] Require. Pointer to a Calendar folder containing items to be rebased.

pwszUpdatePrefix [in] Optional. Pointer to a string containing the prefix to be prepended on meeting requests. May be NULL.

pftInstallDateUTC [in] Optional. Timezone patch install date. Only used if the REBASE_FLAG_ONLY_CREATED_PRE_PATCH flag is set.

lExpansionDepth [in] Expansion depth when expanding distribution lists to exclude EX recipients. Only used if the REBASE_FLAG_FORCE_NO_EX_UPDATES flag is set.

pTZTo [in] Required. Pointer to a TZDEFINITION structure describing the time zone to be rebased to.

pTZMissing [in] Required. Pointer to a TZDEFINITION structure describing the time zone to be assumed if time zone information is not stamped on an item. Must not be NULL, but only used if the REBASE_FLAG_UPDATE_UNMARKED flag is set.

ppError [out] Optional. Pointer to a pointer to a MAPIERROR structure containing version, component, and context information for the error. Can be NULL if no extended error information is desired. Free with MAPIFreeBuffer.

ppApptRebase [out] Pointer to a pointer to the returned IOlkApptRebaser interface.

Remarks

Obtain this function from tzmovelib.dll by calling GetProcAddress with the function name HrCreateApptRebaser@44.

Not all of the flags are valid in combination with each other. View the "Glossary of command-line options for the Outlook Time Zone Data Update tool" section of https://support.microsoft.com/kb/933146 for more information on the various options.

 

IOlkApptRebaser : IUnknown

The IOlkApptRebaser interface is used to rebase appointments in a calendar folder.

Header file: tzmovelib.h
Exposed by: Outlook rebasing object
Implemented by: tzmovelib.dll
Called by: Client applications

Vtable Order

BeginEnumerateAppointments Begins appointment enumeration.
EndEnumerateAppointments Retrieves results of appointment enumeration and returns a list of appointments needing rebasing.
BeginRebaseAppointments Begins appointment rebasing. Takes a list of appointments, usually obtained from EndEnumerateAppointments.
EndRebaseAppointments Retrieves results of appointment rebasing.

 

IOlkApptRebaser::BeginEnumerateAppointments

The IOlkApptRebaser::BeginEnumerateAppointments method begins a task for appointment enumeration. This task runs on a new thread.

Syntax

 HRESULT BeginEnumerateAppointments(
    PFNREBASETASKPROGRESS pfnProgress,
    void **ppContext);

Parameters

pfnProgress [in] Optional. Pointer to a rebase task progress function to receive progress.

ppContext [out] Required. Pointer to a pointer to the returned context. This context will be passed to EndEnumerateAppointments.

 

IOlkApptRebaser::EndEnumerateAppointments

The IOlkApptRebaser::EndEnumerateAppointments method waits for appointment enumeration to complete and retrieves the results.

Syntax

 HRESULT EndEnumerateAppointments(
    void *pContext,
    HRESULT *phResult,
    MAPIERROR **ppError,
    SRowSet **ppRows);

Parameters

pContext [in] Required. Pointer to the context obtained from a call to BeginEnumerateAppointments.

phResult [out] Required. Pointer to an HRESULT to retrieve the result of the enumeration operation.

ppError [out] Optional. Pointer to a pointer to a MAPIERROR structure to retrieve extended error information.

ppRows [out] Required. Pointer to a pointer to an SRowSet structure describing the appointments which need rebasing. This structure will be passed to BeginRebaseAppointments.

 

IOlkApptRebaser::BeginRebaseAppointments

The IOlkApptRebaser::BeginRebaseAppointments method begins a task for appointment rebasing. This task runs on a new thread.

Syntax

 HRESULT BeginRebaseAppointments(
    const SRowSet *pRows,
    PFNREBASETASKPROGRESS pfnProgress,
    PFNREBASETASKCOMPLETE pfnComplete,
    void **ppContext);

Parameters

pRows [in] Required. Pointer to an SRowSet structure describing the appointments which need rebasing. This structure can be obtained from EndEnumerateAppointments.

pfnProgress [in] Optional. Pointer to a rebase task progress function to receive progress.

pfnComplete [out] Optional. Pointer to a rebase task completion function to receive notification of rebase completion.

ppContext [out] Required. Pointer to a pointer to the returned context. This context will be passed to EndRebaseAppointments.

 

IOlkApptRebaser::EndRebaseAppointments

The IOlkApptRebaser::EndRebaseAppointments method waits for appointment rebasing to complete and retrieves the results.

Syntax

 HRESULT EndRebaseAppointments(
    void *pContext,
    HRESULT *phResult);

Parameters

pContext [in] Required. Pointer to the context obtained from a call to BeginRebaseAppointments.

phResult [out] Required. Pointer to an HRESULT to retrieve the result of the rebasing operation.

 

RebaseTaskProgress

The RebaseTaskProgress function reports progress for enumeration and rebasing of appointments. Clients using the IOlkApptRebaser interface implement this function to track item processing.

Quick Info

Header file: tzmovelib.h
Implemented by: Client applications
Called by: Outlook rebasing object
Pointer type: PFNREBASETASKPROGRESS

Syntax

 void STDAPICALLTYPE RebaseTaskProgress( 
    ULONG ulMin,
    ULONG ulMax,
    ULONG ulCur,
    REBASE_APPT_STATE State,
    const SRow* pRowCur);

Parameters
ulMin [in] The low end of the range of appointments being processed. Will usually be zero.

ulMax [in] The high end of the range of appointments being processed. Will usually be the number of items in the calendar folder being processed.

ulCur [in] The current item being processed.

State [in] A value indicating the status of the item being processed. Will be one of the following values:

REBASE_APPT_STATE_SCANNING_EXAMINING - Scanning, examining an item.
REBASE_APPT_STATE_SCANNING_FOUND - Scanning, found an item.
REBASE_APPT_STATE_BEGIN - Fixing, starting an item.
REBASE_APPT_STATE_REBASING - Fixing, adjusting an item.
REBASE_APPT_STATE_SENDING - Fixing, sending a meeting update.
REBASE_APPT_STATE_DONE - Fixing, done with item.

pRowCur [in] Pointer to an SRow structure describing the item being scanned or fixed.

 

RebaseTaskComplete

The RebaseTaskComplete function reports completion for rebasing of appointments. Clients using the IOlkApptRebaser interface implement this function to track completion of item updates.

Quick Info

Header file: tzmovelib.h
Implemented by: Client applications
Called by: Outlook rebasing object
Pointer type: PFNREBASETASKCOMPLETE

Syntax

 void STDAPICALLTYPE RebaseTaskComplete( 
    ULONG ulRowIndex,
    const SRow* pRowCur,
    HRESULT hrResult,
    BOOL fModified,
    BOOL fSentUpdate,
    const MAPIERROR* pError);

Parameters
ulRowIndex [in] The row which was processed. This index refers to the SRowSet structure passed to BeginRebaseAppointments.

pRowCur [in] Pointer to an SRow structure describing the item which was processed.

hrResult [in] An HRESULT indicating the result of the rebasing operation.

fModified [in] A boolean indicating whether the item was modified.

fSentUpdate [in] A boolean indicating whether a meeting update message was sent.

pError [in] Pointer to a MAPIERROR structure with extended error information.

 

Update: 8-20-07 - Reworded section about redistributable package. Added remark about combining flags.

Update: 11-02-07 - The redistributable package will be available soon on the MSDN, so don't contact me about obtaining it. Instead, consult the link at the top of this article.