Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2596 lines
73 KiB

/*++
Copyright (c) 1991-2000, Microsoft Corporation All rights reserved.
Module Name:
ansi.c
Abstract:
This file contains the ANSI versions of the NLS API functions.
APIs found in this file:
CompareStringA
LCMapStringA
GetLocaleInfoA
SetLocaleInfoA
GetCalendarInfoA
SetCalendarInfoA
GetTimeFormatA
GetDateFormatA
GetNumberFormatA
GetCurrencyFormatA
EnumCalendarInfoA
EnumCalendarInfoExA
EnumTimeFormatsA
EnumDateFormatsA
EnumDateFormatsExA
GetStringTypeExA
GetStringTypeA
FoldStringA
EnumSystemLanguageGroupsA
EnumLanguageGroupLocalesA
EnumUILanguagesA
EnumSystemLocalesA
EnumSystemCodePagesA
GetCPInfoExA
GetGeoInfoA
Revision History:
11-10-93 JulieB Created.
07-03-00 lguindon Began GEO API port
--*/
//
// Include Files.
//
#include "nls.h"
//
// Forward Declarations.
//
PCP_HASH
NlsGetACPFromLocale(
LCID Locale,
DWORD dwFlags);
BOOL
NlsAnsiToUnicode(
PCP_HASH pHashN,
DWORD dwFlags,
LPCSTR pAnsiBuffer,
int AnsiLength,
LPWSTR *ppUnicodeBuffer,
int *pUnicodeLength);
int
NlsUnicodeToAnsi(
PCP_HASH pHashN,
LPCWSTR pUnicodeBuffer,
int UnicodeLength,
LPSTR pAnsiBuffer,
int AnsiLength);
BOOL
NlsEnumUnicodeToAnsi(
PCP_HASH pHashN,
LPCWSTR pUnicodeBuffer,
LPSTR *ppAnsiBuffer);
//-------------------------------------------------------------------------//
// API ROUTINES //
//-------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////
//
// CompareStringA
//
// Compares two wide character strings of the same locale according to the
// supplied locale handle.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI CompareStringA(
LCID Locale,
DWORD dwCmpFlags,
LPCSTR lpString1,
int cchCount1,
LPCSTR lpString2,
int cchCount2)
{
PCP_HASH pHashN; // ptr to CP hash node
WCHAR pSTmp1[MAX_STRING_LEN]; // tmp Unicode buffer (string 1)
WCHAR pSTmp2[MAX_STRING_LEN]; // tmp Unicode buffer (string 2)
LPWSTR pUnicode1; // ptr to unicode string 1
LPWSTR pUnicode2; // ptr to unicode string 2
int UnicodeLength1; // length of Unicode string 1
int UnicodeLength2; // length of Unicode string 2
int ResultLen; // result length
BOOL fUseNegCounts = (cchCount1 < 0 && cchCount2 < 0); // flag to use negative counts
//
// Invalid Parameter Check:
// - Get the code page hash node for the given locale.
// - either string is null
//
pHashN = NlsGetACPFromLocale(Locale, dwCmpFlags);
if ((pHashN == NULL) ||
(lpString1 == NULL) || (lpString2 == NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Invalid Flags Check:
// - invalid flags
//
if (dwCmpFlags & CS_INVALID_FLAG)
{
SetLastError(ERROR_INVALID_FLAGS);
return (0);
}
//
// Convert Ansi string 1 to Unicode.
//
pUnicode1 = pSTmp1;
if (!NlsAnsiToUnicode( pHashN,
0,
lpString1,
cchCount1,
&pUnicode1,
&UnicodeLength1 ))
{
return (0);
}
//
// Convert Ansi string 2 to Unicode.
//
pUnicode2 = pSTmp2;
if (!NlsAnsiToUnicode( pHashN,
0,
lpString2,
cchCount2,
&pUnicode2,
&UnicodeLength2 ))
{
NLS_FREE_TMP_BUFFER(pUnicode1, pSTmp1);
return (0);
}
//
// Call the W version of the API.
//
ResultLen = CompareStringW( Locale,
dwCmpFlags,
pUnicode1,
(fUseNegCounts) ? -1 : UnicodeLength1,
pUnicode2,
(fUseNegCounts) ? -1 : UnicodeLength2 );
//
// Free the allocated source buffers (if they were allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode1, pSTmp1);
NLS_FREE_TMP_BUFFER(pUnicode2, pSTmp2);
//
// Return the result of the call to CompareStringW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// LCMapStringA
//
// Maps one wide character string to another performing the specified
// translation. This mapping routine only takes flags that are locale
// dependent.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI LCMapStringA(
LCID Locale,
DWORD dwMapFlags,
LPCSTR lpSrcStr,
int cchSrc,
LPSTR lpDestStr,
int cchDest)
{
PCP_HASH pHashN; // ptr to CP hash node
LPWSTR pUnicode; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, dwMapFlags);
//
// Invalid Parameter Check:
// - valid code page
// - destination buffer size is negative
// - length of dest string is NOT zero AND dest string is NULL
// - same buffer - src = destination
// if not UPPER or LOWER or
// UPPER or LOWER used with Japanese flags
//
if ((pHashN == NULL) ||
(cchDest < 0) ||
((cchDest != 0) && (lpDestStr == NULL)) ||
((lpSrcStr == lpDestStr) &&
((!(dwMapFlags & (LCMAP_UPPERCASE | LCMAP_LOWERCASE))) ||
(dwMapFlags & (LCMAP_HIRAGANA | LCMAP_KATAKANA |
LCMAP_HALFWIDTH | LCMAP_FULLWIDTH)))))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Convert Ansi string to Unicode.
//
pUnicode = pSTmp;
if (!NlsAnsiToUnicode( pHashN,
0,
lpSrcStr,
cchSrc,
&pUnicode,
&UnicodeLength ))
{
return (0);
}
//
// Special case the sortkey flag, since the Unicode buffer does
// NOT need to be converted back to Ansi.
//
if (dwMapFlags & LCMAP_SORTKEY)
{
//
// Call the W version of the API.
//
ResultLen = LCMapStringW( Locale,
dwMapFlags,
pUnicode,
UnicodeLength,
(LPWSTR)lpDestStr,
cchDest );
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Return the result of LCMapStringW.
//
return (ResultLen);
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = LCMapStringW( Locale,
dwMapFlags,
pUnicode,
UnicodeLength,
pBuf,
ResultLen );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = LCMapStringW( Locale,
dwMapFlags,
pUnicode,
UnicodeLength,
NULL,
0 ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
}
}
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
ResultLen = NlsUnicodeToAnsi( pHashN,
pBuf,
ResultLen,
lpDestStr,
cchDest );
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to LCMapStringW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// GetLocaleInfoA
//
// Returns one of the various pieces of information about a particular
// locale by querying the configuration registry. This call also indicates
// how much memory is necessary to contain the desired information.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI GetLocaleInfoA(
LCID Locale,
LCTYPE LCType,
LPSTR lpLCData,
int cchData)
{
PCP_HASH pHashN; // ptr to CP hash node
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
//
// Invalid Parameter Check:
// - count is negative
// - NULL data pointer AND count is not zero
//
if ((cchData < 0) ||
(lpLCData == NULL) && (cchData != 0))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = GetLocaleInfoW( Locale,
LCType,
pBuf,
ResultLen );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = GetLocaleInfoW( Locale,
LCType,
NULL,
0 ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
}
}
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
if ((LCType & LOCALE_RETURN_NUMBER) ||
(NLS_GET_LCTYPE_VALUE(LCType) == LOCALE_FONTSIGNATURE))
{
//
// For the font signature and number value, the result length
// will actually be twice the amount of the wide char version.
//
ResultLen *= 2;
//
// Make sure we can use the buffer.
//
if (cchData)
{
//
// Make sure the buffer is large enough.
//
if (cchData < ResultLen)
{
//
// The buffer is too small.
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return (0);
}
//
// Convert the font signature or number value to its byte
// form. Since it's already byte reversed, just do a move
// memory.
//
RtlMoveMemory(lpLCData, pBuf, ResultLen);
}
}
else
{
//
// If this is LCTYPE == LOCALE_SLANGUAGE, then use the
// CP_ACP of the system. This is what Win9x has done,
// and we need to be compatible with this.
//
if (NLS_GET_LCTYPE_VALUE(LCType) == LOCALE_SLANGUAGE)
{
LCType |= LOCALE_USE_CP_ACP;
}
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, LCType);
if (pHashN == NULL)
{
ResultLen = 0;
}
else
{
//
// Convert to Ansi.
//
ResultLen = NlsUnicodeToAnsi( pHashN,
pBuf,
ResultLen,
lpLCData,
cchData );
}
}
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to GetLocaleInfoW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// SetLocaleInfoA
//
// Sets one of the various pieces of information about a particular
// locale by making an entry in the user's portion of the configuration
// registry. This will only affect the user override portion of the locale
// settings. The system defaults will never be reset.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI SetLocaleInfoA(
LCID Locale,
LCTYPE LCType,
LPCSTR lpLCData)
{
PCP_HASH pHashN; // ptr to CP hash node
LPWSTR pUnicode; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
BOOL Result; // result
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, LCType);
if (pHashN == NULL)
{
return (0);
}
//
// Convert Ansi string to Unicode.
//
pUnicode = pSTmp;
if (!NlsAnsiToUnicode( pHashN,
0,
lpLCData,
-1,
&pUnicode,
&UnicodeLength ))
{
return (FALSE);
}
//
// Call the W version of the API.
//
Result = SetLocaleInfoW( Locale,
LCType,
pUnicode );
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Return the result of the call to SetLocaleInfoW.
//
return (Result);
}
////////////////////////////////////////////////////////////////////////////
//
// GetCalendarInfoA
//
// Returns one of the various pieces of information about a particular
// calendar by querying the configuration registry. This call also indicates
// how much memory is necessary to contain the desired information.
//
// 12-17-97 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI GetCalendarInfoA(
LCID Locale,
CALID Calendar,
CALTYPE CalType,
LPSTR lpCalData,
int cchData,
LPDWORD lpValue)
{
PCP_HASH pHashN; // ptr to CP hash node
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
//
// Invalid Parameter Check:
// - count is negative
// - NULL data pointer AND count is not zero
//
if ((cchData < 0) ||
((lpCalData == NULL) && (cchData != 0)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Need to check the parameters based on the CAL_RETURN_NUMBER
// CalType.
//
if (CalType & CAL_RETURN_NUMBER)
{
if ((lpCalData != NULL) || (cchData != 0) || (lpValue == NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
}
else
{
if ((lpValue != NULL) ||
(cchData < 0) ||
((lpCalData == NULL) && (cchData != 0)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = GetCalendarInfoW( Locale,
Calendar,
CalType,
lpCalData ? pBuf : NULL,
lpCalData ? ResultLen : 0,
lpValue );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) ||
(lpValue != NULL) ||
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = GetCalendarInfoW( Locale,
Calendar,
CalType,
NULL,
0,
NULL ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
}
}
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
if (CalType & CAL_RETURN_NUMBER)
{
//
// For the number value, the result length will actually be
// twice the amount of the wide char version.
//
ResultLen *= 2;
//
// There is nothing else to do in this case, since the value
// has already been stored in lpValue.
//
}
else
{
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, CalType);
if (pHashN == NULL)
{
ResultLen = 0;
}
else
{
//
// Convert to Ansi.
//
ResultLen = NlsUnicodeToAnsi( pHashN,
pBuf,
ResultLen,
lpCalData,
cchData );
}
}
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to GetCalendarInfoW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// SetCalendarInfoA
//
// Sets one of the various pieces of information about a particular
// calendar by making an entry in the user's portion of the configuration
// registry. This will only affect the user override portion of the
// calendar settings. The system defaults will never be reset.
//
// 12-17-97 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI SetCalendarInfoA(
LCID Locale,
CALID Calendar,
CALTYPE CalType,
LPCSTR lpCalData)
{
PCP_HASH pHashN; // ptr to CP hash node
LPWSTR pUnicode; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
BOOL Result; // result
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, CalType);
if (pHashN == NULL)
{
return (0);
}
//
// Convert Ansi string to Unicode.
//
pUnicode = pSTmp;
if (!NlsAnsiToUnicode( pHashN,
0,
lpCalData,
-1,
&pUnicode,
&UnicodeLength ))
{
return (FALSE);
}
//
// Call the W version of the API.
//
Result = SetCalendarInfoW( Locale,
Calendar,
CalType,
pUnicode );
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Return the result of the call to SetCalendarInfoW.
//
return (Result);
}
////////////////////////////////////////////////////////////////////////////
//
// GetTimeFormatA
//
// Returns a properly formatted time string for the given locale. It uses
// either the system time or the specified time. This call also indicates
// how much memory is necessary to contain the desired information.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI GetTimeFormatA(
LCID Locale,
DWORD dwFlags,
CONST SYSTEMTIME *lpTime,
LPCSTR lpFormat,
LPSTR lpTimeStr,
int cchTime)
{
PCP_HASH pHashN; // ptr to CP hash node
LPWSTR pUnicode; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, dwFlags);
//
// Invalid Parameter Check:
// - valid code page
// - count is negative
// - NULL data pointer AND count is not zero
//
if ((pHashN == NULL) ||
(cchTime < 0) ||
((lpTimeStr == NULL) && (cchTime != 0)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Convert Ansi string to Unicode.
//
pUnicode = pSTmp;
if (!NlsAnsiToUnicode( pHashN,
0,
lpFormat,
-1,
&pUnicode,
&UnicodeLength ))
{
return (0);
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = GetTimeFormatW( Locale,
dwFlags,
lpTime,
pUnicode,
pBuf,
ResultLen );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = GetTimeFormatW( Locale,
dwFlags,
lpTime,
pUnicode,
NULL,
0 ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
}
}
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
ResultLen = NlsUnicodeToAnsi( pHashN,
pBuf,
ResultLen,
lpTimeStr,
cchTime );
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to GetTimeFormatW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// GetDateFormatA
//
// Returns a properly formatted date string for the given locale. It uses
// either the system date or the specified date. The user may specify
// the short date format, the long date format, or the year/month format.
// This call also indicates how much memory is necessary to contain the
// desired information.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI GetDateFormatA(
LCID Locale,
DWORD dwFlags,
CONST SYSTEMTIME *lpDate,
LPCSTR lpFormat,
LPSTR lpDateStr,
int cchDate)
{
PCP_HASH pHashN; // ptr to CP hash node
LPWSTR pUnicode; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, dwFlags);
//
// Invalid Parameter Check:
// - valid code page
// - count is negative
// - NULL data pointer AND count is not zero
//
if ((pHashN == NULL) ||
(cchDate < 0) ||
((lpDateStr == NULL) && (cchDate != 0)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Invalid Flags Check:
// - flags other than valid ones
// - more than one of either ltr reading or rtl reading
// - using LTR or RTL flag and not using cp 1255 or 1256
//
if ((dwFlags & GDF_INVALID_FLAG) ||
(MORE_THAN_ONE(dwFlags, GDF_SINGLE_FLAG)) ||
((dwFlags & (DATE_LTRREADING | DATE_RTLREADING)) &&
(pHashN->CodePage != 1255) && (pHashN->CodePage != 1256)))
{
SetLastError(ERROR_INVALID_FLAGS);
return (0);
}
//
// Convert Ansi string to Unicode.
//
pUnicode = pSTmp;
if (!NlsAnsiToUnicode( pHashN,
0,
lpFormat,
-1,
&pUnicode,
&UnicodeLength ))
{
return (0);
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = GetDateFormatW( Locale,
dwFlags,
lpDate,
pUnicode,
pBuf,
ResultLen );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = GetDateFormatW( Locale,
dwFlags,
lpDate,
pUnicode,
NULL,
0 ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
}
}
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
ResultLen = NlsUnicodeToAnsi( pHashN,
pBuf,
ResultLen,
lpDateStr,
cchDate );
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to GetDateFormatW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// GetNumberFormatA
//
// Returns a properly formatted number string for the given locale.
// This call also indicates how much memory is necessary to contain
// the desired information.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI GetNumberFormatA(
LCID Locale,
DWORD dwFlags,
LPCSTR lpValue,
CONST NUMBERFMTA *lpFormat,
LPSTR lpNumberStr,
int cchNumber)
{
PCP_HASH pHashN; // ptr to CP hash node
LPWSTR pValueU; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
NUMBERFMTW FormatU; // Unicode number format
LPNUMBERFMTW pFormatU = NULL; // ptr to Unicode number format
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, dwFlags);
//
// Invalid Parameter Check:
// - valid code page
// - count is negative
// - NULL data pointer AND count is not zero
// - ptrs to string buffers same
//
if ((pHashN == NULL) ||
(cchNumber < 0) ||
((lpNumberStr == NULL) && (cchNumber != 0)) ||
(lpValue == lpNumberStr))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Convert Ansi string to Unicode.
//
pValueU = pSTmp;
if (!NlsAnsiToUnicode( pHashN,
0,
lpValue,
-1,
&pValueU,
&UnicodeLength ))
{
return (0);
}
//
// If the format structure exists, convert the strings
// in the structure.
//
if (lpFormat)
{
//
// Copy Ansi structure to Unicode structure.
//
FormatU = *(NUMBERFMTW *)lpFormat;
FormatU.lpDecimalSep = NULL;
FormatU.lpThousandSep = NULL;
//
// Convert Ansi strings in structure to Unicode strings.
//
if (!NlsAnsiToUnicode( pHashN,
0,
lpFormat->lpDecimalSep,
-1,
&(FormatU.lpDecimalSep),
&UnicodeLength ) ||
!NlsAnsiToUnicode( pHashN,
0,
lpFormat->lpThousandSep,
-1,
&(FormatU.lpThousandSep),
&UnicodeLength ))
{
NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
NLS_FREE_MEM(FormatU.lpDecimalSep);
return (0);
}
pFormatU = &FormatU;
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = GetNumberFormatW( Locale,
dwFlags,
pValueU,
pFormatU,
pBuf,
ResultLen );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = GetNumberFormatW( Locale,
dwFlags,
pValueU,
pFormatU,
NULL,
0 ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
ResultLen = 0;
break;
}
}
}
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
if (lpFormat)
{
NLS_FREE_MEM(FormatU.lpDecimalSep);
NLS_FREE_MEM(FormatU.lpThousandSep);
}
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
ResultLen = NlsUnicodeToAnsi( pHashN,
pBuf,
ResultLen,
lpNumberStr,
cchNumber );
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to GetNumberFormatW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// GetCurrencyFormatA
//
// Returns a properly formatted currency string for the given locale.
// This call also indicates how much memory is necessary to contain
// the desired information.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI GetCurrencyFormatA(
LCID Locale,
DWORD dwFlags,
LPCSTR lpValue,
CONST CURRENCYFMTA *lpFormat,
LPSTR lpCurrencyStr,
int cchCurrency)
{
PCP_HASH pHashN; // ptr to CP hash node
LPWSTR pValueU; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
CURRENCYFMTW FormatU; // Unicode currency format
LPCURRENCYFMTW pFormatU = NULL; // ptr to Unicode currency format
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, dwFlags);
//
// Invalid Parameter Check:
// - count is negative
// - NULL data pointer AND count is not zero
// - ptrs to string buffers same
//
if ((pHashN == NULL) ||
(cchCurrency < 0) ||
((lpCurrencyStr == NULL) && (cchCurrency != 0)) ||
(lpValue == lpCurrencyStr))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Convert Ansi string to Unicode.
//
pValueU = pSTmp;
if (!NlsAnsiToUnicode( pHashN,
0,
lpValue,
-1,
&pValueU,
&UnicodeLength ))
{
return (0);
}
//
// If the format structure exists, convert the strings
// in the structure.
//
if (lpFormat)
{
//
// Copy Ansi structure to Unicode structure.
//
FormatU = *(CURRENCYFMTW *)lpFormat;
FormatU.lpDecimalSep = NULL;
FormatU.lpThousandSep = NULL;
FormatU.lpCurrencySymbol = NULL;
//
// Convert Ansi strings in structure to Unicode strings.
//
if (!NlsAnsiToUnicode( pHashN,
0,
lpFormat->lpDecimalSep,
-1,
&(FormatU.lpDecimalSep),
&UnicodeLength ) ||
!NlsAnsiToUnicode( pHashN,
0,
lpFormat->lpThousandSep,
-1,
&(FormatU.lpThousandSep),
&UnicodeLength ) ||
!NlsAnsiToUnicode( pHashN,
0,
lpFormat->lpCurrencySymbol,
-1,
&(FormatU.lpCurrencySymbol),
&UnicodeLength ))
{
NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
NLS_FREE_MEM(FormatU.lpDecimalSep);
NLS_FREE_MEM(FormatU.lpThousandSep);
return (0);
}
pFormatU = &FormatU;
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = GetCurrencyFormatW( Locale,
dwFlags,
pValueU,
pFormatU,
pBuf,
ResultLen );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = GetCurrencyFormatW( Locale,
dwFlags,
pValueU,
pFormatU,
NULL,
0 ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
ResultLen = 0;
break;
}
}
}
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
if (lpFormat)
{
NLS_FREE_MEM(FormatU.lpDecimalSep);
NLS_FREE_MEM(FormatU.lpThousandSep);
NLS_FREE_MEM(FormatU.lpCurrencySymbol);
}
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
ResultLen = NlsUnicodeToAnsi( pHashN,
pBuf,
ResultLen,
lpCurrencyStr,
cchCurrency );
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to GetCurrencyFormatW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// EnumCalendarInfoA
//
// Enumerates the specified calendar information that is available for the
// specified locale, based on the CalType parameter. It does so by
// passing the pointer to the string buffer containing the calendar info
// to an application-defined callback function. It continues until the
// last calendar info is found or the callback function returns FALSE.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumCalendarInfoA(
CALINFO_ENUMPROCA lpCalInfoEnumProc,
LCID Locale,
CALID Calendar,
CALTYPE CalType)
{
return (Internal_EnumCalendarInfo( (NLS_ENUMPROC)lpCalInfoEnumProc,
Locale,
Calendar,
CalType,
FALSE,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumCalendarInfoExA
//
// Enumerates the specified calendar information that is available for the
// specified locale, based on the CalType parameter. It does so by
// passing the pointer to the string buffer containing the calendar info
// and the calendar id to an application-defined callback function. It
// continues until the last calendar info is found or the callback function
// returns FALSE.
//
// 10-14-96 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumCalendarInfoExA(
CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx,
LCID Locale,
CALID Calendar,
CALTYPE CalType)
{
return (Internal_EnumCalendarInfo( (NLS_ENUMPROC)lpCalInfoEnumProcEx,
Locale,
Calendar,
CalType,
FALSE,
TRUE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumTimeFormatsA
//
// Enumerates the time formats that are available for the
// specified locale, based on the dwFlags parameter. It does so by
// passing the pointer to the string buffer containing the time format
// to an application-defined callback function. It continues until the
// last time format is found or the callback function returns FALSE.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumTimeFormatsA(
TIMEFMT_ENUMPROCA lpTimeFmtEnumProc,
LCID Locale,
DWORD dwFlags)
{
return (Internal_EnumTimeFormats( (NLS_ENUMPROC)lpTimeFmtEnumProc,
Locale,
dwFlags,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumDateFormatsA
//
// Enumerates the short date, long date, or year/month formats that are
// available for the specified locale, based on the dwFlags parameter.
// It does so by passing the pointer to the string buffer containing the
// date format to an application-defined callback function. It continues
// until the last date format is found or the callback function returns
// FALSE.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumDateFormatsA(
DATEFMT_ENUMPROCA lpDateFmtEnumProc,
LCID Locale,
DWORD dwFlags)
{
return (Internal_EnumDateFormats( (NLS_ENUMPROC)lpDateFmtEnumProc,
Locale,
dwFlags,
FALSE,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumDateFormatsExA
//
// Enumerates the short date, long date, or year/month formats that are
// available for the specified locale, based on the dwFlags parameter.
// It does so by passing the pointer to the string buffer containing the
// date format and the calendar id to an application-defined callback
// function. It continues until the last date format is found or the
// callback function returns FALSE.
//
// 10-14-96 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumDateFormatsExA(
DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx,
LCID Locale,
DWORD dwFlags)
{
return (Internal_EnumDateFormats( (NLS_ENUMPROC)lpDateFmtEnumProcEx,
Locale,
dwFlags,
FALSE,
TRUE ));
}
////////////////////////////////////////////////////////////////////////////
//
// GetStringTypeExA
//
// Returns character type information about a particular Ansi string.
//
// 01-18-94 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI GetStringTypeExA(
LCID Locale,
DWORD dwInfoType,
LPCSTR lpSrcStr,
int cchSrc,
LPWORD lpCharType)
{
return (GetStringTypeA( Locale,
dwInfoType,
lpSrcStr,
cchSrc,
lpCharType));
}
////////////////////////////////////////////////////////////////////////////
//
// GetStringTypeA
//
// Returns character type information about a particular Ansi string.
//
// NOTE: The number of parameters is different from GetStringTypeW.
// The 16-bit OLE product shipped this routine with the wrong
// parameters (ported from Chicago) and now we must support it.
//
// Use GetStringTypeEx to get the same set of parameters between
// the A and W version.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI GetStringTypeA(
LCID Locale,
DWORD dwInfoType,
LPCSTR lpSrcStr,
int cchSrc,
LPWORD lpCharType)
{
PCP_HASH pHashCP; // ptr to CP hash node
LPWSTR pUnicode; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
BOOL Result; // result
//
// Get the code page hash node for the given locale.
// This will also return an error if the locale id is invalid,
// so there is no need to check the locale id separately.
//
pHashCP = NlsGetACPFromLocale(Locale, 0);
//
// Invalid Parameter Check:
// - Validate LCID
// - valid code page
// - same buffer - src and destination
//
if ((pHashCP == NULL) ||
(lpSrcStr == (LPSTR)lpCharType))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Convert Ansi string to Unicode.
//
pUnicode = pSTmp;
if (!NlsAnsiToUnicode( pHashCP,
MB_INVALID_CHAR_CHECK,
lpSrcStr,
cchSrc,
&pUnicode,
&UnicodeLength ))
{
return (0);
}
//
// Call the W version of the API.
//
Result = GetStringTypeW( dwInfoType,
pUnicode,
UnicodeLength,
lpCharType );
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Return the result of the call to GetStringTypeW.
//
return (Result);
}
////////////////////////////////////////////////////////////////////////////
//
// FoldStringA
//
// Maps one wide character string to another performing the specified
// translation. This mapping routine only takes flags that are locale
// independent.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int WINAPI FoldStringA(
DWORD dwMapFlags,
LPCSTR lpSrcStr,
int cchSrc,
LPSTR lpDestStr,
int cchDest)
{
LPWSTR pUnicode; // ptr to unicode string
int UnicodeLength; // length of Unicode string
WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
LPWSTR pBuf; // ptr to destination buffer
int ResultLen; // result length
//
// Invalid Parameter Check:
// - dest buffer size is negative
// - length of dest string is NOT zero AND dest string is NULL
// - same buffer - src = destination
//
if ((cchDest < 0) ||
((cchDest != 0) && (lpDestStr == NULL)) ||
(lpSrcStr == lpDestStr))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
//
// Convert Ansi string to Unicode.
//
RtlZeroMemory(pSTmp, sizeof(pSTmp));
pUnicode = pSTmp;
if (!NlsAnsiToUnicode( gpACPHashN,
0,
lpSrcStr,
cchSrc,
&pUnicode,
&UnicodeLength ))
{
return (0);
}
//
// Call the W version of the API.
//
pBuf = pDTmp;
ResultLen = MAX_STRING_LEN;
while (1)
{
ResultLen = FoldStringW( dwMapFlags,
pUnicode,
UnicodeLength,
pBuf,
ResultLen );
//
// Make sure the static buffer was large enough.
//
if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
break;
}
//
// Get the size of the buffer needed for the mapping.
//
if (ResultLen = FoldStringW( dwMapFlags,
pUnicode,
UnicodeLength,
NULL,
0 ))
{
//
// Allocate a buffer of the appropriate size.
//
if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
{
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
SetLastError(ERROR_OUTOFMEMORY);
return (0);
}
}
}
//
// Free the allocated source buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
//
// Convert the destination Unicode buffer to the given Ansi buffer.
//
if (ResultLen > 0)
{
ResultLen = NlsUnicodeToAnsi( gpACPHashN,
pBuf,
ResultLen,
lpDestStr,
cchDest );
}
//
// Free the allocated destination buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
//
// Return the result of the call to FoldStringW.
//
return (ResultLen);
}
////////////////////////////////////////////////////////////////////////////
//
// EnumSystemLanguageGroupsA
//
// Enumerates the system language groups that are installed or supported,
// based on the dwFlags parameter. It does so by passing the pointer to
// the string buffer containing the language group id to an
// application-defined callback function. It continues until the last
// language group id is found or the callback function returns FALSE.
//
// 03-10-98 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumSystemLanguageGroupsA(
LANGUAGEGROUP_ENUMPROCA lpLanguageGroupEnumProc,
DWORD dwFlags,
LONG_PTR lParam)
{
return (Internal_EnumSystemLanguageGroups(
(NLS_ENUMPROC)lpLanguageGroupEnumProc,
dwFlags,
lParam,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumLanguageGroupLocalesA
//
// Enumerates the locales in a given language group. It does so by
// passing the appropriate information to an application-defined
// callback function. It continues until the last locale in the language
// group is found or the callback function returns FALSE.
//
// 03-10-98 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumLanguageGroupLocalesA(
LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc,
LGRPID LanguageGroup,
DWORD dwFlags,
LONG_PTR lParam)
{
return (Internal_EnumLanguageGroupLocales(
(NLS_ENUMPROC)lpLangGroupLocaleEnumProc,
LanguageGroup,
dwFlags,
lParam,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumUILanguagesA
//
// Enumerates the system UI languages that are installed. It does so by
// passing the pointer to the string buffer containing the UI language id
// to an application-defined callback function. It continues until the
// last UI language id is found or the callback function returns FALSE.
//
// 03-10-98 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumUILanguagesA(
UILANGUAGE_ENUMPROCA lpUILanguageEnumProc,
DWORD dwFlags,
LONG_PTR lParam)
{
return (Internal_EnumUILanguages( (NLS_ENUMPROC)lpUILanguageEnumProc,
dwFlags,
lParam,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumSystemLocalesA
//
// Enumerates the system locales that are installed or supported, based on
// the dwFlags parameter. It does so by passing the pointer to the string
// buffer containing the locale id to an application-defined callback
// function. It continues until the last locale id is found or the
// callback function returns FALSE.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumSystemLocalesA(
LOCALE_ENUMPROCA lpLocaleEnumProc,
DWORD dwFlags)
{
return (Internal_EnumSystemLocales( (NLS_ENUMPROC)lpLocaleEnumProc,
dwFlags,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// EnumSystemCodePagesA
//
// Enumerates the system code pages that are installed or supported, based on
// the dwFlags parameter. It does so by passing the pointer to the string
// buffer containing the code page id to an application-defined callback
// function. It continues until the last code page is found or the
// callback function returns FALSE.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI EnumSystemCodePagesA(
CODEPAGE_ENUMPROCA lpCodePageEnumProc,
DWORD dwFlags)
{
return (Internal_EnumSystemCodePages( (NLS_ENUMPROC)lpCodePageEnumProc,
dwFlags,
FALSE ));
}
////////////////////////////////////////////////////////////////////////////
//
// GetCPInfoExA
//
// Returns information about a given code page.
//
// 11-15-96 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI GetCPInfoExA(
UINT CodePage,
DWORD dwFlags,
LPCPINFOEXA lpCPInfoEx)
{
CPINFOEXW lpCPInfoExW;
BOOL rc;
//
// Invalid Parameter Check:
// - lpCPInfoEx is NULL
//
if (lpCPInfoEx == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return (FALSE);
}
//
// Call the W version of the API.
//
rc = GetCPInfoExW(CodePage, dwFlags, &lpCPInfoExW);
//
// Convert the code page name from Unicode to Ansi.
//
if (rc == TRUE)
{
if (!NlsUnicodeToAnsi( gpACPHashN,
lpCPInfoExW.CodePageName,
-1,
lpCPInfoEx->CodePageName,
MAX_PATH ))
{
return (FALSE);
}
}
//
// Copy the rest of the information from the Unicode buffer to the
// Ansi buffer.
//
RtlMoveMemory( lpCPInfoEx,
&lpCPInfoExW,
FIELD_OFFSET(CPINFOEXW, CodePageName) );
//
// Return the result.
//
return (rc);
}
////////////////////////////////////////////////////////////////////////////
//
// GetGeoInfoA
//
// Wrapper funtion of GetGeoInfoW for ANSI. This function return information
// about a geographical region.
//
// 11-20-99 WeiWu Created
// 07-03-00 lguindon Began GEO API port
////////////////////////////////////////////////////////////////////////////
int WINAPI GetGeoInfoA(
GEOID GeoId,
DWORD GeoType,
LPSTR lpGeoData,
int cchData,
LANGID LangId)
{
int iRet = 0;
//
// Create buffer initialized to zero.
//
WCHAR wszBuffer[MAX_REG_VAL_SIZE] = {0};
//
// Sanity check.
//
if ((lpGeoData == NULL) && (cchData > 0))
{
SetLastError(ERROR_INVALID_PARAMETER);
return (iRet);
}
//
// Call the unicode version.
//
iRet = GetGeoInfoW( GeoId,
GeoType,
wszBuffer,
sizeof(wszBuffer) / sizeof(WCHAR),
LangId );
//
// Convert to ANSI if we get something.
//
if (iRet)
{
iRet = WideCharToMultiByte( CP_ACP,
0,
wszBuffer,
iRet,
lpGeoData,
cchData,
NULL,
NULL );
}
return (iRet);
}
//-------------------------------------------------------------------------//
// INTERNAL ROUTINES //
//-------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////
//
// NlsGetACPFromLocale
//
// Gets the CP hash node for the default ACP of the given locale. If
// either the locale or the code page are invalid, then NULL is returned.
//
// 01-19-94 JulieB Created.
////////////////////////////////////////////////////////////////////////////
PCP_HASH NlsGetACPFromLocale(
LCID Locale,
DWORD dwFlags)
{
PLOC_HASH pHashN; // ptr to LOC hash node
PCP_HASH pHashCP; // ptr to CP hash node
UNICODE_STRING ObUnicodeStr; // value string
UINT CodePage; // code page value
//
// See if the system ACP should be used.
//
if (dwFlags & (LOCALE_USE_CP_ACP | LOCALE_RETURN_NUMBER))
{
return (gpACPHashN);
}
//
// Get the locale hash node.
//
VALIDATE_LOCALE(Locale, pHashN, FALSE);
if (pHashN == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return (NULL);
}
//
// Get the ACP code page. If it's equal to CP_ACP (0), then return
// the system ACP hash node.
//
CodePage = pHashN->pLocaleFixed->DefaultACP;
if (CodePage == CP_ACP)
{
return (gpACPHashN);
}
//
// Get the CP hash node for the code page.
//
pHashCP = GetCPHashNode(CodePage);
if (pHashCP == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
}
//
// Return the code page hash node.
//
return (pHashCP);
}
////////////////////////////////////////////////////////////////////////////
//
// NlsAnsiToUnicode
//
// Converts an Ansi string to a Unicode string.
//
// NOTE: The Unicode buffer is allocated if the routine succeeds, so the
// caller will need to free the buffer when it is no longer needed.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL NlsAnsiToUnicode(
PCP_HASH pHashN,
DWORD dwFlags,
LPCSTR pAnsiBuffer,
int AnsiLength,
LPWSTR *ppUnicodeBuffer,
int *pUnicodeLength)
{
LPWSTR pUnicode; // ptr to Unicode buffer
ULONG UnicodeLength; // length of the Unicode string
int ResultLength; // result length of Unicode string
//
// Make sure the pointer passed in is not null.
//
if (pAnsiBuffer == NULL)
{
*ppUnicodeBuffer = NULL;
*pUnicodeLength = 0;
return (TRUE);
}
//
// Make sure the Ansi length is set properly (in bytes).
//
if (AnsiLength < 0)
{
AnsiLength = strlen(pAnsiBuffer) + 1;
}
//
// See if the static buffer is big enough.
//
if ((*ppUnicodeBuffer == NULL) || (AnsiLength > (MAX_STRING_LEN - 1)))
{
//
// Get the size of the Unicode string, including the
// null terminator.
//
UnicodeLength = AnsiLength;
//
// Allocate the Unicode buffer.
//
if ((pUnicode = (LPWSTR)NLS_ALLOC_MEM(
(UnicodeLength + 1) * sizeof(WCHAR) )) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (FALSE);
}
}
else
{
UnicodeLength = MAX_STRING_LEN - 1;
pUnicode = *ppUnicodeBuffer;
}
//
// Make sure the length of the Ansi string is not zero.
//
if (AnsiLength == 0)
{
pUnicode[0] = 0;
*ppUnicodeBuffer = pUnicode;
*pUnicodeLength = 0;
return (TRUE);
}
//
// Convert the Ansi string to a Unicode string.
//
ResultLength = SpecialMBToWC( pHashN,
dwFlags,
pAnsiBuffer,
AnsiLength,
pUnicode,
UnicodeLength );
if (ResultLength == 0)
{
//
// Free the allocated Unicode buffer (if one was allocated).
//
NLS_FREE_TMP_BUFFER(pUnicode, *ppUnicodeBuffer);
//
// See if the failure was due to insufficient buffer size.
//
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
//
// Get the size of the buffer needed to hold the
// Unicode string.
//
UnicodeLength = SpecialMBToWC( pHashN,
dwFlags,
pAnsiBuffer,
AnsiLength,
NULL,
0 );
//
// Allocate the Unicode buffer.
//
if ((pUnicode = (LPWSTR)NLS_ALLOC_MEM(
(UnicodeLength + 1) * sizeof(WCHAR) )) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (FALSE);
}
//
// Try the translation again.
//
ResultLength = SpecialMBToWC( pHashN,
dwFlags,
pAnsiBuffer,
AnsiLength,
pUnicode,
UnicodeLength );
}
//
// If there was still an error, return failure.
//
if (ResultLength == 0)
{
SetLastError(ERROR_INVALID_PARAMETER);
return (FALSE);
}
}
//
// Make sure there is room in the buffer for the null terminator.
//
ASSERT(ResultLength <= (int)UnicodeLength);
//
// Null terminate the string.
//
pUnicode[ResultLength] = UNICODE_NULL;
//
// Return the Unicode buffer and success.
//
*ppUnicodeBuffer = pUnicode;
*pUnicodeLength = ResultLength;
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////
//
// NlsUnicodeToAnsi
//
// Converts a Unicode string to an Ansi string.
//
// This routine does NOT allocate the Ansi buffer. Instead, it uses the
// Ansi buffer passed in (unless AnsiLength is 0) and checks for buffer
// overflow.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
int NlsUnicodeToAnsi(
PCP_HASH pHashN,
LPCWSTR pUnicodeBuffer,
int UnicodeLength,
LPSTR pAnsiBuffer,
int AnsiLength)
{
//
// Convert the Unicode string to an Ansi string and return the
// result. The last error will be set appropriately by
// WideCharToMultiByte.
//
return (WideCharToMultiByte( pHashN->CodePage,
0,
pUnicodeBuffer,
UnicodeLength,
pAnsiBuffer,
AnsiLength,
NULL,
NULL ));
}
////////////////////////////////////////////////////////////////////////////
//
// NlsEnumUnicodeToAnsi
//
// Converts a Unicode string to an Ansi string.
//
// NOTE: The Ansi buffer is allocated if the routine succeeds, so the
// caller will need to free the buffer when it is no longer needed.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL NlsEnumUnicodeToAnsi(
PCP_HASH pHashN,
LPCWSTR pUnicodeBuffer,
LPSTR *ppAnsiBuffer)
{
LPSTR pAnsi; // ptr to Ansi buffer
ULONG AnsiLength; // length of the Ansi string
ULONG UnicodeLength; // length of the Unicode string
ULONG ResultLength; // result length of Ansi string
//
// Get the length of the Unicode string (in bytes), including the
// null terminator.
//
UnicodeLength = NlsStrLenW(pUnicodeBuffer) + 1;
//
// Get the size of the Ansi string (in bytes), including the
// null terminator.
//
AnsiLength = UnicodeLength * sizeof(WCHAR);
//
// Allocate the Ansi buffer.
//
if ((pAnsi = (LPSTR)NLS_ALLOC_MEM(AnsiLength)) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (FALSE);
}
//
// Convert the Unicode string to an Ansi string.
// It will already be null terminated.
//
ResultLength = WideCharToMultiByte( pHashN->CodePage,
0,
pUnicodeBuffer,
UnicodeLength,
pAnsi,
AnsiLength,
NULL,
NULL );
if (ResultLength == 0)
{
//
// Free the allocated Ansi buffer.
//
NLS_FREE_MEM(pAnsi);
//
// See if the failure was due to insufficient buffer size.
//
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
//
// Get the size of the buffer needed to hold the
// ansi string.
//
AnsiLength = WideCharToMultiByte( pHashN->CodePage,
0,
pUnicodeBuffer,
UnicodeLength,
0,
0,
NULL,
NULL );
//
// Allocate the Ansi buffer.
//
if ((pAnsi = (LPSTR)NLS_ALLOC_MEM(AnsiLength)) == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return (FALSE);
}
//
// Try the translation again.
//
ResultLength = WideCharToMultiByte( pHashN->CodePage,
0,
pUnicodeBuffer,
UnicodeLength,
pAnsi,
AnsiLength,
NULL,
NULL );
}
//
// If there was still an error, return failure.
//
if (ResultLength == 0)
{
SetLastError(ERROR_INVALID_PARAMETER);
return (FALSE);
}
}
//
// Return the Ansi buffer and success.
//
*ppAnsiBuffer = pAnsi;
return (TRUE);
}
////////////////////////////////////////////////////////////////////////////
//
// NlsDispatchAnsiEnumProc
//
// Converts a Unicode string to an Ansi string.
//
// 11-10-93 JulieB Created.
////////////////////////////////////////////////////////////////////////////
BOOL NlsDispatchAnsiEnumProc(
LCID Locale,
NLS_ENUMPROC pNlsEnumProc,
DWORD dwFlags,
LPWSTR pUnicodeBuffer1,
LPWSTR pUnicodeBuffer2,
DWORD dwValue1,
DWORD dwValue2,
LONG_PTR lParam,
BOOL fVersion)
{
PCP_HASH pHashN; // ptr to CP hash node
LPSTR pAnsiBuffer1 = NULL; // ptr to ansi buffer
LPSTR pAnsiBuffer2 = NULL; // ptr to ansi buffer
BOOL rc = FALSE; // return code
//
// Get the code page hash node for the given locale.
//
pHashN = NlsGetACPFromLocale(Locale, dwFlags);
if (pHashN == NULL)
{
return (0);
}
//
// Convert the null-terminated Unicode string to a
// null-terminated Ansi string.
//
if (!NlsEnumUnicodeToAnsi( pHashN,
pUnicodeBuffer1,
&pAnsiBuffer1 ))
{
return (FALSE);
}
if ((pUnicodeBuffer2 != NULL) &&
(!NlsEnumUnicodeToAnsi( pHashN,
pUnicodeBuffer2,
&pAnsiBuffer2 )))
{
NLS_FREE_MEM(pAnsiBuffer1);
return (FALSE);
}
//
// Call the callback function.
//
switch (fVersion)
{
case ( 0 ) :
{
rc = (*pNlsEnumProc)(pAnsiBuffer1);
break;
}
case ( 1 ) :
{
rc = (*((NLS_ENUMPROCEX)pNlsEnumProc))(pAnsiBuffer1, dwValue1);
break;
}
case ( 2 ) :
{
rc = (*((NLS_ENUMPROC2)pNlsEnumProc))( dwValue1,
dwValue2,
pAnsiBuffer1,
lParam );
break;
}
case ( 3 ) :
{
rc = (*((NLS_ENUMPROC3)pNlsEnumProc))( dwValue1,
pAnsiBuffer1,
pAnsiBuffer2,
dwValue2,
lParam );
break;
}
case ( 4 ) :
{
rc = (*((NLS_ENUMPROC4)pNlsEnumProc))( pAnsiBuffer1,
lParam );
break;
}
}
//
// Free any allocated memory.
//
NLS_FREE_MEM(pAnsiBuffer1);
if (pAnsiBuffer2)
{
NLS_FREE_MEM(pAnsiBuffer2);
}
//
// Return the result.
//
return (rc);
}