1466 lines
45 KiB
C++
1466 lines
45 KiB
C++
//=======================================================================
|
||
//
|
||
// Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
|
||
//
|
||
// File: osdet.cpp
|
||
//
|
||
// Description:
|
||
//
|
||
// Ported to lib from V3 SLM DLL sources
|
||
//
|
||
//=======================================================================
|
||
|
||
#include <windows.h>
|
||
#include <wuiutest.h>
|
||
#include <tchar.h>
|
||
#include <osdet.h>
|
||
#include <logging.h>
|
||
#include <iucommon.h>
|
||
#include "wusafefn.h"
|
||
#include<MISTSAFE.h>
|
||
|
||
// Forwared Declarations
|
||
static LANGID CorrectGetSystemDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95);
|
||
static LANGID CorrectGetUserDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95);
|
||
static WORD CorrectGetACP(void);
|
||
static WORD CorrectGetOEMCP(void);
|
||
static LANGID MapLangID(LANGID langid);
|
||
static bool FIsNECMachine();
|
||
static int aton(LPCTSTR ptr);
|
||
static int atoh(LPCTSTR ptr);
|
||
|
||
|
||
//
|
||
// Constants and defines
|
||
//
|
||
const LANGID LANGID_ENGLISH = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); // 0x0409
|
||
const LANGID LANGID_GREEK = MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT); // 0x0408
|
||
const LANGID LANGID_JAPANESE = MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT); // 0x0411
|
||
|
||
const LANGID LANGID_ARABIC = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA); // 0x0401
|
||
const LANGID LANGID_HEBREW = MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT); // 0x040D
|
||
const LANGID LANGID_THAI = MAKELANGID(LANG_THAI, SUBLANG_DEFAULT); // 0x041E
|
||
|
||
|
||
const TCHAR Win98_REGPATH_MACHLCID[] = _T("Control Panel\\Desktop\\ResourceLocale");
|
||
const TCHAR REGPATH_CODEPAGE[] = _T("SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage");
|
||
const TCHAR REGKEY_OEMCP[] = _T("OEMCP");
|
||
const TCHAR REGKEY_ACP[] = _T("ACP");
|
||
const TCHAR REGKEY_LOCALE[] = _T("Locale");
|
||
const TCHAR REGKEY_IE[] = _T("Software\\Microsoft\\Internet Explorer");
|
||
const TCHAR REGKEY_VERSION[] = _T("Version");
|
||
const TCHAR REGKEY_CP_INTERNATIONAL[] = _T(".DEFAULT\\Control Panel\\International");
|
||
const TCHAR REGKEY_CP_RESOURCELOCAL[] = _T("Control Panel\\Desktop\\ResourceLocale");
|
||
|
||
|
||
const TCHAR KERNEL32_DLL[] = _T("kernel32.dll");
|
||
|
||
const WORD CODEPAGE_ARABIC = 1256;
|
||
const WORD CODEPAGE_HEBREW = 1255;
|
||
const WORD CODEPAGE_THAI = 874;
|
||
const WORD CODEPAGE_GREEK_MS = 737;
|
||
const WORD CODEPAGE_GREEK_IBM = 869;
|
||
|
||
// ISO code for Greek OS's on Windows 98 ONLY.
|
||
const TCHAR ISOCODE_GREEK_MS[] = _T("el_MS");
|
||
const TCHAR ISOCODE_GREEK_IBM[] = _T("el_IBM");
|
||
|
||
|
||
// Registry keys to determine NEC machines
|
||
const TCHAR NT5_REGPATH_MACHTYPE[] = _T("HARDWARE\\DESCRIPTION\\System");
|
||
const TCHAR NT5_REGKEY_MACHTYPE[] = _T("Identifier");
|
||
const TCHAR REGVAL_MACHTYPE_AT[] = _T("AT/AT COMPATIBLE");
|
||
const TCHAR REGVAL_MACHTYPE_NEC[] = _T("NEC PC-98");
|
||
const TCHAR REGVAL_GREEK_IBM[] = _T("869");
|
||
|
||
// Platform strings
|
||
const TCHAR SZ_PLAT_WIN95[] = _T("w95");
|
||
const TCHAR SZ_PLAT_WIN98[] = _T("w98");
|
||
const TCHAR SZ_PLAT_WINME[] = _T("mil");
|
||
const TCHAR SZ_PLAT_NT4[] = _T("NT4");
|
||
const TCHAR SZ_PLAT_W2K[] = _T("W2k");
|
||
const TCHAR SZ_PLAT_WHISTLER[] = _T("Whi");
|
||
const TCHAR SZ_PLAT_UNKNOWN[] = _T("unk");
|
||
|
||
|
||
#define LOOKUP_OEMID(keybdid) HIBYTE(LOWORD((keybdid)))
|
||
#define PC98_KEYBOARD_ID 0x0D
|
||
|
||
//
|
||
// Globals
|
||
//
|
||
|
||
//
|
||
// We derive this from WINVER >= 0x0500 section of winnls.h
|
||
//
|
||
typedef LANGID (WINAPI * PFN_GetUserDefaultUILanguage) (void);
|
||
typedef LANGID (WINAPI * PFN_GetSystemDefaultUILanguage) (void);
|
||
|
||
typedef struct
|
||
{
|
||
LANGID langidUser;
|
||
TCHAR * pszISOCode;
|
||
|
||
} USER_LANGID;
|
||
|
||
typedef struct
|
||
{
|
||
LANGID langidMachine;
|
||
TCHAR * pszDefaultISOCode;
|
||
int cElems;
|
||
const USER_LANGID * grLangidUser;
|
||
|
||
} MACH_LANGID;
|
||
|
||
|
||
// We give a Japanese NEC machine its own ISO code.
|
||
#define LANGID_JAPANESE 0x0411
|
||
#define ISOCODE_NEC _T("nec")
|
||
#define ISOCODE_EN _T("en")
|
||
#define grsize(langid) (sizeof(gr##langid) / sizeof(USER_LANGID))
|
||
|
||
// These are all the user langids associated with a particular machine.
|
||
|
||
// NTRAID#NTBUG9-220063-2000/12/13-waltw 220063 IU: Specify mappings between GetSystemDefaultUILanguage LANGID and ISO/639/1988
|
||
// From Industry Update XML Schema.doc
|
||
// 3.1 Language Codes
|
||
// The languages are defined by ISO 639. They are represented by lowercase 2 letter symbols such as "en" for English, "fr" for French etc.
|
||
//
|
||
// 3.2 Country Codes
|
||
// The country codes are defined in ISO 3166-1, using the Alpha-2 representation (two letter symbols).
|
||
//
|
||
// 3.3 Representation in Industry Update
|
||
// Industry Update uses the RFC 1766 standard to manage the representation of language+locale symbols.
|
||
// 3.3.1 Simple Case - Language Alone
|
||
// When no regional flavor is considered for a language, or when it pertains to the "standard" version of the language, such as Portuguese as spoken in Portugal, it uses a straight ISO 639 symbol:
|
||
// en, fr, de
|
||
//
|
||
// 3.3.2 Regional Variants
|
||
// Managed by the RFCThe lowercase version of the Alpha-2 ISO 3166-1 country (or region) code is hyphenated to the language code, e.g. en-us, en-ca, fr-be, fr-ca, zh-hk, zh-tw<74>
|
||
|
||
|
||
const USER_LANGID gr0404[] = {{0x0804,_T("zh-CN")},{0x1004,_T("zh-CN")}};
|
||
const USER_LANGID gr0407[] = {{0x0c07,_T("de-AT")},{0x0807,_T("de-CH")}};
|
||
const USER_LANGID gr0409[] = {{0x1c09,_T("en-ZA")},{0x0809,_T("en-GB")},{0x0c09,_T("en-AU")},{0x1009,_T("en-CA")},
|
||
{0x1409,_T("en-NZ")},{0x1809,_T("en-IE")}};
|
||
const USER_LANGID gr040c[] = {{0x080c,_T("fr-BE")},{0x0c0c,_T("fr-CA")},{0x100c,_T("fr-CH")}};
|
||
const USER_LANGID gr0410[] = {{0x0810,_T("it-CH")}};
|
||
const USER_LANGID gr0413[] = {{0x0813,_T("nl-BE")}};
|
||
const USER_LANGID gr0416[] = {{0x0816,_T("pt")}};
|
||
const USER_LANGID gr080a[] = {{0x040a,_T("es")},{0x080a,_T("es-MX")},{0x200a,_T("es-VE")},{0x240a,_T("es-CO")},
|
||
{0x280a,_T("es-PE")},{0x2c0a,_T("es-AR")},{0x300a,_T("es-EC")},{0x340a,_T("es-CL")}};
|
||
const USER_LANGID gr0c0a[] = {{0x040a,_T("es")},{0x080a,_T("es-MX")},{0x200a,_T("es-VE")},{0x240a,_T("es-CO")},
|
||
{0x280a,_T("es-PE")},{0x2c0a,_T("es-AR")},{0x300a,_T("es-EC")},{0x340a,_T("es-CL")}};
|
||
|
||
// These are all the machine langids. If there isn't an associated array of user langids, then
|
||
// the user langid is irrelevant, and the default ISO language code should be used. If there is
|
||
// an associated array of user langids, then it should be searched first and the specific langid used.
|
||
// If no match is found in the user langids, then the default langid is used.
|
||
const MACH_LANGID grLangids[] = {
|
||
{ 0x0401, _T("ar"), 0, NULL },
|
||
{ 0x0403, _T("ca"), 0, NULL },
|
||
{ 0x0404, _T("zh-TW"), grsize(0404), gr0404 },
|
||
{ 0x0405, _T("cs"), 0, NULL },
|
||
{ 0x0406, _T("da"), 0, NULL },
|
||
{ 0x0407, _T("de"), grsize(0407), gr0407 },
|
||
{ 0x0408, _T("el"), 0, NULL },
|
||
{ 0x0409, _T("en"), grsize(0409), gr0409 },
|
||
{ 0x040b, _T("fi"), 0, NULL },
|
||
{ 0x040c, _T("fr"), grsize(040c), gr040c },
|
||
{ 0x040d, _T("iw"), 0, NULL },
|
||
{ 0x040e, _T("hu"), 0, NULL },
|
||
{ 0x0410, _T("it"), grsize(0410), gr0410 },
|
||
{ 0x0411, _T("ja"), 0, NULL },
|
||
{ 0x0412, _T("ko"), 0, NULL },
|
||
{ 0x0413, _T("nl"), grsize(0413), gr0413 },
|
||
{ 0x0414, _T("no"), 0, NULL },
|
||
{ 0x0415, _T("pl"), 0, NULL },
|
||
{ 0x0416, _T("pt-BR"), grsize(0416), gr0416 },
|
||
{ 0x0419, _T("ru"), 0, NULL },
|
||
{ 0x041b, _T("sk"), 0, NULL },
|
||
{ 0x041d, _T("sv"), 0, NULL },
|
||
{ 0x041e, _T("th"), 0, NULL },
|
||
{ 0x041f, _T("tr"), 0, NULL },
|
||
{ 0x0424, _T("sl"), 0, NULL },
|
||
{ 0x042d, _T("eu"), 0, NULL },
|
||
{ 0x0804, _T("zh-CN"), 0, NULL },
|
||
{ 0x080a, _T("es"), grsize(080a), gr080a },
|
||
{ 0x0816, _T("pt"), 0, NULL },
|
||
{ 0x0c0a, _T("es"), grsize(0c0a), gr0c0a }
|
||
};
|
||
|
||
#define cLangids (sizeof(grLangids) / sizeof(MACH_LANGID))
|
||
|
||
static LANGID MapLangID(LANGID langid)
|
||
{
|
||
switch (PRIMARYLANGID(langid))
|
||
{
|
||
case LANG_ARABIC:
|
||
langid = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA);
|
||
break;
|
||
|
||
case LANG_CHINESE:
|
||
if (SUBLANGID(langid) != SUBLANG_CHINESE_TRADITIONAL)
|
||
langid = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
|
||
break;
|
||
|
||
case LANG_DUTCH:
|
||
langid = MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH);
|
||
break;
|
||
|
||
case LANG_GERMAN:
|
||
langid = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN);
|
||
break;
|
||
|
||
case LANG_ENGLISH:
|
||
if (SUBLANGID(langid) != SUBLANG_ENGLISH_UK)
|
||
langid = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
|
||
break;
|
||
|
||
case LANG_FRENCH:
|
||
langid = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH);
|
||
break;
|
||
|
||
case LANG_ITALIAN:
|
||
langid = MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN);
|
||
break;
|
||
|
||
case LANG_KOREAN:
|
||
langid = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
|
||
break;
|
||
|
||
case LANG_NORWEGIAN:
|
||
langid = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL);
|
||
break;
|
||
|
||
case LANG_PORTUGUESE:
|
||
// We support both SUBLANG_PORTUGUESE and SUBLANG_PORTUGUESE_BRAZILIAN
|
||
break;
|
||
|
||
case LANG_SPANISH:
|
||
langid = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH);
|
||
break;
|
||
|
||
case LANG_SWEDISH:
|
||
langid = MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH);
|
||
break;
|
||
};
|
||
return langid;
|
||
}
|
||
|
||
|
||
|
||
// return user language ID
|
||
LANGID WINAPI GetUserLangID()
|
||
{
|
||
LOG_Block("GetUserLangID");
|
||
|
||
#ifdef __WUIUTEST
|
||
// language spoofing
|
||
HKEY hKey;
|
||
DWORD dwLangID = 0;
|
||
int error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUIUTEST, 0, KEY_READ, &hKey);
|
||
if (ERROR_SUCCESS == error)
|
||
{
|
||
DWORD dwSize = sizeof(dwLangID);
|
||
error = RegQueryValueEx(hKey, REGVAL_USER_LANGID, 0, 0, (LPBYTE)&dwLangID, &dwSize);
|
||
RegCloseKey(hKey);
|
||
if (ERROR_SUCCESS == error)
|
||
{
|
||
return (WORD) dwLangID;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
WORD wCodePage = 0;
|
||
BOOL bIsNT4 = FALSE;
|
||
BOOL bIsW95 = FALSE;
|
||
|
||
//
|
||
// get base language id
|
||
//
|
||
LANGID langidCurrent = CorrectGetUserDefaultLangID(bIsNT4, bIsW95); // Passed by reference
|
||
|
||
//
|
||
// // special handling for languages
|
||
// //
|
||
// switch (langidCurrent)
|
||
// {
|
||
// case LANGID_ENGLISH:
|
||
//
|
||
// // enabled langauges
|
||
// wCodePage = CorrectGetACP();
|
||
// if (CODEPAGE_ARABIC != wCodePage &&
|
||
// CODEPAGE_HEBREW != wCodePage &&
|
||
// CODEPAGE_THAI != wCodePage)
|
||
// {
|
||
// wCodePage = 0;
|
||
// }
|
||
// break;
|
||
//
|
||
// case LANGID_GREEK:
|
||
//
|
||
// // Greek IBM?
|
||
// wCodePage = CorrectGetOEMCP();
|
||
// if (wCodePage != CODEPAGE_GREEK_IBM)
|
||
// {
|
||
// // if its not Greek IBM we assume its MS. The language code for Greek MS does not include
|
||
// // the code page
|
||
// wCodePage = 0;
|
||
// }
|
||
// break;
|
||
//
|
||
// case LANGID_JAPANESE:
|
||
//
|
||
// if (FIsNECMachine())
|
||
// {
|
||
// wCodePage = 1;
|
||
// }
|
||
//
|
||
// break;
|
||
//
|
||
// default:
|
||
//
|
||
// map language to the ones we support
|
||
//
|
||
langidCurrent = MapLangID(langidCurrent);
|
||
// break;
|
||
// }
|
||
|
||
//
|
||
// Special treatment of NT4 and W95 languages.
|
||
// On NT4, Enabled Arabic, Thai, and Hebrew systems report as fully localized but we want to map them to Enabled
|
||
// On W95, Enabled Thai is reported as Thai but we want to map to Enabled Thai
|
||
//
|
||
if (bIsNT4)
|
||
{
|
||
// NT4
|
||
switch (langidCurrent)
|
||
{
|
||
case LANGID_ARABIC:
|
||
langidCurrent = LANGID_ENGLISH;
|
||
break;
|
||
|
||
case LANGID_HEBREW:
|
||
langidCurrent = LANGID_ENGLISH;
|
||
break;
|
||
|
||
case LANGID_THAI:
|
||
langidCurrent = LANGID_ENGLISH;
|
||
break;
|
||
}
|
||
}
|
||
else if (bIsW95)
|
||
{
|
||
// W95 - only tweek Thai
|
||
if (langidCurrent == LANGID_THAI)
|
||
{
|
||
// wCodePage = CODEPAGE_THAI;
|
||
langidCurrent = LANGID_ENGLISH;
|
||
}
|
||
}
|
||
|
||
LOG_Driver(_T("Returning 0x%04x"), langidCurrent);
|
||
return langidCurrent;
|
||
}
|
||
|
||
// return system language ID
|
||
LANGID WINAPI GetSystemLangID()
|
||
{
|
||
LOG_Block("GetSystemLangID");
|
||
|
||
#ifdef __WUIUTEST
|
||
// language spoofing
|
||
HKEY hKey;
|
||
DWORD dwLangID = 0;
|
||
int error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUIUTEST, 0, KEY_READ, &hKey);
|
||
if (ERROR_SUCCESS == error)
|
||
{
|
||
DWORD dwSize = sizeof(dwLangID);
|
||
error = RegQueryValueEx(hKey, REGVAL_OS_LANGID, 0, 0, (LPBYTE)&dwLangID, &dwSize);
|
||
RegCloseKey(hKey);
|
||
if (ERROR_SUCCESS == error)
|
||
{
|
||
return (WORD) dwLangID;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
WORD wCodePage = 0;
|
||
BOOL bIsNT4 = FALSE;
|
||
BOOL bIsW95 = FALSE;
|
||
|
||
//
|
||
// get base language id
|
||
//
|
||
LANGID langidCurrent = CorrectGetSystemDefaultLangID(bIsNT4, bIsW95); // Passed by reference
|
||
|
||
//
|
||
// // special handling for languages
|
||
// //
|
||
// switch (langidCurrent)
|
||
// {
|
||
// case LANGID_ENGLISH:
|
||
//
|
||
// // enabled langauges
|
||
// wCodePage = CorrectGetACP();
|
||
// if (CODEPAGE_ARABIC != wCodePage &&
|
||
// CODEPAGE_HEBREW != wCodePage &&
|
||
// CODEPAGE_THAI != wCodePage)
|
||
// {
|
||
// wCodePage = 0;
|
||
// }
|
||
// break;
|
||
//
|
||
// case LANGID_GREEK:
|
||
//
|
||
// // Greek IBM?
|
||
// wCodePage = CorrectGetOEMCP();
|
||
// if (wCodePage != CODEPAGE_GREEK_IBM)
|
||
// {
|
||
// // if its not Greek IBM we assume its MS. The language code for Greek MS does not include
|
||
// // the code page
|
||
// wCodePage = 0;
|
||
// }
|
||
// break;
|
||
//
|
||
// case LANGID_JAPANESE:
|
||
//
|
||
// if (FIsNECMachine())
|
||
// {
|
||
// wCodePage = 1;
|
||
// }
|
||
//
|
||
// break;
|
||
//
|
||
// default:
|
||
//
|
||
// map language to the ones we support
|
||
//
|
||
langidCurrent = MapLangID(langidCurrent);
|
||
// break;
|
||
// }
|
||
|
||
//
|
||
// Special treatment of NT4 and W95 languages.
|
||
// On NT4, Enabled Arabic, Thai, and Hebrew systems report as fully localized but we want to map them to Enabled
|
||
// On W95, Enabled Thai is reported as Thai but we want to map to Enabled Thai
|
||
//
|
||
if (bIsNT4)
|
||
{
|
||
// NT4
|
||
switch (langidCurrent)
|
||
{
|
||
case LANGID_ARABIC:
|
||
langidCurrent = LANGID_ENGLISH;
|
||
break;
|
||
|
||
case LANGID_HEBREW:
|
||
langidCurrent = LANGID_ENGLISH;
|
||
break;
|
||
|
||
case LANGID_THAI:
|
||
langidCurrent = LANGID_ENGLISH;
|
||
break;
|
||
}
|
||
}
|
||
else if (bIsW95)
|
||
{
|
||
// W95
|
||
if (langidCurrent == LANGID_THAI)
|
||
{
|
||
// wCodePage = CODEPAGE_THAI;
|
||
langidCurrent = LANGID_ENGLISH;
|
||
}
|
||
}
|
||
|
||
LOG_Driver(_T("Returning 0x%04x"), langidCurrent);
|
||
return langidCurrent;
|
||
}
|
||
|
||
|
||
HRESULT WINAPI DetectClientIUPlatform(PIU_PLATFORM_INFO pIuPlatformInfo)
|
||
{
|
||
LOG_Block("DetectClientIUPlatform");
|
||
HRESULT hr = S_OK;
|
||
|
||
if (!pIuPlatformInfo)
|
||
{
|
||
LOG_ErrorMsg(E_INVALIDARG);
|
||
return E_INVALIDARG;
|
||
}
|
||
|
||
ZeroMemory(pIuPlatformInfo, sizeof(IU_PLATFORM_INFO));
|
||
|
||
OSVERSIONINFO osverinfo;
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
if ( !GetVersionEx(&osverinfo) )
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
return HRESULT_FROM_WIN32(GetLastError());
|
||
}
|
||
|
||
#ifdef __WUIUTEST
|
||
// platform spoofing
|
||
HKEY hKey;
|
||
int error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUIUTEST, 0, KEY_READ, &hKey);
|
||
if (ERROR_SUCCESS == error)
|
||
{
|
||
DWORD dwSize = sizeof(DWORD);
|
||
RegQueryValueEx(hKey, REGVAL_MAJORVER, 0, 0, (LPBYTE)&osverinfo.dwMajorVersion, &dwSize);
|
||
RegQueryValueEx(hKey, REGVAL_MINORVER, 0, 0, (LPBYTE)&osverinfo.dwMinorVersion, &dwSize);
|
||
RegQueryValueEx(hKey, REGVAL_BLDNUMBER, 0, 0, (LPBYTE)&osverinfo.dwBuildNumber, &dwSize);
|
||
RegQueryValueEx(hKey, REGVAL_PLATFORMID, 0, 0, (LPBYTE)&osverinfo.dwPlatformId, &dwSize);
|
||
int cchValueSize;
|
||
(void) SafeRegQueryStringValueCch(hKey, REGVAL_SZCSDVER, osverinfo.szCSDVersion, ARRAYSIZE(osverinfo.szCSDVersion), &cchValueSize);
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
#endif
|
||
|
||
if ( VER_PLATFORM_WIN32_WINDOWS == osverinfo.dwPlatformId
|
||
|| ( VER_PLATFORM_WIN32_NT == osverinfo.dwPlatformId && 5 > osverinfo.dwMajorVersion ) )
|
||
{
|
||
//
|
||
// We're on a Win9x platform or NT < 5.0 (Win2K) - just copy OSVERSIONINFO
|
||
//
|
||
memcpy(&pIuPlatformInfo->osVersionInfoEx, &osverinfo, sizeof(OSVERSIONINFO));
|
||
//
|
||
// For Win9x platforms, remove redundant Major/Minor info from high word of build
|
||
//
|
||
if (VER_PLATFORM_WIN32_WINDOWS == osverinfo.dwPlatformId)
|
||
{
|
||
pIuPlatformInfo->osVersionInfoEx.dwBuildNumber = (0x0000FFFF & pIuPlatformInfo->osVersionInfoEx.dwBuildNumber);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// We're on Win2K or greater, get and copy OSVERSIONINFOEX
|
||
//
|
||
OSVERSIONINFOEX osverinfoex;
|
||
osverinfoex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||
|
||
if ( !GetVersionEx((OSVERSIONINFO*)&osverinfoex) )
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
return HRESULT_FROM_WIN32(GetLastError());
|
||
}
|
||
memcpy(&pIuPlatformInfo->osVersionInfoEx, &osverinfoex, sizeof(OSVERSIONINFOEX));
|
||
}
|
||
//
|
||
// Fill in the OEM BSTRs
|
||
//
|
||
if (FAILED(hr = GetOemBstrs(pIuPlatformInfo->bstrOEMManufacturer, pIuPlatformInfo->bstrOEMModel, pIuPlatformInfo->bstrOEMSupportURL)))
|
||
{
|
||
goto FreeBSTRsAndReturnError;
|
||
}
|
||
|
||
//
|
||
// Fill in pIuPlatformInfo->fIsAdministrator
|
||
//
|
||
pIuPlatformInfo->fIsAdministrator = IsAdministrator();
|
||
|
||
return S_OK;
|
||
|
||
FreeBSTRsAndReturnError:
|
||
|
||
SafeSysFreeString(pIuPlatformInfo->bstrOEMManufacturer);
|
||
SafeSysFreeString(pIuPlatformInfo->bstrOEMModel);
|
||
SafeSysFreeString(pIuPlatformInfo->bstrOEMSupportURL);
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
static int atoh(LPCTSTR ptr)
|
||
{
|
||
int i = 0;
|
||
|
||
//skip 0x if present
|
||
if ( ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X') )
|
||
ptr += 2;
|
||
|
||
for(;;) // until break
|
||
{
|
||
TCHAR ch = *ptr;
|
||
|
||
if ('0' <= ch && ch <= '9')
|
||
ch -= '0';
|
||
else if ('a' <= ch && ch <= 'f')
|
||
ch -= ('a' - 10);
|
||
else if ('A' <= ch && ch <= 'F')
|
||
ch -= ('A' - 10);
|
||
else
|
||
break;
|
||
i = 16 * i + (int)ch;
|
||
ptr++;
|
||
}
|
||
return i;
|
||
}
|
||
|
||
|
||
static int aton(LPCTSTR ptr)
|
||
{
|
||
int i = 0;
|
||
while ('0' <= *ptr && *ptr <= '9')
|
||
{
|
||
i = 10 * i + (int)(*ptr - '0');
|
||
ptr ++;
|
||
}
|
||
return i;
|
||
}
|
||
|
||
|
||
static LANGID CorrectGetSystemDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95)
|
||
{
|
||
LOG_Block("CorrectGetSystemDefaultLangID");
|
||
LANGID langidMachine = LANGID_ENGLISH; // default is english
|
||
|
||
bIsNT4 = FALSE;
|
||
bIsW95 = FALSE;
|
||
|
||
TCHAR szMachineLCID[MAX_PATH];
|
||
|
||
OSVERSIONINFO osverinfo;
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
if ( GetVersionEx(&osverinfo) )
|
||
{
|
||
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
||
{
|
||
//
|
||
if (5 == osverinfo.dwMajorVersion)
|
||
{
|
||
// langidMachine = GetSystemDefaultLangID();
|
||
typedef LANGID (WINAPI *PFN_GetSystemDefaultUILanguage)(void);
|
||
|
||
//
|
||
//kernel32.dll will always be loaded in process
|
||
//
|
||
HMODULE hLibModule = GetModuleHandle(KERNEL32_DLL);
|
||
if (hLibModule)
|
||
{
|
||
PFN_GetSystemDefaultUILanguage fpnGetSystemDefaultUILanguage =
|
||
(PFN_GetSystemDefaultUILanguage)GetProcAddress(hLibModule, "GetSystemDefaultUILanguage");
|
||
if (NULL != fpnGetSystemDefaultUILanguage)
|
||
{
|
||
langidMachine = fpnGetSystemDefaultUILanguage();
|
||
|
||
if (0 == langidMachine)
|
||
{
|
||
LOG_Driver(_T("GetSystemDefaultUILanguage() returned 0, setting langidMachine back to LANGID_ENGLISH"));
|
||
langidMachine = LANGID_ENGLISH;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Get the OS lang from the registry to correct NT4 bug in
|
||
// GetSystemDefaultLangID -- it returns the UI lang and
|
||
// the UI bits get installed (incorrect) as opposed to the actual OS
|
||
// lang bits.
|
||
HKEY hKey;
|
||
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_USERS, REGKEY_CP_INTERNATIONAL, 0, KEY_QUERY_VALUE, &hKey))
|
||
{
|
||
int cchValueSize = ARRAYSIZE(szMachineLCID);
|
||
if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, REGKEY_LOCALE, szMachineLCID, cchValueSize, &cchValueSize)))
|
||
{
|
||
langidMachine = LANGIDFROMLCID(atoh(szMachineLCID));
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed to get langid from \"Locale\" registry value - defaults to LANGID_ENGLISH"));
|
||
}
|
||
RegCloseKey(hKey);
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed to open \"HKCU\\.DEFAULT\\Control Panel\\International\" - defaults to LANGID_ENGLISH"));
|
||
}
|
||
}
|
||
|
||
if (osverinfo.dwMajorVersion == 4) // NT 4
|
||
{
|
||
bIsNT4 = TRUE;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// hack around a problem introduced in Win95 and still existing
|
||
// in Win98 whereby the System Langid is the same as the User Langid.
|
||
// We must look in the registry to get the real value.
|
||
//
|
||
HKEY hKey;
|
||
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_CP_RESOURCELOCAL, 0, KEY_QUERY_VALUE, &hKey))
|
||
{
|
||
int cchValueSize = ARRAYSIZE(szMachineLCID);
|
||
if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, NULL, szMachineLCID, cchValueSize, &cchValueSize)))
|
||
{
|
||
langidMachine = LANGIDFROMLCID(atoh(szMachineLCID));
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed to get (Default) from \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
|
||
}
|
||
RegCloseKey(hKey);
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed to open \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
|
||
}
|
||
|
||
|
||
if ((osverinfo.dwMajorVersion == 4) && (osverinfo.dwMinorVersion <= 0)) // Windows 95
|
||
{
|
||
bIsW95 = TRUE;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
return langidMachine;
|
||
}
|
||
|
||
static LANGID CorrectGetUserDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95)
|
||
{
|
||
LOG_Block("CorrectGetUserDefaultLangID");
|
||
LANGID langidMachine = LANGID_ENGLISH; // default is english
|
||
|
||
bIsNT4 = FALSE;
|
||
bIsW95 = FALSE;
|
||
TCHAR szMachineLCID[MAX_PATH];
|
||
|
||
OSVERSIONINFO osverinfo;
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
if ( GetVersionEx(&osverinfo) )
|
||
{
|
||
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
||
{
|
||
//
|
||
// We shouldn't be using this function from NT, so just default to LANGID_ENGLISH
|
||
// and log a message. This function will hopefully go away when we port to downlevel OS's
|
||
//
|
||
LOG_ErrorMsg(E_INVALIDARG);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// hack around a problem introduced in Win95 and still existing
|
||
// in Win98 whereby the System Langid is the same as the User Langid.
|
||
// We must look in the registry to get the real value.
|
||
//
|
||
HKEY hKey;
|
||
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_CP_INTERNATIONAL, 0, KEY_QUERY_VALUE, &hKey))
|
||
{
|
||
int cchValueSize = ARRAYSIZE(szMachineLCID);
|
||
if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, NULL, szMachineLCID, cchValueSize, &cchValueSize)))
|
||
{
|
||
langidMachine = LANGIDFROMLCID(atoh(szMachineLCID));
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed to get (Default) from \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
|
||
}
|
||
RegCloseKey(hKey);
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed to open \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
|
||
}
|
||
|
||
|
||
if ((osverinfo.dwMajorVersion == 4) && (osverinfo.dwMinorVersion <= 0)) // Windows 95
|
||
{
|
||
bIsW95 = TRUE;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
return langidMachine;
|
||
}
|
||
|
||
|
||
static WORD CorrectGetACP(void)
|
||
{
|
||
LOG_Block("CorrectGetACP");
|
||
WORD wCodePage = 0;
|
||
HKEY hKey;
|
||
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGPATH_CODEPAGE, 0, KEY_QUERY_VALUE, &hKey))
|
||
{
|
||
TCHAR szCodePage[MAX_PATH];
|
||
int cchValueSize = ARRAYSIZE(szCodePage);
|
||
if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, REGKEY_ACP, szCodePage, cchValueSize, &cchValueSize)))
|
||
{
|
||
wCodePage = (WORD)aton(szCodePage);
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed SafeRegQueryStringValueCch in CorrectGetACP - defaulting to code page 0"));
|
||
}
|
||
RegCloseKey(hKey);
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed RegOpenKeyEx in CorrectGetACP - defaulting to code page 0"));
|
||
}
|
||
return wCodePage;
|
||
}
|
||
|
||
|
||
static WORD CorrectGetOEMCP(void)
|
||
{
|
||
LOG_Block("CorrectGetOEMCP");
|
||
WORD wCodePage = 0;
|
||
HKEY hKey;
|
||
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGPATH_CODEPAGE, 0, KEY_QUERY_VALUE, &hKey))
|
||
{
|
||
TCHAR szCodePage[MAX_PATH];
|
||
int cchValueSize = ARRAYSIZE(szCodePage);
|
||
if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, REGKEY_OEMCP, szCodePage, cchValueSize, &cchValueSize)))
|
||
{
|
||
wCodePage = (WORD)aton(szCodePage);
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed SafeRegQueryStringValueCch in CorrectGetOEMCP - defaulting to code page 0"));
|
||
}
|
||
RegCloseKey(hKey);
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("Failed RegOpenKeyEx in CorrectGetOEMCP - defaulting to code page 0"));
|
||
}
|
||
return wCodePage;
|
||
}
|
||
|
||
|
||
static bool FIsNECMachine()
|
||
{
|
||
LOG_Block("FIsNECMachine");
|
||
bool fNEC = false;
|
||
OSVERSIONINFO osverinfo;
|
||
LONG lErr;
|
||
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
||
if (GetVersionEx(&osverinfo))
|
||
{
|
||
if (osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||
{
|
||
HKEY hKey;
|
||
TCHAR tszMachineType[50];
|
||
int cchValueSize;
|
||
|
||
if (ERROR_SUCCESS == (lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
NT5_REGPATH_MACHTYPE,
|
||
0,
|
||
KEY_QUERY_VALUE,
|
||
&hKey)))
|
||
{
|
||
cchValueSize = ARRAYSIZE(tszMachineType);
|
||
if (SUCCEEDED(SafeRegQueryStringValueCch(hKey,
|
||
NT5_REGKEY_MACHTYPE,
|
||
tszMachineType,
|
||
cchValueSize,
|
||
&cchValueSize)))
|
||
{
|
||
if (lstrcmp(tszMachineType, REGVAL_MACHTYPE_NEC) == 0)
|
||
{
|
||
fNEC = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LOG_ErrorMsg(lErr);
|
||
LOG_Driver(_T("Failed SafeRegQueryStringValueCch in FIsNECMachine - defaulting to fNEC = false"));
|
||
}
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
else
|
||
{
|
||
LOG_ErrorMsg(lErr);
|
||
LOG_Driver(_T("Failed RegOpenKeyEx in FIsNECMachine - defaulting to fNEC = false"));
|
||
}
|
||
}
|
||
else // enOSWin98
|
||
{
|
||
// All NEC machines have NEC keyboards for Win98. NEC
|
||
// machine detection is based on this.
|
||
if (LOOKUP_OEMID(GetKeyboardType(1)) == PC98_KEYBOARD_ID)
|
||
{
|
||
fNEC = true;
|
||
}
|
||
else
|
||
{
|
||
LOG_Driver(_T("LOOKUP_OEMID(GetKeyboardType(1)) == PC98_KEYBOARD_ID was FALSE: defaulting to fNEC = false"));
|
||
}
|
||
}
|
||
}
|
||
|
||
return fNEC;
|
||
}
|
||
|
||
//
|
||
// NOTES: If you pass in a NULL pointer you'll get it right back.
|
||
// dwcBuffLen is in characters, not bytes.
|
||
//
|
||
LPTSTR GetIdentPlatformString(LPTSTR pszPlatformBuff, DWORD dwcBuffLen)
|
||
{
|
||
|
||
HRESULT hr=S_OK;
|
||
LOG_Block("GetIdentPlatformString");
|
||
|
||
if (NULL == pszPlatformBuff || 1 > dwcBuffLen)
|
||
{
|
||
LOG_ErrorMsg(E_INVALIDARG);
|
||
return pszPlatformBuff;
|
||
}
|
||
|
||
LPTSTR szOSNamePtr = (LPTSTR) SZ_PLAT_UNKNOWN;
|
||
OSVERSIONINFO osverinfo;
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
if (GetVersionEx(&osverinfo))
|
||
{
|
||
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
||
{
|
||
// ADD CHECK FOR NEPTUNE HERE!!!!!
|
||
if ( osverinfo.dwMinorVersion >= 90) // Millenium
|
||
{
|
||
szOSNamePtr = (LPTSTR) SZ_PLAT_WINME;
|
||
}
|
||
else if (osverinfo.dwMinorVersion > 0 && osverinfo.dwMinorVersion < 90) // Windows 98
|
||
{
|
||
szOSNamePtr = (LPTSTR) SZ_PLAT_WIN98;
|
||
}
|
||
else // Windows 95
|
||
{
|
||
szOSNamePtr = (LPTSTR) SZ_PLAT_WIN95;
|
||
}
|
||
}
|
||
else // osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT
|
||
{
|
||
if ( osverinfo.dwMajorVersion == 4 ) // NT 4
|
||
{
|
||
szOSNamePtr = (LPTSTR) SZ_PLAT_NT4;
|
||
}
|
||
else if (osverinfo.dwMajorVersion == 5) // NT 5
|
||
{
|
||
if (0 == osverinfo.dwMinorVersion)
|
||
{
|
||
szOSNamePtr = (LPTSTR) SZ_PLAT_W2K;
|
||
}
|
||
else if (1 <= osverinfo.dwMinorVersion)
|
||
{
|
||
szOSNamePtr = (LPTSTR) SZ_PLAT_WHISTLER;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(lstrlen(szOSNamePtr) + 1 > (int) dwcBuffLen)
|
||
{
|
||
pszPlatformBuff[0] = 0;
|
||
}
|
||
else
|
||
{
|
||
|
||
|
||
//The length is validated above. So this function cannot possibly fail
|
||
hr=StringCchCopyEx(pszPlatformBuff,dwcBuffLen,szOSNamePtr,NULL,NULL,MISTSAFE_STRING_FLAGS);
|
||
if(FAILED(hr))
|
||
pszPlatformBuff[0] = 0;
|
||
}
|
||
return pszPlatformBuff;
|
||
}
|
||
|
||
//
|
||
// GetIdentLocaleString and related functions ported from Drizzle Utils
|
||
//
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// DistinguishGreekOSs
|
||
// Append additional code to distinguish the Greek OS version.
|
||
//
|
||
// Parameters:
|
||
// pszISOCodeOut-
|
||
// Greek-specific ISO code is appended to this parameter.
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
|
||
void DistinguishGreekOSs(const TCHAR*& pszISOCodeOut /* out */)
|
||
{
|
||
LOG_Block("DistinguishGreekOSs");
|
||
//
|
||
// Default ISO code to Greek OS (MS).
|
||
//
|
||
|
||
pszISOCodeOut = ISOCODE_GREEK_MS;
|
||
|
||
|
||
//
|
||
// Determine from the registry which version of Greek OS. There are
|
||
// two versions of the Greek OS.
|
||
//
|
||
|
||
HKEY hKey;
|
||
DWORD type;
|
||
TCHAR tszOSType[50];
|
||
int cchValueSize;
|
||
|
||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
REGPATH_CODEPAGE,
|
||
0,
|
||
KEY_QUERY_VALUE,
|
||
&hKey) == ERROR_SUCCESS)
|
||
{
|
||
cchValueSize = ARRAYSIZE(tszOSType);
|
||
if (SUCCEEDED(SafeRegQueryStringValueCch(hKey,
|
||
REGKEY_OEMCP,
|
||
tszOSType,
|
||
cchValueSize,
|
||
&cchValueSize)))
|
||
{
|
||
if (0 == lstrcmp(tszOSType, REGVAL_GREEK_IBM))
|
||
{
|
||
// Greek2
|
||
pszISOCodeOut = ISOCODE_GREEK_IBM;
|
||
}
|
||
}
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// HandleExceptionCases
|
||
// Take care of a few exception cases (i.e. Greek OS).
|
||
//
|
||
// Parameters:
|
||
// langidMachine-
|
||
// Contains a language id for the current OS.
|
||
//
|
||
// pszISOCode-
|
||
// Points to a valid language id string for the current OS.
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
|
||
inline void HandleExceptionCases(const LANGID& langidMachine, /* in */
|
||
const TCHAR*& pszISOCode /* out */)
|
||
{
|
||
LOG_Block("HandleExceptionCases");
|
||
|
||
// NEC machines are treated as having their own langid.
|
||
// See if we have a Japanese machine, then check if it
|
||
// is NEC.
|
||
|
||
|
||
if (LANGID_JAPANESE == langidMachine)
|
||
{
|
||
|
||
if (FIsNECMachine())
|
||
{
|
||
pszISOCode = ISOCODE_NEC;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
// Windows 98 has two versions of Greek OS distinguished
|
||
// only by a key in the registry.
|
||
|
||
if(LANGID_GREEK == langidMachine)
|
||
{
|
||
OSVERSIONINFO osverinfo;
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
||
if (! GetVersionEx(&osverinfo))
|
||
{
|
||
return;
|
||
}
|
||
if (osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
||
{
|
||
if (osverinfo.dwMinorVersion > 0)
|
||
{
|
||
DistinguishGreekOSs(pszISOCode);
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// langidCorrectGetSystemDefaultLangID
|
||
// Make this return what GetSystemDefaultLangID should have returned
|
||
// under Win98.
|
||
//
|
||
// Parameters:
|
||
//
|
||
// Comments :
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
|
||
LANGID langidCorrectGetSystemDefaultLangID(void)
|
||
{
|
||
LOG_Block("langidCorrectGetSystemDefaultLangID");
|
||
|
||
LANGID langidMachine = LANGID_ENGLISH; // default is english
|
||
OSVERSIONINFO osverinfo;
|
||
|
||
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
||
if ( GetVersionEx(&osverinfo) )
|
||
{
|
||
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
||
{
|
||
langidMachine = GetSystemDefaultLangID();
|
||
}
|
||
else
|
||
{
|
||
// hack around a problem introduced in Win95 and still existing
|
||
// in Win98 whereby the System Langid is the same as the User Langid.
|
||
// We must look in the registry to get the real value.
|
||
|
||
HKEY hKey;
|
||
|
||
// determine if we should log transmissions
|
||
if ( RegOpenKeyEx( HKEY_CURRENT_USER,
|
||
Win98_REGPATH_MACHLCID,
|
||
0,
|
||
KEY_QUERY_VALUE,
|
||
&hKey) == ERROR_SUCCESS )
|
||
{
|
||
TCHAR tszMachineLCID[MAX_PATH];
|
||
int cchValueSize = ARRAYSIZE(tszMachineLCID);
|
||
|
||
if (FAILED(SafeRegQueryStringValueCch(hKey,
|
||
NULL,
|
||
tszMachineLCID,
|
||
cchValueSize,
|
||
&cchValueSize)))
|
||
{
|
||
|
||
//The size of tszMachineLCID is much larger than the Source string. So cannot possibly fail
|
||
if(FAILED(StringCchCopyEx(tszMachineLCID,MAX_PATH,_T("00000409"),NULL,NULL,MISTSAFE_STRING_FLAGS)))
|
||
return langidMachine;
|
||
}
|
||
|
||
// Now convert to hexadecimal.
|
||
langidMachine = LANGIDFROMLCID(atoh(tszMachineLCID));
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
}
|
||
}
|
||
|
||
return langidMachine;
|
||
}
|
||
|
||
//
|
||
// NOTES: If you pass in a NULL pointer you'll get it right back.
|
||
// dwcBuffLen is in characters, not bytes.
|
||
//
|
||
LPTSTR GetIdentLocaleString(LPTSTR pszISOCode, DWORD dwcBuffLen)
|
||
{
|
||
LOG_Block("GetIdentLocaleString");
|
||
HRESULT hr=S_OK;
|
||
|
||
if (NULL == pszISOCode || 1 > dwcBuffLen)
|
||
{
|
||
LOG_ErrorMsg(E_INVALIDARG);
|
||
return pszISOCode;
|
||
}
|
||
// if we don't find any matching machine langids, we go to the english page.
|
||
LPTSTR pszISOCodePtr = ISOCODE_EN;
|
||
|
||
// First get the system and user LCID.
|
||
LANGID langidMachine = langidCorrectGetSystemDefaultLangID();
|
||
|
||
// First, locate the machine langid in the table.
|
||
for ( int iMachine = 0; iMachine < cLangids; iMachine++ )
|
||
{
|
||
if ( grLangids[iMachine].langidMachine == langidMachine )
|
||
{
|
||
// set the default langid in case we don't find a matching user langid.
|
||
pszISOCodePtr = grLangids[iMachine].pszDefaultISOCode;
|
||
|
||
// Found the machine langid, now lookup the user langid
|
||
if ( grLangids[iMachine].cElems != 0 )
|
||
{
|
||
LANGID langidUser = GetUserDefaultLangID();
|
||
|
||
// We check for specific user langids
|
||
for ( int iUser = 0; iUser < grLangids[iMachine].cElems; iUser++ )
|
||
{
|
||
if ( grLangids[iMachine].grLangidUser[iUser].langidUser == langidUser )
|
||
{
|
||
pszISOCodePtr = grLangids[iMachine].grLangidUser[iUser].pszISOCode;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Take care of a few exceptions.
|
||
// HandleExceptionCases(langidMachine, pszISOCodePtr);
|
||
|
||
if(lstrlen(pszISOCodePtr) + 1 > (int) dwcBuffLen)
|
||
{
|
||
pszISOCode[0] = 0;
|
||
}
|
||
else
|
||
{
|
||
|
||
|
||
hr=StringCchCopyEx(pszISOCode,dwcBuffLen,pszISOCodePtr,NULL,NULL,MISTSAFE_STRING_FLAGS);
|
||
|
||
//cannot possibly fail since length is already validated
|
||
if(FAILED(hr))
|
||
{
|
||
pszISOCode[0] = 0;
|
||
}
|
||
}
|
||
|
||
return pszISOCode;
|
||
}
|
||
|
||
|
||
BOOL LookupLocaleStringFromLCID(LCID lcid, LPTSTR pszISOCode, DWORD cchISOCode)
|
||
{
|
||
LOG_Block("LookupLocaleStringFromLCID");
|
||
|
||
TCHAR szCountry[MAX_PATH];
|
||
BOOL fRet = FALSE;
|
||
|
||
if (GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME,
|
||
pszISOCode, cchISOCode) == FALSE)
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
goto done;
|
||
}
|
||
|
||
szCountry[0] = _T('-');
|
||
|
||
if (GetLocaleInfo(lcid, LOCALE_SISO3166CTRYNAME,
|
||
szCountry + 1, ARRAYSIZE(szCountry) - 1) == FALSE)
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
goto done;
|
||
}
|
||
else
|
||
{
|
||
HRESULT hr;
|
||
|
||
hr = StringCchCatEx(pszISOCode, cchISOCode, szCountry,
|
||
NULL, NULL, MISTSAFE_STRING_FLAGS);
|
||
if (FAILED(hr))
|
||
{
|
||
SetLastError(HRESULT_CODE(hr));
|
||
LOG_ErrorMsg(hr);
|
||
pszISOCode[0] = _T('\0');
|
||
goto done;
|
||
}
|
||
}
|
||
|
||
fRet = TRUE;
|
||
|
||
done:
|
||
return fRet;
|
||
}
|
||
|
||
|
||
//
|
||
// NOTES: If you pass in a NULL pointer you'll get it right back.
|
||
// dwcBuffLen is in characters, not bytes.
|
||
//
|
||
LPTSTR LookupLocaleString(LPTSTR pszISOCode, DWORD dwcBuffLen, BOOL fIsUser)
|
||
{
|
||
LOG_Block("LookupLocaleString");
|
||
|
||
TCHAR szCtryName[MAX_PATH];
|
||
LANGID langid = 0;
|
||
LCID lcid = 0;
|
||
PFN_GetUserDefaultUILanguage pfnGetUserDefaultUILanguage = NULL;
|
||
PFN_GetSystemDefaultUILanguage pfnGetSystemDefaultUILanguage = NULL;
|
||
HMODULE hModule = NULL;
|
||
HRESULT hr=S_OK;
|
||
|
||
if (NULL == pszISOCode)
|
||
{
|
||
LOG_ErrorMsg(ERROR_INVALID_PARAMETER);
|
||
return NULL;
|
||
}
|
||
//
|
||
// If we hit an error, return a "Error" string
|
||
//
|
||
const TCHAR szError[] = _T("Error");
|
||
|
||
if (lstrlen(szError) < (int) dwcBuffLen)
|
||
{
|
||
|
||
hr=StringCchCopyEx(pszISOCode,dwcBuffLen,szError,NULL,NULL,MISTSAFE_STRING_FLAGS);
|
||
|
||
//This should not ideally happen
|
||
if(FAILED(hr))
|
||
{
|
||
LOG_ErrorMsg(HRESULT_CODE(hr));
|
||
pszISOCode[0] = 0;
|
||
goto CleanUp;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
pszISOCode[0] = 0;
|
||
}
|
||
|
||
OSVERSIONINFO osverinfo;
|
||
osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
if ( GetVersionEx(&osverinfo) )
|
||
{
|
||
if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT && 5 <= osverinfo.dwMajorVersion)
|
||
{
|
||
//
|
||
// Windows 2000 and greater (Windows XP)
|
||
//
|
||
//kernel32.dll will always be loaded in process
|
||
//
|
||
|
||
hModule = GetModuleHandle(KERNEL32_DLL);
|
||
if (NULL == hModule)
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
goto CleanUp;
|
||
}
|
||
|
||
if (TRUE == fIsUser)
|
||
{
|
||
//
|
||
// We want the MUI language rather than the LOCALE_USER_DEFAULT and we are >= Win2k
|
||
//
|
||
pfnGetUserDefaultUILanguage = (PFN_GetUserDefaultUILanguage) GetProcAddress(hModule, "GetUserDefaultUILanguage");
|
||
if (NULL == pfnGetUserDefaultUILanguage)
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
goto CleanUp;
|
||
}
|
||
|
||
langid = pfnGetUserDefaultUILanguage();
|
||
if (0 == langid)
|
||
{
|
||
LOG_ErrorMsg(E_FAIL);
|
||
goto CleanUp;
|
||
}
|
||
|
||
lcid = MAKELCID(langid, SORT_DEFAULT);
|
||
}
|
||
else
|
||
{
|
||
pfnGetSystemDefaultUILanguage = (PFN_GetSystemDefaultUILanguage) GetProcAddress(hModule, "GetSystemDefaultUILanguage");
|
||
if (NULL == pfnGetSystemDefaultUILanguage)
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
goto CleanUp;
|
||
}
|
||
|
||
langid = pfnGetSystemDefaultUILanguage();
|
||
if (0 == langid)
|
||
{
|
||
LOG_ErrorMsg(E_FAIL);
|
||
goto CleanUp;
|
||
}
|
||
|
||
lcid = MAKELCID(langid, SORT_DEFAULT);
|
||
}
|
||
|
||
if (FALSE == fIsUser && FIsNECMachine())
|
||
{
|
||
//
|
||
// 523660 Website is not distinguishing the JA_NEC and JA machine types
|
||
//
|
||
// For context="OS", special case NEC machines and just return "nec" for <language/>
|
||
//
|
||
lstrcpyn(pszISOCode, _T("nec"), (int) dwcBuffLen);
|
||
}
|
||
else
|
||
{
|
||
// don't check for error return because the previous code didn't
|
||
LookupLocaleStringFromLCID(lcid, pszISOCode, dwcBuffLen);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Use methods ported from V3 to get local strings
|
||
//
|
||
|
||
// if we don't find any matching machine langids, we go to the english page.
|
||
LPTSTR pszISOCodePtr = ISOCODE_EN;
|
||
|
||
// First get the system or user LCID.
|
||
LANGID langidMachine = fIsUser ? GetUserLangID() : GetSystemLangID();
|
||
|
||
// First, locate the machine langid in the table.
|
||
for ( int iMachine = 0; iMachine < cLangids; iMachine++ )
|
||
{
|
||
if ( grLangids[iMachine].langidMachine == langidMachine )
|
||
{
|
||
// set the default langid in case we don't find a matching user langid.
|
||
pszISOCodePtr = grLangids[iMachine].pszDefaultISOCode;
|
||
|
||
// Found the machine langid, now lookup the user langid
|
||
if ( grLangids[iMachine].cElems != 0 )
|
||
{
|
||
LANGID langidUser = fIsUser ? GetUserDefaultLangID() : GetSystemDefaultLangID();
|
||
|
||
// We check for specific user langids
|
||
for ( int iUser = 0; iUser < grLangids[iMachine].cElems; iUser++ )
|
||
{
|
||
if ( grLangids[iMachine].grLangidUser[iUser].langidUser == langidUser )
|
||
{
|
||
pszISOCodePtr = grLangids[iMachine].grLangidUser[iUser].pszISOCode;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Take care of a few exceptions.
|
||
// HandleExceptionCases(langidMachine, pszISOCodePtr);
|
||
|
||
if(lstrlen(pszISOCodePtr) < (int) dwcBuffLen)
|
||
{
|
||
|
||
hr=StringCchCopyEx(pszISOCode,dwcBuffLen,pszISOCodePtr,NULL,NULL,MISTSAFE_STRING_FLAGS);
|
||
if(FAILED(hr))
|
||
{
|
||
LOG_ErrorMsg(HRESULT_CODE(hr));
|
||
pszISOCode[0] = 0;
|
||
goto CleanUp;
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LOG_ErrorMsg(GetLastError());
|
||
}
|
||
|
||
CleanUp:
|
||
return pszISOCode;
|
||
}
|
||
|