Many functions and interfaces provide the option of passing either a string or an integer. The parameter is formally declared as a string, and if you want to pass an integer, you smuggle the integer inside a pointer by using the MAKEINTRESOURCE
macro. For example, the FindResource
function lets you load an resource specified by integer identifier by passing the identifier in the form MAKEINTRESOURCE(ID)
. You can tell that it was the resource-loading functions who created the macro in the first place, since the name of the macro is “make integer resource.”
But other functions use the MAKEINTRESOURCE
convention, too. The GetProcAddress
function lets you obtain a function exported by ordinal if you smuggle the ordinal inside a pointer: GetProcAddress(hModule, MAKEINTRESOURCEA(ordinal))
. (You have to use MAKEINTRESOURCEA
because GetProcAddress
explicitly takes an ANSI string.)
What if you’re implementing a function whose interface requires you to accept both strings and integers-smuggled-inside strings? For example, maybe you’re implementing IContextMenu::InvokeCommand
, which needs to look at the CMINVOKECOMMANDINFO.lpVerb
member and determine whether the invoker passed a string or a menu offset.
You can use the IS_INTRESOURCE
macro. It will return non-FALSE
if the pointer you passed is really an integer smuggled inside a pointer.
How does MAKEINTRESOURCE
work? It just stashes the integer in the bottom 16 bits of a pointer, leaving the upper bits zero. This relies on the convention that the first 64KB of address space is never mapped to valid memory, a convention that is enforced starting in Windows 7.
0 comments