📄 lang.c
字号:
/* $Id: lang.c 28020 2007-07-29 19:04:03Z cwittich $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: dll/win32/kernel32/file/lang.c
* PURPOSE: National Laguage Support related funcs
* PROGRAMMER: Thomas Weidenmueller
* Gunnar Andre Dalsnes
* Aleksey Bragin
* Eric Kohl
* Alex Ionescu
* Richard Campbell
* James Tabor
* UPDATE HISTORY:
* Created 21/09/2003
*/
#include <k32.h>
#define NDEBUG
#include "../include/debug.h"
/* FIXME: these are included in winnls.h, however including this file causes alot of
conflicting type errors. */
#define LOCALE_RETURN_NUMBER 0x20000000
#define LOCALE_USE_CP_ACP 0x40000000
#define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|LOCALE_RETURN_NUMBER)
//static LCID SystemLocale = MAKELCID(LANG_ENGLISH, SORT_DEFAULT);
//static RTL_CRITICAL_SECTION LocalesListLock;
/******************************************************************************
* @implemented
* RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
*
* ConvertDefaultLocale (KERNEL32.@)
*
* Convert a default locale identifier into a real identifier.
*
* PARAMS
* lcid [I] LCID identifier of the locale to convert
*
* RETURNS
* lcid unchanged, if not a default locale or its sublanguage is
* not SUBLANG_NEUTRAL.
* GetSystemDefaultLCID(), if lcid == LOCALE_SYSTEM_DEFAULT.
* GetUserDefaultLCID(), if lcid == LOCALE_USER_DEFAULT or LOCALE_NEUTRAL.
* Otherwise, lcid with sublanguage changed to SUBLANG_DEFAULT.
*/
LCID WINAPI
ConvertDefaultLocale(LCID lcid)
{
LANGID langid;
switch (lcid)
{
case LOCALE_SYSTEM_DEFAULT:
lcid = GetSystemDefaultLCID();
break;
case LOCALE_USER_DEFAULT:
case LOCALE_NEUTRAL:
lcid = GetUserDefaultLCID();
break;
default:
/* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */
langid = LANGIDFROMLCID(lcid);
if (SUBLANGID(langid) == SUBLANG_NEUTRAL)
{
langid = MAKELANGID(PRIMARYLANGID(langid), SUBLANG_DEFAULT);
lcid = MAKELCID(langid, SORTIDFROMLCID(lcid));
}
}
return lcid;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumCalendarInfoExA(
CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx,
LCID Locale,
CALID Calendar,
CALTYPE CalType)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumCalendarInfoExW(
CALINFO_ENUMPROCEXW lpCalInfoEnumProcEx,
LCID Locale,
CALID Calendar,
CALTYPE CalType)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumCalendarInfoW(
CALINFO_ENUMPROCW lpCalInfoEnumProcEx,
LCID Locale,
CALID Calendar,
CALTYPE CalType)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/**************************************************************************
* EnumDateFormatsExA (KERNEL32.@)
*
* FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
* LOCALE_NOUSEROVERRIDE here as well?
*/
BOOL
STDCALL
EnumDateFormatsExA(
DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx,
LCID Locale,
DWORD dwFlags)
{
CALID cal_id;
char szBuf[256];
if (!lpDateFmtEnumProcEx)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!GetLocaleInfoW(Locale,
LOCALE_ICALENDARTYPE|LOCALE_RETURN_NUMBER,
(LPWSTR)&cal_id,
sizeof(cal_id)/sizeof(WCHAR)))
{
return FALSE;
}
switch (dwFlags & ~LOCALE_USE_CP_ACP)
{
case 0:
case DATE_SHORTDATE:
if (GetLocaleInfoA(Locale,
LOCALE_SSHORTDATE | (dwFlags & LOCALE_USE_CP_ACP),
szBuf, 256))
{
lpDateFmtEnumProcEx(szBuf, cal_id);
}
break;
case DATE_LONGDATE:
if (GetLocaleInfoA(Locale,
LOCALE_SLONGDATE | (dwFlags & LOCALE_USE_CP_ACP),
szBuf, 256))
{
lpDateFmtEnumProcEx(szBuf, cal_id);
}
break;
case DATE_YEARMONTH:
if (GetLocaleInfoA(Locale,
LOCALE_SYEARMONTH | (dwFlags & LOCALE_USE_CP_ACP),
szBuf, 256))
{
lpDateFmtEnumProcEx(szBuf, cal_id);
}
break;
default:
// FIXME: Unknown date format
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
/**************************************************************************
* EnumDateFormatsExW (KERNEL32.@)
*/
BOOL
STDCALL
EnumDateFormatsExW(
DATEFMT_ENUMPROCEXW lpDateFmtEnumProcEx,
LCID Locale,
DWORD dwFlags)
{
CALID cal_id;
WCHAR wbuf[256]; // FIXME
if (!lpDateFmtEnumProcEx)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!GetLocaleInfoW(Locale,
LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER,
(LPWSTR)&cal_id,
sizeof(cal_id)/sizeof(WCHAR)))
{
return FALSE;
}
switch (dwFlags & ~LOCALE_USE_CP_ACP)
{
case 0:
case DATE_SHORTDATE:
if (GetLocaleInfoW(Locale,
LOCALE_SSHORTDATE | (dwFlags & LOCALE_USE_CP_ACP),
wbuf,
256))
{
lpDateFmtEnumProcEx(wbuf, cal_id);
}
break;
case DATE_LONGDATE:
if (GetLocaleInfoW(Locale,
LOCALE_SLONGDATE | (dwFlags & LOCALE_USE_CP_ACP),
wbuf,
256))
{
lpDateFmtEnumProcEx(wbuf, cal_id);
}
break;
case DATE_YEARMONTH:
if (GetLocaleInfoW(Locale,
LOCALE_SYEARMONTH | (dwFlags & LOCALE_USE_CP_ACP),
wbuf,
256))
{
lpDateFmtEnumProcEx(wbuf, cal_id);
}
break;
default:
// FIXME: Unknown date format
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumLanguageGroupLocalesA(
LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc,
LGRPID LanguageGroup,
DWORD dwFlags,
LONG_PTR lParam)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumLanguageGroupLocalesW(
LANGGROUPLOCALE_ENUMPROCW lpLangGroupLocaleEnumProc,
LGRPID LanguageGroup,
DWORD dwFlags,
LONG_PTR lParam)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumSystemCodePagesW (
CODEPAGE_ENUMPROCW lpCodePageEnumProc,
DWORD dwFlags
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumSystemCodePagesA (
CODEPAGE_ENUMPROCA lpCodePageEnumProc,
DWORD dwFlags
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumSystemGeoID(
GEOCLASS GeoClass,
GEOID ParentGeoId,
GEO_ENUMPROC lpGeoEnumProc)
{
if(!lpGeoEnumProc)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
switch(GeoClass)
{
case GEOCLASS_NATION:
/*RtlEnterCriticalSection(&DllLock);
FIXME - Get GEO IDs calling Csr
RtlLeaveCriticalSection(&DllLock);*/
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
break;
default:
SetLastError(ERROR_INVALID_FLAGS);
return FALSE;
}
return FALSE;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumSystemLanguageGroupsA(
LANGUAGEGROUP_ENUMPROCA pLangGroupEnumProc,
DWORD dwFlags,
LONG_PTR lParam)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumSystemLanguageGroupsW(
LANGUAGEGROUP_ENUMPROCW pLangGroupEnumProc,
DWORD dwFlags,
LONG_PTR lParam)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumSystemLocalesA (
LOCALE_ENUMPROCA lpLocaleEnumProc,
DWORD dwFlags
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* @implemented
*/
BOOL
STDCALL
EnumSystemLocalesW (
LOCALE_ENUMPROCW lpLocaleEnumProc,
DWORD dwFlags
)
{
NTSTATUS result;
HANDLE langKey;
UNICODE_STRING langKeyName = RTL_CONSTANT_STRING(
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Locale");
OBJECT_ATTRIBUTES objectAttributes;
ULONG index, length;
unsigned char fullInfo[sizeof(KEY_VALUE_FULL_INFORMATION)+255*2]; //FIXME: MAX_PATH*2
PKEY_VALUE_FULL_INFORMATION pFullInfo;
//TODO: Combine with EnumSystemLocalesA - maybe by having one common part, driven by some
// unicode/non-unicode flag.
//FIXME: dwFlags is really not used, sorry
// Check if enum proc is a real one
if (lpLocaleEnumProc == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// Open language registry key
//FIXME: Should we use critical section here?
InitializeObjectAttributes(&objectAttributes,
&langKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
result = NtOpenKey(&langKey,
KEY_READ,
&objectAttributes);
if (!NT_SUCCESS(result))
return result;
DPRINT1("Registry key succesfully opened\n");
length = sizeof(KEY_VALUE_FULL_INFORMATION) + 255*2;//MAX_PATH*sizeof(WCHAR);
pFullInfo = (PKEY_VALUE_FULL_INFORMATION)&fullInfo;
RtlZeroMemory(pFullInfo, length);
index = 0;
result = NtEnumerateValueKey(langKey,
index,
KeyValueFullInformation,
pFullInfo,
length,
&length);
DPRINT1("First enumerate call result=%x\n", result);
while (result != STATUS_NO_MORE_ENTRIES)
{
int i;
WCHAR lpLocale[9];
// TODO: Here we should check, in case dwFlags & LCID_INSTALLED is specified,
// if this locale is really installed
// but for now we skip it
for (i=0; i<8; i++)
lpLocale[i] = pFullInfo->Name[i];
lpLocale[8]=0;
DPRINT1("Locale=%S\n", lpLocale);
// Call Enum func
if (!lpLocaleEnumProc((LPWSTR)lpLocale))
break;
// Zero previous values
RtlZeroMemory(pFullInfo, length);
index++;
result = NtEnumerateValueKey(langKey, index,KeyValueFullInformation, pFullInfo, length, &length);
}
NtClose(langKey);
return STATUS_SUCCESS;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumUILanguagesA(
UILANGUAGE_ENUMPROCA lpUILanguageEnumProc,
DWORD dwFlags,
LONG_PTR lParam)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
EnumUILanguagesW(
UILANGUAGE_ENUMPROCW lpUILanguageEnumProc,
DWORD dwFlags,
LONG_PTR lParam)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
int
STDCALL
GetCalendarInfoA(
LCID Locale,
CALID Calendar,
CALTYPE CalType,
LPSTR lpCalData,
int cchData,
LPDWORD lpValue)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
int
STDCALL
GetCalendarInfoW(
LCID Locale,
CALID Calendar,
CALTYPE CalType,
LPWSTR lpCalData,
int cchData,
LPDWORD lpValue)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
BOOL
STDCALL
GetCPInfo (
UINT CodePage,
LPCPINFO CodePageInfo
)
{
unsigned i;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
CodePageInfo->MaxCharSize = 1;
CodePageInfo->DefaultChar[0] = '?';
for (i = 1; i < MAX_DEFAULTCHAR; i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -