summaryrefslogtreecommitdiffstats
path: root/private/os2/server/srvnls.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/os2/server/srvnls.c')
-rw-r--r--private/os2/server/srvnls.c1410
1 files changed, 1410 insertions, 0 deletions
diff --git a/private/os2/server/srvnls.c b/private/os2/server/srvnls.c
new file mode 100644
index 000000000..52ad539dc
--- /dev/null
+++ b/private/os2/server/srvnls.c
@@ -0,0 +1,1410 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ srvnls.c
+
+Abstract:
+
+ This module contains the support for NLS for the OS/2 Subsystem Server
+
+Author:
+
+ Michael Jarus (mjarus) 25-Aug-1992
+
+Environment:
+
+ User Mode Only
+
+Revision History:
+
+--*/
+
+#include <windows.h>
+#define WIN32_ONLY
+#include "sesport.h"
+#include "os2nt.h"
+#include "os2dbg.h"
+#include <stdio.h>
+#include <string.h>
+
+#include "os2crt.h"
+
+// Flag to let OS2SRV know whether or not to ignore LOGOFF (when started as a service)
+extern BOOLEAN fService;
+
+//
+// Counted String
+//
+
+typedef struct _STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+#ifdef MIDL_PASS
+ [size_is(MaximumLength), length_is(Length) ]
+#endif // MIDL_PASS
+ PCHAR Buffer;
+} STRING;
+typedef STRING *PSTRING;
+
+typedef STRING ANSI_STRING;
+typedef PSTRING PANSI_STRING;
+
+//
+// Unicode strings are counted 16-bit character strings. If they are
+// NULL terminated, Length does not include trailing NULL.
+//
+
+typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+#ifdef MIDL_PASS
+ [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
+#else // MIDL_PASS
+ PWSTR Buffer;
+#endif // MIDL_PASS
+} UNICODE_STRING;
+typedef UNICODE_STRING *PUNICODE_STRING;
+
+VOID
+RtlInitUnicodeString(
+ PUNICODE_STRING DestinationString,
+ PCWSTR SourceString
+ );
+
+APIRET
+Or2UnicodeStringToMBString(
+ PANSI_STRING DestinationString,
+ PUNICODE_STRING SourceString,
+ BOOLEAN AllocateDestinationString);
+
+ULONG Or2ProcessCodePage;
+ULONG Or2CurrentCodePageIsOem;
+PSZ Os2ServerSystemDirectory;
+HKEY KeyboardLayoutKeyHandle = NULL;
+HANDLE hKeyEvent;
+BOOL KeyboardFromConfigSysRegistry = FALSE;
+OS2_SES_GROUP_PARMS ServerSesGrp;
+
+#define XCPT_SIGNAL_KILLPROC 3
+#define WBUFFER_SIZE 6
+
+BOOL
+Os2SrvHandleCtrlEvent(
+ IN int CtrlType
+ );
+
+ULONG
+Or2NlsUnicodeStringToInteger(
+ IN WCHAR *WString,
+ IN ULONG Base
+ );
+
+extern WCHAR Os2SystemDirectory[];
+extern ULONG Os2Debug;
+extern ULONG Os2ssCountryCode;
+extern ULONG Os2ssCodePage[2];
+extern UCHAR Os2ssKeyboardLayout[2];
+#if PMNT
+extern UCHAR Os2ssKeyboardName[4];
+#endif
+extern ULONG Os2ssKeysOnFlag;
+extern ULONG Os2SrvExitNow;
+
+#if DBG
+BYTE SetEventHandlersAndErrorModeStr[] = "SetEventHandlersAndErrorMode";
+BYTE Os2InitializeNLSStr[] = "Os2InitializeNLS";
+#endif
+
+typedef struct _LANG_TABLE_ENTRY {
+ ULONG Ctry;
+ ULONG Lang;
+ ULONG SubLang;
+ ULONG Cp1;
+ ULONG Cp2;
+ ULONG MessageLanguage;
+} LANG_TABLE_ENTRY, *PLANG_TABLE_ENTRY;
+
+
+PLANG_TABLE_ENTRY
+CheckCountryCodePage(
+ IN ULONG CountryCode,
+ IN ULONG *Os2srvCodePages,
+ OUT ULONG *CodePages
+ );
+
+ULONG
+InitKeyboardRegistry(
+ VOID
+ );
+
+ULONG
+ReadKeyboardLayoutFromRegistry(
+ OUT PULONG pKeyBoardCountry
+ );
+
+LANG_TABLE_ENTRY LANG_TABLE [] =
+ {
+ { /* United States */
+
+ CTRY_UNITED_STATES,
+ LANG_ENGLISH,
+ SUBLANG_ENGLISH_US,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+ { /* Canadian-French */
+
+ CTRY_CANADA,
+ LANG_FRENCH,
+ SUBLANG_FRENCH_CANADIAN,
+ CODEPAGE_CANADIAN,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+ { /* Latin-America */
+
+ COUNTRY_LATIN_AMERICA,
+ LANG_SPANISH,
+ SUBLANG_SPANISH_MEXICAN,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_SPANISH,
+ },
+ { /* Netherlands */
+
+ CTRY_NETHERLANDS,
+ LANG_DUTCH,
+ SUBLANG_DUTCH,
+ CODEPAGE_MULTI,
+ CODEPAGE_US,
+ LANG_DUTCH,
+ },
+ { /* Belgiun */
+
+ CTRY_BELGIUM,
+ LANG_FRENCH,
+ SUBLANG_FRENCH_BELGIAN,
+ CODEPAGE_MULTI,
+ CODEPAGE_US,
+ LANG_DUTCH,
+ },
+ { /* France */
+
+ CTRY_FRANCE,
+ LANG_FRENCH,
+ SUBLANG_FRENCH,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_FRENCH,
+ },
+ { /* Spain */
+
+ CTRY_SPAIN,
+ LANG_SPANISH,
+ SUBLANG_SPANISH,
+ CODEPAGE_MULTI,
+ CODEPAGE_US,
+ LANG_SPANISH,
+ },
+ { /* Italy */
+
+ CTRY_ITALY,
+ LANG_ITALIAN,
+ SUBLANG_ITALIAN,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_ITALIAN,
+ },
+ { /* Switzerland */
+
+ CTRY_SWITZERLAND,
+ LANG_GERMAN,
+ SUBLANG_GERMAN_SWISS,
+ CODEPAGE_MULTI,
+ CODEPAGE_US,
+ LANG_GERMAN,
+ },
+ { /* Austria */
+
+ CTRY_AUSTRIA,
+ LANG_GERMAN,
+ SUBLANG_GERMAN_AUSTRIAN,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_GERMAN,
+ },
+ { /* United Kingdom */
+
+ CTRY_UNITED_KINGDOM,
+ LANG_ENGLISH,
+ SUBLANG_ENGLISH_UK,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+ { /* Denmark */
+
+ CTRY_DENMARK,
+ LANG_DANISH,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_MULTI,
+ CODEPAGE_NORDIC,
+ LANG_DANISH,
+ },
+ { /* Sweden */
+
+ CTRY_SWEDEN,
+ LANG_SWEDISH,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_SWEDISH,
+ },
+ { /* Norway */
+
+ CTRY_NORWAY,
+ LANG_NORWEGIAN,
+ SUBLANG_NORWEGIAN_BOKMAL, /* or SUBLANG_NORWEGIAN_NYNORSK */
+ CODEPAGE_MULTI,
+ CODEPAGE_NORDIC,
+ LANG_NORWEGIAN,
+ },
+ { /* Germany */
+
+ CTRY_GERMANY,
+ LANG_GERMAN,
+ SUBLANG_GERMAN,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_GERMAN,
+ },
+ { /* Mexico */
+
+ CTRY_MEXICO,
+ LANG_SPANISH,
+ SUBLANG_SPANISH_MEXICAN,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_SPANISH,
+ },
+ { /* Brazil */
+
+ CTRY_BRAZIL,
+ LANG_PORTUGUESE,
+ SUBLANG_PORTUGUESE_BRAZILIAN,
+ CODEPAGE_PORTUGESE,
+ CODEPAGE_MULTI,
+ LANG_PORTUGUESE,
+ },
+ { /* Australia */
+
+ CTRY_AUSTRALIA,
+ LANG_ENGLISH,
+ SUBLANG_ENGLISH_AUS,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+ { /* New Zeland */
+
+ CTRY_NEW_ZEALAND,
+ LANG_ENGLISH,
+ SUBLANG_ENGLISH_NZ,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+ { /* Portugal */
+
+ CTRY_PORTUGAL,
+ LANG_PORTUGUESE,
+ SUBLANG_PORTUGUESE,
+ CODEPAGE_PORTUGESE,
+ CODEPAGE_MULTI,
+ LANG_PORTUGUESE,
+ },
+ { /* Ireland */
+
+ CTRY_IRELAND,
+ LANG_ENGLISH,
+ SUBLANG_ENGLISH_UK,
+ CODEPAGE_US,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+ { /* Iceland */
+
+ CTRY_ICELAND,
+ LANG_ICELANDIC,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_MULTI,
+ CODEPAGE_NORDIC,
+ LANG_DANISH,
+ },
+ { /* Finland */
+
+ CTRY_FINLAND,
+ LANG_FINNISH,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_MULTI,
+ CODEPAGE_US,
+ LANG_FINNISH,
+ },
+ { /* Japan */
+
+ CTRY_JAPAN,
+ LANG_JAPANESE,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_JAPAN,
+ CODEPAGE_US,
+ LANG_JAPANESE,
+ },
+ { /* Korea */
+
+ CTRY_SOUTH_KOREA,
+ LANG_KOREAN,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_KOREA,
+ CODEPAGE_US,
+ LANG_KOREAN,
+ },
+#if 0
+ { /* Taiwan */
+
+ CTRY_TAIWAN,
+ LANG_THAI,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_TAIWAN,
+ CODEPAGE_US,
+ LANG_THAI,
+ },
+ { /* Taiwan */
+
+ COUNTRY_TAIWAN,
+ LANG_THAI,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_TAIWAN,
+ CODEPAGE_US,
+ LANG_THAI,
+ },
+#ifdef OS2SS_INCLUDE_HEBREW
+ { /* Hebrew speaking */
+
+ COUNTRY_HEBREW,
+ LANG_HEBREW,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_HEBREW,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+#endif
+#ifdef OS2SS_INCLUDE_ARABIC
+ { /* Arabic speaking */
+
+ COUNTRY_ARABIC,
+ LANG_ARABIC,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_ARABIC,
+ CODEPAGE_MULTI,
+ LANG_ENGLISH,
+ },
+#endif
+#endif
+#ifdef OS2SS_INCLUDE_PRCHINA
+ { /* Peoples Republic of China */
+
+ CTRY_PRCHINA,
+ LANG_CHINESE,
+ SUBLANG_NEUTRAL,
+ CODEPAGE_PRC,
+ CODEPAGE_US,
+ LANG_CHINESE,
+ },
+#endif
+ { /* End of Table */
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ }
+ };
+
+
+#ifdef JAPAN
+// MSKK Nov.02.1992 V-AkihiS
+UINT CPTable[] =
+{
+ 932, 437, 850
+ , 0 /* end */
+};
+#else
+UINT CPTable[] =
+{
+ 437, 850
+ , 860, 862, 863, 864, 865, 932, 934, 936, 938 //WinNLS doesn't support NLS yet
+ , 0 /* end */
+};
+#endif
+
+
+VOID
+Os2SrvExitProcess(
+ IN ULONG uExitCode
+ )
+{
+ ExitProcess((UINT) uExitCode);
+}
+
+
+BOOL
+Os2SrvEventHandlerRoutine(
+ IN DWORD CtrlType
+ )
+{
+ BOOL Rc = TRUE;
+ int Signal = XCPT_SIGNAL_KILLPROC;
+
+#if DBG
+ IF_OS2_DEBUG( SIG )
+ {
+ KdPrint(("OS2SRV(EventHandlerRoutine): Ctr-Type %u\n", CtrlType));
+ }
+#endif
+
+ if ((CtrlType == CTRL_LOGOFF_EVENT) && fService)
+ {
+#if DBG
+ DbgPrint("OS2SRV: running as a service - ignoring CTRL_LOGOFF_EVENT !\n");
+#endif //DBG
+ return FALSE;
+ }
+
+ if ((CtrlType == CTRL_CLOSE_EVENT) ||
+ (CtrlType == CTRL_LOGOFF_EVENT) ||
+ (CtrlType == CTRL_SHUTDOWN_EVENT))
+ {
+ Rc = Os2SrvHandleCtrlEvent(Signal);
+ }
+
+ return(Rc);
+}
+
+
+VOID
+SetEventHandlersAndErrorMode(
+ IN BOOL fSet
+ )
+{
+ if (fSet)
+ {
+ Os2SrvExitNow = 0;
+ SetErrorMode(1);
+ }
+
+ Or2WinSetConsoleCtrlHandler(
+ #if DBG
+ SetEventHandlersAndErrorModeStr,
+ #endif
+ Os2SrvEventHandlerRoutine,
+ fSet
+ );
+}
+
+
+APIRET
+Os2InitializeNLS()
+{
+ PLANG_TABLE_ENTRY pLangEntry;
+ ULONG i, j, AvailableCp[256], NumAvailableCp, TestCountry;
+ USHORT LocaleLang;
+ ANSI_STRING SystemDirectory_A;
+ UNICODE_STRING SystemDirectory_U;
+
+ memset(&ServerSesGrp,
+ 0,
+ sizeof(OS2_SES_GROUP_PARMS));
+ /*
+ * Get Current CP, Country, Language and Console CP
+ */
+
+ ServerSesGrp.Win32OEMCP = Or2WinGetOEMCP(
+ #if DBG
+ Os2InitializeNLSStr
+ #endif
+ );
+ ServerSesGrp.Win32ACP = Or2WinGetACP(
+ #if DBG
+ Os2InitializeNLSStr
+ #endif
+ );
+ ServerSesGrp.Win32LANGID = (ULONG)Or2WinGetUserDefaultLangID(
+ #if DBG
+ Os2InitializeNLSStr
+ #endif
+ );
+ ServerSesGrp.Win32LCID = (ULONG)Or2WinGetThreadLocale(
+ #if DBG
+ Os2InitializeNLSStr
+ #endif
+ );
+
+ Or2NlsGetCountryFromLocale((LCID)ServerSesGrp.Win32LCID, &ServerSesGrp.Win32CountryCode);
+
+ /*
+ * find all available CPs
+ */
+
+ for ( i = 0, NumAvailableCp = 0 ; CPTable[i] && (NumAvailableCp < 200) ; i++ )
+ {
+ if( Or2WinIsValidCodePage(
+ #if DBG
+ Os2InitializeNLSStr,
+ #endif
+ CPTable[i]
+ ))
+ {
+ AvailableCp[NumAvailableCp++] = CPTable[i];
+ }
+ }
+
+ /*
+ * Try to work with the definitions in the registry
+ */
+
+ ServerSesGrp.Os2srvUseRegisterInfo = TRUE;
+
+ if (pLangEntry = CheckCountryCodePage(Os2ssCountryCode,
+ Os2ssCodePage,
+ &ServerSesGrp.PrimaryCP))
+ {
+ while (TRUE) // this is done to enable break
+ {
+ if (ServerSesGrp.SecondaryCP)
+ {
+ for ( i = 0 ; (i < NumAvailableCp) &&
+ (AvailableCp[i] != ServerSesGrp.SecondaryCP) ; i++ ) ;
+
+ if ( i == NumAvailableCp )
+ {
+ ServerSesGrp.SecondaryCP = 0;
+ }
+ }
+
+ for ( i = 0 ; (i < NumAvailableCp) &&
+ (AvailableCp[i] != ServerSesGrp.PrimaryCP) ; i++ ) ;
+
+ if ( i == NumAvailableCp )
+ {
+ ServerSesGrp.PrimaryCP = ServerSesGrp.SecondaryCP;
+ ServerSesGrp.SecondaryCP = 0;
+ }
+
+ if (ServerSesGrp.PrimaryCP)
+ {
+ ServerSesGrp.CountryCode = Os2ssCountryCode;
+ ServerSesGrp.LanguageID = pLangEntry->MessageLanguage;
+ ServerSesGrp.Os2ssLCID = (ULONG)
+ MAKELANGID(pLangEntry->Lang, pLangEntry->SubLang);
+
+ // check CTRY, LANG legalty. (fall down if fail)
+
+ Or2NlsGetCountryFromLocale(
+ (LCID)ServerSesGrp.Os2ssLCID,
+ &TestCountry
+ );
+
+ if (TestCountry == Os2ssCountryCode)
+ {
+ // BUGBUG: change locale
+
+ Or2WinSetThreadLocale(
+ #if DBG
+ Os2InitializeNLSStr,
+ #endif
+ (LCID)ServerSesGrp.Os2ssLCID
+ );
+#if DBG
+ IF_OS2_DEBUG( NLS )
+ {
+ KdPrint(("InitNls: user NLS definitions: Ctry %lu, CP %lu & %lu\n",
+ Os2ssCountryCode, Os2ssCodePage[0], Os2ssCodePage[1]));
+ }
+#endif
+ break; // SUCCESS
+ }
+ }
+#if DBG
+ IF_OS2_DEBUG( NLS )
+ {
+ KdPrint(("InitNls: illegal NLS definitions: Ctry %lu, CP %lu & %lu\n",
+ Os2ssCountryCode, Os2ssCodePage[0], Os2ssCodePage[1]));
+ }
+#endif
+ pLangEntry = NULL;
+ break; // FAIL
+ }
+ }
+
+ /*
+ * Inherit NLS definitions from Win32
+ */
+
+ if (pLangEntry == NULL)
+ {
+ ServerSesGrp.Os2srvUseRegisterInfo = FALSE;
+ ServerSesGrp.PrimaryCP = ServerSesGrp.Win32OEMCP;
+ ServerSesGrp.CountryCode = ServerSesGrp.Win32CountryCode;
+ ServerSesGrp.Os2ssLCID = ServerSesGrp.Win32LCID;
+#ifdef JAPAN
+// MSKK Nov.04.1992 V-AkihiS
+ ServerSesGrp.LanguageID = LANG_JAPANESE;
+#else
+ ServerSesGrp.LanguageID = LANG_ENGLISH;
+#endif
+
+ /*
+ * Find if we can second code page to this country
+ */
+
+ for ( j = 0 ; (LANG_TABLE[j].Ctry) && // find the country entry
+ (LANG_TABLE[j].Ctry != ServerSesGrp.CountryCode) ; j++ );
+
+ if (LANG_TABLE[j].Ctry == ServerSesGrp.CountryCode)
+ {
+ if (ServerSesGrp.PrimaryCP != LANG_TABLE[j].Cp1)
+ {
+ // OEM CP is not the Cp1, so if Cp1 is available add it as secondary CP
+
+ for ( i = 0 ; (i < NumAvailableCp) &&
+ (AvailableCp[i] != LANG_TABLE[j].Cp1) ; i++ ) ;
+
+ if ( i < NumAvailableCp )
+ {
+ ServerSesGrp.SecondaryCP = LANG_TABLE[j].Cp1;
+ }
+ }
+
+ if ((ServerSesGrp.SecondaryCP == 0) &&
+ (ServerSesGrp.PrimaryCP != LANG_TABLE[j].Cp2))
+ {
+ // OEM CP is not the Cp2, so if Cp2 is available add it as secondary CP
+
+ for ( i = 0 ; (i < NumAvailableCp) &&
+ (AvailableCp[i] != LANG_TABLE[j].Cp2) ; i++ ) ;
+
+ if ( i < NumAvailableCp )
+ {
+ ServerSesGrp.SecondaryCP = LANG_TABLE[j].Cp2;
+ }
+
+ }
+ }
+
+ LocaleLang = PRIMARYLANGID(LANGIDFROMLCID(ServerSesGrp.Win32LCID));
+ for ( i = 0 ; Or2NlsLangIdTable[i] ; i++ )
+ {
+ if (Or2NlsLangIdTable[i] == LocaleLang)
+ {
+ ServerSesGrp.LanguageID = Or2NlsLangIdTable[i];
+ break;
+ }
+ }
+ }
+
+ ServerSesGrp.VioCP = ServerSesGrp.KbdCP = ServerSesGrp.DosCP = ServerSesGrp.PrimaryCP;
+
+ /*
+ * Get CtryInfo, DBCSEv, CollateTable, CaseMapTable for the default
+ */
+
+ Or2NlsGetCPInfo(
+ (UINT)ServerSesGrp.PrimaryCP,
+ &ServerSesGrp.PriDBCSVec
+ );
+
+ Or2NlsGetMapTable(
+ (LCID)ServerSesGrp.Os2ssLCID,
+ ServerSesGrp.PrimaryCP,
+ LCMAP_SORTKEY,
+ ServerSesGrp.PriCollateTable
+ );
+
+ Or2NlsGetMapTable(
+ (LCID)ServerSesGrp.Os2ssLCID,
+ ServerSesGrp.PrimaryCP,
+ LCMAP_UPPERCASE,
+ ServerSesGrp.PriCaseMapTable
+ );
+
+ if ( ServerSesGrp.SecondaryCP )
+ {
+ Or2NlsGetCPInfo(
+ (UINT)ServerSesGrp.SecondaryCP,
+ &ServerSesGrp.SecDBCSVec
+ );
+
+ Or2NlsGetMapTable(
+ (LCID)ServerSesGrp.Os2ssLCID,
+ ServerSesGrp.SecondaryCP,
+ LCMAP_SORTKEY,
+ ServerSesGrp.SecCollateTable
+ );
+
+ Or2NlsGetMapTable(
+ (LCID)ServerSesGrp.Os2ssLCID,
+ ServerSesGrp.SecondaryCP,
+ LCMAP_UPPERCASE,
+ ServerSesGrp.SecCaseMapTable
+ );
+ }
+
+ Or2NlsGetCtryInfo(
+ (LCID)ServerSesGrp.Os2ssLCID,
+ (UINT)ServerSesGrp.PrimaryCP,
+ &ServerSesGrp.CountryInfo
+ );
+
+ if (ServerSesGrp.PriDBCSVec.Vector[0] || ServerSesGrp.PriDBCSVec.Vector[1] ||
+ ServerSesGrp.SecDBCSVec.Vector[0] || ServerSesGrp.SecDBCSVec.Vector[1])
+ {
+ ServerSesGrp.DBCSCountryFlag = TRUE;
+ }
+
+ ServerSesGrp.KeysOnFlag = Os2ssKeysOnFlag;
+
+ InitKeyboardRegistry();
+
+ // BugBug: maybe according to ServerSesGrp.PrimaryCP or in the future
+ // according to the Process' CodePage
+
+ Or2CurrentCodePageIsOem = TRUE;
+ Or2ProcessCodePage = ServerSesGrp.Win32OEMCP;
+
+ RtlInitUnicodeString(&SystemDirectory_U, Os2SystemDirectory);
+
+ SystemDirectory_A.Buffer = ServerSesGrp.SystemDirectory;
+ SystemDirectory_A.MaximumLength = CCHMAXSYSTEMPATH;
+ SystemDirectory_A.Length = 0;
+
+ Os2ServerSystemDirectory = &ServerSesGrp.SystemDirectory[0];
+
+ Or2UnicodeStringToMBString(
+ &SystemDirectory_A,
+ &SystemDirectory_U,
+ FALSE
+ );
+
+#if DBG
+
+ /*
+ * Dump all NLS info to the debugger
+ */
+
+ IF_OS2_DEBUG( NLS )
+ {
+ KdPrint(("OS2SRV(Os2-NLS): CP %lu (%lu,%lu), Country %lu, LangID %lx ,LCID %lx\n",
+ ServerSesGrp.DosCP, ServerSesGrp.PrimaryCP,
+ ServerSesGrp.SecondaryCP, ServerSesGrp.CountryCode,
+ ServerSesGrp.LanguageID, ServerSesGrp.Os2ssLCID));
+
+ KdPrint(("OS2SRV(Win32-NLS): OEMCP %lu, ACP %lu, Country %lu, LangID %lx\n",
+ ServerSesGrp.Win32OEMCP, ServerSesGrp.Win32ACP,
+ ServerSesGrp.Win32CountryCode, ServerSesGrp.Win32LANGID));
+
+ KdPrint((" LCID %lx, ConCP %lu, ConOutCP %lu\n",
+ ServerSesGrp.Win32LCID, Or2WinGetConsoleCP(Os2InitializeNLSStr),
+ Or2WinGetConsoleOutputCP(Os2InitializeNLSStr)));
+
+ KdPrint((" SystemDirectory %s\n",
+ ServerSesGrp.SystemDirectory));
+ }
+#endif
+
+ return (NO_ERROR);
+}
+
+
+PLANG_TABLE_ENTRY
+CheckCountryCodePage(
+ IN ULONG CountryCode,
+ IN ULONG *Os2srvCodePages,
+ OUT ULONG *CodePages
+ )
+{
+ ULONG i, j = 0;
+
+ if (!CountryCode)
+ {
+ return(NULL);
+ }
+
+ for ( i = 0 ; LANG_TABLE[i].Ctry ; i++ )
+ {
+ if (LANG_TABLE[i].Ctry == CountryCode)
+ {
+ if (Os2srvCodePages[0] != 0)
+ {
+ if (Os2srvCodePages[1] == 0)
+ {
+ if ((Os2srvCodePages[0] == LANG_TABLE[i].Cp1) ||
+ (Os2srvCodePages[0] == LANG_TABLE[i].Cp2))
+ {
+ CodePages[0] = Os2srvCodePages[0];
+ return(&LANG_TABLE[i]);
+ }
+ } else if (((Os2srvCodePages[0] == LANG_TABLE[i].Cp1) &&
+ (Os2srvCodePages[1] == LANG_TABLE[i].Cp2)) ||
+ ((Os2srvCodePages[1] == LANG_TABLE[i].Cp1) &&
+ (Os2srvCodePages[0] == LANG_TABLE[i].Cp2)))
+ {
+ CodePages[0] = Os2srvCodePages[0];
+ CodePages[1] = Os2srvCodePages[1];
+ return(&LANG_TABLE[i]);
+ } else if ((Os2srvCodePages[0] == LANG_TABLE[i].Cp1) ||
+ (Os2srvCodePages[0] == LANG_TABLE[i].Cp2))
+ {
+ CodePages[0] = Os2srvCodePages[0];
+ return(&LANG_TABLE[i]);
+ } else if ((Os2srvCodePages[1] == LANG_TABLE[i].Cp1) ||
+ (Os2srvCodePages[1] == LANG_TABLE[i].Cp2))
+ {
+ CodePages[0] = Os2srvCodePages[1];
+ return(&LANG_TABLE[i]);
+ }
+ }
+
+ CodePages[0] = LANG_TABLE[i].Cp1;
+ CodePages[1] = LANG_TABLE[i].Cp2;
+ return(&LANG_TABLE[i]);
+ }
+ }
+
+ // end of table
+ return(NULL);
+}
+
+
+struct
+{
+ ULONG Country;
+ UCHAR Prefix[2];
+} KBD_PREFIX_TABLE[] =
+ {
+ { CTRY_BELGIUM, "BE" },
+ { CTRY_CANADA, "CF" },
+ { CTRY_DENMARK, "DK" },
+ { CTRY_FRANCE, "FR" },
+ { CTRY_GERMANY, "GR" },
+ { CTRY_ITALY, "IT" },
+ { COUNTRY_LATIN_AMERICA, "LA" },
+ { CTRY_NETHERLANDS, "NL" },
+ { CTRY_NORWAY, "NO" },
+ { CTRY_PORTUGAL, "PO" },
+ { CTRY_SWITZERLAND, "SF" },
+ { CTRY_SWITZERLAND, "SG" },
+ { CTRY_SPAIN, "SP" },
+ { CTRY_FINLAND, "SU" },
+ { CTRY_SWEDEN, "SV" },
+ { CTRY_UNITED_KINGDOM, "UK" },
+ { CTRY_UNITED_STATES, "US" },
+ { 0, "XX" }
+ };
+
+ULONG
+InitKeyboardRegistry(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This initialization function reads the keybaord layout from the registry
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The value is an ULONG type that is returned when some failure occurs. It
+ may indicate any of several errors that occur during the APIs called in
+ this function. The return value should be tested if NZ.
+
+--*/
+
+{
+#ifdef JAPAN
+// MSKK Aug.10.1993 V-AkihiS
+ ServerSesGrp.KeyboardCountry = CTRY_JAPAN;
+ ServerSesGrp.KeyboardType = OS2SS_EN_KBD;
+#else
+ LONG Rc;
+ int KbdType, i;
+ ULONG KeyBoardCountry = CTRY_UNITED_STATES;
+
+
+ if (((KbdType = GetKeyboardType(0)) == 2) || (KbdType == 4))
+ {
+ ServerSesGrp.KeyboardType = OS2SS_EN_KBD; // EN
+ } else
+ {
+ ServerSesGrp.KeyboardType = OS2SS_AT_KBD; // AT
+ }
+
+ ServerSesGrp.KeyboardCountry = CTRY_UNITED_STATES;
+
+#if PMNT
+ // Keyboard sub-code must be 3 digits or 4 (Swiss-german 150G + 150F only)
+ // Check that we have at least 3 valid digits.
+ // Note that the string is padded with blanks (not null-terminated)
+ if (isdigit(Os2ssKeyboardName[0])
+ && isdigit(Os2ssKeyboardName[1])
+ && isdigit(Os2ssKeyboardName[2]))
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ &Os2ssKeyboardName[0],
+ 4);
+ }
+ else
+ {
+ // Keyboard layout not specified or in incorrect format. Pick default
+ // layout according to specified keyboard layout. See OS/2
+ // documentation (user's guide)
+ if (!strnicmp(&Os2ssKeyboardLayout[0], "BE", 2)) // Belgium
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "120 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "CF", 2)) // Canada (French)
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "058 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "DK", 2)) // Denmark
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "159 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "FR", 2)) // France
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "189 ", // Other possible choice is 120
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "GR", 2)) // Germany
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "129 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "IT", 2)) // Italy
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "141 ", // Other possible choice is 142
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "LA", 2)) // Latin America
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "171 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "NL", 2)) // Netherlands
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "143 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "NO", 2)) // Norway
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "155 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "PO", 2)) // Poland
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "163 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "SF", 2)) // Switerland (FR)
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "150F",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "SG", 2)) // Switzerland (GR)
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "150G",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "SP", 2)) // Spain
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "172 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "SU", 2)) // Finland
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "153 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "SV", 2)) // Sweden
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "153 ",
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "UK", 2)) // UK
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "166 ", // Other possible choice is 168
+ 4);
+ }
+ else if (!strnicmp(&Os2ssKeyboardLayout[0], "US", 2)) // US
+ {
+ memcpy(&ServerSesGrp.KeyboardName[0],
+ "103 ",
+ 4);
+ }
+ else
+ {
+ // Use US default keyboard
+ strcpy(&ServerSesGrp.KeyboardName[0], "103 ");
+ }
+ }
+#endif
+
+ if (Os2ssKeyboardLayout[0] && Os2ssKeyboardLayout[1])
+ {
+ for ( i = 0 ; KBD_PREFIX_TABLE[i].Country ; i++ )
+ {
+ if ((KBD_PREFIX_TABLE[i].Prefix[0] == Os2ssKeyboardLayout[0]) &&
+ (KBD_PREFIX_TABLE[i].Prefix[1] == Os2ssKeyboardLayout[1]))
+ {
+ break;
+ }
+ }
+
+ if (KBD_PREFIX_TABLE[i].Country)
+ {
+ ServerSesGrp.KeyboardCountry = KBD_PREFIX_TABLE[i].Country;
+ KeyboardFromConfigSysRegistry = TRUE;
+ ServerSesGrp.KeyboardLayout[0] = Os2ssKeyboardLayout[0];
+ ServerSesGrp.KeyboardLayout[1] = Os2ssKeyboardLayout[1];
+ return(0);
+ }
+ }
+
+#if PMNT
+ // Keyboard layout not found, use default (US)
+ ServerSesGrp.KeyboardLayout[0] = 'U';
+ ServerSesGrp.KeyboardLayout[1] = 'S';
+#endif // PMNT
+
+ Rc = RegOpenKeyExW(
+ HKEY_CURRENT_USER,
+ L"Keyboard Layout",
+ 0,
+ KEY_READ,
+ &KeyboardLayoutKeyHandle
+ );
+
+ if (Rc != ERROR_SUCCESS)
+ {
+#if DBG
+ IF_OS2_DEBUG3( INIT, KBD, NLS )
+ {
+ KdPrint(("InitKeyboardRegistry: Can't open key, rc %lx\n",
+ Rc));
+ }
+#endif
+ return((ULONG)Rc);
+ }
+
+ hKeyEvent = CreateEventW(
+ NULL,
+ FALSE, /* auto reset */
+ FALSE,
+ NULL
+ );
+
+ if (hKeyEvent == NULL)
+ {
+ ULONG Rc1 = GetLastError();
+
+#if DBG
+ IF_OS2_DEBUG3( INIT, KBD, NLS )
+ {
+ KdPrint(("InitKeyboardRegistry: Can't create event, rc %lx\n",
+ Rc1));
+ }
+#endif
+ return(Rc1);
+ }
+
+ Rc = ReadKeyboardLayoutFromRegistry(&KeyBoardCountry);
+
+ if (Rc == 0)
+ {
+ ServerSesGrp.KeyboardCountry = KeyBoardCountry;
+ }
+
+#if DBG
+ IF_OS2_DEBUG3( NLS, INIT, KBD )
+ {
+ KdPrint(("InitKeyboardRegistry: Country %d, Type %s (%d)\n",
+ ServerSesGrp.KeyboardCountry,
+ (ServerSesGrp.KeyboardType == OS2SS_AT_KBD) ? "AT" :
+ ((ServerSesGrp.KeyboardType == OS2SS_ENNEW_KBD) ? "EN-NEW" : "EN"),
+ KbdType));
+ }
+#endif
+#endif
+ return(0);
+}
+
+
+ULONG
+ReadKeyboardLayoutFromRegistry(
+ OUT PULONG pKeyBoardCountry
+ )
+{
+ LONG Rc;
+ DWORD ValueType;
+ DWORD DataSize = 40;
+ WCHAR DataBuffer[40];
+#ifdef JAPAN
+// MSKK Jul.29.1993 V-AkihiS
+ LCID KeyBoardLayOut = MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_NEUTRAL), 0);
+#else
+ LCID KeyBoardLayOut = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0);
+#endif
+ int CountryLength;
+ WCHAR sCountryCode[WBUFFER_SIZE];
+
+ Rc = RegQueryValueExW(
+ KeyboardLayoutKeyHandle,
+ L"Active",
+ NULL,
+ &ValueType,
+ (LPBYTE)&DataBuffer[0],
+ &DataSize
+ );
+
+ if ((Rc == ERROR_FILE_NOT_FOUND) || (Rc == ERROR_KEY_DELETED))
+ {
+ if (KeyboardLayoutKeyHandle)
+ {
+ RegCloseKey(KeyboardLayoutKeyHandle);
+ KeyboardLayoutKeyHandle = NULL;
+ }
+
+ //
+ // In NT4 the key was changed - try it.
+ //
+ Rc = RegOpenKeyExW(
+ HKEY_CURRENT_USER,
+ L"Keyboard Layout\\Preload",
+ 0,
+ KEY_READ,
+ &KeyboardLayoutKeyHandle
+ );
+ if (Rc == ERROR_SUCCESS)
+ {
+ Rc = RegQueryValueExW(
+ KeyboardLayoutKeyHandle,
+ L"1",
+ NULL,
+ &ValueType,
+ (LPBYTE)&DataBuffer[0],
+ &DataSize
+ );
+ }
+ }
+
+ if (Rc != ERROR_SUCCESS)
+ {
+#if DBG
+ IF_OS2_DEBUG3( NLS, KBD, INIT )
+ {
+ KdPrint(("ReadKeyboardLayoutFromRegistry: Can't query value, rc %lx\n",
+ Rc));
+ }
+#endif
+ return((ULONG)Rc);
+ }
+
+ if (ValueType != REG_SZ)
+ {
+ return((ULONG)-1);
+ }
+
+ KeyBoardLayOut = (LCID)Or2NlsUnicodeStringToInteger(
+ DataBuffer,
+ 16
+ );
+
+ CountryLength = GetLocaleInfoW(
+ KeyBoardLayOut,
+ LOCALE_ICOUNTRY,
+ sCountryCode,
+ WBUFFER_SIZE
+ );
+
+ *pKeyBoardCountry = Or2NlsUnicodeStringToInteger(
+ sCountryCode,
+ 10
+ );
+
+ if ((*pKeyBoardCountry == CTRY_AUSTRALIA) ||
+ (*pKeyBoardCountry == CTRY_NEW_ZEALAND))
+ {
+ *pKeyBoardCountry = CTRY_UNITED_STATES;
+ } else if (*pKeyBoardCountry == CTRY_AUSTRIA)
+ {
+ *pKeyBoardCountry = CTRY_GERMANY;
+ } else if (*pKeyBoardCountry == CTRY_BRAZIL)
+ {
+ *pKeyBoardCountry = CTRY_PORTUGAL;
+ } else if (*pKeyBoardCountry == CTRY_ICELAND)
+ {
+ *pKeyBoardCountry = CTRY_NORWAY; // BUGBUG: or CTRY_DENMARK
+ } else if (*pKeyBoardCountry == CTRY_IRELAND)
+ {
+ *pKeyBoardCountry = CTRY_UNITED_KINGDOM;
+ } else if (*pKeyBoardCountry == CTRY_MEXICO)
+ {
+ *pKeyBoardCountry = COUNTRY_LATIN_AMERICA;
+ }
+
+#if DBG
+ IF_OS2_DEBUG2( NLS, KBD )
+ {
+ KdPrint(("ReadKeyboardLayoutFromRegistry: Value %ws-%x, Country %d\n",
+ DataBuffer, KeyBoardLayOut, *pKeyBoardCountry));
+ }
+#endif
+
+ return(0);
+}
+
+
+ULONG
+GetKeyboardRegistryChange(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This initialization function wait for a change in the keybaord layout
+ in the registry and update all sessions.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The Keyboard Country code
+
+--*/
+
+{
+ LONG Rc;
+ ULONG KeyBoardCountry = ServerSesGrp.KeyboardCountry;
+
+
+ if (KeyboardFromConfigSysRegistry)
+ {
+ return(0);
+ }
+
+ if (KeyboardLayoutKeyHandle == NULL)
+ {
+ return(0);
+ }
+
+ while ( 1 )
+ {
+ Rc = RegNotifyChangeKeyValue(
+ KeyboardLayoutKeyHandle,
+ TRUE,
+ REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME,
+ hKeyEvent, // hEvent (async)
+ TRUE // aSync
+ );
+
+ if (Rc != ERROR_SUCCESS)
+ {
+#if DBG
+ IF_OS2_DEBUG2( KBD, NLS )
+ {
+ KdPrint(("GetKeyboardRegistryChange: Can't wait for notify, rc %lx\n",
+ Rc));
+ }
+#endif
+ return(0);
+ }
+
+ WaitForSingleObject( hKeyEvent, INFINITE );
+
+ Rc = ReadKeyboardLayoutFromRegistry(&KeyBoardCountry);
+
+ if ((Rc == 0) && KeyBoardCountry &&
+ (KeyBoardCountry != ServerSesGrp.KeyboardCountry))
+ {
+ break;
+ }
+
+ while ((Rc == ERROR_FILE_NOT_FOUND) || (Rc == ERROR_KEY_DELETED))
+ {
+ //
+ // In NT4 the when the key is being updated, it's actually
+ // being deleted and recreated. We may have to wait for its
+ // recreaction.
+ //
+#if DBG
+ IF_OS2_DEBUG2( KBD, NLS )
+ {
+ KdPrint(("GetKeyboardRegistryChange: Waiting for registry key to be created.\n"));
+ }
+#endif // DBG
+ Sleep(200L); // 0.2 sec
+ Rc = ReadKeyboardLayoutFromRegistry(&KeyBoardCountry);
+
+ if ((Rc == 0) && KeyBoardCountry &&
+ (KeyBoardCountry != ServerSesGrp.KeyboardCountry))
+ {
+ goto Change;
+ }
+ }
+ }
+
+Change:
+#if DBG
+ IF_OS2_DEBUG2( KBD, NLS )
+ {
+ KdPrint(("GetKeyboardRegistryChange: KbdCountry %u, Old %lu\n",
+ KeyBoardCountry, ServerSesGrp.KeyboardCountry));
+ }
+#endif
+ ServerSesGrp.KeyboardCountry = KeyBoardCountry;
+
+ return(KeyBoardCountry);
+}