Supporting Pre-Windows Vista Operating Systems

This topic describes how you can adapt an MUI application to run on pre-Windows Vista operating systems, sometimes known as "downlevel" systems. MUI technology allows you to develop fully globalized applications to run on nearly all pre-Windows Vista operating systems.

To take advantage of MUI support for pre-Windows Vista operating systems, you only need to make small adjustments to code developed to run on Windows Vista and later. You can then build separate versions of your application to run on Windows Vista and the older operating systems that you are supporting. All versions make full use of the main Windows Vista features, while the versions for the older operating systems retain system-specific features as required.

For pre-Windows Vista operating systems, a single-language localized version of an MUI application is built with different technology from the MUI operating system. The single-language localized version normally stores the localizable user interface resources together with programming execution code, and different versions have different program binaries.

Note: You can use Windows Vista to run applications localized for a single language, as well as applications that use satellite .dll files or an equivalent approach to delivering a multilingual user interface.

Represent Languages for the User

Representation of languages for the user uses the basic techniques discussed for applications to run on Windows Vista. For more information, see Representing the Correct Language to the User. However, an MUI application developed for a pre-Windows Vista operating system always requires explicit control of its user interface language.

Your MUI application can obtain the user interface language of the current user by calling GetUserDefaultUILanguage. If the application will run on Windows 95, Windows 98, and Windows Me, it does not have to access this language, because the user interface language of the current user is always the language of the operating system. To find out the language of the operating system installed on the local computer, your application can call GetSystemDefaultUILanguage.

The application can use the "en-US" language as a fallback language corresponding to the English (United States) locale. Another alternative for the fallback language is for the application to query the .mui file installed in the same folder as the LN file. Alternatively, the application can use the LN file itself and link fallback resources into this file.

Your application running on Windows 2000 or later must decide on a default language for use during initialization. To detect installed user interface languages, the application should call EnumUILanguages. To retrieve the user default and system default user interface languages, the application uses GetUserDefaultUILanguage and GetSystemDefaultUILanguage, respectively.

If running on any older operating system, your application should check the registry to determine the user interface language of the operating system. On Windows 95/98/Me, this language matches the resource locale indicated in the HKEY_CURRENT_USER\Control Panel\desktop\ResourceLocale registry key. On Windows NT, the operating system user interface language matches the locale of the default user indicated in HKEY_USERS\.Default\Control Panel\International\Locale.

Handle Strings

Your MUI application should handle strings using the instructions in Rendering Shell and Registry Strings.

Place Resource Files

An MUI application to run on a pre-Windows Vista operating system can use the Windows Vista convention of placing .mui files in folders based on language names, as described in Placing and Loading Win32 Resource Files. Alternatively, the application can conform to an older convention that forms paths from language identifiers.

For example, consider an LN file called BakerDelta.dll, with .mui files for English (United Kingdom), English (United States), English (Neutral), Spanish (Spain), Spanish (Mexico), and Spanish (Neutral). An installation on a pre-Windows Vista operating system might place these files as follows:

  • X:\\<somepath>\BakerDelta.dll
  • X:\\<somepath>\MUI\0809\BakerDelta.dll.mui
  • X:\\<somepath>\MUI\0409\BakerDelta.dll.mui
  • X:\\<somepath>\MUI\0209\BakerDelta.dll.mui
  • X:\\<somepath>\MUI\040a\BakerDelta.dll.mui
  • X:\\<somepath>\MUI\080a\BakerDelta.dll.mui
  • X:\\<somepath>\MUI\0209\BakerDelta.dll.mui

In addition to these files, the application can set up an ultimate fallback .mui file, to reside in same folder as the application itself. For the above example, this file is X:\<somepath>\BakerDelta.dll.mui. See Language Defaults, Preferences, and Fallbacks for a further discussion of the resource loader fallback language.

Create Partially Localized Resources

Your user interface might define partially localized resources, as described in Partial Localization. For these resources, you only have to place language-specific resources in separate .mui files for the supported languages. Note that you cannot partially localize resources within a single .mui file.

