Quantcast
Channel: SGriffin's MAPI Internals
Viewing all 84 articles
Browse latest View live

Exchange 2013 OWA URLs

$
0
0

If you dig around in the EWS documentation, you’ll find this element: WebClientReadFormQueryString, which should give you a URL for an item in OWA. When Exchange Server 2013 shipped, we had some EWS developers who noticed this element was still giving out URLs in Exchange Server 2010’s OWA URL format, which no longer works with Exchange 2013. If you look in the Remarks for the  WebClientReadFormQueryString article, you’ll see we‘ve added documentation to allow you to build URLs for 2013 by hand.

So – what happened? As Kristian describes it, Outlook Web Access in Exchange 2013 is a complete rewrite from the previous versions of OWA. This means a whole lot of new features (like Office Mail Apps), but it also means some features got left out. This article gives the highlights. In that article, you’ll note that Outlook Web App customization, as it existed in earlier versions, is not available in Exchange 2013. Part of this includes the old 2010 style URLs that could be used to create and access different types of items.

So – with Exchange 2013, you can use the format given in the documentation for WebClientReadFormQueryString to create a URL to view an existing email message. We do not have a similar URL format for other types of items, such as Appointments, Contacts, or Tasks. We also do not have a URL format for creation of items.


The Wrapped PST and Unicode Paths

$
0
0

A customer just raised this issue with our Wrapped PST provider sample. They were trying to retrofit the sample to use Unicode paths to the NST and found that the CreateStoreEntryID routine was producing an invalid entry ID after they changed to to use a Unicode path. Through experimentation, they were able to produce a valid entry ID and wondered if I could document the necessary format. It turns out we use two different formats for the entry ID of a wrapped PST. One format is for ASCII paths and the other is for Unicode paths. Here they are, represented as structures:

typedefstruct// short format
{
	BYTE		rgbFlags[4];	// MAPI-defined flags
	MAPIUID		uid;		// PST provider MUID
	BYTE		bReserved;	// Reserved (must be zero)
	CHAR		szPath[1];	// Full path to store (ASCII)
} EIDMS;
// Unicode version of EIDMSW is an extension of EIDMS
// and szPath is always NULL
typedefstruct// Long format to support Unicode path and name
{
	BYTE		rgbFlags[4];	// MAPI-defined flags
	MAPIUID		uid;		// PST provider MUID
	BYTE		bReserved;	// Reserved (must be zero)
	CHAR		szPath[1];	// ASCII path to store is always NULL
	WCHAR		wzPath[1];	// Full path to store (Unicode)
} EIDMSW;

The net effect of the difference in these structures is there are two NULL bytes prior to a Unicode path. If you’re interpreting the entry ID, one way to determine how to interpret it would be to cast it as EIDMS first, then check if szPath[0] is NULL. If it is, you need to cast it as EIDMSW instead.

Putting a Path in MAPISVC.INF

$
0
0

