Random HRESULT From Outlook Object Model

I don't normally write much about the Outlook Object Model, but this was just too interesting to pass up. Suppose we run the following code in Outlook 2003 VBA:

 Sub TestHRESULT()
  Dim ons As Outlook.NameSpace
' If running this code in Outlook 2007 VBA, use Outlook.Folder here
  Dim f As Outlook.MAPIFolder 
  Dim imi As Outlook.MailItem
  
  Set ons = Me.Application.GetNamespace("MAPI")
  Set f = ons.GetDefaultFolder(olFolderInbox)
  Set imi = f.Items.GetFirst
  On Error Resume Next
  imi.SaveAs "c:?", Outlook.OlSaveAsType.olMSG
  Debug.Print "Error: " & Hex(Err.Number)
End Sub

What would we expect to happen? The path we passed to SaveAs is invalid, so we should get an error. Let's see what it prints the first few times we run it:

 Error: A72300FC
Error: A93300FC
Error: AB4300FC

What gives? Some of the digits here are constant (like the 00FC at the end) but why is the beginning changing? Turns out this is a bug in the way the Outlook Object Model is handling error codes. Under the covers, Outlook has gotten the right error code. But while passing this error around internally, the designers of Outlook wanted a simple way to track when and where the error happened. They did this by hijacking 11 unused bits of the HRESULT - specifically bits 20-30 (AKA - 0x7FF00000). What's supposed to happen is that these bits get stripped out before they get returned to the caller. However, we missed a few cases and these extra bits sometimes get out.

However, since we know what extra bits got set, we can clear them and get the real error code. Here's how we can do this in VBA:

 Debug.Print "Error: " & Hex(Err.Number And Not &H7FF00000)

Which will produce the desired result:

 Error: 800300FC

Looking this error code up, we find it is STG_E_INVALIDNAME, an appropriate error for an invalid file path.

BTW - we're pretty sure we've squashed this bug in Outlook 2007