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.

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.

@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.

@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.)

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)

>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.

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.

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.

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!