Skip to main content

The Microsoft Layer for Unicode on Windows 95/98/ME Systems

For years, Microsoft has evangelized the benefits of creating applications that support Unicode.  On Windows NT, Windows 2000, and Windows XP, these benefits are obvious, and include:

  • Improving international and multilingual support.

  • Better integration with the features of the Windows NT platform.

  • Shipping a single binary instead of separate builds for each locale.

  • Better support of the Multilingual UI (MUI) features of Windows 2000 and Windows XP.

  • Support for the many new "Unicode only" languages such as Hindi and Georgian.

The problem was the difficulty in supporting a Unicode application on Windows 95/98/ME; developers had to support those customers as well. Because those platforms do not have the native Unicode support provided by the Windows NT family of operating systems, it was just easier to write non-Unicode applications.

However, starting with the Windows XP version of the Platform SDK, the Microsoft Layer for Unicode on Windows 95/98/ME Systems (MSLU for short) can help developers solve this important challenge. This component provides a layer over the Win32 API on Windows 95/98/ME so that you can write a single Unicode version of your application and have it run properly on all platforms.

3squares

Feature Overview

  • Easy to integrate - All you need to do is compile your application as a Unicode component and include the unicows.lib file with the other libraries you use.

  • Does not slow down applications on Windows NT, Windows 2000, or Windows XP - The custom loader for unicows.dll is built into unicows.lib and compiled with your application.  It does not even load MSLU unless you are on a Win95/98/ME machine! The technology is similar to the VC++ delayload mechanism, but is an independent solution that does not rely on any particular compiler.

  • Easy customization - Developers who use the MS Layer for Unicode can override any API they want to and still take advantage of the custom loader.

  • Good coverage of the Win32 API - MSLU provides fully implemented wrappers for over 440 API calls, with an additional group of "stub" wrappers that developers can override to implement themselves.

  • Lightweight and easy to use - Weighing in at ~160kb and with no dependencies, no registration requirement, no special file location needed, its careful avoidance of "DLL Hell" issues, and its APIs staying so nearly identical to those found on the Unicode platforms, MSLU is exceptionally easy to add to your application.

  • Works well with commonly used libraries - You may be using the Microsoft Foundation Classes (MFC), the VC++ Runtime (CRT), or the ActiveX Template Library (ATL). If you statically link these DLLs and subsequently integrate the MS Layer for Unicode, all of them will properly use the Unicode APIs that MSLU provides.

  • Good interoperability - Whether you need to work with other that use MSLU in the current process, applications that are out of the current process, or even solutions that do not have Unicode support at all, The Microsoft Layer for Unicode is able to behave appropriately.

  • Comprehensive documentation - The Platform SDK provides information in the topics for every single API that is supported by MSLU, including special issues for those few APIs to which you need to pay special attention. In addition, there are many specific topics to assist with integration.

  • Developer newsgroup support - You can visit the dedicated newsgroup for MSLU. Here you can receive the help of both Microsoft Product Support specialists and other developers who are working with this exciting new technology.

  • Part of a complete package - There are many other tools that Microsoft develops, such as RichEdit, the Windows Common Controls, MLang, Uniscribe, and GDI+, which can be combined with the MS Layer for Unicode. This helps developers provide a full cross-platform experience that leverages the best features of every OS their applications support.

Of course, MSLU is not a panacea for creating well-globalized applications that run just as well on Windows 95/98/ME as on Windows NT, Windows 2000, and Windows XP. The architectural challenges inherent in creating a multilingual application on Windows code page-based platforms still exist.

  1. There is considerably less multilingual support available on Windows 95/98/ME than on Windows NT, Windows 2000, and Windows XP even after implementing MSLU (such as when entering Arabic on Korean versions of Windows 98).

  2. MSLU does not make these code page-based platforms support Unicode internally.

  3. MSLU was not designed to support existing solutions and for code page-based platforms that provide their own Unicode functionality, such as MLang, Uniscribe, Rich Edit, common controls, and others.

  4. You must still follow best practices associated with globalization.

  5. From an international standpoint, MSLU has a distinct disadvantage when compared to a Unicode platform. While MSLU does provide a Unicode “face” to your applications, it must talk internally to a non-Unicode operating system.

Therefore, when your Unicode application that is running on Windows 95/98/ME is limited to a single code page, it is important to make sure that the application behaves properly. A good Unicode application would not be expected to have too many problems. However, you should test your application on each of these three platforms to make sure that nothing breaks and that the user does not lose any data. By first seeing what happens if your application is used beyond what the system can support, you can address any problems before the application is shipped.

