|
|
/*++
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"
#include "nlssafe.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) { NLS_FREE_MEM(pAnsi); 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); }
|