📄 lang.c
字号:
}
}
HeapFree( GetProcessHeap(), 0, bufferW );
return ret;
}
/*
* @implemented
*/
LANGID STDCALL
GetSystemDefaultLangID(VOID)
{
return LANGIDFROMLCID(GetSystemDefaultLCID());
}
/*
* @implemented
*/
LCID STDCALL
GetSystemDefaultLCID(VOID)
{
LCID lcid;
NtQueryDefaultLocale(FALSE, &lcid);
return lcid;
}
/*
* @implemented
*/
LANGID STDCALL
GetSystemDefaultUILanguage(VOID)
{
LANGID LanguageId;
NTSTATUS Status;
Status = NtQueryInstallUILanguage(&LanguageId);
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return 0;
}
return LanguageId;
}
/*
* @implemented
*/
LCID STDCALL
GetThreadLocale(VOID)
{
return NtCurrentTeb()->CurrentLocale;
}
/*
* @implemented
*/
LANGID STDCALL
GetUserDefaultLangID(VOID)
{
return LANGIDFROMLCID(GetUserDefaultLCID());
}
/*
* @implemented
*/
LCID STDCALL
GetUserDefaultLCID(VOID)
{
LCID lcid;
NTSTATUS Status;
Status = NtQueryDefaultLocale(TRUE, &lcid);
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return 0;
}
return lcid;
}
/*
* @implemented
*/
LANGID STDCALL
GetUserDefaultUILanguage(VOID)
{
LANGID LangId;
NTSTATUS Status;
Status = NtQueryDefaultUILanguage(&LangId);
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return 0;
}
return LangId;
}
/*
* @unimplemented
*/
GEOID
STDCALL
GetUserGeoID(
GEOCLASS GeoClass)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/******************************************************************************
* IsValidLanguageGroup
*
* Determine if a language group is supported and/or installed.
*
* PARAMS
* LanguageGroup [I] Language Group Id (LGRPID_ values from "winnls.h")
* dwFlags [I] LGRPID_SUPPORTED=Supported, LGRPID_INSTALLED=Installed
*
* RETURNS
* TRUE, if lgrpid is supported and/or installed, according to dwFlags.
* FALSE otherwise.
*
* @implemented
*/
BOOL
STDCALL
IsValidLanguageGroup(
LGRPID LanguageGroup,
DWORD dwFlags)
{
static const WCHAR szFormat[] = { '%','x','\0' };
UNICODE_STRING szNlsKeyName =
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls");
UNICODE_STRING szLangGroupsKeyName =
RTL_CONSTANT_STRING(L"Language Groups");
const int MAX_VALUE_NAME = 16;
const int MAX_VALUE_SYMB = 128;
BOOL bNtQuery;
PKEY_VALUE_PARTIAL_INFORMATION kvpiInfo;
WCHAR szValueName[MAX_VALUE_NAME];
UNICODE_STRING ucsValueName;
DWORD dwRetSize;
PWSTR pwszValueData;
DWORD dwSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_VALUE_SYMB * sizeof(WCHAR);
OBJECT_ATTRIBUTES oaAttr;
HANDLE hkey, hRootKey;
BOOL bSupported = FALSE, bInstalled = FALSE;
DPRINT("IsValidLanguageGroup() called\n");
kvpiInfo = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
dwSize);
switch (dwFlags)
{
case LGRPID_INSTALLED:
case LGRPID_SUPPORTED:
InitializeObjectAttributes(&oaAttr, &szNlsKeyName, 0, 0, NULL);
if(NtOpenKey(&hRootKey, KEY_ALL_ACCESS, &oaAttr) != STATUS_SUCCESS) return FALSE;
InitializeObjectAttributes(&oaAttr, &szLangGroupsKeyName, 0, hRootKey, NULL);
if(NtOpenKey(&hkey, KEY_ALL_ACCESS, &oaAttr) != STATUS_SUCCESS) return FALSE;
if(hRootKey) NtClose(hRootKey);
swprintf(szValueName, szFormat, (ULONG)LanguageGroup);
RtlInitUnicodeString(&ucsValueName, szValueName);
bNtQuery = NtQueryValueKey(hkey,
&ucsValueName,
KeyValuePartialInformation,
kvpiInfo,
dwSize,
&dwRetSize);
if(hkey) NtClose(hkey);
if(bNtQuery == STATUS_SUCCESS &&
kvpiInfo->DataLength == sizeof(DWORD))
{
pwszValueData = (PWSTR)&kvpiInfo->Data[0];
bSupported = TRUE;
if(pwszValueData[0] == L'1') bInstalled = TRUE;
}
else
{
DPRINT("NtQueryValueKey() failed (Status %lx)\n", bNtQuery);
RtlFreeHeap(RtlGetProcessHeap(), 0, kvpiInfo);
return FALSE;
}
break;
}
RtlFreeHeap(RtlGetProcessHeap(), 0, kvpiInfo);
if((dwFlags == LGRPID_SUPPORTED && bSupported) ||
(dwFlags == LGRPID_INSTALLED && bInstalled))
{
DPRINT("Language group is supported and installed\n");
return TRUE;
}
return FALSE;
}
/******************************************************************************
* IsValidLocale
*
* Determine if a locale is valid.
*
* PARAMS
* Locale [I] LCID of the locale to check
* dwFlags [I] LCID_SUPPORTED = Valid
* LCID_INSTALLED = Valid and installed on the system
*
* RETURN
* TRUE, if Locale is valid,
* FALSE, otherwise.
*
* @implemented
*/
BOOL STDCALL
IsValidLocale(LCID Locale,
DWORD dwFlags)
{
OBJECT_ATTRIBUTES ObjectAttributes;
PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
WCHAR ValueNameBuffer[9];
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
ULONG KeyInfoSize;
ULONG ReturnedSize;
HANDLE KeyHandle;
PWSTR ValueData;
NTSTATUS Status;
DPRINT("IsValidLocale() called\n");
if ((dwFlags & ~(LCID_SUPPORTED | LCID_INSTALLED)) ||
(dwFlags == (LCID_SUPPORTED | LCID_INSTALLED)))
{
DPRINT("Invalid flags: %lx\n", dwFlags);
return FALSE;
}
if (Locale & 0xFFFF0000)
{
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Locale\\Alternate Sorts");
}
else
{
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Locale");
}
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&KeyHandle,
KEY_QUERY_VALUE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
return FALSE;
}
swprintf(ValueNameBuffer, L"%08lx", (ULONG)Locale);
RtlInitUnicodeString(&ValueName, ValueNameBuffer);
KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4 * sizeof(WCHAR);
KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
KeyInfoSize);
if (KeyInfo == NULL)
{
DPRINT("RtlAllocateHeap() failed (Status %lx)\n", Status);
NtClose(KeyHandle);
return FALSE;
}
Status = NtQueryValueKey(KeyHandle,
&ValueName,
KeyValuePartialInformation,
KeyInfo,
KeyInfoSize,
&ReturnedSize);
NtClose(KeyHandle);
if (!NT_SUCCESS(Status))
{
DPRINT("NtQueryValueKey() failed (Status %lx)\n", Status);
RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
return FALSE;
}
if (dwFlags & LCID_SUPPORTED)
{
DPRINT("Locale is supported\n");
RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
return TRUE;
}
ValueData = (PWSTR)&KeyInfo->Data[0];
if ((KeyInfo->Type == REG_SZ) &&
(KeyInfo->DataLength == 2 * sizeof(WCHAR)) &&
(ValueData[0] == L'1'))
{
DPRINT("Locale is supported and installed\n");
RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
return TRUE;
}
RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
DPRINT("IsValidLocale() called\n");
return FALSE;
}
/*
* @unimplemented
*/
int
STDCALL
LCMapStringA (
LCID Locale,
DWORD dwMapFlags,
LPCSTR lpSrcStr,
int cchSrc,
LPSTR lpDestStr,
int cchDest
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
int
STDCALL
LCMapStringW (
LCID Locale,
DWORD dwMapFlags,
LPCWSTR lpSrcStr,
int cchSrc,
LPWSTR lpDestStr,
int cchDest
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
SetCalendarInfoA(
LCID Locale,
CALID Calendar,
CALTYPE CalType,
LPCSTR lpCalData)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
SetCalendarInfoW(
LCID Locale,
CALID Calendar,
CALTYPE CalType,
LPCWSTR lpCalData)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/**********************************************************************
* @implemented
* RIPPED FROM WINE's dlls\kernel\locale.c ver 0.9.29
*
* SetLocaleInfoA (KERNEL32.@)
*
* Set the current locale info.
*
* PARAMS
* Locale [I] LCID of the locale
* LCType [I] LCTYPE_ flags from "winnls.h"
* lpLCData [I] Information to set
*
* RETURNS
* Success: TRUE. The information given will be returned by GetLocaleInfoA()
* whenever it is called without LOCALE_NOUSEROVERRIDE.
* Failure: FALSE. Use GetLastError() to determine the cause.
*/
BOOL
STDCALL
SetLocaleInfoA (
LCID Locale,
LCTYPE LCType,
LPCSTR lpLCData
)
{
UINT codepage = CP_ACP;
WCHAR *strW;
DWORD len;
BOOL ret;
if (!(LCType & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( Locale );
if (!lpLCData)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
len = MultiByteToWideChar( codepage, 0, lpLCData, -1, NULL, 0 );
if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
MultiByteToWideChar( codepage, 0, lpLCData, -1, strW, len );
ret = SetLocaleInfoW( Locale, LCType, strW );
HeapFree( GetProcessHeap(), 0, strW );
return ret;
}
/**********************************************************************
* @implemented
* RIPPED FROM WINE's dlls\kernel\locale.c ver 0.9.29
*
* SetLocaleInfoW (KERNEL32.@)
*
* See SetLocaleInfoA.
*
*/
BOOL
STDCALL
SetLocaleInfoW (
LCID Locale,
LCTYPE LCType,
LPCWSTR lpLCData
)
{
const WCHAR *value;
UNICODE_STRING valueW;
NTSTATUS status;
HANDLE hkey;
LCType &= 0xffff;
value = RosGetLocaleValueName( LCType );
if (!lpLCData || !value)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (LCType == LOCALE_IDATE || LCType == LOCALE_ILDATE)
{
SetLastError( ERROR_INVALID_FLAGS );
return FALSE;
}
if (!(hkey = RosCreateRegistryKey())) return FALSE;
RtlInitUnicodeString( &valueW, value );
status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, (PVOID)lpLCData, (lstrlenW(lpLCData)+1)*sizeof(WCHAR) );
if (LCType == LOCALE_SSHORTDATE || LCType == LOCALE_SLONGDATE)
{
/* Set I-value from S value */
WCHAR *lpD, *lpM, *lpY;
WCHAR szBuff[2];
lpD = wcschr(lpLCData, 'd');
lpM = wcschr(lpLCData, 'M');
lpY = wcschr(lpLCData, 'y');
if (lpD <= lpM)
{
szBuff[0] = '1'; /* D-M-Y */
}
else
{
if (lpY <= lpM)
szBuff[0] = '2'; /* Y-M-D */
else
szBuff[0] = '0'; /* M-D-Y */
}
szBuff[1] = '\0';
if (LCType == LOCALE_SSHORTDATE)
LCType = LOCALE_IDATE;
else
LCType = LOCALE_ILDATE;
value = RosGetLocaleValueName( LCType );
RtlInitUnicodeString( &valueW, value );
status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, szBuff, sizeof(szBuff) );
}
NtClose( hkey );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
/**********************************************************************
* @implemented
* RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
*
* SetThreadLocale (KERNEL32.@)
*
* Set the current threads locale.
*
* PARAMS
* lcid [I] LCID of the locale to set
*
* RETURNS
* Success: TRUE. The threads locale is set to lcid.
* Failure: FALSE. Use GetLastError() to determine the cause.
*
*/
BOOL WINAPI SetThreadLocale( LCID lcid )
{
DPRINT("SetThreadLocale(0x%04lX)\n", lcid);
lcid = ConvertDefaultLocale(lcid);
if (lcid != GetThreadLocale())
{
if (!IsValidLocale(lcid, LCID_SUPPORTED))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
NtCurrentTeb()->CurrentLocale = lcid;
/* FIXME: NtCurrentTeb()->code_page = get_lcid_codepage( lcid );
* Wine save the acp for easy/fast access, but ROS has no such Teb member.
* Maybe add this member to ros as well?
*/
/*
Lag test app for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -