Finding Windows error messages

Thursday 10 November 2005This is nearly 19 years old. Be careful.

One of the difficult things about programming in Windows, and especially with COM, is that when you receive an error code, it can be difficult to find the message that goes with it. I was writing some new LDAP code today against Active Directory, and got this message:

Couldn't read LDAP property member: COM exception 0x80005010

What does it mean? The “Couldn’t read LDAP property member” was my text, the 0x80005010 part is the HRESULT. Our error handling code tries to find a text message, but it couldn’t, and so made do with just the hex. I fired up errlook, the Microsoft error code lookup tool, but it couldn’t find a message either. Using DevStudio, I searched all of the include files for “80005010”. It found this section of adserr.h:

//
// MessageId: E_ADS_COLUMN_NOT_SET
//
// MessageText:
//
//  The specified column in the directory was not set.
//
#define E_ADS_COLUMN_NOT_SET   _HRESULT_TYPEDEF_(0x80005010L)

OK, now I knew what the error meant, and I had a symbol to use in my code if I wanted to handle it specially. But I’d like to display error messages at run time. How can I get that text message automatically? The errlook tool couldn’t find the message, so it was natural that my application couldn’t, but could I look further?

Windows stores error messages in DLLs, and the FormatMessage function can take an explicit module handle to a module containing error messages. My application already has a list of modules it searches when looking for error messages. If I could find the DLL with this message, I could get a nice message next time.

To find the error message, I resorted to the blunt instrument of the command line tool strings. It searches binary files for printable strings. Here I’ve told it to search the entire file (rather than interpret the executable format), look for a minimum string length of 10, print the file name along with each string, and look for little-endian 16-bit characters:

$ cd c:\windows\system32
$ strings -a -n 10 -f -e l *.dll | grep "specified column"
activeds.dll: The specified column in the directory was not set.
$

Aha! ActiveDS.DLL is my guy. I registered it into my application’s search list of error modules, ran the app again, and got a nice error message:

Couldn't read LDAP property member: COM exception 0x80005010:
The specified column in the directory was not set.

Bliss.

Comments

[gravatar]
OMG

You poor man.

The only text that helped me do LDAP programming in AD was the "Inside Active Directory" by Kouti/Seitsonen book. Worth its weight in gold. And its hefty.

Doing this type of programming in MS just underlines how horrible their API's are, how badly documented they are, and how fecking unreliable they are.

For instance. Lets imagine I have an AD object. I want AD to tell me the list of valid attribute names.

Can you do it ? I've wasted weeks wading through buggy code and giving up. Scary, eh ?

---* Bill

Add a comment:

Ignore this:
Leave this empty:
Name is required. Either email or web are required. Email won't be displayed and I won't spam you. Your web site won't be indexed by search engines.
Don't put anything here:
Leave this empty:
Comment text is Markdown.