Cheap amusement: Searching for spelling errors in the registry


One source of cheap amusement is searching for spelling errors in the registry. For example, one program tried to register a new file extension, or at least they tried, except that they spelled Extension wrong.

And they wonder why that feature never worked.

My discovery was that my registry contained the mysterious key HKEY_CURRENT_USER\S. After some debugging, I finally found the culprit. There was a program on my computer that did the equivalent of this:

RegCreateKeyA(HKEY_CURRENT_USER, (PCSTR)L"Software\\...", &hk);

One of my colleagues remarked, "With enough force, any peg will fit in any hole."

I suspect that the code was not that aggressively wrong. It was probably something more subtle.

Comments (34)
  1. Anonymous says:

    Luckily, casting is the greatest force of all.

  2. Anonymous says:

    What part of registering a file extension involves using the word "Extension" in a registry key name?

  3. I suspect the programmer was overenjoying the newly found power of the reinterpret_cast operator:

    RegCreateKeyA(HKEY_CURRENT_USER, reinterpret_cast<PCSTR>(L"Software..."), &hk);

  4. SvenG says:

    Way back I modified (and eventually basically rewrote from scratch except for the recognition algorithm) a Japanese handwriting SIP for Windows Mobile. The original version used a huge collection of bitmaps to display the recognized characters, even though the assumption was you'd have a Japanese font (otherwise you couldn't insert the characters into whatever program you were typing in, and also the dictionary app that the SIP was primarily for wouldn't work).

    I wondered why it did that, and looking through the code I found a commented out bit that tried to use the font to draw the characters with a comment that it didn't work. The cause: the font name was spelled wrong. Yeah, so my rewritten version did away with the bitmaps.

  5. Anonymous says:

    @Sven Groot: My jaw literally literally dropped.

  6. Anonymous says:

    @David Walker: How About:

    HKLMSoftwareLitware CorpCustomer Essentials

    HKLMSoftwareWOW6432nodeLitware CorpCustomer Essentials

    Both contain the same data. If you change one, something syncs it automatically to the other.

    Incidentally I have a HKLMSoftwareWOW6432NodeMicrosoft on my Win7 x86 machine.

  7. Anonymous says:

    @Joshua

    Courtesy Wikipedia (en.wikipedia.org/…/WoW64):

    "Some Registry keys are mapped from 64-bit to their 32-bit equivalents, while others have their contents mirrored, depending on the edition of Windows."

  8. Anonymous says:

    @Joshua, Danny is right, that's an artifact of 32/64 bit processing, and not carelessness (or something) on the part of the software developer.

  9. speedfan says:

    Well on Windows 8, there's HKCUSofwareMicrosoftFeedbacktool. Dunno if that's a typo or intentional.

  10. Anonymous says:

    Can someone explain for the non-C(++) developers who read the blog, what causes the string to get truncated? Is it supposed to cast as a PCSTR* instead of a PCSTR or something?

  11. Anonymous says:

    Let's just stop using the non-Unicode Win32 API altogether.  I'm sick of programs blowing up because they're in a directory whose name can't be represented in the current code page.

    At my company, the standard is to use UTF-8 internally, then convert to UTF-16 when interacting with the Win32 API, which is a lossless conversion.

  12. Anonymous says:

    @Michael Kopinsky – I believe that the string is encoded as UTF-16. But the cast is forcing it to be interpreted as an ASCII string (for the A suffix on the function name). Since A-Z characters tend to be encoded in UTF-16 as the two byte sequence <byte equivalent of the ASCII encoding> + <byte that is zero>, and since an ASCII string ends with a single null (<byte that is zero>), the cast makes it seem like a string containing a single character.

  13. Anonymous says:

    WndSks: Or possibly they defined UNICODE in some source files but not in others (see the article Raymond linked to for more detail).

    This is why a) you always should specify UNICODE in your build settings and not in the source files and b) Microsoft should change its header files so they no longer work unless UNICODE is specified.

    Not supporting Unicode is an unforgivable sin.

  14. Anonymous says:

    @David Walker: Are you sure some not-shipped-by-Microsoft key is mirrored by Microsoft?

  15. Anonymous says:

    Steve FTW!

    @WndSks:

    I reported that feedbacktool typo a while ago

    Did you use the Feedback Tool to do so?

  16. Anonymous says:

    I find it weird, funnny, sad when installing a program creates keys named:

    HKLMSoftwareLitwareCorp

    and

    HKLMSoftwareLitware Corp

    both of which have some items related to the same program that I just installed.

    Microsoft does something else that's weird; I think there are keys named *WindowsNT* and *Windows NT*.

  17. #if !defined(UNICODE) || !defined(_UNICODE)

    #error Please add -DUNICODE -D_UNICODE to the compiler flags and recompile

    #endif

  18. Anonymous says:

    Heh, the linked article in the post reminds me what I should have done…

    #define  LPCTSTR LPCSTR

    #include "City Wok 3rd party non-unicode API that uses LPCTSTR's in its function declarations.h"

    #undef   LPCTSTR // restore typedef from <wtypes.h>

    … rather than:

    api_function( reinterpret_cast< LPCWSTR >( "Argument" ) ); // bleh

  19. @Joshua: Entire branches of the registry automatically mirrored by the operating system. It is not looking for that 3rd party registry key specifically; it is syncing everything in the place the key was created.

    Even when the synching isn't automatic, there can be valid reasons to manually create a registry key below both the main branch and the WOW6432node branch. You may need separate settings for 32-bit and 64-bit components. e.g. an In-process COM DLL may have different paths for the 32-bit and 64-bit versions. (If it's stored in a virtualised folder then it may not, but that doesn't have to be the case.)

  20. skSdnW says:

    I reported that feedbacktool typo a while ago. There are a couple of other MS entries that are not really typos but the information is in the wrong place, not sure if there are compatibility issues or what. WinObj was also stupid for a long time, it would store its settings under "SysInternals, Inc" while all the other entries used "SysInternals"

    @Michael Kopinsky: Normal strings in C ends with the null character () The *A versions of the API functions take a narrow string (1 byte per character mostly) so the string looks like S O F … in memory, string constants starting with L are wide strings (Unicode) and they are stored in memory like S O F … so the A version of the function reads it as S (To fix it the L prefix should be removed OR the code should call the W version of the function. The current code forces the string from WCHAR* to char*, it is a bogus cast that is only there to "fix" the compiler error/warning)

  21. Anonymous says:

    >Can someone explain for the non-C(++) developers who read the blog, what causes the

    >string to get truncated? Is it supposed to cast as a PCSTR* instead of a PCSTR or something?

    The thing about (reinterpret) casting is that it forces the compiler to pretend that some data of actual type T1 has type T2.

    The naive programmer thinks that this somehow *converts* the data from type T1 to type T2.  In fact, it has as much effect as closing your eyes when crossing a busy highway (hey, you can't *see* any traffic coming, so it's safe, right).

    If you've got a Unicode string that contains typical Western-alphabet characters, then the second set of eight bits will be zero.  And if you go ahead and feed this to a function expecting an ANSI string, those eight-zero-bits will signal the end of the string.

  22. cheong00 says:

    @No One: Me too… :O

    @Myria: I'd think that lots of VB6 applications defaults to import "A" versions of Win32 API, so at least we still have to deal with them until the next version after Win8 release.

  23. I don't see what the problem is with people referring to their company names in two different ways for the same program with different keys… the registry isn't exactly the pinnacle of the Windows UI.

    Non-obvious spelling mistakes are the worst; they look just like what they should spell and give so much hassle.  I wonder if there are string literal spell-checkers…

  24. Anonymous says:

    @xp.client *hurries to make a popular Windows 8 application that depends on this key to work*. There, now Microsoft doesn't have to fix it.

  25. >cheong00

    >I'd think that lots of VB6 applications defaults to import "A" versions of Win32 API

    VB6 will pass anything to any function. The programmer decides when s/he writes the function Declare. There is the Any data type that turns off type checking all together.

    BUT passing a string to a Win32API it is automatically converted from UTF16 to ANSI. So if defining strings one has to use the A version API calls. However s/he can declare it as a byte, and pass a unicode string in a byte array and pass that instead.

    Public Declare Function SetWindowText Lib "user32" Alias "SetWindowTextW" (ByVal hWnd As Long, ByRef lpString As Byte) As Long

    then to use it

    Ret = SetWindowText(EditNote.gStatusBarHwnd, AArray(0))

  26. cheong00 says:

    @DavidMCandy: Yes, but what I'm referring to is something different.

    In the days of VB6, when we need to call Win32 API, we get the function signature from an application called "API Viewer", and the function signature generated there defaults to the "A" function declaration. That's why I said the majority of VB6 application would have been using "A" functions.

    This was not a problem back at that time, because in 1998 there aren't much people running Windows with Unicode support yet.

  27. Anonymous says:

    Hypothetically speaking, you don't need to break VB6 at all, since VB6 programs do not include windows.h. You don't have to get rid of the *A functions, just make windows.h not use them.

    That said, there exist those who would see breaking VB6 as a very good thing.

  28. Anonymous says:

    I don't see what the problem is with people referring to their company names in two different ways for the same program with different keys…

    It doesn't manifest an air of professional competency: if they can't get the trivial stuff right, what are the chances that the complicated stuff will be ok?

  29. Anonymous says:

    Ansi string API functions are already removed on WinCE. Look how that worked out.

  30. It doesn't manifest an air of professional competency: if they can't get the trivial stuff right, what are the chances that the complicated stuff will be ok?

    Except it's not exactly the most important thing, or trivially easy to get right across a large program.  It's the sort of thing you should be told-off for /worrying/ about when trying to develop applications!

  31. From MSDN topic on RegCreateKey: "Note  This function is provided only for compatibility with 16-bit versions of Windows. Applications should use the RegCreateKeyEx function."

    The ANSI version of a 16-bit compatibility function, now that's what you should be told-off for!

  32. xpclient says:

    @LeoDavidson, isn't registry mirroring removed in Windows 7: msdn.microsoft.com/…/dd464643(v=vs.85).aspx and previously reflected keys shared?

  33. Anonymous says:

    Speaking of typos in Registry, I remember seeing HKEY_CURRENT_USERSoftware/Company/Product more than once (Registry permits / in key and value names, so Software/Company/Product was a single key).

  34. Anonymous says:

    Really just cheap amusement?

    Not missing functionality?

    On Windows NT5.x, look for "PropertyShellHandlers" or "TypeSupported", for example.

Comments are closed.