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.
2597 lines
75 KiB
2597 lines
75 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"
|
|
#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);
|
|
}
|