As you know, when you install a new provider on a system, you have to update MAPISVC.INF to point it to the new provider. There are a few standard properties set during this configuration which tell MAPI where to find your DLL. One is PR_SERVICE_DLL_NAME, set in the Message Service section, and the other is PR_PROVIDER_DLL_NAME, set in the Service Provider section. For both properties, you are expected to set the name of your provider’s DLL (minus the “32” suffix"). MAPI will then load your provider by looking for it on the path.

What if the path isn’t good enough? What if, like any other modern application, you want to drop your provider over in Program Files and not dirty the path? According to the MAPI documentation, you shouldn’t be able to do that. However, it turns out that, with a few restrictions, Outlook’s MAPI can deal with full paths to MAPI providers. Outlook development has agreed to support this for Outlook 2010 and higher.

Here are the particulars:

  • When registering your provider in MAPISVC.INF, you should put the full path to the provider in PR_SERVICE_DLL_NAME and PR_PROVIDER_DLL_NAME.
  • Further, in a store provider, you will from time to time generate entry IDs using WrapStoreEntryID, which takes as a parameter the name of your provider. If you’re using full paths in MAPISVC.INF, you must use the same path in WrapStoreEntryID.
  • In both cases, this full path must be without the “32” suffix, as MAPI will continue to append it before looking for your file. So if you register the path “c:\mypath\myprovider.dll”, MAPI will try to load “c:\mypath\myprovider32.dll”.
  • Because Outlook’s MAPI was not originally designed with full paths in mind, it does this insertion of the “32” by looking for the first period in the string. This means that paths which contain other periods cannot work. So you cannot use paths such as “c:\my.groovy.path\myprovider.dll” or “c:\mypath\my.groovy.provider.dll”.
  • The path you use may be converted to and from Unicode using the code page provided by GetACP. You will see failures if you choose a path which contains characters cannot survive such a roundtrip through MultiByteToWideChar/WideCharToMultiByte.

To demonstrate this, I’ve updated the Wrapped PST sample over on Codeplex. The magic happens in MErgeWithMAPISVC and GenerateProviderPath.

Enjoy!

August 2012 Release of MFCMAPI and MrMAPI

$
0
0

The August 2012 Release (build 15.0.0.1035) is live: http://mfcmapi.codeplex.com.

In honor of the Outlook 2013 Preview, this month I’ve decided to turn MFCMAPI blue. Along the way, I was able to fix a number of nagging flicker issues, as well as fix the system button placement on XP systems. However, the changes I made for Outlook 2013 weren’t just cosmetic. As you may have noticed in the updated MAPI Reference, it’s now possible to have more than one version of Outlook installed on a machine at the same time. This poses a problem for MFCMAPI: which MAPI to load? To solve this problem, MFCMAPI locates all the implementations of MAPI it can and puts them on a menu. You’ll find this under Session/MAPI Initialization/Load MAPI. Of course, if you’re happy with the default MAPI, you don’t to do anything different. If you’re interested in seeing how MFCMAPI looks for MAPI implementations, consult stubutils.cpp and the MAPIPathIterator class.

[Edit] How could I change the UI (again) without posting a screenshot?

MFCMAPINewUIBlue

Here's a change list - see the Issue Tracker on Codeplex for more details, or look at the code:

  • MrMAPI: fixed a parameter parsing crash
  • MFCMAPI: Corrected location of system buttons on some WIndows XP systems
  • MFCMAPI: Found and corrected a number of minor flicker issues
  • MFCMAPI: Implemented a blue highlight
  • MFCMAPI: Much better handling of the OLE attachment type
  • MFCMAPI: Click-to-Run and side-by-side support for the Outlook 2013 Preview

Enjoy.

MAPICDO, Distribution Lists, and Exchange 2010

$
0
0

One of the lesser known tricks in MAPI is that when you open a distribution list (MAPI_DISTLIST) from an address book using OpenEntry, if you don’t specify an interface what you get is not an IMailUser, but is in fact an IDistList, which inherits from IMAPIContainer. This gives you a means to access the members of the distribution list. Just call GetContentsTable and there they are. However, this trick doesn’t always work with MAPICDO when you’re talking to Exchange 2010. When you look at an Exchange 2010 address book using MFCMAPI, you’ll notice that all of the entry IDs are short term entry IDs. They don’t contain the DN of the entry being referred to. Instead, what they contain is an ephemeral ID, which is supposed to be a way to refer to an entry in the address book without constantly sending a DN back and forth. With the introduction of the Address Book Service in Exchange 2010, we split the concept of ephemeral IDs to include those generated by the Active Directory, and those generated by the Address Book service. The ID we find in these short term entry IDs is an Active Directory ID.

The upshot of all this is that when we use this short term entry ID to open an entry in the address book, we don’t get the full complement of properties we would normally expect (and that we would get if the short term Entry ID had used an Address Book ID). A side effect of this is that when we further try to call GetContentsTable, NspiGetMatches, the NSPI function which we’re calling under the covers, doesn’t understand the ID we pass to it and the call fails with the error MAPI_E_CALL_FAILED.

All is not lost, however. One of the properties we DO get using the short term entry ID is a proper long term entry ID with a full DN. And objects opened with this entry ID contain the full set of properties we normally expect to see. Further, we can now call GetContentsTable and get the members of the distribution list.

If you’re playing along in MFCMAPI, you would do this by:

  1. Select the distribution list whose members you wish to see.
  2. Right click on PR_ENTRY_ID in the bottom pane and select “Open as Entry ID or object”

The DL members will now appear in a new window. Back in the original window, the full set of properties for the DL will appear in the lower pane. In code, you would do this by opening the item with the short term entry ID, calling GetProps to get the long term entry ID, then calling OpenEntry again to get the full item.

This trick works for any of the PT_OBJECT type properties you expect to find on any entry in the address book, MAPI_MAILUSER included.

Enjoy!

MAPICDO and Exchange Server 2013

$
0
0

I’ve just been given clearance to publicize this since apparently it was discussed at MEC: The MAPICDO download *will* be updated to support Exchange Server 2013. This is important because:

  1. As has been discussed, Exchange Server 2013 will only allow MAPI connections over RPC/HTTP, aka Outlook Anywhere.
  2. RPC/HTTP is (until now) only implemented in Outlook’s MAPI.

So without this update to MAPICDO, the only MAPI implementation which would be able to connect to Exchange 2013 would be Outlook’s MAPI.

Publication dates, instructions for usage, etc. are all forthcoming.

Enjoy!

MAPICDO and the Impersonation Hang

$
0
0

So – there’s a potential hang in the current builds of MAPICDO, but you can avoid it, so it doesn’t have to be a huge problem.

The repro scenario for the hang is this: You’ve got an application which does thread level impersonation and also uses MAPI. Your application starts up multiple threads under different user contexts, each of which log in to MAPI. Eventually, as each of these threads completes its work, you start releasing objects. Your thread hangs while releasing a message store object. If you were to attach a debugger and knew the stacks to look for, this hang would look almost identical to the hang we fixed in MAPICDO 6.5.8244, discussed here.

What’s going on here is related to how MAPI tracks connection lists. Each user context gets its own connection list, stored in shared memory and indexed using what is essentially the CRC of the SID of the user who initiated the connection. When starting, there are no connection lists being tracked. The first MAPI thread to initiate a connection builds a connection list which is stored in this shared memory. This thread then spins up a polling thread using CreateThread. No special effort is made to adjust the thread token of this helper thread, so it ends up running with the thread token of the calling process. At some point, this thread needs to access the connection lists. As long as only one connection list exists, we assume it must be the one we need and use it – everything’s fine.

The problems happen when we have a second MAPI thread under a new user context. We create a second connection list and add this to the list. The polling thread spun up for this thread now has two connection lists to choose from. It concludes that neither is appropriate because the SIDs don’t match, and ends up shutting down without doing any work. Later, the first polling thread encounters the two connection lists and ends up shutting itself down without ever signaling that it has finished its work.

This is where the main MAPI threads are now in trouble, as they will wait for those polling threads to signal completion, which will never happen because those threads are no longer running.

Fortunately, most MAPI server applications don’t work this way. Most MAPI server applications run as a single service account which has appropriate permissions to log in to the various mailboxes it needs to. So either there is no impersonation at all, or all of the MAPI threads impersonate the same user. Either way, there is no opportunity to run in to this problem.

So – if you do happen to run in to this issue, you should look in to creating a single service account to handle all your MAPI work, then reduce/eliminate your thread level impersonation.

October 2012 Release of MFCMAPI and MrMAPI

$
0
0

The (very late) October 2012 Release (build 15.0.0.1036) is live: http://mfcmapi.codeplex.com.

As part of my work to get MFCMAPI and MrMAPI working well in side-by-side scenarios where both Outlook 2013 and an earlier version of Outlook are installed, I’ve added a –version switch to MrMAPI. This will help us ship builds of OCAT that work properly in these situations

Here's a change list - see the Issue Tracker on Codeplex for more details, or look at the code:

  • MrMAPI: Added –version switch.
  • MFCMAPI: Corrected column name in mailbox table
  • MFCMAPI: Fix blank headers when headers are dragged around.
  • MFCMAPI: Corrected an unnecessary crash in an Outlook+EMS (unsupported) scenario
  • MFCMAPI: Updated a number of flags, tags, and dispids

Enjoy.


MAPICDO and Exchange Server 2013 (Update)

$
0
0

I’ve just been given permission to announce we’re targeting the release of the updated MAPICDO which will support Exchange 2013 to coincide with the release of Exchange 2010 SP3.

Exchange 2010 SP3 was announced a while back on the Ehlo blog. As you can see from that announcement, SP3 provides much needed changes to allow for coexistence between Exchange 2010 and Exchange 2013. The updated MAPICDO is part of this work.

I don’t have dates for SP3, but you can track the Ehlo blog for that.

Locating the POP3 UIDL History

$
0
0

When Outlook’s POP3 provider syncs with a POP3 mailbox and the user chooses to leave a copy of the messages on the server, it has to remember which messages it has already downloaded so it doesn’t accidently download the same message twice. It does this by tracking the UIDL of each message it has downloaded in a binary property on a hidden message. This post describes how Outlook locates this binary property. My next post will detail how to parse this property.

Locate the Message

  1. Get PR_SEARCH_KEY from the profile (from the profile section MUID_PROFILE_INSTANCE)
  2. Open the Associated Contents for Inbox.
  3. Build this restriction:
    SRestriction rgRes[3]; 
    SPropValue rgProps[3]; 
    rgRes[0].rt = RES_AND; 
    rgRes[0].res.resAnd.cRes = 2; 
    rgRes[0].res.resAnd.lpRes = &rgRes[1]; 
    rgRes[1].rt = RES_PROPERTY; 
    rgRes[1].res.resProperty.relop = RELOP_EQ; 
    rgRes[1].res.resProperty.ulPropTag = PR_CONVERSATION_KEY; 
    rgRes[1].res.resProperty.lpProp = &rgProps[0]; 
    rgRes[2].rt = RES_PROPERTY; 
    rgRes[2].res.resProperty.relop = RELOP_EQ; 
    rgRes[2].res.resProperty.ulPropTag = PR_MESSAGE_CLASS; 
    rgRes[2].res.resProperty.lpProp = &rgProps[1]; 
    rgProps[0].ulPropTag = PR_CONVERSATION_KEY; 
    rgProps[0].Value.bin = pVals[iSearchKey].Value.bin; // PR_SEARCH_KEY from the profile 
    rgProps[1].ulPropTag = PR_MESSAGE_CLASS; 
    rgProps[1].Value.LPSZ = (LPTSTR)"IPM.MessageManager";
  4. Find the message using FindRow.
  5. If this fails, change the restriction:
    rgRes[1].res.resProperty.ulPropTag = rgProps[0].ulPropTag = PR_SEARCH_KEY;
    And re-run the FindRow
  6. If THAT fails, for non-Exchange stores (compare PR_MDB_PROVIDER to pbExchangeProviderPrimaryUserGuid), restrict instead on PR_SUBJECT (using printf style substitution here for brevity):: 
    "Outlook Message Manager (%s) (KEY: %s)", PR_PROFILE_NAME, HexFromBin(PR_SEARCH_KEY)
  7. Open the message located in step 5, 6, or 7.

For Outlook 2010 and higher, you can substitute the following for steps 3-6:

CHAR g_szGeneralKey[] = "General Key"; 
const SBinary g_binGeneralKey = {sizeof(g_szGeneralKey), (LPBYTE)g_szGeneralKey};

Now, use these values for PR_SEARCH_KEY and PR_PROFILE_NAME and run through steps 3-6. If this fails to find a message, fall back to the original steps 3-6.

Open the Attachment

There may be more than one attachment on the message. Try the following, in order (note again the use of printf style notation)::

  1. Look for an attachment whose PR_ATTACH_LONG_FILENAME matches "BlobPOP%s", szEmailAddress
  2. Look for an attachment whose PR_ATTACH_FILENAME matches "BlobPOP%s", szEmailAddress
  3. Look for an attachment whose PR_DISPLAY_NAME matches "BlobPOP%s", szEmailAddress
  4. Look for an attachment whose PR_ATTACH_FILENAME matches "Blob%.8x", dwAcctUID, where dwAcctUID comes from PROP_ACCT_MINI_UID.

PRO_ACCT_MINI_UID is a property you can retrieve via the Account Management API. Here’s the definition:

#define PROP_ACCT_MINI_UID PROP_TAG(PT_DWORD, 0x0003)

Open the Blob

The POP3 UIDL data blob is stored in PR_ATTACH_DATA_BIN.

Parse the Blob

We’ll discuss how to parse this blob in my next post. Stay tuned.

Enjoy!

Parsing the POP3 UIDL History

$
0
0

In my previous post, we discussed how to locate Outlook’s POP3 UIDL history. Now that we have the blob, let’s look at how to parse it:

POPBlob Structure:

  • Version (2 bytes): Must be PBLOB_VERSION_NUM (3)
  • Count (2 bytes): Count of resource tags
  • Resource tags (variable): 0 or more null terminated UTF-8 strings encoding the resource tags. The number of null terminated strings must match Count.

Resource Tags:

A resource tag encodes a UID with some metadata. The format of a resource tag string is represented as follows:

Mcyyyymmddhhmmssuuuuuuuuuuuuuuuuuu...

where

  • M (1 char): '+', '-', or '&', indicating a successful get, delete, or get-and-delete
  • c (1 char): ' ', 'h', or 'b', indicating content of none, header, body
  • yyyy (4 chars: Four digit year of download
  • mm (2 chars): Two digit month of download
  • dd (2 chars): Two digit day of download
  • hh (2 chars): Two digit hour of download
  • mm (2 chars): Two digit minute of download
  • ss (2 chars): Two digit second of download
  • uuuu... (variable): Encoded uid (Unique Identifier) of a message

The encoded uid of the message has been escaped so only alphanumeric characters and the character '$' are present. Non-alphanumeric characters in the original UID are represented as '$'+ 2 digit hex encoding. For instance, the character '-' is encoded in the UID as $2d

For example, this blob:

030017002B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 
2B623230313230393036313331313337313433444242434224326445413636243264313145312432644135463224326430303232363443313534424100 
2B623230313230393036313331313339323445383833333324326445413334243264313145312432644133414324326430303231354144374631353600 
2B623230313230393036313331313336333446324533383124326445423236243264313145312432644244353924326430303231354144383043324300 
2B623230313230393036313331313339333733443545363924326445413236243264313145312432644231363024326430303231354144393946303000 
... 

Can be interpreted as follows:
0300 Version: PBLOB_VERSION_NUM 
1700 Count: Count of restags (0x17 = 23) 
2B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 Tag 1 
2B623230313230393036313331313337313433444242434224326445413636243264313145312432644135463224326430303232363443313534424100 Tag 2 
2B623230313230393036313331313339323445383833333324326445413334243264313145312432644133414324326430303231354144374631353600 Tag 3 
2B623230313230393036313331313336333446324533383124326445423236243264313145312432644244353924326430303231354144383043324300 Tag 4 
2B623230313230393036313331313339333733443545363924326445413236243264313145312432644231363024326430303231354144393946303000 Tag 5 
...

And we can parse one of the resource tags as follows:
2B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 = 
"+b201209061311380BC535DB$2dEA63$2d11E1$2dA75C$2d00215AD7BB74" 
+ = Successful get 
b = Content is body 
2012 = Year 
09 = Month 
06 = Day 
13 = Hour 
11 = Minute 
38 = Second 
0BC535DB$2dEA63$2d11E1$2dA75C$2d00215AD7BB74 = UID

This UID can then be interpreted as:
0BC535DB + $2d + EA63 + $2d + 11E1 + $2d + A75C + $2d + 00215AD7BB74 = 
0BC535DB + '-' + EA63 + '-' + 11E1 + '-' + A75C + '-' + 00215AD7BB74 = 
0BC535DB-EA63-11E1-A75C-00215AD7BB74


So the first UID encoded in this blob is "0BC535DB-EA63-11E1-A75C-00215AD7BB74", and the body was successfully retrieved on 9/6/2012 at 13:11:38.

When to Build a Mail App

Wrapped PST Sample Updated for Outlook 2013

$
0
0

I’ve just checked in a fix for the Wrapped PST sample that should allow it to work with Outlook 2013. Let me know if you find any problems with the sample. I haven’t tested the other samples yet as they don’t appear to get as much attention as the wrapped PST.

Enjoy!

January 2013 Release of MFCMAPI and MrMAPI

$
0
0

The January 2013 Release (build 15.0.0.1037) is live: http://mfcmapi.codeplex.com.

We’ve been working a few issues lately related to the size of a OST versus the size of a mailbox. I’ve added some features to MrMAPI to aid in these sorts of issues. First is the –Size switch, which calculates the size of all the items in a folder and it’s subfolders. You can combine it with the –Folder switch to get the size of any folder. For instance, using the @2 notation to refer to the Contacts folder, I can get the size in my own mailbox as follows:

C:\>mrmapi -size -f "@2"
Folder size (including subfolders)
Bytes: 388867
KB: 379
MB: 0

The second feature uses the documentation of the PST file format to read the header of a PST/OST file and report free space. Note that this does require that the file not be loaded in Outlook when you run it. Simply closing Outlook is sufficient. Here’s an example run against an OST here:

C:\>mrmapi -pst -i c:\Users\sgriffin\AppData\Local\Microsoft\Outlook\outlook.ost
Analyzing c:\Users\sgriffin\AppData\Local\Microsoft\Outlook\outlook.ost
Unicode PST
File Size           = 2.71 GB (2911577088 bytes)
Free Space          = 1.05 GB (1132028480 bytes)
Percent free        = 38.88%

Here's a change list - see the Issue Tracker on Codeplex for more details, or look at the code:

  • MrMAPI: Added –PST for PST whitespace calculations
  • MrMAPI: Added –Size for folder size calculations
  • MrMAPI: Corrected handling of –Store parameter
  • QuickStart: Using QuickStart now populates the main window UI when appropriate
  • Property Editor: If you paste a property name in with extra whitespace or commas, these are now ignored
  • SmartView: Added a few more properties

Enjoy.

Custom Providers and Outlook 2013

$
0
0

Some of you may have already noticed this by now, but the logic used to load MAPI providers has changed in Outlook 2013. Previously, we would use LoadLibrary to load a MAPI provider. This API has logic in it to search the user’s PATH for the provider, which is great if you placed the provider somewhere on the user’s PATH. In Outlook 2013, though, we call LoadLibraryEx, passing the LOAD_LIBRARY_SEARCH_DEFAULT_DIRS flag. The effect of this flag is that Outlook no longer searches the path.

Fortunately, you can still put your provider wherever you want by putting the full path in MAPISVC.INF. You may need to rethink how you load your own dependencies, but now that you know what’s going on that problem shouldn’t be insurmountable. BTW – Process Monitor is invaluable in investigating this sort of issue.


Using MAPI In An Installer

$
0
0

If you have an installer which uses MAPI, specifically, which calls MAPIInitialize, you should be aware of this. After calling MAPIInitialize from the installer, you may note that you can no longer start Outlook! This only happens with Outlook 2010 and higher.

This was initially reported here: http://social.msdn.microsoft.com/forums/office/en-US/4cd23859-c5f5-40b2-a294-48cfc24bdc99/mapiinitialize-cause-outlook-2010-to-not-start-up, but I didn’t see it until recently. What’s happening is a change we made in Outlook 2010 to prevent potential cross user security issues with data stored in the MAPI profile. Every time MAPI starts up, we set an ACL on the following key:

HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles

The exact path may vary on different systems. The ACL we set contains three entries in it: System, the Administrators group, and the current user. When you start MAPI normally, the current user is the user the application is running as, which is typically the desktop user, so everything is fine. But when you run MAPI from the context of the installer, the current user can end up NOT being the desktop user. In that case we end up setting an ACL that denies the desktop user access to the registry key!

When Outlook subsequently tries to run, it finds it has no access to the Profiles registry key, so it has no MAPI profiles. Without MAPI profiles, Outlook can’t function, so you get an error, “Cannot start Outlook”. If you then try to run Outlook elevated, and you happen to be in the Administrators group, MAPI can then access this key and reset the ACL to the usual ACL, fixing the problem.

As far as I’m aware, not many applications call in to MAPI from an installer context, so this is somewhat a corner case. Additionally, it’s difficult to detect from MAPI’s perspective that we’re running like this. But if you want to avoid causing this problem for your users, you can use the functions GetSecurityInfo and SetSecurityInfo to grab the ACL before you call MAPIInitialize and then set the ACL back afterwards. Specifically, call GetSecurityInfo with SE_REGISTRY_KEY and a NULL Owner and Group parameter. Save off the Dacl and Sacl you get, then supply these to the SetSecurityInfo call after MAPIInitialize completes. This will prevent MAPIInitialize from rewriting the ACL on the Profiles key. You should only do this when running in an Installer or any other context where you find MAPI is writing an ACL that ends up affecting the desktop user.

MAPI and Exchange 2013 Public Folders

$
0
0

Prior to Exchange 2013, when Outlook’s emsmdb32 provider would log on to the server, it would get various bits of information back from the server, including information needed to connect to the Public Folder store. The provider would use this information to add the Public Folder store to the profile. This work involved pumping messages and this is where the workaround given here was involved:

http://blogs.msdn.com/b/stephen_griffin/archive/2007/05/30/outlook-2007-public-folders-mapi-and-you.aspx

With Exchange 2013, logon no longer returns any information related to Public Folders. Instead, the information needed to connect to Public Folders is handled through Autodiscover. When we do the initial AutoDiscover for profile creation, we get an entry back indicating that there is a Public Folder mailbox. Here’s what it looked like for my test mailbox:

<PublicFolderInformation>
<SmtpAddress>TestPFMailbox@tailspintoys.com</SmtpAddress>
</PublicFolderInformation>

We see the name of the Public Folder mailbox is TestPFMailbox. Outlook uses this information to conduct another Autodiscover conversation to get information on the Public Folder mailbox. Essentially, we send a request that looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
<Request>
<EMailAddress>TestPFMailbox@tailspintoys.com</EMailAddress>
<AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
</Request>
</Autodiscover>

We get a response back with information on the PF mailbox. Outlook then uses this information to make a call to CreateProvider to actually add the Public Folder store to the profile. CreateProvider takes a set of MAPI properties, whose values were derived from the information in the Autodiscover response. The properties we pass to CreateProvider are all derived from the AutoDiscover response:

PropertySource/ValueComment
PR_DISPLAY_NAME_W Public Folders –%s”, where %s is the value of PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_W. So, for my folder, it would be “Public Folders – sgriffin@tailspintoys.com
PR_PROFILE_USERPR_PROFILE_USERThis is the value of PR_PROFILE_USER from the Exchange Profile Section
PR_PROFILE_ALTERNATE_STORE_TYPE"Public"Hardcoded value
PR_EMSMDB_SECTION_UIDUser’s emsmdbUIDThis is the GUID of the Exchange Profile Section
PR_PROFILE_SERVERServer from the EXCH node in the Autodiscover responseTruncate this value at the first ‘.’ in the Server value. For instance, if Server is “1234…5678@tailspintoys.com”, this value would be “1234…5678@tailspintoys
PR_PROFILE_SERVER_DNServerDN from the EXCH node in the Autodiscover response 
PR_PROFILE_SERVER_FQDNServer from the EXCH node in the Autodiscover response 
PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_WSMTPAddress from the PublicFolderInformation node in the Autodiscover response 
PR_PROFILE_AUTH_PACKAGEMapped from AuthPackage from the EXCH node in the Autodiscover responseFor instance, a value of kerb would translate to RPC_C_AUTHN_GSS_KERBEROS. Special cases include:
Anonymous maps to 0x8000F001
PR_ROH_FLAGSROHFLAGS_USE_ROH | ROHFLAGS_SSL_ONLY If ServerExclusiveConnect is on, include ROHFLAGS_HTTP_FIRST_ON_FAST | ROHFLAGS_HTTP_FIRST_ON_SLOW
if CertPrincipalName is not none, include ROHFLAGS_MUTUAL_AUTH
PR_ROH_PROXY_SERVER_WServer from the EXPR  node in the Autodiscover response 
PR_ROH_PROXY_AUTH_SCHEMEMapped from AuthPackage from the EXPR node in the Autodiscover responseFor instance, a value of Basic would translate to ROHAUTH_BASIC
PR_ROH_PROXY_PRINCIPAL_NAMECertPrincipalName from the EXPR node in the Autodiscover response 

I’ve done a bit of hand waiving above, and I’ve likely missed a number of corner cases, but this should be enough for someone to get started. All of this work actually happens in Outlook.exe, so there is no way for external MAPI processes to trigger it (though it’s possible it might happen while using the Outlook Object Model).

 

For more information on the Autodiscover process, see [MS-OXDSCLI]: Autodiscover Publishing and Lookup Protocol. Enjoy!

Mail Apps and OAuth (AKA “Your Mail App is Busted”)

$
0
0

Jens has a really good post over on his blog about an issue he faced trying to configure OAuth integration between Lync Server 2013 and Exchange Server 2013:

http://blogs.technet.com/b/jenstr/archive/2012/11/22/getting-internal-server-error-500-when-creating-new-cspartnerapplication-for-exchange-2013.aspx

Why do I point this out? Because the same issue he saw is the one that’s been causing my Message Header Analyzer app for Office to fail in some environments. So far, I’ve only gotten one bad review:

Loads into mail preview grey bar okay but doesn't work. 
1. Something went wrong and we couldn't start this app. Try again.
then retry
2. This app may not load properly
then start
'Message Header Analyser' title appears.
thats it.

It turns out, that’s a symptom of Jens’ OAuth problem! The customer actually has an issue they need to correct in their environment. If you’re out there Richard Collins, this article is for you!

The Problem

Here’s what typically happens:

  1. Administrator installs an App for Outlook that requires Restricted Permissions.
  2. User activates this app on a message in OWA.
  3. The app attempts to make an EWS request.
  4. As part of making this request, the framework needs to get an access token.
  5. The request for the access token fails. The EWS call is never actually made and an error is returned to the app.
  6. How the app handles the error is dependent on the app, but whatever functionality depended on the EWS call is now broken.

In the case of Message Header Analyzer – it just stops rendering. I could perhaps handle this case more gracefully, and might in the future. Other apps display an error to the user.

Under the Covers

If we use F12 in IE to look at the network traffic, we’ll see the final frame’s request looks something like this:

{"__type":"GetClientAccessTokenJsonRequest:#Exchange","Header":{"__type":"JsonRequestHeaders:#Exchange","RequestServerVersion":"Exchange2012","TimeZoneContext":{"__type":"TimeZoneContext:#Exchange","TimeZoneDefinition":{"__type":"TimeZoneDefinitionType:#Exchange","Id":"Eastern Standard Time"
         }
      }
   },"Body":{"__type":"GetClientAccessTokenRequest:#Exchange","TokenRequests":[
         {"__type":"TokenRequest:#Exchange","TokenType":"ExtensionCallback","Id":"62916641-fc48-44ae-a2a3-163811f1c945"
         },
         {"__type":"TokenRequest:#Exchange","TokenType":"ExtensionCallback","Id":"d39dee0e-fdc3-4015-af8d-94d4d49294b3"
         },
         {"__type":"TokenRequest:#Exchange","TokenType":"ExtensionCallback","Id":"f60b8ac7-c3e3-4e42-8dad-e4e1fea59ff7"
         }
      ]
   }
}

This will be met with an error. The exact error appears to depend on the version of Exchange 2013, but I’ve seen both a GetClientAccessTokenResponseMessage with the text “The token for this extension could not be retrieved.” as well as a 503 Service Unavailable. In both cases, when we checked Get-AuthConfig, we found a thumbprint which was not present on any of the certificates found when we ran Get-ExchangeCertificate. Following the steps in Jens’ article to ensure that the thumbprint listed in Get-AuthConfig matched a cert in Get-ExchangeCertificate allowed OAuth to work, in turn allowing the App to work.

Conclusion

Administrators: If you find a mail app can load, but doesn’t function, it might be a problem with your OAuth configuration. Check your F12 trace to see if the GetClientAccessTokenRequest frame is the one that fails. If it is, check your OAuth configuration.

Developers: If your mail app uses EWS, be on the lookout for this sort of error and react appropriately. I suggest directing the user to someone who can help their administrator check the OAuth configuration.

Help Us Track Down A Missing Property

$
0
0

Some of you may have seen this:

http://support.microsoft.com/kb/2849083

The title of the KB is “"Could not complete the operation. One or more parameter values are not valid" error message when an organizer updates a recurring meeting” and it concerns an issue where we find PR_SENT_REPRESENTING_NAME to be missing on various calendar entries, which in turn leads Outlook to complain when you try to update the meeting. We’re working on a fix for Outlook that should be out soon, but I’m still trying to track down why that property went missing in the first place. Here’s where I was hoping the community could help. I know several of you out there have encountered this problem. I need data from a mailbox where the issue has been seen. In particular, I need to get the Calendar Version Store and Calendar Logging  that Exchange keeps. In that data I hope to find some clues as to where the property went.

What I need

What I want to get is the Calendar Logs for a user who has seen the problem, but I don’t want to get them the usual way, using Powershell. Instead, I want to get them directly using MFCMAPI. Here are the instructions:

  1. Build a profile for an affected user.
  2. Add a new, empty PST to this profile.
  3. Open MFCMAPI, go to Tools/Options, and check the two options, “Use the MDB_ONLINE flag when calling OpenMsgStore” and “Use the MAPI_NO_CACHE flag when calling OpenEntry”. Hit OK to close the dialog.
  4. Session/Logon, then open the mailbox.
  5. In the tree view, expand Root Container and locate the folder “Calendar Version Store”.
  6. Right click on this folder and select Copy.
  7. Back in the main window for MFCMAPI, open the PST store.
  8. Right click on Root Container in the PST tree view and select Paste.
  9. Accept the defaults and hit OK on this and the next dialog.
  10. MFCMAPI will take some time finishing the copy. When it becomes responsive again, it’s done.
  11. Back in the mailbox, expand Dumpster and locate the folder named “Calendar Logging”. (This folder might be missing – that’s OK)
  12. Repeat steps 6-10 on this folder.
  13. Close MFCMAPI (and Outlook if it’s open).
  14. Locate the PST, zip it, and send it to me.

You can do this on any user who has seen the problem, regardless of whether you have “fixed” the appointments by restoring the property via MFCMAPI.  If you happen to know the subject of an appointment which was broken to help me focus my research, that would be helpful, but not essential.

Can you help?

If you can – great! I can offer my undying gratitude in return. Just contact me through this blog and I’ll arrange a secure means to transfer the logs to me. The data will be kept securely here while I analyze it, then will be deleted. I’ll keep you updated on anything I find in the data that may help us track this problem down.

Thanks in advance to anyone who can help us track this issue down.

MAPI Provider Sorting

$
0
0

Outlook likes to sort folders alphabetically. When Outlook 2010 came out, some of our custom store provider developers came to us and asked that Outlook not sort the folders they returned. So we gave them a way to advertise to Outlook that the order they returned is the order Outlook should use. However, we didn’t port this fix to Outlook 2013. Why? Because in Outlook 2013 we already had a new feature which allows users to reorder their folders however they like and Outlook would remember the order. The missing piece of the puzzle is to document how Outlook remembers this order so store providers can give a default to their liking.

The key property is PR_SORT_POSITION. Here’s the definition:

#define PR_SORT_POSITION PROP_TAG( PT_BINARY, 0x3020)

Outlook will use this property as part of it’s sort order when requesting folders from a provider, so it’s important that your provider can handle sorting on a binary property – or can fake it when asked to sort by this property. Outlook will also use this property directly when deciding where to insert nodes in the visible tree, so it’s also important that your provider can return this property when Outlook looks for it on a folder.

If you look at some folders with MFCMAPI, you’ll see that Outlook usually only puts only a single byte into this property. Outlook will look at the first byte of this property to do the first pass of the sort. If two folders have the same first byte, Outlook looks at the second byte to break the tie, and so on. You can watch these values change as you continually drag the bottom folder of a list to the top and watch as eventually Outlook has assigned multiple folders a first byte of 00 and has to move to the second byte to break the tie,

There’s a second property Outlook will use for custom sort ordering:

#define PR_SORT_PARENTID PROP_TAG( PT_BINARY, 0x3021)

As the name suggests, this property stores an entry ID which can be used to sort a folder under a different node than it’s natural parent. Normally, a folder will be sorted under the folder represented by PR_PARENT_ENTRYID. This property allows you to suggest a different parent for display.

By presetting these properties appropriately, you can direct Outlook in how you wish your provider’s folders to be sorted. And if you allow Outlook to write to these properties, you can preserve whatever sort order your users desire.

Enjoy!

Viewing all 84 articles
Browse latest View live