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

  • Advanced search options...
  • About
  • Email Blog Author
  • RSS for posts
  • Atom
  • RSS for comments
    • OK
  • CDO (20)
  • Code Snippet (42)
  • Custom Providers (15)
  • Debugging (7)
  • DevMsgTeam (268)
  • Documentation (96)
  • DST (8)
  • EWS (7)
  • Exchange (98)
  • Gotchas (89)
  • Hotfix (26)
  • MAPI (212)
  • MAPI Download (47)
  • MFCMAPI (87)
  • MSDN (49)
  • Non Dev (11)
  • OOM (17)
  • Outlook (154)
  • Outlook 2007 Auxiliary Reference (44)
  • Outlook Integration API (11)
  • Protocol Docs (20)
  • PST/OST (21)
  • Public Folders (3)
  • Vista (12)
  • WrapPST (14)
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
  • 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)
Blogs I Read
  • Exchange

  • Raymond Chen [MSFT]

  • Larry Osterman [MSFT]

  • Peter David

  • Aaron Margosis [MSFT]

  • Jason Johnston [MSFT]

  • Matt Stehle (MSFT)

  • Patrick Creehan [MSFT]

  • Ryan Gregg [MSFT]

    Outlook PM
  • WebDav 101

    Dan Bagley (MSFT)
  • Dave Vespa [MSFT]

  • Randy Topken

    Outlook EE

MSDN Blogs > SGriffin's MAPI Internals
  • Subscribe via RSS
