📄 lang.c
字号:
}
/*
* @unimplemented
*/
BOOL
STDCALL
GetCPInfoExW(
UINT CodePage,
DWORD dwFlags,
LPCPINFOEXW lpCPInfoEx)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
GetCPInfoExA(
UINT CodePage,
DWORD dwFlags,
LPCPINFOEXA lpCPInfoEx)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
int
STDCALL
GetGeoInfoW(
GEOID Location,
GEOTYPE GeoType,
LPWSTR lpGeoData,
int cchData,
LANGID LangId)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
int
STDCALL
GetGeoInfoA(
GEOID Location,
GEOTYPE GeoType,
LPSTR lpGeoData,
int cchData,
LANGID LangId)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
const WCHAR *RosGetLocaleValueName( DWORD lctype )
{
switch (lctype & ~LOCALE_LOCALEINFOFLAGSMASK)
{
/* These values are used by SetLocaleInfo and GetLocaleInfo, and
* the values are stored in the registry, confirmed under Windows.
*/
case LOCALE_ICALENDARTYPE: return L"iCalendarType";
case LOCALE_ICURRDIGITS: return L"iCurrDigits";
case LOCALE_ICURRENCY: return L"iCurrency";
case LOCALE_IDIGITS: return L"iDigits";
case LOCALE_IFIRSTDAYOFWEEK: return L"iFirstDayOfWeek";
case LOCALE_IFIRSTWEEKOFYEAR: return L"iFirstWeekOfYear";
case LOCALE_ILZERO: return L"iLZero";
case LOCALE_IMEASURE: return L"iMeasure";
case LOCALE_INEGCURR: return L"iNegCurr";
case LOCALE_INEGNUMBER: return L"iNegNumber";
case LOCALE_IPAPERSIZE: return L"iPaperSize";
case LOCALE_ITIME: return L"iTime";
case LOCALE_S1159: return L"s1159";
case LOCALE_S2359: return L"s2359";
case LOCALE_SCURRENCY: return L"sCurrency";
case LOCALE_SDATE: return L"sDate";
case LOCALE_SDECIMAL: return L"sDecimal";
case LOCALE_SGROUPING: return L"sGrouping";
case LOCALE_SLIST: return L"sList";
case LOCALE_SLONGDATE: return L"sLongDate";
case LOCALE_SMONDECIMALSEP: return L"sMonDecimalSep";
case LOCALE_SMONGROUPING: return L"sMonGrouping";
case LOCALE_SMONTHOUSANDSEP: return L"sMonThousandSep";
case LOCALE_SNEGATIVESIGN: return L"sNegativeSign";
case LOCALE_SPOSITIVESIGN: return L"sPositiveSign";
case LOCALE_SSHORTDATE: return L"sShortDate";
case LOCALE_STHOUSAND: return L"sThousand";
case LOCALE_STIME: return L"sTime";
case LOCALE_STIMEFORMAT: return L"sTimeFormat";
case LOCALE_SYEARMONTH: return L"sYearMonth";
/* The following are not listed under MSDN as supported,
* but seem to be used and also stored in the registry.
*/
case LOCALE_ICOUNTRY: return L"iCountry";
case LOCALE_IDATE: return L"iDate";
case LOCALE_ILDATE: return L"iLDate";
case LOCALE_ITLZERO: return L"iTLZero";
case LOCALE_SCOUNTRY: return L"sCountry";
case LOCALE_SLANGUAGE: return L"sLanguage";
}
return NULL;
}
HKEY RosCreateRegistryKey(void)
{
OBJECT_ATTRIBUTES objAttr;
UNICODE_STRING nameW;
HANDLE hKey;
if (RtlOpenCurrentUser( KEY_ALL_ACCESS, &hKey ) != STATUS_SUCCESS) return 0;
objAttr.Length = sizeof(objAttr);
objAttr.RootDirectory = hKey;
objAttr.ObjectName = &nameW;
objAttr.Attributes = 0;
objAttr.SecurityDescriptor = NULL;
objAttr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, L"Control Panel\\International");
if (NtCreateKey( &hKey, KEY_ALL_ACCESS, &objAttr, 0, NULL, 0, NULL ) != STATUS_SUCCESS) hKey = 0;
NtClose( objAttr.RootDirectory );
return hKey;
}
INT RosGetRegistryLocaleInfo( LPCWSTR lpValue, LPWSTR lpBuffer, INT nLen )
{
DWORD dwSize;
HKEY hKey;
INT nRet;
NTSTATUS ntStatus;
UNICODE_STRING usNameW;
KEY_VALUE_PARTIAL_INFORMATION *kvpiInfo;
const int nInfoSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
if (!(hKey = RosCreateRegistryKey())) return -1;
RtlInitUnicodeString( &usNameW, lpValue );
dwSize = nInfoSize + nLen * sizeof(WCHAR);
if (!(kvpiInfo = HeapAlloc( GetProcessHeap(), 0, dwSize )))
{
NtClose( hKey );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return 0;
}
ntStatus = NtQueryValueKey( hKey, &usNameW, KeyValuePartialInformation, kvpiInfo, dwSize, &dwSize );
if (ntStatus == STATUS_BUFFER_OVERFLOW && !lpBuffer) ntStatus = 0;
if (!ntStatus)
{
nRet = (dwSize - nInfoSize) / sizeof(WCHAR);
if (!nRet || ((WCHAR *)kvpiInfo->Data)[nRet - 1])
{
if (nRet < nLen || !lpBuffer) nRet++;
else
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
nRet = 0;
}
}
if (nRet && lpBuffer)
{
memcpy( lpBuffer, kvpiInfo->Data, (nRet - 1) * sizeof(WCHAR) );
lpBuffer[nRet - 1] = 0;
}
}
else
{
if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND) nRet = -1;
else
{
SetLastError( RtlNtStatusToDosError(ntStatus) );
nRet = 0;
}
}
NtClose( hKey );
HeapFree( GetProcessHeap(), 0, kvpiInfo );
return nRet;
}
/*
* @implemented
*/
int
STDCALL
GetLocaleInfoW (
LCID Locale,
LCTYPE LCType,
LPWSTR lpLCData,
int cchData
)
{
LANGID liLangID;
HRSRC hRsrc;
HGLOBAL hMem;
HMODULE hModule;
INT nRet;
UINT uiFlags;
const WCHAR *ch;
int i;
if (cchData < 0 || (cchData && !lpLCData))
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (!cchData) lpLCData = NULL;
if (Locale == LOCALE_NEUTRAL || Locale == LOCALE_SYSTEM_DEFAULT) Locale = GetSystemDefaultLCID();
else if (Locale == LOCALE_USER_DEFAULT) Locale = GetUserDefaultLCID();
uiFlags = LCType & LOCALE_LOCALEINFOFLAGSMASK;
LCType &= ~LOCALE_LOCALEINFOFLAGSMASK;
if (!(uiFlags & LOCALE_NOUSEROVERRIDE) && Locale == GetUserDefaultLCID())
{
const WCHAR *value = RosGetLocaleValueName(LCType);
if (value && ((nRet = RosGetRegistryLocaleInfo( value, lpLCData, cchData )) != -1)) return nRet;
}
liLangID = LANGIDFROMLCID( Locale );
if (SUBLANGID(liLangID) == SUBLANG_NEUTRAL)
liLangID = MAKELANGID(PRIMARYLANGID(liLangID), SUBLANG_DEFAULT);
hModule = GetModuleHandleW( L"kernel32.dll" );
if (!(hRsrc = FindResourceExW( hModule, (LPWSTR)RT_STRING, (LPCWSTR)((LCType >> 4) + 1), liLangID )))
{
SetLastError( ERROR_INVALID_FLAGS );
return 0;
}
if (!(hMem = LoadResource( hModule, hRsrc )))
return 0;
ch = LockResource( hMem );
for (i = 0; i < (int)(LCType & 0x0f); i++) ch += *ch + 1;
if (uiFlags & LOCALE_RETURN_NUMBER) nRet = sizeof(UINT) / sizeof(WCHAR);
else nRet = (LCType == LOCALE_FONTSIGNATURE) ? *ch : *ch + 1;
if (!lpLCData) return nRet;
if (nRet > cchData)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return 0;
}
if (uiFlags & LOCALE_RETURN_NUMBER)
{
UINT uiNum;
WCHAR *chEnd, *chTmp = HeapAlloc( GetProcessHeap(), 0, (*ch + 1) * sizeof(WCHAR) );
if (!chTmp)
return 0;
memcpy( chTmp, ch + 1, *ch * sizeof(WCHAR) );
chTmp[*ch] = L'\0';
uiNum = wcstol( chTmp, &chEnd, 10 );
if (!*chEnd)
memcpy( lpLCData, &uiNum, sizeof(uiNum) );
else
{
SetLastError( ERROR_INVALID_FLAGS );
nRet = 0;
}
HeapFree( GetProcessHeap(), 0, chTmp );
}
else
{
memcpy( lpLCData, ch + 1, *ch * sizeof(WCHAR) );
if (LCType != LOCALE_FONTSIGNATURE) lpLCData[nRet-1] = 0;
}
return nRet;
}
/***********************************************************************
* get_lcid_codepage
*
* Retrieve the ANSI codepage for a given locale.
*/
__inline static UINT get_lcid_codepage( LCID lcid )
{
UINT ret;
if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret,
sizeof(ret)/sizeof(WCHAR) )) ret = 0;
return ret;
}
/*
* @implemented
*/
/* Synced to Wine-20102004 */
int
STDCALL
CompareStringA (
LCID Locale,
DWORD dwCmpFlags,
LPCSTR lpString1,
int cchCount1,
LPCSTR lpString2,
int cchCount2
)
{
WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
WCHAR *buf2W = buf1W + 130;
LPWSTR str1W, str2W;
INT len1W, len2W, ret;
UINT locale_cp;
if (!lpString1 || !lpString2)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (cchCount1 < 0) cchCount1 = strlen(lpString1);
if (cchCount2 < 0) cchCount2 = strlen(lpString2);
locale_cp = get_lcid_codepage(Locale);
len1W = MultiByteToWideChar(locale_cp, 0, lpString1, cchCount1, buf1W, 130);
if (len1W)
str1W = buf1W;
else
{
len1W = MultiByteToWideChar(locale_cp, 0, lpString1, cchCount1, NULL, 0);
str1W = HeapAlloc(GetProcessHeap(), 0, len1W * sizeof(WCHAR));
if (!str1W)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
MultiByteToWideChar(locale_cp, 0, lpString1, cchCount1, str1W, len1W);
}
len2W = MultiByteToWideChar(locale_cp, 0, lpString2, cchCount2, buf2W, 130);
if (len2W)
str2W = buf2W;
else
{
len2W = MultiByteToWideChar(locale_cp, 0, lpString2, cchCount2, NULL, 0);
str2W = HeapAlloc(GetProcessHeap(), 0, len2W * sizeof(WCHAR));
if (!str2W)
{
if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
MultiByteToWideChar(locale_cp, 0, lpString2, cchCount2, str2W, len2W);
}
ret = CompareStringW(Locale, dwCmpFlags, str1W, len1W, str2W, len2W);
if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
if (str2W != buf2W) HeapFree(GetProcessHeap(), 0, str2W);
return ret;
}
static int compare_unicode_string(
PUNICODE_STRING String1,
PUNICODE_STRING String2,
DWORD Flags
)
{
ULONG len1, len2;
PWCHAR s1, s2;
WCHAR c1, c2;
if (String1 && String2)
{
len1 = String1->Length / sizeof(WCHAR);
len2 = String2->Length / sizeof(WCHAR);
s1 = String1->Buffer;
s2 = String2->Buffer;
while (len1 > 0 && len2 > 0)
{
if (Flags & NORM_IGNORESYMBOLS)
{
int skip = 0;
/* FIXME: not tested */
if (iswctype(*s1, _SPACE | _PUNCT))
{
s1++;
len1--;
skip = 1;
}
if (iswctype(*s2, _SPACE | _PUNCT))
{
s2++;
len2--;
skip = 1;
}
if (skip) continue;
}
/* hyphen and apostrophe are treated differently depending on
* whether SORT_STRINGSORT specified or not
*/
if (!(Flags & SORT_STRINGSORT))
{
if (*s1 == '-' || *s1 == '\'')
{
if (*s2 != '-' && *s2 != '\'')
{
s1++;
len1--;
continue;
}
}
else if (*s2 == '-' || *s2 == '\'')
{
s2++;
len2--;
continue;
}
}
if (Flags & NORM_IGNORECASE)
{
c1 = len1-- ? RtlUpcaseUnicodeChar(*s1++) : 0;
c2 = len2-- ? RtlUpcaseUnicodeChar(*s2++) : 0;
if (!c1 || !c2 || c1 != c2)
return c1 - c2;
}
else
{
c1 = len1-- ? *s1++ : 0;
c2 = len2-- ? *s2++ : 0;
if (!c1 || !c2 || c1 != c2)
return c1 - c2;
}
}
return (int) len1 - (int) len2;
}
return 0;
}
/*
* @unimplemented
*/
int
STDCALL
CompareStringW (
LCID Locale,
DWORD dwCmpFlags,
LPCWSTR lpString1,
int cchCount1,
LPCWSTR lpString2,
int cchCount2
)
{
INT Result;
UNICODE_STRING String1, String2;
if (!lpString1 || !lpString2)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (dwCmpFlags & ~(NORM_IGNORECASE | NORM_IGNORENONSPACE |
NORM_IGNORESYMBOLS | SORT_STRINGSORT | NORM_IGNOREKANATYPE |
NORM_IGNOREWIDTH | 0x10000000))
{
SetLastError(ERROR_INVALID_FLAGS);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -