There are several places in the Windows API where a parameter is used only under certain conditions and is otherwise ignored. A customer wanted to know what to pass for an unused parameter.
“I know that it says that the FormatÂMessage
function ignores the lpSource parameter if neither FORMAT_
nor FORMAT_
is passed. So what should I use if I’m not passing either of those flags?”
This is the developer version of “The computer says to press any key, but I don’t have a key called Any.”
Instead of asking the customer to contemplate whether a parameter that is never used makes a sound, I just answered, “Just pass nullptr
.”
You sometimes see this recommendation in the Windows documentation. “Under condition X, the parameter is not used and should be zero.”
Sometimes it’s easier to just give an answer than to engage in a philosophical discussion.
It is very high privilege that we can frequently read insightful articles from someone with years of experience from Microsoft. Normally this kind of privilege is reserved for colleges in a company.
With PREfast you should be able to annotate the function with _When_ to indicate the times when a pointer can be NULL, for example _When_( dwFlags & FORMAT_MESSAGE_FROM_HMODULE ), _Pre_null_( lpSource ) (alongside all the other cases when it should be _Pre_notnull_).
Not sure whether that will help guide other tools like debuggers though.
Sometimes it’s not so easy to tell if a parameter is unused. For example, if the ExtTextOut input string length is 0 (useful for drawing solid rectangles), is the lpString parameter “unused” and therefore can be nullptr or does it need to be a valid (empty) string? Don’t see anything definitive in the documentation but the MFC source for CDC::FillSolidRect indicates that using nullptr is OK.
It is also important to have the source code reflect that the parameter is unused. “nullptr” does this but perhaps UNUSED_PARAM (#defined as nullptr) does it even better. Perhaps there’s a Windows header macro for this.
There’s REG_OPTION_RESERVED but I’m not sure which Registry function it’s intended for. Was it defined before REG_OPTION_OPEN_LINK was supported in RegOpenKeyExW? (The documentation of native ZwOpenKey and ZwCreateKey does not mention REG_OPTION_OPEN_LINK; I guess Win32 translates it to OBJ_OPENLINK in OBJECT_ATTRIBUTES.)
If nothing else, the debugger will thank you for passing a NULL for an unused pointer parameter.
It’s an extremely bad idea to pass an arbitrary value to an unused pointer parameter. When the API is exposed via COM, marshaling could kick in and actually touch the argument.