Implement GetLocaleInfoW

svn path=/trunk/; revision=7626
This commit is contained in:
Richard Campbell 2004-01-14 21:40:12 +00:00
parent fa6209cc0f
commit da051e4b51
2 changed files with 264 additions and 7 deletions

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.73 2003/12/30 05:10:31 hyperion Exp $
# $Id: makefile,v 1.74 2004/01/14 21:40:12 rcampbell Exp $
PATH_TO_TOP = ../..
@ -13,7 +13,7 @@ TARGET_CFLAGS += -D_DISABLE_TIDENTS -Wall -Werror
TARGET_LFLAGS = -nostartfiles -nostdlib
TARGET_SDKLIBS = rosrtl.a ntdll.a
TARGET_SDKLIBS = rosrtl.a ntdll.a kernel32.a
TARGET_GCCLIBS = gcc

View file

@ -1,4 +1,4 @@
/* $Id: lang.c,v 1.3 2004/01/14 07:22:17 rcampbell Exp $
/* $Id: lang.c,v 1.4 2004/01/14 21:40:12 rcampbell Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT : ReactOS user mode libraries
@ -13,6 +13,14 @@
#include <kernel32/kernel32.h>
#include <string.h>
#define LOCALE_SYEARMONTH 0x1006
#define LOCALE_IPAPERSIZE 0x100A
#define LOCALE_RETURN_NUMBER 0x20000000
#define LOCALE_USE_CP_ACP 0x40000000
#define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|LOCALE_RETURN_NUMBER)
#define LOCALE_NEUTRAL (MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT))
#define LOCALE_FONTSIGNATURE 0x00000058
static LCID SystemLocale = MAKELCID(LANG_ENGLISH, SORT_DEFAULT);
//#define _OLE2NLS_IN_BUILD_
@ -608,22 +616,271 @@ GetGeoInfoA(
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
const WCHAR *RosGetLocaleValueName( DWORD lctype )
{
static const WCHAR iCalendarTypeW[] = {'i','C','a','l','e','n','d','a','r','T','y','p','e',0};
static const WCHAR iCountryW[] = {'i','C','o','u','n','t','r','y',0};
static const WCHAR iCurrDigitsW[] = {'i','C','u','r','r','D','i','g','i','t','s',0};
static const WCHAR iCurrencyW[] = {'i','C','u','r','r','e','n','c','y',0};
static const WCHAR iDateW[] = {'i','D','a','t','e',0};
static const WCHAR iDigitsW[] = {'i','D','i','g','i','t','s',0};
static const WCHAR iFirstDayOfWeekW[] = {'i','F','i','r','s','t','D','a','y','O','f','W','e','e','k',0};
static const WCHAR iFirstWeekOfYearW[] = {'i','F','i','r','s','t','W','e','e','k','O','f','Y','e','a','r',0};
static const WCHAR iLDateW[] = {'i','L','D','a','t','e',0};
static const WCHAR iLZeroW[] = {'i','L','Z','e','r','o',0};
static const WCHAR iMeasureW[] = {'i','M','e','a','s','u','r','e',0};
static const WCHAR iNegCurrW[] = {'i','N','e','g','C','u','r','r',0};
static const WCHAR iNegNumberW[] = {'i','N','e','g','N','u','m','b','e','r',0};
static const WCHAR iPaperSizeW[] = {'i','P','a','p','e','r','S','i','z','e',0};
static const WCHAR iTLZeroW[] = {'i','T','L','Z','e','r','o',0};
static const WCHAR iTimeW[] = {'i','T','i','m','e',0};
static const WCHAR s1159W[] = {'s','1','1','5','9',0};
static const WCHAR s2359W[] = {'s','2','3','5','9',0};
static const WCHAR sCountryW[] = {'s','C','o','u','n','t','r','y',0};
static const WCHAR sCurrencyW[] = {'s','C','u','r','r','e','n','c','y',0};
static const WCHAR sDateW[] = {'s','D','a','t','e',0};
static const WCHAR sDecimalW[] = {'s','D','e','c','i','m','a','l',0};
static const WCHAR sGroupingW[] = {'s','G','r','o','u','p','i','n','g',0};
static const WCHAR sLanguageW[] = {'s','L','a','n','g','u','a','g','e',0};
static const WCHAR sListW[] = {'s','L','i','s','t',0};
static const WCHAR sLongDateW[] = {'s','L','o','n','g','D','a','t','e',0};
static const WCHAR sMonDecimalSepW[] = {'s','M','o','n','D','e','c','i','m','a','l','S','e','p',0};
static const WCHAR sMonGroupingW[] = {'s','M','o','n','G','r','o','u','p','i','n','g',0};
static const WCHAR sMonThousandSepW[] = {'s','M','o','n','T','h','o','u','s','a','n','d','S','e','p',0};
static const WCHAR sNegativeSignW[] = {'s','N','e','g','a','t','i','v','e','S','i','g','n',0};
static const WCHAR sPositiveSignW[] = {'s','P','o','s','i','t','i','v','e','S','i','g','n',0};
static const WCHAR sShortDateW[] = {'s','S','h','o','r','t','D','a','t','e',0};
static const WCHAR sThousandW[] = {'s','T','h','o','u','s','a','n','d',0};
static const WCHAR sTimeFormatW[] = {'s','T','i','m','e','F','o','r','m','a','t',0};
static const WCHAR sTimeW[] = {'s','T','i','m','e',0};
static const WCHAR sYearMonthW[] = {'s','Y','e','a','r','M','o','n','t','h',0};
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 iCalendarTypeW;
case LOCALE_ICURRDIGITS: return iCurrDigitsW;
case LOCALE_ICURRENCY: return iCurrencyW;
case LOCALE_IDIGITS: return iDigitsW;
case LOCALE_IFIRSTDAYOFWEEK: return iFirstDayOfWeekW;
case LOCALE_IFIRSTWEEKOFYEAR: return iFirstWeekOfYearW;
case LOCALE_ILZERO: return iLZeroW;
case LOCALE_IMEASURE: return iMeasureW;
case LOCALE_INEGCURR: return iNegCurrW;
case LOCALE_INEGNUMBER: return iNegNumberW;
case LOCALE_IPAPERSIZE: return iPaperSizeW;
case LOCALE_ITIME: return iTimeW;
case LOCALE_S1159: return s1159W;
case LOCALE_S2359: return s2359W;
case LOCALE_SCURRENCY: return sCurrencyW;
case LOCALE_SDATE: return sDateW;
case LOCALE_SDECIMAL: return sDecimalW;
case LOCALE_SGROUPING: return sGroupingW;
case LOCALE_SLIST: return sListW;
case LOCALE_SLONGDATE: return sLongDateW;
case LOCALE_SMONDECIMALSEP: return sMonDecimalSepW;
case LOCALE_SMONGROUPING: return sMonGroupingW;
case LOCALE_SMONTHOUSANDSEP: return sMonThousandSepW;
case LOCALE_SNEGATIVESIGN: return sNegativeSignW;
case LOCALE_SPOSITIVESIGN: return sPositiveSignW;
case LOCALE_SSHORTDATE: return sShortDateW;
case LOCALE_STHOUSAND: return sThousandW;
case LOCALE_STIME: return sTimeW;
case LOCALE_STIMEFORMAT: return sTimeFormatW;
case LOCALE_SYEARMONTH: return sYearMonthW;
/* The following are not listed under MSDN as supported,
* but seem to be used and also stored in the registry.
*/
case LOCALE_ICOUNTRY: return iCountryW;
case LOCALE_IDATE: return iDateW;
case LOCALE_ILDATE: return iLDateW;
case LOCALE_ITLZERO: return iTLZeroW;
case LOCALE_SCOUNTRY: return sCountryW;
case LOCALE_SLANGUAGE: return sLanguageW;
}
return NULL;
}
HKEY RosCreateRegistryKey(void)
{
static const WCHAR intlW[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
OBJECT_ATTRIBUTES objAttr;
UNICODE_STRING nameW;
HKEY 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, intlW );
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;
}
/*
* @unimplemented
* @implemented
*/
int
STDCALL
GetLocaleInfoW (
LCID Locale,
LCID Locale,
LCTYPE LCType,
LPWSTR lpLCData,
int cchData
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
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 = GetModuleHandleA( "kernel32.dll" );
if (!(hRsrc = FindResourceExW( hModule, RT_STRINGW, (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 < (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] = 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;
}