/*++ 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 #define WIN32_ONLY #include "sesport.h" #include "os2nt.h" #include "os2dbg.h" #include #include #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); }