• Sign in
 
  •  
  • MSDN Blogs
  • Microsoft Blog Images
  • More ...

  • Blog Home
  • About
  • Email Blog Author
  • Share this
  • RSS for posts
  • Atom
  • RSS for comments
  • CDO (25)
  • Code Snippet (43)
  • Custom Providers (17)
  • Debugging (7)
  • DevMsgTeam (301)
  • Documentation (109)
  • DST (8)
  • EWS (7)
  • Exchange (109)
  • Gotchas (97)
  • Hotfix (28)
  • MAPI (240)
  • MAPI Download (54)
  • MFCMAPI (101)
  • MSDN (59)
  • Non Dev (11)
  • OOM (17)
  • Outlook (171)
  • Outlook 2007 Auxiliary Reference (45)
  • Outlook Integration API (12)
  • Protocol Docs (20)
  • PST/OST (23)
  • Referrals (8)
  • Vista (12)
  • WrapPST (18)
Links:
  • Download MFCMAPI
  • MFCMAPI on Facebook
  • Troubleshooting Outlook Crashes
  • Office Update Center
  • Developer Messaging Team Blog
This site is provided "AS IS" with no warranties, and confers no rights. Use of included code samples are subject to the terms specified in the Terms of Use.
Archives
  • May 2013 (3)
  • April 2013 (1)
  • March 2013 (2)
  • February 2013 (2)
  • January 2013 (2)
  • December 2012 (4)
  • November 2012 (2)
  • October 2012 (2)
  • September 2012 (1)
  • August 2012 (3)
  • June 2012 (2)
  • May 2012 (1)
  • April 2012 (3)
  • March 2012 (3)
  • February 2012 (3)
  • January 2012 (1)
  • December 2011 (3)
  • November 2011 (1)
  • October 2011 (3)
  • September 2011 (1)
  • August 2011 (1)
  • July 2011 (4)
  • June 2011 (3)
  • May 2011 (3)
  • April 2011 (3)
  • March 2011 (5)
  • February 2011 (1)
  • January 2011 (2)
  • December 2010 (1)
  • November 2010 (4)
  • October 2010 (1)
  • September 2010 (3)
  • August 2010 (5)
  • July 2010 (3)
  • June 2010 (3)
  • May 2010 (1)
  • April 2010 (3)
  • March 2010 (3)
  • February 2010 (3)
  • January 2010 (2)
  • December 2009 (3)
  • November 2009 (5)
  • October 2009 (4)
  • September 2009 (5)
  • August 2009 (5)
  • July 2009 (11)
  • June 2009 (6)
  • May 2009 (5)
  • April 2009 (3)
  • March 2009 (18)
  • February 2009 (10)
  • January 2009 (3)
  • December 2008 (2)
  • November 2008 (2)
  • October 2008 (5)
  • September 2008 (4)
  • August 2008 (10)
  • July 2008 (6)
  • June 2008 (8)
  • May 2008 (2)
  • April 2008 (4)
  • March 2008 (2)
  • February 2008 (2)
  • January 2008 (5)
  • December 2007 (3)
  • November 2007 (2)
  • October 2007 (3)
  • September 2007 (1)
  • August 2007 (4)
  • July 2007 (5)
  • June 2007 (3)
  • May 2007 (4)
  • April 2007 (1)
  • March 2007 (6)
  • February 2007 (3)
  • January 2007 (2)
  • December 2006 (4)
  • November 2006 (3)
  • October 2006 (1)
  • August 2006 (1)
  • June 2006 (5)
  • May 2006 (5)
  • December 2005 (1)
  • November 2005 (4)
  • October 2005 (2)
  • September 2005 (1)
  • April 2005 (3)
  • December 2004 (2)
  • September 2004 (2)
  • August 2004 (3)
  • July 2004 (3)

(Less Than) Portable Search Folders

MSDN Blogs > SGriffin's MAPI Internals > (Less Than) Portable Search Folders

(Less Than) Portable Search Folders

Stephen Griffin - MSFT
21 May 2009 4:47 PM
  • Comments 5

