reupload this
This commit is contained in:
472
locale.c
Normal file
472
locale.c
Normal file
@@ -0,0 +1,472 @@
|
||||
#include "progwrp.h"
|
||||
#include "export.h"
|
||||
#include "implementations.h"
|
||||
#include "strsafe.h"
|
||||
#include "locale.h"
|
||||
|
||||
BOOL WINAPI LimitedStrCmp(int StartIdx, int EndIdx, PCWSTR Str0, PCWSTR Str1)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < EndIdx - StartIdx; i++)
|
||||
{
|
||||
if(Str0[i + StartIdx] != Str1[i])
|
||||
return FALSE;
|
||||
|
||||
if(Str1[i] == '\0' && i < ((EndIdx - StartIdx) - 1))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int WINAPI Implementation_LCIDToLocaleName(
|
||||
LCID Locale,
|
||||
LPWSTR lpName,
|
||||
int cchName,
|
||||
DWORD dwFlags)
|
||||
/*
|
||||
The process of the non-neutral locales will be a little more complex.
|
||||
There are some that aren't even associated to a neutral locale.
|
||||
*/
|
||||
{
|
||||
int RequiredSize = 0;
|
||||
size_t Length;
|
||||
|
||||
if(!lpName && !cchName)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(dwFlags & ~(LOCALE_ALLOW_NEUTRAL_NAMES))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(Locale == LOCALE_INVARIANT || (Locale % 0x400) > LOCALE_NEUTRAL_LIMIT)
|
||||
{
|
||||
Locale = 0x409;
|
||||
}
|
||||
|
||||
if(Locale == LOCALE_SYSTEM_DEFAULT)
|
||||
{
|
||||
Locale = GetSystemDefaultLCID();
|
||||
}
|
||||
|
||||
if(Locale == LOCALE_USER_DEFAULT)
|
||||
{
|
||||
Locale = GetUserDefaultLCID();
|
||||
}
|
||||
|
||||
if ((Locale < LOCALE_NEUTRAL_LIMIT) && (dwFlags & LOCALE_ALLOW_NEUTRAL_NAMES))
|
||||
{
|
||||
while(NeutralLangIdTbl[Locale][RequiredSize] != L'\0')
|
||||
{
|
||||
++RequiredSize;
|
||||
}
|
||||
|
||||
++RequiredSize;
|
||||
|
||||
if(cchName && (cchName < RequiredSize))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(cchName && lpName)
|
||||
StringCchCopyW(lpName, cchName, NeutralLangIdTbl[Locale]);
|
||||
|
||||
return RequiredSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(NeutralLangIdTbl[Locale % 0x400][RequiredSize] != L'\0')
|
||||
{
|
||||
++RequiredSize;
|
||||
}
|
||||
|
||||
++RequiredSize;
|
||||
++RequiredSize;
|
||||
|
||||
if(StringCchLengthW(LocaleIdentifierTbl[Locale % 0x400][(Locale / 0x400) - 1], STRSAFE_MAX_CCH, &Length) == STRSAFE_E_INVALID_PARAMETER)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RequiredSize += Length;
|
||||
|
||||
if(cchName && (cchName < RequiredSize))
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(cchName && lpName)
|
||||
{
|
||||
StringCchCopyW(lpName, cchName, NeutralLangIdTbl[Locale % 0x400]);
|
||||
StringCchCatW(lpName, cchName, L"-");
|
||||
StringCchCatW(lpName, cchName, LocaleIdentifierTbl[Locale % 0x400][(Locale / 0x400) - 1]);
|
||||
}
|
||||
|
||||
return RequiredSize;
|
||||
}
|
||||
// First handle the special locale cases that aren't linked to a neutral locale,
|
||||
// then handle locales linked to a neutral locale.
|
||||
// Each LCID pertaining to a particular locale has an offset of 0x400 from the neutral locale.
|
||||
// e.g. en is 0x9, en-US is 0x409, en-GB is 0x809... ending with 0x3009 for en-ZW (Zimbabwe).
|
||||
// So all we need to do is build a table for each locale, and derive an index from (LCID / 0x400 - 1) to get the full locale name.
|
||||
}
|
||||
|
||||
LCID WINAPI Implementation_LocaleNameToLCID(
|
||||
LPCWSTR lpName,
|
||||
DWORD dwFlags
|
||||
)
|
||||
/*
|
||||
First checks the neutral portion of the locale, which is either two or three characters long.
|
||||
If it matches an entry in the table, (and it is not a neutral locale outright), then compare
|
||||
locations.
|
||||
*/
|
||||
{
|
||||
int NeutralLocaleLen = 0, NeutralLocaleIdx, FullLocaleIdx = 0, LocaleLen;
|
||||
if(dwFlags & ~(LOCALE_ALLOW_NEUTRAL_NAMES) || !lpName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
if(lpName == LOCALE_NAME_SYSTEM_DEFAULT)
|
||||
{
|
||||
return GetSystemDefaultLCID();
|
||||
}
|
||||
*/
|
||||
if(lpName[0] == L' ' && lpName[1] == L'\0')
|
||||
{
|
||||
return 0x409;
|
||||
}
|
||||
|
||||
if(lpName == LOCALE_NAME_USER_DEFAULT)
|
||||
{
|
||||
return GetUserDefaultLCID();
|
||||
}
|
||||
|
||||
while(lpName[NeutralLocaleLen] != L'-')
|
||||
{
|
||||
++NeutralLocaleLen;
|
||||
|
||||
if(lpName[NeutralLocaleLen] == L'\0')
|
||||
{
|
||||
if(dwFlags & LOCALE_ALLOW_NEUTRAL_NAMES)
|
||||
break;
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(NeutralLocaleIdx = 0; NeutralLocaleIdx < LOCALE_NEUTRAL_LIMIT; NeutralLocaleIdx++)
|
||||
{
|
||||
if(LimitedStrCmp(0, NeutralLocaleLen, lpName, NeutralLangIdTbl[NeutralLocaleIdx]))
|
||||
break;
|
||||
}
|
||||
|
||||
if(NeutralLocaleIdx == LOCALE_NEUTRAL_LIMIT)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
else if(dwFlags & LOCALE_ALLOW_NEUTRAL_NAMES)
|
||||
return NeutralLocaleIdx - 1;
|
||||
|
||||
LocaleLen = NeutralLocaleLen + 1;
|
||||
|
||||
while(lpName[LocaleLen] != L'\0')
|
||||
{
|
||||
++LocaleLen;
|
||||
}
|
||||
|
||||
while(LocaleIdentifierTbl[NeutralLocaleIdx - 1][FullLocaleIdx][0] != L'\0')
|
||||
{
|
||||
if(LimitedStrCmp(NeutralLocaleLen + 1, LocaleLen, lpName, LocaleIdentifierTbl[NeutralLocaleIdx - 1][FullLocaleIdx]))
|
||||
{
|
||||
return ((FullLocaleIdx + 1) * 0x400) + (NeutralLocaleIdx - 1);
|
||||
}
|
||||
|
||||
++FullLocaleIdx;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WINAPI Implementation_ResolveLocaleName(
|
||||
LPCWSTR lpNameToResolve,
|
||||
LPWSTR lpLocaleName,
|
||||
int cchLocaleName
|
||||
)
|
||||
/*
|
||||
This will be part and parcel of my new locale API.
|
||||
|
||||
The real implementation of this function was criticized for poor
|
||||
results at first, so I'll outline what one can expect.
|
||||
|
||||
If lpNameToResolve's language label does not match any known neutral locale,
|
||||
return the user locale.
|
||||
|
||||
If lpNameToResolve's language label matches a neutral locale, but there is
|
||||
no other matching information, return the user locale if it has the same neutral
|
||||
locale or return the "base locale" for the neutral locale (i.e. en-US for "en-RU"
|
||||
or "en-BLAHBLAHBLAH").
|
||||
|
||||
If there is a valid region identifier at the end of lpNameToResolve (between the last
|
||||
'-' and null character), in addition to a neutral locale that also has a valid entry
|
||||
for the region, return the "lan-reg" form.
|
||||
*/
|
||||
{
|
||||
if(lpLocaleName && lpNameToResolve)
|
||||
{
|
||||
StringCchCopyW(lpLocaleName, cchLocaleName, lpNameToResolve);
|
||||
return cchLocaleName;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL WINAPI Implementation_EnumSystemLocalesEx(
|
||||
LOCALE_ENUMPROCEX lpLocaleEnumProcEx,
|
||||
DWORD dwFlags,
|
||||
LPARAM lParam,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int WINAPI Implementation_GetCurrencyFormatEx(
|
||||
LPCWSTR lpLocaleName,
|
||||
DWORD dwFlags,
|
||||
LPCWSTR lpValue,
|
||||
const CURRENCYFMTW *lpFormat,
|
||||
LPWSTR lpCurrencyStr,
|
||||
int cchCurrency
|
||||
)
|
||||
{
|
||||
return GetCurrencyFormatW(Implementation_LocaleNameToLCID(lpLocaleName, 0), dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency);
|
||||
}
|
||||
|
||||
int WINAPI Implementation_GetDateFormatEx(
|
||||
LPCWSTR lpLocaleName,
|
||||
DWORD dwFlags,
|
||||
const SYSTEMTIME *lpDate,
|
||||
LPCWSTR lpFormat,
|
||||
LPWSTR lpDateStr,
|
||||
int cchDate,
|
||||
LPCWSTR lpCalendar
|
||||
)
|
||||
{
|
||||
return GetDateFormatW(Implementation_LocaleNameToLCID(lpLocaleName, 0), dwFlags, lpDate, lpFormat, lpDateStr, cchDate);
|
||||
}
|
||||
|
||||
DWORD WINAPI Implementation_GetDynamicTimeZoneInformation(
|
||||
PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation
|
||||
)
|
||||
{
|
||||
DWORD Result;
|
||||
TIME_ZONE_INFORMATION tzif;
|
||||
|
||||
if(!pTimeZoneInformation)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return TIME_ZONE_ID_INVALID;
|
||||
}
|
||||
|
||||
|
||||
Result = GetTimeZoneInformation(pTimeZoneInformation);
|
||||
|
||||
pTimeZoneInformation->TimeZoneKeyName[0] = '\0';
|
||||
pTimeZoneInformation->DynamicDaylightTimeDisabled = FALSE;
|
||||
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
int WINAPI Implementation_GetTimeFormatEx(
|
||||
LPCWSTR lpLocaleName,
|
||||
DWORD dwFlags,
|
||||
const SYSTEMTIME *lpTime,
|
||||
LPCWSTR lpFormat,
|
||||
LPWSTR lpTimeStr,
|
||||
int cchTime
|
||||
)
|
||||
{
|
||||
return GetTimeFormatW(Implementation_LocaleNameToLCID(lpLocaleName, 0), dwFlags, lpTime, lpFormat, lpTimeStr, cchTime);
|
||||
}
|
||||
|
||||
int WINAPI Implementation_GetLocaleInfoEx(
|
||||
LPCWSTR lpLocaleName,
|
||||
LCTYPE LCType,
|
||||
LPWSTR lpLCData,
|
||||
int cchData
|
||||
)
|
||||
{
|
||||
return GetLocaleInfoW(Implementation_LocaleNameToLCID(lpLocaleName, 0), LCType, lpLCData, cchData);
|
||||
}
|
||||
|
||||
int WINAPI Implementation_GetNumberFormatEx(
|
||||
LPCWSTR lpLocaleName,
|
||||
DWORD dwFlags,
|
||||
LPCWSTR lpValue,
|
||||
const NUMBERFMTW *lpFormat,
|
||||
LPWSTR lpNumberStr,
|
||||
int cchNumber
|
||||
)
|
||||
{
|
||||
return GetNumberFormatW(Implementation_LocaleNameToLCID(lpLocaleName, 0), dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber);
|
||||
}
|
||||
|
||||
int WINAPI Implementation_GetUserDefaultLocaleName(
|
||||
LPWSTR lpLocaleName,
|
||||
int cchLocaleName
|
||||
)
|
||||
{
|
||||
return Implementation_LCIDToLocaleName(GetUserDefaultLCID(), lpLocaleName, cchLocaleName, 0);
|
||||
}
|
||||
|
||||
#define THREAD_LOCALE 1
|
||||
#define USER_LOCALE 2
|
||||
#define SYSTEM_LOCALE 4
|
||||
|
||||
BOOL WINAPI Implementation_GetThreadPreferredUILanguages(
|
||||
DWORD dwFlags,
|
||||
PULONG pulNumLanguages,
|
||||
PZZWSTR pwszLanguagesBuffer,
|
||||
PULONG pcchLanguagesBuffer
|
||||
)
|
||||
/*
|
||||
Objective: get the "thread locale" first. Offer the user locale second, and the system locale third.
|
||||
*/
|
||||
{
|
||||
LCID ThreadLocale;
|
||||
LCID UserLocale;
|
||||
LCID SystemLocale;
|
||||
int i;
|
||||
WCHAR szLocaleName [45];
|
||||
int szLocaleName_lens [3] = {0, 0, 0};
|
||||
|
||||
if(!pulNumLanguages || !pcchLanguagesBuffer)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pulNumLanguages = 3;
|
||||
|
||||
ThreadLocale = GetThreadLocale();
|
||||
|
||||
UserLocale = GetUserDefaultLCID();
|
||||
|
||||
SystemLocale = GetSystemDefaultLCID();
|
||||
|
||||
if(dwFlags & MUI_LANGUAGE_ID)
|
||||
{
|
||||
*pcchLanguagesBuffer = 10;
|
||||
|
||||
if(pwszLanguagesBuffer)
|
||||
{
|
||||
pwszLanguagesBuffer[0] = HIWORD(ThreadLocale);
|
||||
pwszLanguagesBuffer[1] = LOWORD(ThreadLocale);
|
||||
pwszLanguagesBuffer[2] = L'\0';
|
||||
pwszLanguagesBuffer[3] = HIWORD(UserLocale);
|
||||
pwszLanguagesBuffer[4] = LOWORD(UserLocale);
|
||||
pwszLanguagesBuffer[5] = L'\0';
|
||||
pwszLanguagesBuffer[6] = HIWORD(SystemLocale);
|
||||
pwszLanguagesBuffer[7] = LOWORD(SystemLocale);
|
||||
pwszLanguagesBuffer[8] = L'\0';
|
||||
pwszLanguagesBuffer[9] = L'\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
szLocaleName_lens[0] = Implementation_LCIDToLocaleName(ThreadLocale, szLocaleName, 45, 0);
|
||||
|
||||
if(pwszLanguagesBuffer)
|
||||
{
|
||||
StringCchCopyW(pwszLanguagesBuffer, *pcchLanguagesBuffer, szLocaleName);
|
||||
StringCchCatW(pwszLanguagesBuffer, *pcchLanguagesBuffer, L";");
|
||||
}
|
||||
|
||||
szLocaleName_lens[1] = Implementation_LCIDToLocaleName(UserLocale, szLocaleName, 45, 0);
|
||||
|
||||
if(pwszLanguagesBuffer)
|
||||
{
|
||||
StringCchCatW(pwszLanguagesBuffer, *pcchLanguagesBuffer, szLocaleName);
|
||||
StringCchCatW(pwszLanguagesBuffer, *pcchLanguagesBuffer, L";");
|
||||
}
|
||||
|
||||
szLocaleName_lens[2] = Implementation_LCIDToLocaleName(SystemLocale, szLocaleName, 45, 0);
|
||||
|
||||
if(pwszLanguagesBuffer)
|
||||
{
|
||||
StringCchCatW(pwszLanguagesBuffer, *pcchLanguagesBuffer, szLocaleName);
|
||||
StringCchCatW(pwszLanguagesBuffer, *pcchLanguagesBuffer, L";");
|
||||
StringCchCatW(pwszLanguagesBuffer, *pcchLanguagesBuffer, L"\0");
|
||||
for(i = 0; i < *pcchLanguagesBuffer; i++)
|
||||
{
|
||||
if(pwszLanguagesBuffer[i] == L';')
|
||||
pwszLanguagesBuffer[i] = 0;//L'\0';
|
||||
}
|
||||
}
|
||||
|
||||
*pcchLanguagesBuffer = (szLocaleName_lens[0] + szLocaleName_lens[1] + szLocaleName_lens[2] + 1);
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int WINAPI Implementation_GetGeoInfoW(
|
||||
GEOID Location,
|
||||
GEOTYPE GeoType,
|
||||
LPWSTR lpGeoData,
|
||||
int cchData,
|
||||
LANGID LangId
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GEOID WINAPI Implementation_GetUserGeoID(
|
||||
GEOCLASS GeoClass
|
||||
)
|
||||
{
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
BOOL WINAPI Implementation_TzSpecificLocalTimeToSystemTime(
|
||||
const TIME_ZONE_INFORMATION *lpTimeZoneInformation,
|
||||
const SYSTEMTIME *lpLocalTime,
|
||||
LPSYSTEMTIME lpUniversalTime
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int WINAPI Implementation_LCMapStringEx(
|
||||
LPCWSTR lpLocaleName,
|
||||
DWORD dwMapFlags,
|
||||
LPCWSTR lpSrcStr,
|
||||
int cchSrc,
|
||||
LPWSTR lpDestStr,
|
||||
int cchDest,
|
||||
LPNLSVERSIONINFO lpVersionInformation,
|
||||
LPVOID lpReserved,
|
||||
LPARAM sortHandle
|
||||
)
|
||||
{
|
||||
return LCMapStringW(Implementation_LocaleNameToLCID(lpLocaleName, 0), dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest);
|
||||
}
|
||||
Reference in New Issue
Block a user