The troolean strikes back

There is a particularly amusing curiousity in Microsoft Win32 code that I have seen crop up a couple of times over the year: The “troolean”, or the “boolean” value with true/false/other as possible values.

You have probably seen this before in the winuser messaging APIs, such as the classic example of GetMessage:

WINUSERAPI
BOOL
WINAPI
GetMessageW(
    __out LPMSG lpMsg,
    __in_opt HWND hWnd,
    __in UINT wMsgFilterMin,
    __in UINT wMsgFilterMax);

According to the GetMessage documentation on MSDN, the return value has the following meanings:

If the function retrieves a message other than WM_QUIT, the return value is nonzero.

If the function retrieves the WM_QUIT message, the return value is zero.

If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer. To get extended error information, call GetLastError.

Yep, it’s zero, non-zero, or negative one.

Okay, I’ll give Microsoft a bit of slack there, since GetMessage has been around since the 16-bit Windows days, and the alternate return value for GetMessage was probably not there in the original design.

The thing that really got me started writing this article, though, was a little gem that I found while poking around in the CRT source code included with Visual Studio 2005. In “mstartup.cpp”, I found the following bit of code which is apparently used for Managed C++ support (which is not exactly legacy/old code):

class TriBool
{
public:
    enum State { False = 0, True = -1, Unknown = 2 };
private:
    TriBool();
    ~TriBool();
};

I guess trooleans are still all the rage these days (for some of us, anyway). Perhaps somebody needs to introduce the CRT programmer(s) to The Daily WTF

2 Responses to “The troolean strikes back”

  1. Yuhong Bao says:

    Indeed, GetMessage in the Win16 days had no way to return an error and therefore the return code of GetMessage had to be overloaded.

  2. Jeff says:

    Come on! What’s wrong with Trooleans? Language was made to serve us, not the reverse…

    I come across a need for three buckets all the time, for example, in user preferences, there are three possible values: update to true, update to false, and don’t update at this time.

    Just imagine two codebases, one of which uses troolean primitives and another that tries to fake it with lots and lots of if statements. Avoiding using trooleans where they truly are needed would be more of a WTF. On the other hand, I would agree if you said that TriBool was a bad name…