Here's an example of managing a partially localized resource in an application.designed to run on a pre-Windows Vista operating system:

The application supports twenty or thirty languages, but you do not want to localize the messages that go in the error log for most of these languages. You put error logging code in a separate .dll file with its own .mui files, and the only resources provided for that .dll file are for English and Japanese. Spanish-language users of your application see a user interface in Spanish, but receive English-language error logs. If you later decide to add Spanish-language error logging to your application, it will just be a matter of shipping an .mui file with Spanish-language resources. The LN files and the .dll file with error logging functionality will not change at all.

Load Resources

For loading resources on pre-Windows Vista operating systems, your application uses the functions of the redistributable MUILoad library in the Windows SDK for Vista. Your application can statically link with the MUILoad library to take full advantage of the multilingual capabilities of the resource loader.

Note: Use of the MUILoad library functions assumes that the MUI application uses the MUI-specific Win32 resource technology. If your application uses another resource technology, it must implement its own approach to loading these resources.

Include Code to Load Satellite .dll Files

The application places resources for each supported language in a separate .dll file. For a single portable executable, each language-specific .dll file uses the same resource identifiers, but contains strings and other language-specific resources in the appropriate language. The localization process either localizes .rc files and then builds an additional satellite .dll file from the modified files, or uses a localization tool that directly localizes a .dll file. The path of each resource .dll file on the target computer indicates the language of the associated resources.

For your MUI application to run on an older operating system, you need to write special code to manage satellite .dll files. At install time, the application can call EnumSystemLanguageGroups to determine the supported languages. To retrieve a handle to the resource .dll file for a particular language, the application calls LoadLibraryEx. The application uses the retrieved handle in all subsequent calls to load resources.

Here is an example of code that loads resources from a .dll file.

   HMODULE hResModule = LoadLibraryEx(TEXT("Mymodule.dll"), NULL, NULL);
         ...
LoadString(hResModule, myID, lpBuffer, cbBufferSize);
         ...
FreeLibrary(hResModule);

If your application implements a multilingual user interface on multiple operating system versions, you must be aware of platform differences in the LoadLibraryEx function. For example, it is desirable to load the resource-only .dll files as data files without referencing any executable code. However, on Windows 95/98/Me, LoadLibraryEx requires retrieval of the module handle using the lower-level resource functions, such as FindResource and LoadResource. Because the resource .dll files cannot be loaded as data files, each .dll file must define a dummy DLLMAIN.

Implement the MUILoad Library

The MUILoad library includes the LoadMUILibrary and FreeMUILibrary functions. Use of these functions enables a single LN file and a number of .mui files that provide MUI support.

Here is an example of application code using the MUILoad library functions to access user interface languages based on system settings:

   #include "MuiLoad.h"
 
   HMODULE hResModule = LoadMUILibrary(Text("Mymodule.dll"), MUI_LANGUAGE_ID, 0);
         ...
   LoadString(hResModule, myID, lpBuffer, cbBufferSize);
         ...
   FreeMUILibrary(hResModule); 

The following code loads a resource from a .dll file based on a user-selected language.

   LANGID langid;
         ... code here must allow user to set langid ...

   HMODULE hResModule = LoadLibraryEx(TEXT("Mymodule.dll"), NULL, NULL);
   HRSRC hResInfo = FindResourceEx(hResModule, RT_DIALOG, myID, langid);
         ...
   FreeLibrary(hResModule);

You can make this older code compatible for both Windows Vista and pre-Windows Vista operating systems as shown below.

   #include "MuiLoad.h"

   LANGID langid;
         ... code here must allow user to set langid ...
 
   HMODULE hResModule = LoadMUILibrary(TEXT("Mymodule.dll"), MUI_LANGUAGE_ID, langid);
   HRSRC hResInfo = FindResourceEx(hResModule, RT_DIALOG, myID, langid);
         ...
   FreeMUILibrary(hResModule); 

Using Multilingual User Interface (MUI)