mirror of
https://github.com/reactos/reactos.git
synced 2024-08-27 21:58:49 +00:00
932 lines
20 KiB
C
932 lines
20 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS system libraries
|
|
* FILE: lib/rtl/nls.c
|
|
* PURPOSE: National Language Support (NLS) functions
|
|
* PROGRAMMERS: Emanuele Aliberti
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <rtl.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
PUSHORT NlsUnicodeUpcaseTable = NULL;
|
|
PUSHORT NlsUnicodeLowercaseTable = NULL;
|
|
|
|
USHORT NlsAnsiCodePage = 0; /* exported */
|
|
BOOLEAN NlsMbCodePageTag = FALSE; /* exported */
|
|
PWCHAR NlsAnsiToUnicodeTable = NULL;
|
|
PCHAR NlsUnicodeToAnsiTable = NULL;
|
|
PWCHAR NlsDbcsUnicodeToAnsiTable = NULL;
|
|
PUSHORT NlsLeadByteInfo = NULL; /* exported */
|
|
|
|
|
|
USHORT NlsOemCodePage = 0;
|
|
BOOLEAN NlsMbOemCodePageTag = FALSE; /* exported */
|
|
PWCHAR NlsOemToUnicodeTable = NULL;
|
|
PCHAR NlsUnicodeToOemTable =NULL;
|
|
PWCHAR NlsDbcsUnicodeToOemTable = NULL;
|
|
PUSHORT _NlsOemLeadByteInfo = NULL; /* exported */
|
|
|
|
USHORT NlsOemDefaultChar = '\0';
|
|
USHORT NlsUnicodeDefaultChar = 0;
|
|
|
|
|
|
#define NlsOemLeadByteInfo _NlsOemLeadByteInfo
|
|
#define INIT_FUNCTION
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlCustomCPToUnicodeN(IN PCPTABLEINFO CustomCP,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize,
|
|
PULONG ResultSize,
|
|
PCHAR CustomString,
|
|
ULONG CustomSize)
|
|
{
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (CustomCP->DBCSCodePage == 0)
|
|
{
|
|
/* single-byte code page */
|
|
if (CustomSize > (UnicodeSize / sizeof(WCHAR)))
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
else
|
|
Size = CustomSize;
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size * sizeof(WCHAR);
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
*UnicodeString = CustomCP->MultiByteTable[(UCHAR)*CustomString];
|
|
UnicodeString++;
|
|
CustomString++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
WCHAR NTAPI
|
|
RtlDowncaseUnicodeChar (IN WCHAR Source)
|
|
{
|
|
USHORT Offset;
|
|
|
|
if (Source < L'A')
|
|
return Source;
|
|
|
|
if (Source <= L'Z')
|
|
return Source + (L'a' - L'A');
|
|
|
|
if (Source < 0x80)
|
|
return Source;
|
|
|
|
Offset = ((USHORT)Source >> 8);
|
|
DPRINT("Offset: %hx\n", Offset);
|
|
|
|
Offset = NlsUnicodeLowercaseTable[Offset];
|
|
DPRINT("Offset: %hx\n", Offset);
|
|
|
|
Offset += (((USHORT)Source & 0x00F0) >> 4);
|
|
DPRINT("Offset: %hx\n", Offset);
|
|
|
|
Offset = NlsUnicodeLowercaseTable[Offset];
|
|
DPRINT("Offset: %hx\n", Offset);
|
|
|
|
Offset += ((USHORT)Source & 0x000F);
|
|
DPRINT("Offset: %hx\n", Offset);
|
|
|
|
Offset = NlsUnicodeLowercaseTable[Offset];
|
|
DPRINT("Offset: %hx\n", Offset);
|
|
|
|
DPRINT("Result: %hx\n", Source + (SHORT)Offset);
|
|
|
|
return Source + (SHORT)Offset;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID NTAPI
|
|
RtlGetDefaultCodePage(OUT PUSHORT AnsiCodePage,
|
|
OUT PUSHORT OemCodePage)
|
|
{
|
|
*AnsiCodePage = NlsAnsiCodePage;
|
|
*OemCodePage = NlsOemCodePage;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID NTAPI
|
|
RtlInitCodePageTable(IN PUSHORT TableBase,
|
|
OUT PCPTABLEINFO CodePageTable)
|
|
{
|
|
PNLS_FILE_HEADER NlsFileHeader;
|
|
|
|
DPRINT("RtlInitCodePageTable() called\n");
|
|
|
|
NlsFileHeader = (PNLS_FILE_HEADER)TableBase;
|
|
|
|
/* Copy header fields first */
|
|
CodePageTable->CodePage = NlsFileHeader->CodePage;
|
|
CodePageTable->MaximumCharacterSize = NlsFileHeader->MaximumCharacterSize;
|
|
CodePageTable->DefaultChar = NlsFileHeader->DefaultChar;
|
|
CodePageTable->UniDefaultChar = NlsFileHeader->UniDefaultChar;
|
|
CodePageTable->TransDefaultChar = NlsFileHeader->TransDefaultChar;
|
|
CodePageTable->TransUniDefaultChar = NlsFileHeader->TransUniDefaultChar;
|
|
|
|
RtlCopyMemory(&CodePageTable->LeadByte,
|
|
&NlsFileHeader->LeadByte,
|
|
MAXIMUM_LEADBYTES);
|
|
|
|
/* Offset to wide char table is after the header */
|
|
CodePageTable->WideCharTable = TableBase + NlsFileHeader->HeaderSize + 1 +
|
|
TableBase[NlsFileHeader->HeaderSize];
|
|
|
|
/* Then multibyte table (256 wchars) follows */
|
|
CodePageTable->MultiByteTable = TableBase + NlsFileHeader->HeaderSize + 1;
|
|
|
|
/* Check the presence of glyph table (256 wchars) */
|
|
if (!CodePageTable->MultiByteTable[256])
|
|
CodePageTable->DBCSRanges = CodePageTable->MultiByteTable + 256 + 1;
|
|
else
|
|
CodePageTable->DBCSRanges = CodePageTable->MultiByteTable + 256 + 1 + 256;
|
|
|
|
/* Is this double-byte code page? */
|
|
if (*CodePageTable->DBCSRanges)
|
|
{
|
|
CodePageTable->DBCSCodePage = 1;
|
|
CodePageTable->DBCSOffsets = CodePageTable->DBCSRanges + 1;
|
|
}
|
|
else
|
|
{
|
|
CodePageTable->DBCSCodePage = 0;
|
|
CodePageTable->DBCSOffsets = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID NTAPI
|
|
RtlInitNlsTables(IN PUSHORT AnsiTableBase,
|
|
IN PUSHORT OemTableBase,
|
|
IN PUSHORT CaseTableBase,
|
|
OUT PNLSTABLEINFO NlsTable)
|
|
{
|
|
DPRINT("RtlInitNlsTables()called\n");
|
|
|
|
if (AnsiTableBase == NULL ||
|
|
OemTableBase == NULL ||
|
|
CaseTableBase == NULL)
|
|
return;
|
|
|
|
RtlInitCodePageTable (AnsiTableBase,
|
|
&NlsTable->AnsiTableInfo);
|
|
|
|
RtlInitCodePageTable (OemTableBase,
|
|
&NlsTable->OemTableInfo);
|
|
|
|
NlsTable->UpperCaseTable = (PUSHORT)CaseTableBase + 2;
|
|
NlsTable->LowerCaseTable = (PUSHORT)CaseTableBase + *((PUSHORT)CaseTableBase + 1) + 2;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlMultiByteToUnicodeN(
|
|
IN PWCHAR UnicodeString,
|
|
IN ULONG UnicodeSize,
|
|
IN PULONG ResultSize,
|
|
IN PCSTR MbString,
|
|
IN ULONG MbSize)
|
|
{
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (NlsMbCodePageTag == FALSE)
|
|
{
|
|
/* single-byte code page */
|
|
if (MbSize > (UnicodeSize / sizeof(WCHAR)))
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
else
|
|
Size = MbSize;
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size * sizeof(WCHAR);
|
|
|
|
for (i = 0; i < Size; i++)
|
|
UnicodeString[i] = NlsAnsiToUnicodeTable[(UCHAR)MbString[i]];
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
|
|
UCHAR Char;
|
|
USHORT LeadByteInfo;
|
|
PCSTR MbEnd = MbString + MbSize;
|
|
|
|
for (i = 0; i < UnicodeSize / sizeof(WCHAR) && MbString < MbEnd; i++)
|
|
{
|
|
Char = *(PUCHAR)MbString++;
|
|
|
|
if (Char < 0x80)
|
|
{
|
|
*UnicodeString++ = Char;
|
|
continue;
|
|
}
|
|
|
|
LeadByteInfo = NlsLeadByteInfo[Char];
|
|
|
|
if (!LeadByteInfo)
|
|
{
|
|
*UnicodeString++ = NlsAnsiToUnicodeTable[Char];
|
|
continue;
|
|
}
|
|
|
|
if (MbString < MbEnd)
|
|
*UnicodeString++ = NlsLeadByteInfo[LeadByteInfo + *(PUCHAR)MbString++];
|
|
}
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = i * sizeof(WCHAR);
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
RtlMultiByteToUnicodeSize(PULONG UnicodeSize,
|
|
PCSTR MbString,
|
|
ULONG MbSize)
|
|
{
|
|
ULONG Length = 0;
|
|
|
|
if (!NlsMbCodePageTag)
|
|
{
|
|
/* single-byte code page */
|
|
*UnicodeSize = MbSize * sizeof (WCHAR);
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
|
|
while (MbSize--)
|
|
{
|
|
UCHAR Char = *(PUCHAR)MbString++;
|
|
|
|
if (Char >= 0x80 && NlsLeadByteInfo[Char])
|
|
{
|
|
if (MbSize)
|
|
{
|
|
/* Move on */
|
|
MbSize--;
|
|
MbString++;
|
|
}
|
|
}
|
|
|
|
/* Increase returned size */
|
|
Length++;
|
|
}
|
|
|
|
/* Return final size */
|
|
*UnicodeSize = Length * sizeof(WCHAR);
|
|
}
|
|
|
|
/* Success */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlOemToUnicodeN (PWCHAR UnicodeString,
|
|
ULONG UnicodeSize,
|
|
PULONG ResultSize,
|
|
PCHAR OemString,
|
|
ULONG OemSize)
|
|
{
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (NlsMbOemCodePageTag == FALSE)
|
|
{
|
|
/* single-byte code page */
|
|
if (OemSize > (UnicodeSize / sizeof(WCHAR)))
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
else
|
|
Size = OemSize;
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size * sizeof(WCHAR);
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
*UnicodeString = NlsOemToUnicodeTable[(UCHAR)*OemString];
|
|
UnicodeString++;
|
|
OemString++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
|
|
UCHAR Char;
|
|
USHORT OemLeadByteInfo;
|
|
PCHAR OemEnd = OemString + OemSize;
|
|
|
|
for (i = 0; i < UnicodeSize / sizeof(WCHAR) && OemString < OemEnd; i++)
|
|
{
|
|
Char = *(PUCHAR)OemString++;
|
|
|
|
if (Char < 0x80)
|
|
{
|
|
*UnicodeString++ = Char;
|
|
continue;
|
|
}
|
|
|
|
OemLeadByteInfo = NlsOemLeadByteInfo[Char];
|
|
|
|
if (!OemLeadByteInfo)
|
|
{
|
|
*UnicodeString++ = NlsOemToUnicodeTable[Char];
|
|
continue;
|
|
}
|
|
|
|
if (OemString < OemEnd)
|
|
*UnicodeString++ =
|
|
NlsOemLeadByteInfo[OemLeadByteInfo + *(PUCHAR)OemString++];
|
|
}
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = i * sizeof(WCHAR);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID NTAPI
|
|
RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable)
|
|
{
|
|
DPRINT("RtlResetRtlTranslations() called\n");
|
|
|
|
/* Set ANSI data */
|
|
NlsAnsiToUnicodeTable = (PWCHAR)NlsTable->AnsiTableInfo.MultiByteTable; /* Real type is PUSHORT */
|
|
NlsUnicodeToAnsiTable = NlsTable->AnsiTableInfo.WideCharTable;
|
|
NlsDbcsUnicodeToAnsiTable = (PWCHAR)NlsTable->AnsiTableInfo.WideCharTable;
|
|
NlsMbCodePageTag = (NlsTable->AnsiTableInfo.DBCSCodePage != 0);
|
|
NlsLeadByteInfo = NlsTable->AnsiTableInfo.DBCSOffsets;
|
|
NlsAnsiCodePage = NlsTable->AnsiTableInfo.CodePage;
|
|
DPRINT("Ansi codepage %hu\n", NlsAnsiCodePage);
|
|
|
|
/* Set OEM data */
|
|
NlsOemToUnicodeTable = (PWCHAR)NlsTable->OemTableInfo.MultiByteTable; /* Real type is PUSHORT */
|
|
NlsUnicodeToOemTable = NlsTable->OemTableInfo.WideCharTable;
|
|
NlsDbcsUnicodeToOemTable = (PWCHAR)NlsTable->OemTableInfo.WideCharTable;
|
|
NlsMbOemCodePageTag = (NlsTable->OemTableInfo.DBCSCodePage != 0);
|
|
NlsOemLeadByteInfo = NlsTable->OemTableInfo.DBCSOffsets;
|
|
NlsOemCodePage = NlsTable->OemTableInfo.CodePage;
|
|
DPRINT("Oem codepage %hu\n", NlsOemCodePage);
|
|
|
|
/* Set Unicode case map data */
|
|
NlsUnicodeUpcaseTable = NlsTable->UpperCaseTable;
|
|
NlsUnicodeLowercaseTable = NlsTable->LowerCaseTable;
|
|
|
|
/* set the default characters for RtlpDidUnicodeToOemWork */
|
|
NlsOemDefaultChar = NlsTable->OemTableInfo.DefaultChar;
|
|
NlsUnicodeDefaultChar = NlsTable->OemTableInfo.TransDefaultChar;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP,
|
|
PCHAR CustomString,
|
|
ULONG CustomSize,
|
|
PULONG ResultSize,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize)
|
|
{
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (CustomCP->DBCSCodePage == 0)
|
|
{
|
|
/* single-byte code page */
|
|
if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
|
|
Size = CustomSize;
|
|
else
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size;
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
*CustomString = ((PCHAR)CustomCP->WideCharTable)[*UnicodeString];
|
|
CustomString++;
|
|
UnicodeString++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlUnicodeToMultiByteN (PCHAR MbString,
|
|
ULONG MbSize,
|
|
PULONG ResultSize,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize)
|
|
{
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (NlsMbCodePageTag == FALSE)
|
|
{
|
|
/* single-byte code page */
|
|
Size = (UnicodeSize > (MbSize * sizeof (WCHAR)))
|
|
? MbSize
|
|
: (UnicodeSize / sizeof (WCHAR));
|
|
|
|
if (ResultSize != NULL)
|
|
{
|
|
*ResultSize = Size;
|
|
}
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
*MbString++ = NlsUnicodeToAnsiTable[*UnicodeString++];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
|
|
USHORT WideChar;
|
|
USHORT MbChar;
|
|
|
|
for (i = MbSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
|
|
{
|
|
WideChar = *UnicodeString++;
|
|
|
|
if (WideChar < 0x80)
|
|
{
|
|
*MbString++ = LOBYTE(WideChar);
|
|
continue;
|
|
}
|
|
|
|
MbChar = NlsDbcsUnicodeToAnsiTable[WideChar];
|
|
|
|
if (!HIBYTE(MbChar))
|
|
{
|
|
*MbString++ = LOBYTE(MbChar);
|
|
continue;
|
|
}
|
|
|
|
if (i >= 2)
|
|
{
|
|
*MbString++ = HIBYTE(MbChar);
|
|
*MbString++ = LOBYTE(MbChar);
|
|
i--;
|
|
}
|
|
else break;
|
|
}
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = MbSize - i;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
RtlUnicodeToMultiByteSize(PULONG MbSize,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize)
|
|
{
|
|
ULONG UnicodeLength = UnicodeSize / sizeof(WCHAR);
|
|
ULONG MbLength = 0;
|
|
|
|
if (!NlsMbCodePageTag)
|
|
{
|
|
/* single-byte code page */
|
|
*MbSize = UnicodeLength;
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
|
|
while (UnicodeLength--)
|
|
{
|
|
USHORT WideChar = *UnicodeString++;
|
|
|
|
if (WideChar >= 0x80 && HIBYTE(NlsDbcsUnicodeToAnsiTable[WideChar]))
|
|
{
|
|
MbLength += sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
MbLength++;
|
|
}
|
|
}
|
|
|
|
*MbSize = MbLength;
|
|
}
|
|
|
|
/* Success */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlUnicodeToOemN (PCHAR OemString,
|
|
ULONG OemSize,
|
|
PULONG ResultSize,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize)
|
|
{
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (NlsMbOemCodePageTag == FALSE)
|
|
{
|
|
/* single-byte code page */
|
|
if (UnicodeSize > (OemSize * sizeof(WCHAR)))
|
|
Size = OemSize;
|
|
else
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size;
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
*OemString = NlsUnicodeToOemTable[*UnicodeString];
|
|
OemString++;
|
|
UnicodeString++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
|
|
USHORT WideChar;
|
|
USHORT OemChar;
|
|
|
|
for (i = OemSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
|
|
{
|
|
WideChar = *UnicodeString++;
|
|
|
|
if (WideChar < 0x80)
|
|
{
|
|
*OemString++ = LOBYTE(WideChar);
|
|
continue;
|
|
}
|
|
|
|
OemChar = NlsDbcsUnicodeToOemTable[WideChar];
|
|
|
|
if (!HIBYTE(OemChar))
|
|
{
|
|
*OemString++ = LOBYTE(OemChar);
|
|
continue;
|
|
}
|
|
|
|
if (i >= 2)
|
|
{
|
|
*OemString++ = HIBYTE(OemChar);
|
|
*OemString++ = LOBYTE(OemChar);
|
|
i--;
|
|
}
|
|
else break;
|
|
}
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = OemSize - i;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WCHAR NTAPI
|
|
RtlUpcaseUnicodeChar(IN WCHAR Source)
|
|
{
|
|
USHORT Offset;
|
|
|
|
if (Source < 'a')
|
|
return Source;
|
|
|
|
if (Source <= 'z')
|
|
return (Source - ('a' - 'A'));
|
|
|
|
Offset = ((USHORT)Source >> 8) & 0xFF;
|
|
Offset = NlsUnicodeUpcaseTable[Offset];
|
|
|
|
Offset += ((USHORT)Source >> 4) & 0xF;
|
|
Offset = NlsUnicodeUpcaseTable[Offset];
|
|
|
|
Offset += ((USHORT)Source & 0xF);
|
|
Offset = NlsUnicodeUpcaseTable[Offset];
|
|
|
|
return Source + (SHORT)Offset;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlUpcaseUnicodeToCustomCPN (IN PCPTABLEINFO CustomCP,
|
|
PCHAR CustomString,
|
|
ULONG CustomSize,
|
|
PULONG ResultSize,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize)
|
|
{
|
|
WCHAR UpcaseChar;
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (CustomCP->DBCSCodePage == 0)
|
|
{
|
|
/* single-byte code page */
|
|
if (UnicodeSize > (CustomSize * sizeof(WCHAR)))
|
|
Size = CustomSize;
|
|
else
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size;
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
|
|
*CustomString = ((PCHAR)CustomCP->WideCharTable)[UpcaseChar];
|
|
CustomString++;
|
|
UnicodeString++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlUpcaseUnicodeToMultiByteN (PCHAR MbString,
|
|
ULONG MbSize,
|
|
PULONG ResultSize,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize)
|
|
{
|
|
WCHAR UpcaseChar;
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
if (NlsMbCodePageTag == FALSE)
|
|
{
|
|
/* single-byte code page */
|
|
if (UnicodeSize > (MbSize * sizeof(WCHAR)))
|
|
Size = MbSize;
|
|
else
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size;
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
|
|
*MbString = NlsUnicodeToAnsiTable[UpcaseChar];
|
|
MbString++;
|
|
UnicodeString++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlUpcaseUnicodeToOemN (PCHAR OemString,
|
|
ULONG OemSize,
|
|
PULONG ResultSize,
|
|
PWCHAR UnicodeString,
|
|
ULONG UnicodeSize)
|
|
{
|
|
WCHAR UpcaseChar;
|
|
ULONG Size = 0;
|
|
ULONG i;
|
|
|
|
ASSERT(NlsUnicodeToOemTable != NULL);
|
|
|
|
if (NlsMbOemCodePageTag == FALSE)
|
|
{
|
|
/* single-byte code page */
|
|
if (UnicodeSize > (OemSize * sizeof(WCHAR)))
|
|
Size = OemSize;
|
|
else
|
|
Size = UnicodeSize / sizeof(WCHAR);
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = Size;
|
|
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
|
|
*OemString = NlsUnicodeToOemTable[UpcaseChar];
|
|
OemString++;
|
|
UnicodeString++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
|
|
USHORT WideChar;
|
|
USHORT OemChar;
|
|
|
|
for (i = OemSize, Size = UnicodeSize / sizeof(WCHAR); i && Size; i--, Size--)
|
|
{
|
|
WideChar = RtlUpcaseUnicodeChar(*UnicodeString++);
|
|
|
|
if (WideChar < 0x80)
|
|
{
|
|
*OemString++ = LOBYTE(WideChar);
|
|
continue;
|
|
}
|
|
|
|
OemChar = NlsDbcsUnicodeToOemTable[WideChar];
|
|
|
|
if (!HIBYTE(OemChar))
|
|
{
|
|
*OemString++ = LOBYTE(OemChar);
|
|
continue;
|
|
}
|
|
|
|
if (i >= 2)
|
|
{
|
|
*OemString++ = HIBYTE(OemChar);
|
|
*OemString++ = LOBYTE(OemChar);
|
|
i--;
|
|
}
|
|
else break;
|
|
}
|
|
|
|
if (ResultSize != NULL)
|
|
*ResultSize = OemSize - i;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
CHAR NTAPI
|
|
RtlUpperChar (IN CHAR Source)
|
|
{
|
|
WCHAR Unicode;
|
|
CHAR Destination;
|
|
|
|
/* Check for simple ANSI case */
|
|
if (Source <= 'z')
|
|
{
|
|
/* Check for simple downcase a-z case */
|
|
if (Source >= 'a')
|
|
{
|
|
/* Just XOR with the difference */
|
|
return Source ^ ('a' - 'A');
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise return the same char, it's already upcase */
|
|
return Source;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NlsMbCodePageTag == FALSE)
|
|
{
|
|
/* single-byte code page */
|
|
|
|
/* ansi->unicode */
|
|
Unicode = NlsAnsiToUnicodeTable[(UCHAR)Source];
|
|
|
|
/* upcase conversion */
|
|
Unicode = RtlUpcaseUnicodeChar (Unicode);
|
|
|
|
/* unicode -> ansi */
|
|
Destination = NlsUnicodeToAnsiTable[(USHORT)Unicode];
|
|
}
|
|
else
|
|
{
|
|
/* multi-byte code page */
|
|
/* FIXME */
|
|
Destination = Source;
|
|
}
|
|
}
|
|
|
|
return Destination;
|
|
}
|
|
|
|
/* EOF */
|