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/2000/XP, these benefits are obvious, and
include:
- Improving international and multilingual support;
- Better integration with the features of the NT platform;
- Shipping a single binary instead of separate builds for each locale;
- Better support of the Multilingual UI (MUI) features of Windows 2000/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 NT family of
operating systems, it was just easier to write non-Unicode applications.
However, times have changed.... Starting with the Windows XP RC1 version of the Platform SDK, the Microsoft Layer for Unicode on Windows 95/98/ME Systems (MSLU for short) can help you 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.
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 WinNT/2K/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
components 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 will provide 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 components 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 upon which their applications run.
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/2000/XP. The architectural
challenges inherent in creating a multilingual application on Windows code page–based platforms still exist. First, there is considerably less multilingual
support available on Windows 95/98/Me than on Windows NT/2000/ XP3 even after implementing MSLU (such as when entering Arabic on Korean versions of Windows
98). Second, MSLU does not make these code page–based platforms support Unicode internally. Third, MSLU was not designed to support existing solutions and
components for code page–based platforms that provide their own Unicode functionality, such as MLang, Uniscribe, Rich Edit, common controls, and others.
Fourth, you must still follow best practices associated with globalization. Finally, 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.)
How MSLU Works
MSLU actually consists of two parts. The first part is a dynamic-link library (DLL)— Unicows.dll—that is redistributed with the application that the user
creates. The second part is a library (LIB) file—Unicows.lib—that is compiled with this same application. This LIB contains the MSLU loader, which determines
whether to load the DLL and call it; alternatively, it can call the original operating-system version of the API. (The former scenario would occur on Windows
95/98/Me; the latter would occur on Windows NT/2000/XP.) The loader also contains all of the necessary failure stubs like the operating system itself
does, so that in case the DLL cannot be found, you can gracefully handle the failure of the APIs in your code. From a technical perspective, the only time
your code would ever call the functions in Unicows.dll is when you are using Windows 95/98/Me. Even if you circumvent the loader (for instance, by calling
LoadLibrary/GetProcAddress yourself, or by using the P/Invoke syntax of the Microsoft .NET Framework) and call the DLL directly, on an NT/2000/XP platform
the DLL will simply forward the call to the API rather than call the MLSU “wrapper” function. This is because the wrapper has less functionality than the
full operating-system version, which has full Unicode support. If you are using C or C++, it is not a good idea to intentionally slow yourself down by adding a
DLL call you do not need that will simply call the operating system anyway. You can instead decide whether to call the operating-system version of a function or
the MSLU version yourself, thus avoiding the performance hit. With every Unicode wrapper function in MSLU, there must obviously be a conversion to a non-Unicode
string. This is usually done using the system default code page (CP_ACP) of the computer—a setting that cannot be changed on Windows 95/98/Me. There are some
specific APIs that do not use CP_ACP Microsoft Layer for Unicode (MSLU) Chapter 18 because they have information in another parameter, such as a locale ID
(LCID) value or a device context that would suggest a better code page to use. 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 with your specific path.
hMod = LoadLibraryA("\\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://msdn.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);
Microsoft Layer for Unicode (MSLU) Chapter 18
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 - (" ").
|
|