Let’s have fun with the object model and search folders:

  1. Outlook running a profile in online mode.
  2. Create this macro:

    Sub TestAdvancedSearchComplete()

        Dim sch As Outlook.Search

        set sch = Application.AdvancedSearch("Inbox", "urn:schemas-microsoft-com:office:office#Keywords like 'Test'", True, "MySearchFolder")

        sch.Save ("MySearchFolder")

    End Sub

  3. Run the macro, observe the folder.
  4. On the same machine, create a new profile in cached mode and start Outlook
  5. Run macro, get “Run-time error '-2147219964 (80040604)': Cannot create folder.”

If we want to have more fun, instead of running the macro the second time, we can locate the folder “MySearchFolder” under the Search Folder node in Outlook. If we click on it, Outlook creates a search folder, but it doesn’t populate with the items we expect to find.

What’s going on here? To answer that, we have to know a bit about how Outlook’s persisted search folder feature works. When you create a search folder, either using the Object Model, or directly in Outlook, the folder isn’t the first thing created. The first thing created is the search folder definition message. This is a message with the message class “IPM.Microsoft.WunderBar.SFInfo” which lives in the associated contents of the Common Views folder. We can use MFCMAPI to take a look at this message:

Our search folder definition message from Common Views

And we can use MFCMAPI’s Smart View feature to parse the search folder definition stored in PR_WB_SF_DEFINITION:

PR_WB_SF_DEFINITION, with parsing courtesy Smart View

From this, we find that the search folder definition contains the restriction that will form the basis of the search folder:

Restriction:
lpRes->rt = RES_CONTENT
lpRes->res.resContent.ulFuzzyLevel = FL_IGNORECASE | FL_FULLSTRING = 0x00010000
lpRes->res.resContent.ulPropTag = 0x8010101F (PT_MV_UNICODE)
lpRes->res.resContent.lpProp->ulPropTag = 0x8010001F (PT_UNICODE)
lpRes->res.resContent.lpProp->Value = Test
  Alt: cb: 8 lpb: 5400650073007400

Note that this restriction includes a property in the 0x8000 range, meaning it’s a named property. In fact, it’s the named property “Keywords” in the PS_PUBLIC_STRINGS namespace. Note also that there’s nothing in the restriction which tells me this. I only know it because I created the search folder and I know what the search folder is supposed to be looking for.

Now – what happens when we go to a different profile looking at the same mailbox? The search folder itself doesn’t get synched back to the server. Only this search folder definition message gets synced. When Outlook encounters this message, it places a dummy node under Search Folders and waits for the user to click on it. If the user does click on it, it builds the search folder using the information from PR_WB_SF_DEFINITION.

And that’s where the problem comes in: Named property mappings are store specific. A named property mapping that’s valid for one store will most likely be invalid for another store. When we switched to cached mode, we’re now working with the OST, not Exchange. Even if there happens to be an 0x8010101F property in this store, it’s not going to be the “Keywords” property. So when we clicked on the folder in Outlook, it created a search folder that searched for a bogus property.

What happened when we ran the macro is even more interesting: Outlook looked at our search string and built a search folder definition message with the appropriate PR_WB_SF_DEFINITION. However, it couldn’t save the message because it already existed, with a different definition!

Why don’t we have a problem when we create search folders directly in Outlook? The Outlook user interface severely restricts the kinds of restrictions you can set up. Because of that, Outlook is able to store the PR_WB_SF_DEFINITION in a different format (using SFST_FILTERSTREAM instead of SFST_MRES). That format is more flexible with named properties, but isn’t capable of storing the wide variety of restrictions that could be specified through the Outlook Object Model.

Workaround

We did look at taking a fix for this, but the limitations of SFST_FILTERSTREAM eliminated it as a possibility for a fix. And the fact that this problem only happens if the restriction contains a named property (IE it won’t repro on a search for subject or recipients) limited the scope of the problem.

However, for the case where the search folder is being created by a macro and we’re getting the “Cannot create folder” error, we found a neat workaround. We can use Outlook’s PropertyAccessor to delete the search folder definition message so it can be recreated. Here’s a sketch of the code:

