Tuesday, August 3, 2010

COMExceptions, HRESULTS, and Windows Calculator

I was recently building a small web application in ASP.Net and C# where I had to deal with a little bit of ADSI and the System.DirectoryServices namespace. During the debugging phase, I used try/catch block to catch exceptions and present them in a label for development purposes and to create useful error messages for users for reasons that they would know and care about (such as an invalid username and password). One of the errors was a COMException with an ErrorCode property of 8007052E:
# as an HRESULT: Severity: FAILURE (1), Facility: 0x7, Code 0x52e
# for hex 0x52e / decimal 1326 :   ERROR_LOGON_FAILURE                                           winerror.h
# 1 matches found for "8007052e"

So, obviously I give the following a try in C# and am presented with a warning:

if (ex.ErrorCode == 0x8007052E)

Visual studio says "Comparison of integral constant is useless; the constant is outside the range of type 'int'". So I start working with the Exchange Error Code Look-up Tool  (note that it is not just for Exchange, but for any of the "19871 return codes registered from 172 sources" that it has archived on my system) and trial and error and do a little bit of truncation, looking up 0x7052E and 0x52E, which are presumably the same error code,

C:\>err 7052e
# as an HRESULT: Severity: SUCCESS (0), Facility: 0x7, Code 0x52e
# for hex 0x52e / decimal 1326 :   ERROR_LOGON_FAILURE                                           winerror.h
# 1 matches found for "7052e"

C:\>err 52e
# for hex 0x52e / decimal 1326 :   ERROR_LOGON_FAILURE                                           winerror.h
# 1 matches found for "52e"

Sadly, these don't work. Then I remember what I learned when I studied a little bit about two's complement numbers and realize that these error codes will never match and that the MSB of the 8-digit hex value is the one that is going to make the value negative for a 4-byte number, but in a decimal representation. **Note above that I was in error to work with 0x7052E, the error lookup tool was primarily interested in 4 or 8 digit hexadecimal representations of the error, so for the second one it was interested in 0x052E, returning the same error**.

I start poking around with some of the improvements to Windows Calculator (since I didn't want to use pencil and paper) in Windows Server 2008 R2 and Windows 7 and stumble upon the new Programmer mode (you can still perform this in the old calculator application, but using the Scientific mode). I enter the hex code 8007052E, remember that HRESULTs are dwords (4 bytes/32 bits)  and convert to decimal.

The correct value to use in the branch is actually -2147023570. No more warning. The word value is 0x52e (decimal 46), another possible result if the return value for a function written in an old version of Windows or one that only returns a 2 byte (16 bit) value.