MAPI Provider Sorting
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!
Comments
Anonymous
November 08, 2013
Will Outlook dynamically update the sort order if I modify that property at run-time?Anonymous
November 08, 2013
Yes - Outlook will update the tree dynamically.Anonymous
November 08, 2013
Will Outlook use PR_SORT_PARENTID with search folders? Can I set where search folders are shown in the tree?Anonymous
November 08, 2013
I haven't tried that - it'd be easy enough to test.Anonymous
November 08, 2013
It looks like Outlook resets the PR_SORT_PARENTID property if it does not like the value. the script below will work fine if the property is set to the entry id of the parent folder, but if I set it to the entry id of the Inbox folder, Outlook resets it to (cb:0; lpb:null) PR_CLIENT_SUBMIT_TIME = "schemas.microsoft.com/.../0x00390040" PR_MESSAGE_DELIVERY_TIME = "schemas.microsoft.com/.../0x0E060040" set Folder = Application.ActiveExplorer.CurrentFolder set Inbox = Application.Session.GetDefaultFolder(olFolderInbox) 'Folder.PropertyAccessor.SetProperty "schemas.microsoft.com/.../0x30210102", Folder.Parent.PropertyAccessor.GetProperty("schemas.microsoft.com/.../0x0FFF0102") Folder.PropertyAccessor.SetProperty "schemas.microsoft.com/.../0x30210102", Inbox.PropertyAccessor.GetProperty("schemas.microsoft.com/.../0x0FFF0102")Anonymous
November 08, 2013
LOL Stephen are you reading my mind? I spent two hours yesterday scouring hidden messages and registry settings trying to find out how this works! Thanks!Anonymous
February 11, 2014
Great! And what about GetMsgStoreTable()? How to get stores in the same order they're showing in Outlook (because I can reorder stores in Outlook with drag'n'drop)?Anonymous
February 11, 2014
Alexyey: Try adding PR_SORT_POSITION to your sort order.Anonymous
February 19, 2014
It seems that there is no PR_SORT_POSITION on storages. I can reorder storages even in Outlook 2010, but can't find the way to get sorting criteria...Anonymous
July 10, 2014
I seem to be doing something wrong with this stuff. I have our IMAPIFolder objects supporting the PR_SORT_POSITION property and it looks like Outlook is reading the property fine, but the sort order is still showing alphabetical. I'm using a ULONG member variable for the order: pProps[i].Value.bin.cb = sizeof(ULONG); pProps[i].Value.bin.lpb = (LPBYTE)&m_ulSortPos; This ends up getting called as part of our IMAPITable::QueryRows implementation. Should I be putting it somewhere else?Anonymous
July 22, 2014
Outlook should be asking you to sort the table on this property. Do you see that happening and how do you handle it?Anonymous
August 05, 2014
I can see the PR_SORT_POSITION coming in as the first item in the LPSSortOrderSet parameter of our IMAPITable::Sort implementation, but I'm not sure what we need to do with that. Our internal order is already in the order we want it, so that's what we are giving back to Outlook when it queries rows. There isn't ever going to be a different order for these particular items. We want them in our order and don't want Outlook or a user to mess with that order.Anonymous
August 05, 2014
And does Outlook ask for the property as a column? If so, what do you return?Anonymous
August 05, 2014
We get it requested in our GetProps implementation, and we return a byte value, essentially an ordinal number for each item in the table 0-n. I can see the property for the items in Outlook via OutlookSpy.Anonymous
August 05, 2014
You might want to open a support case then.