Sub DeleteSFItem()
    Dim CommonViewsEIDBin As String
    Dim CommonViewsEIDString As String
    Dim CommonViewsFolder As Folder
    Dim ACTable As Table
    Dim oRow As Row
    Dim SFDefinitionEID As String
    Dim SFDefinitionItem As StorageItem
        
    CommonViewsEID = Session.DefaultStore.PropertyAccessor.GetProperty( _
        "http://schemas.microsoft.com/mapi/proptag/0x35E60102")
    CommonViewsEIDString = Session.DefaultStore.PropertyAccessor.BinaryToString( _
        CommonViewsEID)
    Set CommonViewsFolder = Session.GetFolderFromID(CommonViewsEIDString)
    Set ACTable = CommonViewsFolder.GetTable( _
        "[Subject] = 'MySearchFolder'", olHiddenItems)
    
    Set oRow = ACTable.GetNextRow()
    If (Not (oRow Is Nothing)) Then
        SFDefinitionEID = oRow("EntryID")
        Set SFDefinitionItem = Session.GetItemFromID(SFDefinitionEID)
        SFDefinitionItem.Delete
    End If
End Sub

For further reading on the inner workings of search folder definition messages, check out the Exchange Protocol Doc [MS-OSOSRCH].

  • 5 Comments
Outlook, MAPI, Code Snippet, Gotchas, OOM, MFCMAPI, Protocol Docs, DevMsgTeam
Comments
  • Dmitry Streblechenko
    21 May 2009 6:37 PM

    So is there a chance of having the SFST_FILTERSTREAM format documented?

    The very real problem I have is that firstly I cannot re-created a search folder with the search definition stored in that format and, secondly, whatever custom search folder I create in my code, teh restriction will not be displayed by OUtlook if the user were to modify teh search folder definition.

    Thanks!

  • Nick De Lancie
    10 Jun 2009 8:38 PM

    Stephen:

    All for my own personal use, I am an inveterate Word and Outlook VBA amateur programmer, and reasonably accomplished, particularly on the Word side.

    I am stumped, however, by how to delete an existing Outlook search folder programatically (or, in fact, to open it as a folder in an explorer programatically) in Outlook 2003.

    I can enumerate all the search folders in my mailbox's store (and see that there are numerous folders of the tag form "Search Folder[x]" where [x] is either null or 1 to 24 in addition to the built-in search folders and those I have created, whether manually or through VBA) using CDO and MAPI stores, but for the life of me, I can't programatically delete the folder or otherwise deal with it.

    Any help would be much appreciated.

    Thanks,

    Nick De Lancie

  • Stephen Griffin - MSFT
    11 Jun 2009 9:17 AM

    Nick,

    I haven't tried to delete the actual search folders, but in this scenario, deleting the folder itself doesn't help. It's the folder definition, which is an item, that has to be wiped out.

    Steve

  • Nick De Lancie
    12 Jun 2009 1:48 PM

    Steve:

    Thank you for your reply.

    I probably should have been more specific before, but I think you almost certainly already know that executing, for a search folder "sfldr" identified by running through the InfoStore of the MAPI Session with the Finder EntryID to enumerate the search folders, the method sfldr.Delete only changes the text of the name of the search folder in the search folders display in the Outlook folder view list to italics, but the search folder is still "there" so that a new programmatic search with the same tag name given fails with "unable to create".

    Since I need to delete the search folder definition item as you note above, do you know how that can programmatically be accessed in Outlook 2003, which does not have the PropertyAccessor and Table capabilities you utilized in your code example?

    Also, what is the programmatic methodology for displaying the found sfldr in a new explorer (so at least I could trap the cannot create folder error and display the existing one rather than deleting and recreating it, although this doesn't get to the clean-up problem of programmatically deleting multiple created search folders now no longer needed)?

    Again, any help would be much appreciated.

    Thanks,

    Nick

  • Stephen Griffin - MSFT
    12 Jun 2009 1:58 PM

    I don't think there's a way to delete the item with the Outlook 2003 object model. Of course, if you use MAPI, all things are possible.

Page 1 of 1 (5 items)
Leave a Comment
  • Please add 4 and 2 and type the answer here:
  • Post
  • © 2013 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy & Cookies
  • Report Abuse
  • 5.6.426.415