October 12th, 2016

Nasty gotcha: The inadvertently named resource

In the resources of a Win32 module, resource files, you can identify a resource by number (ordinal) or by name (string). One horrific gotcha of the resource file format is that it doesn’t require you to quote strings that are used to name resources.

Suppose you have this resource header file.

// resource.h

#define IDD_ENTERPASSWORD 100

and you use it in your resource file like this:

#include <resource.h>

IDD_ENTERPASWORD DIALOG ...
BEGIN
    ...
END

And your code tries to use the dialog like this:

DialogBox(g_hinst, MAKEINTRESOURCE(IDD_ENTERPASSWORD),
          hwndParent, DialogProc);

Everything compiles, but the Dialog­Box function returns -1 without displaying any dialog box. Your breakpoint on the Dialog­Proc is never hit. What’s going on?

What’s going on is that in your resource file, you misspelled “password”.

IDD_ENTERPASWORD DIALOG ...

This typo was not reported by the resource compile because of the strange rule that named resources permit but do not require quotation marks around the name. If you omit the quotation marks, the resource compile will “helpfully” insert them for you. Since IDD_ENTER­PASWORD is not defined anywhere, the resource compile assumes you meant

"IDD_ENTERPASWORD" DIALOG ...

and generates a named dialog resource called "IDD_ENTERPASWORD". If you did this on purpose, then the way you would access the dialog box would be

DialogBox(g_hinst, TEXT("IDD_ENTERPASWORD"),
          hwndParent, DialogProc);

But you didn’t misspell the symbol on purpose. It was a mistake. You meant IDD_ENTER­PASSWORD. And your misspelling cost you dearly: The resource was given the wrong identifier.

Sucks to be you.

The diagnosis for this class of problems is to verify that the dialog box you describe does indeed exist.

// Diagnosing the problem: Let's see if the resource exists.
// DialogBox(g_hinst, MAKEINTRESOURCE(IDD_ENTERPASSWORD), ...)

auto res = FindResource(g_hinst,
                        MAKEINTRESOURCE(IDD_ENTERPASSWORD),
                        RT_DIALOG);

In the debugger, check the return value of Find­Resource. If it’s nullptr, then the reason the Dialog­Box function failed is that the resource didn’t exist. The next step of the investigation would be to find out why the resource isn’t there.

Maybe you misspelled it.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.

Feedback