Top of pageTop of page

How (and When) to Handle Overrides

For the most typical uses of MSLU, there is no need to write any code, with two exceptions:

  • When you are overriding the loading of MSLU
  • When you are overriding an individual API

Note:Both of these cases assume you are using the MSLU loader. If you are using Microsoft C# or Microsoft Visual Basic .NET P/Invoke mechanism instead of the MSLU loader, you can call the APIs in Unicows.dll directly, and the code in the DLL will determine whether to handle the function itself or to call the operating-system version.

Overriding the Loading of MSLU

There are two steps required to override the loading of MSLU:

  1. Set the “hook” that informs the MSLU loader which function it should call.

  2. Provide the function that the loader will call when it first tries to load the DLL.

The callback function shown in the following code attempts to load the DLL without a path first. This way, if any other component in the process has already loaded the DLL, you can be sure to share the same instance. If the function still fails to find the DLL, it will cause the process to exit. This is the same logic that the loader will use even without an override.

Ideal usage of the override would build a path from information in the registry or from some other application-defined location.

Exiting is important for a Microsoft Foundation Class (MFC) application, since MFC does not handle the failure of Unicode APIs very well. MFC assumes that certain functions will work. For this reason, an MFC application will crash when trying to dereference a NULL pointer during its initialization— after a call to an API fails—since it does not check for failure in this case.

extern FARPROC _PfnLoadUnicows = (FARPROC) &LoadUnicowsProc;
HMODULE LoadUnicowsProc(void)
   {
   HMODULE hMod = LoadLibraryA("unicows.dll");
   if(hMod == 0)
      {
      // Replace [specific path] with your specific path.
      hMod = LoadLibraryA("[specific path]\\unicows.dll");
      }
   if(hMod == 0)
      {
      // If the load still failed, then exit.
      MessageBoxA(0,
      "Unicode wrapper not found",
      "My Company",
      MB_ICONSTOP | MB_OK);
      _exit(-1);
      }
   return(hMod);
}

 

You must not call any Unicode APIs from the callback function, since the very first Unicode API that is loaded causes the loader to call this function. If you cause another Unicode API to be called, it will try to call itself again, recursively, until it runs out of stack space. Thus no APIs that MSLU wraps should ever be called from this function.

Overriding an Individual API

The syntax for overriding an API is similar to that for overriding the DLL’s load. You simply set a hook to inform the loader of which function it should call, and then provide the actual function. The Microsoft Windows Platform SDK documentation, available at http://msdn2.microsoft.com, includes a code sample that overrides the LoadCursorW API. However, the sample here provides an override function for an API that is covered by MSLU only in stub form. This API is OleUIInsertObjectW, which calls the InsertObject method that many applications use to support Microsoft ActiveX object insertion.

static UINT __stdcall
MyOleUIInsertObjectW (LPOLEUIINSERTOBJECTW lpouiiow)
   {
   UINT result = OLEUI_CANCEL;
   OLEUIINSERTOBJECTA ouiioa;
   memcpy(&ouiioa, lpouiiow, sizeof (OLEUIINSERTOBJECTA));
   ouiioa.lpszFile = (char *)alloca (ouiioa.cchFile + 1);
   ouiioa.lpszFile [0] = '\0';
   result = OleUIInsertObjectA(&ouiioa);

   if (result == OLEUI_SUCCESS)
      {
      memcpy(lpouiiow,
      &ouiioa,
      sizeof(OLEUIINSERTOBJECTW));
      MultiByteToWideChar(CP_ACP,
      0,
      ouiioa.lpSzFile,
      ouiioa.cchFile,
      lpowiiow->lpszFile,
      lpowiiow->cchFile);
      }
   return result;
   }
extern "C" FARPROC Unicows_OleUIInsertObjectW =
(FARPROC)&MyOleUIInsertObjectW;

Note that the preceding override will only be called on Windows 95/98/ME. One important limitation of this override is that it is a part of the MSLU loader, so it is only available in C and C++. However, within those languages, you can use the syntax described here to override as many APIs you want. In fact, you could override every API and simply use the MSLU loader around your own application. You could even call the MSLU API after some special processing by making calls to LoadLibrary("unicows.dll") followed by GetProcAddress - (" ").

Top of pageTop of page

Related Links