Abstract:
Hexadecimal locale IDs, saving user data on shutdown, and other bugs.

Created by Peter Kankowski
Last changed
Filed under Win32 programming

Share on social sitesReddit Digg Delicious Buzz Facebook Twitter

Dark corners in Microsoft's documentation

Microsoft Platform SDK was greatly improved since the times of Windows 95. Many errors in documentation were corrected; examples were added for common functions, etc. But descriptions for some functions still remain vague or incomplete.

Locale IDs are hexadecimal

The reference for EnumLocalesProc says lpLocaleString "points to a buffer containing a null-terminated locale identifier string", but it doesn't mention that locale ID is written in hexadecimal notation.

The description for GetLocaleInfo shares the same mistake: it says "If the information is a numeric value, the function converts the number to text using decimal notation". While this is true for LOCALE_IDEFAULTCODEPAGE or LOCALE_ICALENDARTYPE, it's simply wrong for LOCALE_ILANGUAGE. Locale ID is returned in hexadecimal if you use LOCALE_ILANGUAGE. Try this code:

LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
                     SORT_DEFAULT);
GetLocaleInfo(lcid, LOCALE_ILANGUAGE, buff, NUM_OF(buff));
// Now lcid == 0x0409, buff == "0409"

Hexadecimal notation is non-obvious here because commonly used locale IDs contain only hexadecimal figures from 0 to 9 (for example, US English is 0409 hexadecimal, and German is 0407), so one may erroneously believe they are decimal. (BTW, decimal locale IDs are also used: English version of Visual Studio contains a folder "1033", which stands for English locale ID in decimal notation.)

Saving files on Windows shutdown

When Windows shuts down, it doesn't send WM_CLOSE and WM_DESTROY messages to your application. Many programmers are unaware of this because Platform SDK never states it explicitly. As a result, programs fail to save configuration files or user's data when you press power button. For example, old versions of 1by1 did not save the last played song (the author have corrected the bug already).

You should handle WM_QUERYENDSESSION or WM_ENDSESSION to avoid this problem in your programs. In the simplest case, use the same handler for WM_ENDSESSION and WM_DESTROY:

LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) {
    switch(msg) {
        case WM_DESTROY:
        case WM_ENDSESSION;
            SaveConfig();
            FreeMemory();
            PostQuitMessage(0);
            return 0;
        ...
    }
}

Platform SDK says you need not call PostQuitMessage if the session is ending (wParam == TRUE for WM_ENDSESSION), but, for simplicity, you may wish to call PostQuitMessage always. Also, don't presume that you need not to free your memory because nobody will use it when the computer will be turned off :). WM_ENDSESSION may be sent to your application even if some other program has interrupted the shutdown process by returning FALSE in respond to WM_QUERYENDSESSION, so it's safer and easier to perform all termination steps.

Raymond Chen answered about this problem.

CDIS_SHOWKEYBOARDCUES meaning is reversed

CDIS_SHOWKEYBOARDCUES actually means "Hide keyboard cues". When the flag is set, a cue should be hidden; when it's cleared, the cue should be shown. The flag is named incorrectly and MSDN documentation does not explain this.

More dark corners

Raymond Chen sometimes fills up documentation weaknesses in his blog:

There is at least one shareware program that finds *.html files when you enter *.htm file mask. Beware of documentation errors, and if you know some of them, please add them here.

Peter Kankowski
Peter Kankowski

About the author

Peter lives in Siberia, the land of sleeping sun, beautiful mountains, and infinitely deep snow. He likes to program in C with a bit of C++, also in x86 assembly language, Python, and PHP (on Windows platform). He can be reached at kankowski@narod.ru.

Created by Peter Kankowski
Last changed

Leave your comment

Your name:


Comment:


Please ignore this field: