diff options
Diffstat (limited to 'private/os2/server/srvnls.c')
-rw-r--r-- | private/os2/server/srvnls.c | 1410 |
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); +} |