Getting the language (and more!) of an LCID-less keyboard

by Michael S. Kaplan, published on 2007/08/23 22:05 -04:00, original URI:

So back in May when I was talking about Getting the language of an LCID-less keyboard, I promised to do a bit more explaining about how support for custom locales was integrated into MSKLC 1.4, so that people could write code to work with specific keyboards.

I've been busy so I did not get to it right away, but I am going to talk about it a bit more now. :-)

It was actually way back in 2004 in Some Keyboarding Terms that the story begins; in that post I discussed the Keyboard Layout Identifier (KLID) and the fact that a KLID value with an "A" prefix meant an MSKLC-created layout. And I have talked about KLID values a few times since then, including that time in May when I talked about the custom ones.

I don't think I have ever explained what the install package for the keyboard provided by MSKLC does, though, so I'll start there.

Let's say we have installed that Valley Girl custom locale I asked Shawn to make for our fearless leader that I talk about in You wonder if like Vista supports custom locales? Fer shur!. It will show up in the Vista and Server 2008 user interface:

The fact that it is installed on Windows will mean that MSKLC picks it up in its own language list from Project|Properties, whether you select it as I have or not:

When the install package is built, it will include a LANGID value in it (it will end up in the MSI Property table, in string form in the LCIDValue property, in numeric form in the ProductLanguage property. For custom locales, the values of 0c00 and 3072 are used.

At install time of that package, a small process occurs:

  1. That LANGID is used as the LOWORD of the KLID of the keyboard -- thus for our custom locale we have 0x00000c00;
  2. An "A" prefix is put in the front, to signify an MSKLC layout -- thus for our custom locale we have 0xA0000c00;
  3. The registry key with the layouts (HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts) is checked to see if that subkey exists; if it is not, then it is created and the process skips to step 5;
  4. 0x00010000 is added to the KLID candidate (thus for our custom locale we will have 0xA0010c00 the first time we hit this step) and then step #3 is repeated;
  5. The following relevant registry values are added underneath the new subkey:
    1. Custom Language Display Name - an SHLoadIndirectString style string pointing to a resource in the layout DLL that contains the name of the custom language -- for our custom locale, the resource it points to is Valley Girl (California);
    2. Custom Language Name - A plain text version of the name of the custom language -- for our custom locale, Valley Girl (California). 
    3. Layout Display Name - an SHLoadIndirectString style string pointing to a resource in the layout DLL that contains the name of the custom keyboard layout -- for our custom keyboard, the resource it points to is Like Totally For Shure.
    4. Layout Text - A plain text version of the name of the custom keyboard layout -- for our custom keyboard, Like Totally For Shure.
    5. Layout Locale Name - Only present for custom languages, the name of the locale for use in name-based NLS API calls, e.g. en-US for English (United States) -- for our custom keyboard, valley-GIRL.
    6. Layout Product Code - a GUID representing the ProductCode in the MSI's Property table -- for our package, {B883CD61-769F-4488-8070-FBD07C0147E7}.

The view of the Property Table in the MSI file will look something like this (almost completely identical between all three MSI files):

And after the install, the registry will look something like this:

Without further adieu, the "cool for the ISV" design consequences:

1) The Layout Product Code is identical between the i386, amd64, and ia64 versions of each package, which is a theoretical violation that may cause the likes of fellow traveler Heath Stewart to cringe but ends up being a sound decision since each of the three different packages cannot ever be run on any architecture other than the one for which it is intended.

2) That Layout Product Code provides an excellent way for an application that installs an MSKLC-generated keyboard layout to find that specific layout, even though the KLID value may be different if other custom keyboards that use the same LANGID value are already installed.

3) The KLID value's LOWORD provides either an excellent LANGID to use for getting locale information if it is needed OR when the LOWORD is 0c00 a signal to look at the Layout Locale Name registry value.

4) The Layout Locale Name provides the name of the custom locale when one was used for the layout's creation.

Now I will cover some other interesting and/or important design consequences in the next post in the series, but this should be plenty to get people started....


This post brought to you by (U+1553, a.k.a. CANADIAN SYLLABICS FE)

# Ivan Petrov on 24 Aug 2007 6:06 AM:

Hi Michael :-)

I've the following question:

How can someone USE, let's say something like the MUI technology, for the Description text when the custom Keyboard Layout is installed?

I mean when some user is using English User interface (MUI) to see the English Description text and if some user (on the same machine) is using a Bulgarian User interface, to see a Bulgarian Description text. All this at the Language bar and in the Text Services and Input Languages window in the Installed services under the Keyboard tree as localized node!



# Michael S. Kaplan on 24 Aug 2007 7:39 AM:

That is one of those interesting (and dare I say it, important!) design consequences/considerations I'll be covering in the next part. :-)

# Ivan Petrov on 24 Aug 2007 8:29 AM:

OK Michael,

I'll be waiting for the next post!



# Ivan Petrov on 26 Aug 2007 5:26 PM:


I've one more question here:

What does this "A" prefix mean in the Keyboard Layout Identifiers (KLID) values created by MSKLC? I'm wondering from where it came from?

If it was "C" I can say that it came from 'C'ustom - Custom created keyboard layout!?

But it's "A"? ...



# Michael S. Kaplan on 26 Aug 2007 6:00 PM:

I actually had to choose a letter and I only had a few choices -- so I picked 'A'. :-)

Ok, that is not entirely true....

It is I suppose an easter egg of sorts, as I arbitrarily based the decision on the first names of two different women I've known -- the first being Andrea who I have talked about before, and the second a girl from Long Island that I met at a summer program in Boston many years ago. We never did keep in touch and life is such that I doubt I would ever run across her (even accidentally), but she was kind of inspiring way back when so I figured a small gesture couldn't hurt anything.

Well, that and wanting to keep the prefix farther away from the other prefixes that were being used.

Please consider a donation to keep this archive running, maintained and free of advertising.
Donate €20 or more to receive an offline copy of the whole archive including all images.

referenced by

2012/05/17 That 'keyboard culture list' you may have heard so much about

2011/11/02 The evolving Story of Locale Support, part 2 (raising the roof on keyboards)

2008/02/25 What the #$!*& is a KeyboardLayoutId, anyway?

2007/09/02 When the NLS keyboard's notions about LCIDs aren't the same as in NLS, part #1

2007/08/25 MSKLC keyboard layout names in your own language

go to newer or older post, or back to index or month or day