Sort by: Most Recent | Most Views | Most Comments
Excerpt View | Full Post View
  • SGriffin's MAPI Internals

    January 2012 Release of MFCMAPI and MrMAPI

    Posted 17 days ago
    by Stephen Griffin - MSFT
    • 2 Comments

    No one’s taking my subtle hints about Wikipedia. One more try: It sure would be nice if someone added MFCMAPI to the article about MAPI.

    The January 2012 Release (build 15.0.0.1030) is live: http://mfcmapi.codeplex.com.

    I’m continuing to crunch on the UI overhaul. This release has a ton of fixes for various flicker issues and glitches, especially those which show under the Windows Classic theme. Most of the problems were bad assumptions on my part that the Classic Theme helped expose. I also worked a good bit on making my various dialogs more pretty, practically rewriting the layout engine in the process. Finally, I finished up my work on painting the system buttons. This last bit required a bit of kernel debugging to figure out why Windows liked to repaint on top of my icons when I moved the mouse around. It turns out that initialization of the window’s system menu is what caused this. If you’re interested, look at how I handle WM_CREATE.

    I’m continuing to tweak the colors. Here’s another hero screenshot highlighting the new new color scheme, including the new system buttons:

    MFCMAPINewUI

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

    • MFCMAPI: Rewrote/cleaned up most of the dialog rendering
    • MFCMAPI: Much more double buffering to reduce flicker
    • MFCMAPI: Custom system icons
    • MrMAPI: New –Restrict switch to limit output from folders
    • MFCMAPI: Softer color scheme
    • MFCMAPI: Fixed all known Classic Theme glitches
    • SmartView: Added PidTagRoamingBinary
    • MFCMAPI: Much smaller options dialog now scrolls.

    Enjoy.

  • SGriffin's MAPI Internals

    December 2011 Release of MFCMAPI and MrMAPI

    Posted 1 month ago
    by Stephen Griffin - MSFT
    • 2 Comments

    What’s an app got to do to get on Wikipedia? You know I can’t put it there myself – that’s against the rules.

    The December 2011 Release (build 15.0.0.1030) is live: http://mfcmapi.codeplex.com.

    When I started working on the UI overhaul, I knew it was going to take a few releases to get it right. After all, I’m a one man development team, and while I’ve got a number of folks who do testing for me, I can’t catch everything. Since the last release, I’ve found (or been pointed at) a number of issues with the new UI, mostly relating to the abundance of themes out there. I’ve also found a new (to me) code analysis tool which has uncovered a number of potential issues. So I’ve decided to release an off schedule build to address everything. I’m still not done with the UI, but this release should be more visually stable on more machines.

    Since I’ve changed some colors in this release, I took a new screenshot:

    MFCMAPINewUI

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

    • MFCMAPI: Border painting was weird on some systems (never figured out exactly which, but did find my math error).
    • MFCMAPI: Underlying window bleed through in About dialog without Aero (fixed)
    • MFCMAPI: Clipping in the tree control as we hover highlight
    • MFCMAPI: Color choices conflicted with certain themes (switched to system colors which should not conflict)
    • Function annotations: Fixed a number of annotation and signature issues.
    • Other sundry code sanitation issues.

    Enjoy.

  • SGriffin's MAPI Internals

    EWSEditor December 2011 Update

    Posted 2 months ago
    by Stephen Griffin - MSFT
    • 0 Comments

    Matt has just announced that EWSEditor has been updated and moved over to Codeplex. Read his announcement here, then go download EWSEditor here.

    Enjoy!

  • SGriffin's MAPI Internals

    Enabling Kerberos Authentication

    Posted 2 months ago
    by Stephen Griffin - MSFT
    • 0 Comments

    We had a customer recently who was using Outlook 2010’s MAPI in their application to talk to the Exchange server. They wanted to enable Kerberos authentication, but were having trouble enabling it programmatically. They had found the property that gets changed when you enable Kerberos authentication through the UI: PR_PROFILE_AUTH_PACKAGE in the global profile section gets set to RPC_C_AUTHN_GSS_KERBEROS. When they tried setting this value in their profile though, they’d find that OpenAddressBook would return MAPI_W_ERRORS_RETURNED and subsequent calls to ResolveName would return MAPI_E_CALL_FAILED. What was really strange was if they opened the profile using Outlook or MFCMAPI, the profile would somehow be “fixed”, and their application would work.

    By comparing the profile before and after “fixing” it, we were able to track the difference down to a single property, which development has given me permission to document, PR_PROFILE_HOME_SERVER_FQDN (0x662A001F). This property is located in the address book section, dca740c8c042101ab4b908002b2fe182 (aka muidEMSAB). Setting this property to the DN of the user’s directory server was sufficient to turn a non-working profile into a working profile using Kerberos authentication. For example, if my DC was named ExampleDC, I might set this property to “ExampleDC.example.com”.

    So why would running MFCMAPI or Outlook fix the profile? It all has to do with the flags the customer passed to MAPILogonEx. They were passing MAPI_NT_SERVICE. To the Exchange address book provider, this indicated (among other things) that we should not load our user interface (UI) support object, since we’re running in a context that doesn’t allow UI. Later, when we’re attempting to connect to the server, we check if we have been referred to a DC yet. This is the PR_PROFILE_HOME_SERVER_FQDN property. Finding this property not set, we enter the code that would normally request a referral from the Exchange server. However, this code is dependent on the UI support object, so it does not execute. Ultimately, we decide to just talk directly to the Exchange server and let it handle proxying our calls over to the DC as needed.

    This all works fine as long as we’re not using Kerberos authentication. However, as we saw in the Check Names article, you cannot use Kerberos to make address book calls to the Exchange server (Exchange 2010 may fix this, but I believe this customer was using Exchange 2007). That’s why setting PR_PROFILE_HOME_SERVER_FQDN fixes the problem, since we connect directly to the DC.

    Notes:

    • Exchange 2010 handles address book calls made to the CAS differently from how Exchange 2007 and earlier handle them. The DSProxy process is no longer used. So the Kerberos authentication may succeed. However, the client would still be talking to the Exchange server instead of directly to the DC, which may not be desired. Setting PR_PROFILE_HOME_SERVER_FQDN will avoid this.
    • Logging on without MAPI_NT_SERVICE sets additional properties besides  PR_PROFILE_HOME_SERVER_FQDN, but investigation has not shown any of them to be essential. I’ll update this post if this changes.

    Enjoy!

  • SGriffin's MAPI Internals

    November 2011 Release of MFCMAPI and MrMAPI

    Posted 2 months ago
    by Stephen Griffin - MSFT
    • 3 Comments

    Still no mention of MFCMAPI on Wikipedia. I had such high hopes. Sigh.

    The November 2011 Release (build 15.0.0.1029) is live: http://mfcmapi.codeplex.com.

    Note that build number. That’s right. I jumped all the way from 6 (where I’ve been stuck forever) to 15. That’s the sort of jump that’s normally only accompanied by a full UI refresh. And that’s exactly what you get! I’ve overhauled just about every aspect of the UI for a more modern, some might say “Metro inspired”, look. I’ll admit, there’s still some work to be done (I didn’t get to scrollbars for instance) but this is a pretty good start. Let’s take a look:

    [See the new screenshot here.]

    I’ve drastically slimmed down the menus, stuffing most of the little used functionality into Advanced menus that most of you will never need to open. The old, usually empty, File menu is gone and Session now takes prominence. This should help new users immensely. Long time users of MFCMAPI may want to spend a little time figuring out where their favorite features went, but nothing’s been cut.

    A note about the tree: In the past, whenever you selected or expanded a folder, MFCMAPI would register for notifications on that folder and a number of it’s child folders. This was represented in the UI by bolding the folder name. This just confused people, so now, the only time I bold a folder name is to represent the currently selected folder. You can tell if MFCMAPI is listening for notifications on a folder by looking for a little red “I’m listening”icon after the folder name. It looks like this:

    Listening Icon

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

    • MFCMAPI: The entire UI (save scrollbars) has been updated with our new look.
    • MFCMAPI: The menu system has been given a long overdue scrub and overhaul.
    • MFCMAPI: The links in the help are now clickable.
    • MFCMAPI: Options shortcut – Ctrl+O brings up the newly slimmed options dialog.
    • MFCMAPI: While reskinnng the tree view I found several opportunities for performance enhancements. The tree should load faster, with less chatter to the server, and fewer issues with refresh as notifications come in.
    • Hex Editor: I’ve added commas (,) to the list of ignored characters for hex strings, making importing hex from other applications simpler.
    • Debug Viewer: Cancel has been replaced with Close, which makes much more sense.
    • MrMAPI: I’ve added pbGlobalProfileSectionGuid to our guid list

    Enjoy.

  • SGriffin's MAPI Internals

    MAPICDO 6.5.8244

    Posted 3 months ago
    by Stephen Griffin - MSFT
    • 3 Comments

    It’s been a while, but we just shipped a new version of the MAPICDO download. Per tradition, I’ve put together release notes:

    Installation details:

    • This version is 6.5.8244.0. All of the files in the update are dated October 17th, 2011.
    • If you already have a version of the MAPI Download installed, you must uninstall it before installing the new version. The installer does not upgrade, nor does it warn you if you try to install it without uninstalling the previous version.

    Fixes:

    • Kerberos authentication support when server FQDN is over 16 characters: This is a hard issue to spot. Basically, if your server FQDN is greater than 16 characters and you configure your MAPI profile to use RPC_C_AUTHN_GSS_NEGOTIATE, if you’re watching with a network monitor you’ll see your Kerberos authentication use a truncated UPN, which fails, and the authentication will be retried using NTLM. This fix corrects the truncation issue, giving Kerberos authentication a chance to work. No code change on the client side is required to enable this fix.
    • Hang releasing message store: Clients will typically see this problem when rapidly logging in and out of MAPI while doing work, but it can also be hit on a single log on and off, if the timing is just right. The problem was a timing issue in how we set up a polling thread. The fix was to change the order we did some initialization to remove the timing issue.
    • IOREPL fails to replicate FB data from Exchange 2010 to Exchange 2003: I wasn’t involved in this one myself, but it appears emsmdb32 was having trouble parsing otherwise valid Incremental Change Synchronization (ICS) data generated by Exchange 2010. The fix augmented the parser to allow emsmdb32 to handle this data correctly. This is the issue Henrik discusses here.
    • CDO Free Busy Lookup fails in Hosted Exchange: The key to CDO’s FB lookup is in matching a user to a message in the public Free Busy folder by comparing the user’s search key to the subject of the message. Hosted Exchange changed some assumption about the format of a user’s Exchange Legacy DN, on which the search key was based. The fix here was to make CDO aware of this change so it can map the DN to the form it needs for the FB lookup. This fix was first shipped in 8211, but I missed it then.
    • August 2011 DST cadence update: CDO has been updated with the DST changes outlined here.

    Enjoy!

  • SGriffin's MAPI Internals

    Random MAPI_E_CALL_FAILED Errors With Exchange 2010

    Posted 3 months ago
    by Stephen Griffin - MSFT
    • 4 Comments

    We have gotten a number of cases lately involving applications using Outlook 2010's MAPI failing when connecting to Exchange 2010 servers. The primary symptom observed by our customers is that random MAPI calls to Exchange return MAPI_E_CALL_FAILED. At first blush, there is no rhyme or reason as to which calls fail, except that all of the applications which see the problem have multiple threads using MAPI. It turns out the underlying problem is very complicated and we won't be able to fix it in a hotfix (though we do have a long term plan for a solution), so I wanted to get this information out there in case this problem is affecting you.

    The Issue

    The root of this problem has to do with how the Exchange MAPI provider (henceforth called just MAPI here) packs remote operations, or rops, into the RPC buffer to send them to Exchange to be processed. In all versions up until Outlook 2003 (and including all versions of the MAPI download), most rops are sent synchronously to the server as soon as the client calls in to MAPI. So if you were to call GetProps and follow along in the debugger, you would see your call go in to emsmdb32, then to rpcrt4, at which point a packet would be sent on the wire. Your thread would then wait for Exchange to respond, then it would parse the response buffer and hand it back to the client. The MAPI_DEFERRED_ERRORS flag can cause multiple rops from the same thread to get packed together in the same buffer, but the key point here is that everything usually happens on the initial calling thread.

    Outlook 2007 changed the model for how Outlook’s MAPI handles MAPI operations. Most MAPI operations are now issued asynchronously. MAPI maintains a worker thread which queues up pending MAPI operations from the various client threads and packs them into buffers as needed, resulting in fewer packets being sent between the client and server. So for instance, if one thread issued an operation to read a stream and another issued an operation to set properties at the same time, both operations could be packed into the same buffer and sent to the server. When the results come back, MAPI decodes them and sends them back to any client threads which were waiting on the results. This has the benefit of greatly reducing the amount of data sent across the wire, which is a primary concern for the developers of Outlook’s MAPI. The side effect of this change is that we can now see operations packed together in combinations that were never possible to see with Outlook 2003. This is the first change which leads to the random MAPI_E_CALL_FAILED results.

    On the server side, Exchange 2010 made a series of fixes to prevent looping calls which can overwhelm networks and bring down Exchange servers. The key rop here is RopBufferTooSmall, which is the rop the Exchange server can send back to a MAPI client if the server needs to send more data back to the client than is available in the response buffer. This is a signal to the client that it retry the operation, but this time either use a larger buffer, pack fewer operations into the request buffer, or both. Through analysis of numerous hang dumps we had received over the years, the Exchange team identified a number of scenarios where the server would send this response back to the client and the client's response would be to issue the exact same request the server had just rejected. This would result in a loop, with client and server exchanging the exact same packets until one or both was shut down. The key characteristics in these loops were that RopReadStream was the operation for which the result could not fit in the response buffer, that it was the first and usually only operation in the request buffer, and that we were already using the maximum size response buffer. The fix then was to special case when RopReadStream was the first operation in the request buffer. Instead of returning the RopBufferTooSmall rop, we would return the error ecBufferTooSmall (0x47D, or 1149 in decimal). This change, being more picky about how Exchange 2010 will accept packed rops, is the second change leading to random MAPI_E_CALL_FAILED_RESULTS.

    We combine these changes to see how they interact: prior to Outlook 2007, if Outlook’s MAPI issued a request buffer with RopReadStream as the first operation in the buffer, it was most likely also the last operation. A single client thread was waiting synchronously for the response to this rop. If the response buffer was already maximized and the request still could not fit, re-issuing the request could not be expected to work, so Exchange’s error would be the best response, as it avoids the loop. With Outlook 2007 and higher though, this RopReadStream could be packed in the same buffer as rops for other threads. Some of these rops may carry a large payload, which complicates the math Exchange uses to calculate the remaining space in the response buffer. This calculation occurs before Exchange executes the rops (since it would do no good to execute the rops first and discover we have no room for the results) so Exchange has to assume that every rop in the buffer could potentially fail. The upshot is that RopReadStream gets the short end of the stick, and Exchange concludes it does not have enough space for its response. When RopReadStream is not the first operation in the buffer, we send RopBufferTooSmall back to the client so it can break up the operations and try again. But when it’s the first operation in the buffer, the entire packetful of rops fails outright.

    And when they fail, since MAPI doesn’t have a targeted error code to match ecBufferTooSmall, everybody gets the default error of MAPI_E_CALL_FAILED.

    Our Response

    The Exchange and Outlook development teams both take this issue very seriously and want to correct this. That said, the risk of regression when you start playing with how Outlook packs rops or how Exchange calculates response buffers is incredibly high. The amount of testing we can do for a hotfix does not reduce this risk enough for us to be comfortable approaching this as a hotfix. So the Outlook team has agreed to attempt a fix for this in the next version of Outlook, currently under development. By getting the fix in to Outlook this early in the development cycle, we’ll have plenty of opportunity to test the fix, and also to observe how it affects clients in both dogfood and beta deployments. We will evaluate our options for Outlook 2010 if/when it comes time to consider what goes in to SP2, depending heavily, of course, on how things go in the next version.

    What You Can Do

    Given the nature of this problem, if your application is multithreaded, uses Outlook’s MAPI, and reads streams, there is a high likelihood you will run in to this problem at some point. Here are the options we’ve identified so far, in no particular order:

    1. Use the MAPI download instead of Outlook’s MAPI. Of course, this option does not apply if you are dependent on Unicode PSTs or the MAPI<->MIME conversion API.
    2. Use EWS to communicate with Exchange. This is your best long term resolution, and also the one with the highest development cost. However, if you’ve been looking for an excuse to make the switch, this is your chance.
    3. Use cached mode. When working in cached mode, all of your calls operate locally against the OST. The methods used to keep the OST in sync do not appear vulnerable to this issue.
    4. Serialize your MAPI calls. We’ve had some customers who have had success with this. The simplest way to serialize all of your MAPI calls is to use a single thread. If you cannot do this, then you need to isolate your calls which result in reading a stream from calls which are likely to carry a large request payload. One way to do this is to classify your MAPI operations into three classes:
      1. Calls which do or are likely to result in RopReadStream, such as: ISequentialStream::Read, CopyTo, MAPIToMIMEStm, IStream::Commit, etc.
      2. Calls which do or can handle a large amount of data, such as: ISequentialStream::Write, GetPropList, GetProps (for more than a handful of properties), SetProps (again, for more than a handful of properties), etc.
      3. Other calls, such as OpenEntry, SaveChanges, etc
      Once your calls are classified, you would then use mutexes or other control mechanisms to ensure you never issue a call from the first class while you’re waiting on the result of a call in either the first or second class. Calls in the third class would be safe to issue indiscriminatingly.
    5. Insert manual retry logic for all MAPI operations. Since the issue will cause all operations in a packet to fail, it is not sufficient to just retry rops which read streams. But since some MAPI operations will fail internally and swallow the error, it’s also not possible to protect all calls. This is not considered a viable resolution.

    Hopefully one of the first three options is available to your application.

    Diagnostics

    Given that this problem is one that is going to happen despite your best efforts to avoid it, it helps to be able to identify the issue. The best diagnostic here is to use Exchange’s RPC Client Access (aka RCA) logs, which are on by default. These logs contain an entry for every time Exchange failed a call with ecBufferTooSmall. The key word to look for in these logs is BufferTooSmallException. You should expect to find several entries with BufferTooSmall, without Exception. These are the normal retry results and can be ignored. Here are a couple of examples of the log entry you need to look for:

    2011-03-17T08:23:58.188Z,2,8548,/o=org/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=User,,
    customerapp.exe,14.0.4760.1000,Classic,,,ncacn_ip_tcp,,,1149 (rpc::BufferTooSmall),00:00:00,,
    RpcDispatch: [BufferTooSmallException] Une exception de type 'Microsoft.Exchange.RpcClientAccess.BufferTooSmallException' a été levée.

    2011-09-15T13:59:20.762Z,5,1351,/o=org/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=User,,
    customerapp.exe,14.0.4760.1000,Classic,,,ncacn_ip_tcp,,,,>ReadStream;>FastTransferDestinationPutBuffer,
    RpcDispatch: Exception of type 'Microsoft.Exchange.RpcClientAccess.BufferTooSmallException' was thrown.

    You'll find these logs on the Client Access Server (CAS) for Exchange 2010 in the following directory:
    %ExchangeInstallPath%\Logging\RPC Client Access

    Note that the second entry contains more information on the other operations which were included in the buffer. While you don’t need this information to identify the problem, it might be helpful in matching the logs to your own error logs. Here’s how to crank that logging higher (note that this must be done on every CAS for which you want greater logging:

    1. Locate the  %ExchangeInstallPath%\Bin folder
    2. Open Microsoft.Exchange.RpcClientAccess.Service.exe.Config in notepad.
    3. Near the bottom, there is a line which will look like this:
      <Add key=”LoggingTag” Value=”ConnectDisconnect, Logon, Failures, ApplicationData, Warnings” />
      To this list, add the word Rops. It should then look like this:
      <Add key=”LoggingTag” Value=”ConnectDisconnect, Logon, Failures, ApplicationData, Warnings, Rops” />
    4. Restart the RpcClientAccess Service.

    Now Exchange will log the rops which were in the buffer. By the way, RCA logs are great for troubleshooting other issues as well. Any time Exchange 2010 isn’t returning the results you expect, these logs are a good place to start. Also, I should remind anyone looking at these logs that we do know at least one other reason you might see BufferTooSmallException. I discussed it in my article on Large Multivalued Properties.

    Summary

    This is a complicated issue that can present itself in multiple ways (due to the random nature of which calls fail). Even though I was the engineer who discovered it and figured out what was happening, I still worked two further issues where this issue was the root cause but did not recognize it. In one case I happened to get debug trace that reminded me to check for this issue, and in the other, in desperation when no other troubleshooting was working, I rolled the dice and had the customer check the RCA logs on the off chance this was their issue. It turned out it not only lined up perfectly, but the customer was able to apply the same troubleshooting to other sites experiencing issues they though were unconnected and confirmed the issue was happening there as well. So while we don’t have a fix for this yet, at least we can determine when the problem is happening and stop troubleshooting.

    If development informs me of any plans to fix this earlier than the next version of Outlook, I will report them here. However, don’t ask me if or when SP2 is expected. For that, track the Office Sustained Engineering blog or the Update Center for Microsoft Office.

  • SGriffin's MAPI Internals

    The Elusive 0x81002746 Error

    Posted 3 months ago
    by Stephen Griffin - MSFT
    • 0 Comments

    If you look around for it, you’ll find a lot of posts on a 0x81002746 error that you might get from ConfigureMsgService. But no one seems to know what the error really means or why it happens. I thought I’d fill in some details.

    For starters, this error has nothing to do with WSAECONNRESET, which is 0x2746. Some error lookup tools will make this connection, assuming the value was built as a traditional HRESULT and reading the Code from within it. This has lead many people down the wrong path. Actually, the error is MAIL_E_NAMENOTFOUND. Once we know the real name of the error, we can make some sense of when and why it happens.

    When you call ConfigureMsgService to configure the Exchange provider, you provide the name of an Exchange server and a mailbox. The Exchange provider uses these to query the GAL to get more information to finish configuring the profile. It talks to the GAL using NSPI. In particular, it binds to the server and issues an NspiGetMatches call, passing a filter built using the mailbox name you gave to ConfigureMsgService. If this call succeeds and returns a record, it parses the results and continues configuring the message service. If it fails, we bubble up some version of the error we got back. But if the call succeeds with no records? Normally, we’d put up a dialog asking the user to check the name. But if we’re running as a service or the client passed flags to disable UI? That’s when we return MAIL_E_NAMENOTFOUND.

    Let’s examine the implications of this: We asked the server for any records matching a given name. The server responded with zero matches. This means it didn’t recognize the name. In other words, we looked in the GAL and did not find the mailbox we were looking for! We can now list some common causes:

    1. The mailbox really doesn’t exist.
    2. The mailbox exists, but is hidden from the GAL.
    3. The mailbox exists, isn’t hidden, but strange permissions have been set. Here are a couple examples.

    I recently had a customer encounter this error. I was able to eliminate the first two possibilities, but I knew better than to try and personally chase all the whackadoodle permissions that could be set in their Exchange environment. I’m a debugger, not an administrator! So I enlisted Kevin Carker, from our Exchange Admin team, to work with the customer and figure this out. His ace sleuthing uncovered a reason we had not previously considered: the customer had multiple GALs! They must have created them while playing around in the management console, and since nothing broke for their users, didn’t clean them up. But the way they left things configured, the user they were running their application as defaulted to one of the other GALs, which was empty. So NSPIGetMatches looked in that GAL, did not find the mailbox, and we returned MAIL_E_NAMENOTFOUND. Now, the customer could have configured everything so the presence of this empty GAL didn’t cause a problem, but, seeing as it was empty, they chose to delete it instead, at which point their account defaulted back to the regular GAL and could now configure a profile.

    Hopefully, now that we understand what this error means and why it happens, no one else will need to rip their hair out trying to troubleshoot it. If you’re getting MAIL_E_NAMENOUTFOUND from ConfigureMsgService, the mailbox you looked up could not be found in the GAL you looked in. By working through the various reasons why this may be, you should be able to resolve this without making a support call.

    Enjoy!

  • SGriffin's MAPI Internals

    September 2011 Release of MFCMAPI and MrMAPI

    Posted 4 months ago
    by Stephen Griffin - MSFT
    • 2 Comments

    Before we get to business, a comment: MFCMAPI does not appear anywhere in Wikipedia. This is a sad. Very very sad.

    The September 2011 Release (build 6.0.0.1028) is live: http://mfcmapi.codeplex.com.

    We got a handful of new features this time. MrMAPI can now parse flags on the fly, For instance, if you want to know what 0x3a means in PR_MESSAGE_FLAGS, MrMAPI can tell you:
    C:\>mrmapi PR_MESSAGE_FLAGS -flag 3a
    Found property PR_MESSAGE_FLAGS (0x0E070003).
    0x0000003A = MSGFLAG_UNMODIFIED | MSGFLAG_UNSENT | MSGFLAG_HASATTACH | MSGFLAG_FROMME

    Additionally, I added a feature to MFCMAPI to sort the names of properties such that the more common name is listed first. For instance, if you looked at an Exchange profile for the property 0x6612001E, you used to see the following list of property names, in alphabetical order:
    PR_CONTAB_STORE_NAME, PR_CONTAB_STORE_NAME_A, PR_PROFILE_HOME_SERVER_DN, PidTagContactAddressBookStoreName
    Now, when you look at the same property, we see the name we expect to see come first:
    PR_PROFILE_HOME_SERVER_DN, PR_CONTAB_STORE_NAME, PR_CONTAB_STORE_NAME_A, PidTagContactAddressBookStoreName

    I also added property name lookup to the restriction editor and a switch in Options to force MFCMAPI to load MAPI from the System directory, useful for older Exchange servers where Outlook Express may also be installed.

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

    • MFCMAPI: Better property name sorting. All alternate property names are now hand sorted with the most common name first. Please let me know if you find any which could be sorted better!
    • MrMAPI: Flag lookup via the new –Flag switch.
    • MFCMAPI: Force System MAPI, allowing MFCMAPI to work again on older Exchange servers.
    • MFCMAPI: Prop lookup in the Restriction Editor
    • Hex Editor: Bug fix when editing Base64.
    • SmartView: Found a type of Public Folder entry ID I wasn’t parsing correctly.
    • MFCMAPI: Count Named Properties will now report the highest named property in more situations.

    Enjoy.

  • SGriffin's MAPI Internals

    Undocumented MAPI

    Posted 6 months ago
    by Stephen Griffin - MSFT
    • 0 Comments

    It has come to our attention that a handful of functions exposed in the MAPI Stub Library don’t have documentation in the Outlook 2010 MAPI Reference. We’re working on correcting that, but in the meantime, here are the functions and some basic documentation of what they do.

    Update: All of these now have articles in the MSDN:

    • LpValFindProp
    • GetTnefStreamCodepage
    • FtAdcFt
    • HrAddColumns
    • IsBadBoundedStringPtr

    LpValFindProp

    Searches for a specified property in a property set.

    Header file: mapiutil.h

    Implemented by:

    MAPI
    Called by: Client applications and service providers.

    LPSPropValue LpValFindProp(
    
      ULONG ulPropTag,
    
      ULONG cValues,
    
      LPSPropValue lpPropArray
    
    );
    
    Parameters
    ulPropTag
    [in] Property tag for the property to search for in the property set indicated by the lpPropArray parameter.
    cValues
    [in] Count of properties in the property set indicated by the lpPropArray parameter.
    lpPropArray
    [in] Array of SPropValue structures that define the properties to be searched.

    Return Value
    LpValFindProp returns an SPropValue structure defining the property that matches the input propert tag, and NULL if there is no match.

    Remarks
    LpValFindProp is functionally identical to PpropFindProp.

    GetTnefStreamCodepage

    Determines the code page for a TNEF stream.

    Header file: tnef.h

    Implemented by:

    MAPI
    Called by: Client applications and service providers.
    HRESULT GetTnefStreamCodepage ( 
    
      LPSTREAM lpStream, 
    
      ULONG FAR * lpulCodepage, 
    
      ULONG FAR * lpulSubCodepage); 
    Parameters
    lpStream
    [in] Pointer to a storage stream object OLE IStream interface providing a source for a TNEF stream message.
    lpulCodepage
    [out] Pointer to the code page of the stream
    lpulSubCodepage
    [out] Pointer to the sub code page of the stream.
    Return Value
    S_OK
    The call succeeded and has returned the expected value or values.
    MAPI_E_NOT_ENOUGH_DISK
    There was an error reading an attribute in the TNEF stream.
    MAPI_E_CORRUPT_DATA
    Either the stream was not a TNEF stream or there was an error reading the attOemCodepage attribute.

    Remarks
    GetTnefStreamCodepage reads the attOemCodepage attribute of the TNEF stream to determine the code page and sub code page. If attOemCodepage is not found, will return a code page of 437 and a subcodepage of 0.

    FtAdcFt

    Adds one unsigned 64-bit integer to another, optionally using a carry flag.

    Implemented by:

    MAPI
    Called by: Client applications and service providers.
    FILETIME FtAdcFt( 
    
      FILETIME ft1, 
    
      FILETIME ft2, 
    
      WORD FAR *pwCarry); 
    Parameters
    ft1
    [in] A FILETIME structure that contains the first unsigned 64-bit integer to be added.
    ft2
    [in] A FILETIME structure that contains the second unsigned 64-bit integer to be added.
    pwCarry
    [in, out, optional] On input, a pointer to the incoming carry flag. On output, a pointer to the carry result for the addition. This parameter can be NULL if the carry result is not required.

    Return Value
    The FtAdcFt function returns a FILETIME structure that contains the sum of the two integers. The two input parameters remain unchanged. If pwCarry is non-NULL, it will contain the carry result for the sum, either 0 or 1.

    Remarks
    FtAdcFt is functionally identical to FtAddFt when pwCarry is NULL. If pwCarry is non-NULL and points to 0, FtAdcFt will return the same FILETIME value which FtAddFt would return.

    HrAddColumns

    Adds or moves columns to the beginning of an existing table.

    Header file: mapiutil.h

    Implemented by:

    MAPI
    Called by: Client applications and service providers.
    HRESULT HrAddColumns( 
    
      LPMAPITABLE lptbl, 
    
      LPSPropTagArray lpproptagColumnsNew, 
    
      LPALLOCATEBUFFER lpAllocateBuffer, 
    
      LPFREEBUFFER lpFreeBuffer); 
    Parameters
    lptbl
    [in] Pointer to the MAPI table affected.
    lpproptagColumnsNew
    [in] Pointer to an SPropTagArray structure that contains an array of property tags for the properties to be added or moved to the beginning of the table.
    lpAllocateBuffer
    [in] Pointer to the MAPIAllocateBuffer function, to be used to allocate memory.
    lpFreeBuffer
    [in] Pointer to the MAPIFreeBuffer function, to be used to free memory.
    Return Value
    S_OK
    The call succeeded and the specified columns were moved or added.

    Remarks
    HrAddColumns is functionally equivalent to HrAddColumnsEx with lpfnFilterColumns set to NULL.

    IsBadBoundedStringPtr

    Verifies that the calling process has read access to the specified range of memory.

    Header file: mapiwin.h

    Implemented by:

    MAPI
    Called by: Client applications and service providers.
    BOOL IsBadBoundedStringPtr( 
    
      const void FAR* lpsz, 
    
      UINT cchMax); 
    Parameters
    lpsz
    [in] A pointer to a null-terminated ASCII string.
    cchMax
    [in] The maximum size of the string, in CHARs. The function checks for read access in all characters up to the string's terminating null character or up to the number of characters specified by this parameter, whichever is smaller. If this parameter is zero, the return value is zero.

    Return Value
    If the calling process has read access to all characters up to the string's terminating null character or up to the number of characters specified by cchMax, the return value is zero.
    If the calling process does not have read access to all characters up to the string's terminating null character or up to the number of characters specified by cchMax, the return value is nonzero.

    Remarks
    IsBadBoundedStringPtr is functionally equivalent to IsBadStringPtr.

    Enjoy!

  • SGriffin's MAPI Internals

    July 2011 Release of MFCMAPI and MrMAPI

    Posted 6 months ago
    by Stephen Griffin - MSFT
    • 2 Comments

    The July 2011 Release (build 6.0.0.1027) is live: http://mfcmapi.codeplex.com.

    This round, the focus was on bulking up MrMAPI’s feature set. MrMAPI is one of the core data collection tools being used in a future update to our Software Diagnostics Platform for Outlook issues. This has driven several of the features I’ve added to MrMAPI to make it easier for the engineers writing the diagnostics to grab the bits of information they need so we can resolve issues faster.

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

    • MFCMAPI: Empty Folder can now delete one message at a time. Useful for those stubborn super large folders where the EmptyFolder API can’t complete.
    • MrMAPI: Fid/Mid lookup can now be performed.
    • MrMAPI: Open folders by name. Anywhere that takes a folder can now take a full path to the folder by name, or rooted on one of the “known” folders. The known folders list has been augmented to include the Sync Issues folders.
    • MrMAPI: Restrict by subject and message class. In case you just want to output certain messages.
    • MrMAPI: List folder contents and hierarchy tables.
    • MrMAPI: Better handling of non-Exchange mailboxes.
    • SmartView: I’ve augmented how PT_I8 is handled.

    Enjoy.

  • SGriffin's MAPI Internals

    Store Entry ID v2

    Posted 6 months ago
    by Stephen Griffin - MSFT
    • 0 Comments

    As I intimated before, Outlook’s MAPI supports a special kind of store entry ID which allows you to encode the full DN for the server and avoid redirects. Here’s the documentation for it.

    An Exchange Store Entry ID encodes an Exchange server and mailbox for us in OpenMsgStore. The base version of this format is documented here:
    http://msdn.microsoft.com/en-us/library/ee203516(EXCHG.80).aspx

    If you follow the format documented there, you will build an internal entry identifier for the Exchange MAPI provider, emsmdb32.dll. This entry ID can be wrapped with WrapStoreEntryID to get an entry ID that you can pass to OpenMsgStore. If you do this, what you generate will be the same as the entry ID generated by CreateStoreEntryID. In Outlook 2003, we introduced support for a v2 entry ID format that builds on the original format. In protocol documentation format, it looks like this:

    Store Object EntryIDs

    A Store object EntryID identifies a mailbox Store object or a public folder Store object itself, rather than a message or Folder object residing in such a database. It is used in certain property values.

    0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1

    Flags

    ProviderUID

    ...

    ...

    Version

    Flag

    DLLFileName

    ...

    ...

    WrappedFlags

    WrappedProvider UID

    ...

    ...

    WrappedType

    ServerShortname (variable)

    ...

    MailboxDN (variable)

    ...

    V2 (variable)

    ...

    Flags (4 bytes): MUST be 0x00000000.

    ProviderUID (16 bytes): MUST be %x38.A1.BB.10.05.E5.10.1A.A1.BB.08.00.2B.2A.56.C2.

    Version (1 byte): MUST be zero.

    Flag (1 byte): MUST be zero.

    DLLFileName (14 bytes): MUST be set to the following value which represents "emsmdb.dll": %x45.4D.53.4D.44.42.2E.44.4C.4C.00.00.00.00.

    WrappedFlags (4 bytes): MUST be 0x00000000.

    WrappedProvider UID (16 bytes): MUST be one of the following values:

    Store object type

    ProviderUID value

    Mailbox Store object

    %x1B.55.FA.20.AA.66.11.CD.9B.C8.00.AA.00.2F.C4.5A

    Public folder Store object

    %x1C.83.02.10.AA.66.11.CD.9B.C8.00.AA.00.2F.C4.5A

    WrappedType (4 bytes): MUST be %x0C.00.00.00 for a mailbox store, or %x06.00.00.00 for a public store.

    ServerShortname (variable): A string of single-byte characters terminated by a single zero byte, indicating the shortname or NetBIOS name of the server.

    MailboxDN (optional) (variable): A string of single-byte characters terminated by a single zero byte and representing the X500 DN of the mailbox, as specified in [MS-OXOAB]. This field is present only for mailbox databases.

    V2 (optional) (variable): An EntryIDv2 structure giving DN and FQDN for the server.

    EntryIDv2 Struct

    0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1

    Magic

    Size

    Version

    OffsetDN

    OffsetFQDN

    ServerDN (variable)

    ...

    ServerFQDN (variable)

    ...

    ReservedBlock

    Magic (4 bytes): MUST be 0xF32135D8.

    Size (4 bytes): An unsigned 32 bit integer giving the total size of the EntryIDv2 structure, including the ServerDN and ServerFQDN.

    Version (4 bytes): MUST be 0x00000001.

    OffsetDN (4 bytes): The offset in the buffer of the ServerDN. Should be 0x00000000 if ServerDN is not present.

    OffsetFQDN (4 bytes): The offset in the buffer of the ServerFQDN. Should be 0x00000000 if ServerFQDN is not present.

    ServerDN (optional) (variable): A string of single-byte characters terminated by a single zero byte, indicating the DN of the server.

    ServerFQDN (optional) (variable): A string of Unicode characters terminated by two zero bytes, indicating the FQDN of the server.

    ReservedBlock (2 bytes): MUST be set to 0x0000.

    Remarks

    • This format is only understood by Outlook’s MAPI. It may cause errors if used with Exchange’s MAPI.
    • If you are accustomed to building DNs to pass in to CreateStoreEntryID, take care not to append \cn=Microsoft Private MDB to the DN used in the v2 entry ID. That suffix is a hint used by CreateStoreEntryID and is not part of the entry ID format.
    • If you build an entry ID using the above format, you will need to wrap it using WrapStoreEntryID.
    • As a shortcut, you can use CreateStoreEntryID to build a v1 entry ID, then append the EntryIDv2 struct. If you build the entry ID in this manner, it will already be wrapped and WrapStoreEntryID will not be necessary.
    • The ServerDN is an ANSI string, but ServerFQDN is a Unicode string. Be careful not to encode them incorrectly.
    • For purposes of avoiding redirects, you can set ServerDN and leave out ServerFQDN. This will trigger a single unavoidable redirect the first time the entry ID is used, followed by direct connections on each subsequent use.
    • Some C++ definitions that may be helpful in implementing this:
      #define MDB_STORE_EID_V2_VERSION (0x1)
      
      #define MDB_STORE_EID_V2_MAGIC (0xf32135d8)
      
      struct MDB_STORE_EID_V2
      
      {
      
      	ULONG	ulMagic; // MDB_STORE_EID_V2_MAGIC
      
      	ULONG	ulSize; // size of this struct plus the size of szServerDN and wszServerFQDN
      
      	ULONG	ulVersion; // MDB_STORE_EID_V2_VERSION
      
      	ULONG	ulOffsetDN; // offset past the beginning of the MDB_STORE_EID_V2 struct where szServerDN starts
      
      	ULONG	ulOffsetFQDN; // offset past the beginning of the MDB_STORE_EID_V2 struct where wszServerFQDN starts
      
      };
    • If you’re using the above struct, you can compute the ulSize field as follows:
      ulSize = sizeof(MDB_STORE_EID_V2) + (lstrlenA(szServerDN)+1)*sizeof(char) + (lstrlenW(wszServerFQDN)+1)*sizeof(WCHAR);

    Enjoy!

    Update (8/15/2011)

    I’ve recently discovered that some Public Folder entry IDs seen in Outlook 2010 do contain a mailbox DN. This interferes with the usual logic for parsing such an entry ID, since there is no definitive indicator whether the data following Server Shortname is a DN or a structure. A slight modification to the algorithm is necessary: If the DWORD following the ServerShortName is MDB_STORE_EID_V2_MAGIC, then there is no DN and we have a v2 structure. If it is anything else, we have a DN following the Server ShortName. There may or may not still be a v2 structure after the DN, which should be parsed in the usual fashion.

  • SGriffin's MAPI Internals

    Outlook 2010 MAPI Reference July 2011 Update

    Posted 6 months ago
    by Stephen Griffin - MSFT
    • 0 Comments

    I just got word that the Outlook 2010 MAPI Reference has been updated. There were a number of minor bug fixes. The most notable addition was the incorporation of information about the MAPIStubLIbrary into the article about linking MAPI.

    Enjoy!

  • SGriffin's MAPI Internals

    Enough With The Redirects Already

    Posted 7 months ago
    by Stephen Griffin - MSFT
    • 1 Comments

    Here’s the scenario the customer gave us: They use Outlook’s MAPI and a single MAPI profile connect to an admin mailbox, and then use CreateStoreEntryID and OpenMsgStore to open various work mailboxes to do their processing. All day they’re opening and closing these mailboxes. In some environments, after they run for some time, one of the OpenMsgStore calls will return MAPI_E_FAILONEPROVIDER. There were a number of variations of the issue, as we’ll discuss below, but what they all had in common was that they were rapidly logging in to mailboxes, at least 5 times over a 10 second span.

    This was key to the issue. When we traced the process and debugged the reason for the failure, we saw the Exchange server was returning ecServerPaused when we got the error. Digging further back, we saw we were getting ecWrongServer on earlier, successful connections. If you read through the documentation on these errors, you’ll see this is a defense mechanism for Exchange. The ecWrongServer error, which never bubbles up to the caller, indicates that the mailbox requested is not on the server we’re talking to. This initiates a redirect conversation to find the right server. This negotiation is expensive, especially since the server conducting it shouldn’t have been contacted in the first place. So if the same client triggers too many redirects, Exchange returns ecServerPaused as a signal to the client that maybe it’s doing something wrong. You can find this error by calling GetLastError after OpenMsgStore fails. Outlook itself will use this information to trigger an update to the profile to ensure it’s talking to the right server.

    So, armed with this information, we went looking at the customer’s code to see what they were doing wrong. They would connect to mailbox Homer on server Alpha, obtain the DNs for mailbox Bart and server Beta, and pass these in to CreateStoreEntryID. They would then use this entry ID, and still see the problem if they logged in rapidly. They did nothing wrong and still had a problem.

    This is where things get complicated. First, let’s look at the output of CreateStoreEntryID (as parsed with MFCMAPI):

    MAPI Message Store Entry ID:
    abFlags = 0x00000000
    Provider GUID = {10BBA138-E505-1A10-A1BB-08002B2A56C2} = muidStoreWrap
    Version = 0x00 = MAPIMDB_VERSION
    Flag = 0x00 = MAPIMDB_NORMAL
    DLLFileName = EMSMDB.DLL
    Wrapped Flags = 0x00000000
    WrappedProviderUID = {20FA551B-66AA-CD11-9BC8-00AA002FC45A} = g_muidStorePrivate
    WrappedType = 0x0000000C = OPENSTORE_HOME_LOGON | OPENSTORE_TAKE_OWNERSHIP
    ServerShortname = Beta
    MailboxDN = /o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=Bart

    Note that the entry ID contains the server name “Beta”, but not the full DN, even though the full DN was passed in to CreateStoreEntryID. This is because the entry ID format generated by CreateStoreEntryID does not support using the full server DN. So only the short name is kept, and that’s all emsmdb32 has to work with. To talk to the server, we need the full DN, so we have to manufacture a DN using the information we have at hand. We do this by grabbing the DN of a known good server (in this example, Alpha) and replacing the server name. We then have a dilemma – this new DN may point to a real server, or it may be total garbage, for instance, if the OUs of the servers were different, this made up DN doesn’t exist. So instead of using this newly constructed DN to connect, we instead connect to the only server we know is functioning, using the server DN of the mailbox in the profile.

    Of course, this is wrong and we get redirected, and if we repeat this dance several times we’ll hit ecServerPaused. We recognized the potential to do better by implementing a cache of recently used DNs. If the DN we constructed was on this list, we’d go ahead and try it. So the first time we connect to Beta, we redirect through Alpha, but subsequent connections will use Beta’s DN since it’s in the cache. This fix first showed up in Outlook 2003 and 2007 via 929307 and 937949 respectively. So I had the customer check that their customer’s Outlook was up to date. Sure enough, one of their clients wasn’t, and updating it fixed the problem. This didn’t fix the others though, so we debugged again.

    The next site we looked at had an updated Outlook, but the the two servers were in different OUs. We’d build a (wrong) DN for Beta using Alpha’s DN. This DN wouldn’t be in our cache, so we’d connect to Alpha for a redirect. We’d then cache the (correct) DN for Beta. This same sequence of steps would repeat the next time we log in to Beta. As long as the two servers are in different OUs, we’ll always redirect. This customer was able to move mailboxes around and eliminate the problem.

    We then encountered a site with a single OU and up to date Outlook where the problem still happened. A close look at a trace of the problem revealed that in this particular configuration, the customer’s code managed to log all the way out of MAPI in between mailbox logons. So the cache we went through all the trouble to maintain was torn down and rebuilt on every pass, making it totally ineffective. Keeping one mailbox open the entire time was enough to keep the cache alive.

    We were able to get their code running in every environment except the ones where they couldn’t move their mailboxes and had to keep them in different OUs. For those, the only workaround they can use right now is to slow down a bit. Of course, things would be easier if there was a documented entry ID format that included the FQDN. Maybe one day there well be…

    Update: I just documented the v2 Store Entry ID format.

  • SGriffin's MAPI Internals

    MFCMAPI: Documentation By Committee

    Posted 7 months ago
    by Stephen Griffin - MSFT
    • 2 Comments

    I’ve noticed over the years that a number of articles have been written documenting how to use MFCMAPI to troubleshoot various issues. I thought it would be a good idea to put together a list of these articles in one central location. So after much searching with the Bing and with the Google, I’ve put together this list:

    MFCMAPI Articles

    I made an effort to classify the articles by topic. I know I’ve probably missed a number of articles – if you wrote an article or are aware of one that ought to be on the list, just let me know.

    Enjoy!

Page 1 of 18 (270 items) 12345»
  • © 2012 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy Statement
  • Report Abuse
  • 5.6.131.143