branch update for HEAD-2003091401
[reactos.git] / lib / ntdll / rtl / nls.c
index b65e453..7e95c73 100644 (file)
@@ -8,17 +8,8 @@
  *                  20/08/99 Created by Emanuele Aliberti
  *                  10/11/99 Added translation functions.
  *
- * NOTE:
- *   Multi-byte code pages are not supported yet. Even single-byte code
- *   pages are not supported properly. Only stupid CHAR->WCHAR and
- *   WCHAR->CHAR (Attention: data loss!!!) translation is done.
- *
  * TODO:
- *   1) Implement code to initialize the translation tables.
- *   2) Use fixed translation table for translation.
- *   3) Add loading of translation tables (NLS files).
- *   4) Implement unicode upcase and downcase handling.
- *   5) Add multi-byte translation code.
+ *   1) Add multi-byte translation code.
  */
 
 #include <ddk/ntddk.h>
 #include <debug.h>
 
 
-BOOLEAN
-NlsMbCodePageTag = FALSE;
-
-BOOLEAN
-NlsMbOemCodePageTag = FALSE;
-
-BYTE
-NlsLeadByteInfo = 0; /* ? */
-
-USHORT
-NlsOemLeadByteInfo = 0;
+/* GLOBALS *******************************************************************/
 
-USHORT
-NlsAnsiCodePage = 0;
+USHORT NlsAnsiCodePage = 0; /* exported */
+BOOLEAN NlsMbCodePageTag = FALSE; /* exported */
+PWCHAR NlsAnsiToUnicodeTable = NULL;
+PCHAR NlsUnicodeToAnsiTable = NULL;
+PUSHORT NlsLeadByteInfo = NULL;
 
-USHORT
-NlsOemCodePage = 0; /* not exported */
 
-#if 0
-PWCHAR NlsAnsiToUnicodeTable = NULL;
+USHORT NlsOemCodePage = 0;
+BOOLEAN NlsMbOemCodePageTag = FALSE; /* exported */
 PWCHAR NlsOemToUnicodeTable = NULL;
-
-PCHAR NlsUnicodeToAnsiTable = NULL;
 PCHAR NlsUnicodeToOemTable = NULL;
+PUSHORT NlsOemLeadByteInfo = NULL;
 
-PWCHAR NlsUnicodeUpcaseTable = NULL;
-PWCHAR NlsUnicodeLowercaseTable = NULL;
-#endif
 
+PUSHORT NlsUnicodeUpcaseTable = NULL;
+PUSHORT NlsUnicodeLowercaseTable = NULL;
 
-/* FUNCTIONS *****************************************************************/
 
-/*
- * Missing functions:
- *   RtlInitCodePageTable
- *   RtlInitNlsTables
- *   RtlResetRtlTranslations
- */
+/* FUNCTIONS *****************************************************************/
 
 /*
  * RtlConsoleMultiByteToUnicodeN@24
  */
 
-NTSTATUS
-STDCALL
-RtlCustomCPToUnicodeN (
-       PRTL_NLS_DATA   NlsData,
-       PWCHAR          UnicodeString,
-       ULONG           UnicodeSize,
-       PULONG          ResultSize,
-       PCHAR           CustomString,
-       ULONG           CustomSize)
+
+NTSTATUS STDCALL
+RtlCustomCPToUnicodeN(IN PCPTABLEINFO CustomCP,
+                     PWCHAR UnicodeString,
+                     ULONG UnicodeSize,
+                     PULONG ResultSize,
+                     PCHAR CustomString,
+                     ULONG CustomSize)
 {
-       ULONG Size = 0;
-       ULONG i;
+  ULONG Size = 0;
+  ULONG i;
 
-       if (NlsData->DbcsFlag == FALSE)
-       {
-               /* 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 = NlsData->MultiByteToUnicode[(int)*CustomString];
-                       UnicodeString++;
-                       CustomString++;
-               }
-       }
-       else
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
+         *UnicodeString = CustomCP->MultiByteTable[(int)*CustomString];
+         UnicodeString++;
+         CustomString++;
        }
-
-       return STATUS_SUCCESS;
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
 }
 
 
-VOID
-STDCALL
-RtlGetDefaultCodePage (
-       PUSHORT AnsiCodePage,
-       PUSHORT OemCodePage
-       )
+WCHAR
+RtlDowncaseUnicodeChar (IN WCHAR Source)
 {
-       *AnsiCodePage = NlsAnsiCodePage;
-       *OemCodePage = NlsOemCodePage;
+  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;
 }
 
 
-NTSTATUS
-STDCALL
-RtlMultiByteToUnicodeN (
-       PWCHAR  UnicodeString,
-       ULONG   UnicodeSize,
-       PULONG  ResultSize,
-       PCHAR   MbString,
-       ULONG   MbSize
-       )
+VOID STDCALL
+RtlGetDefaultCodePage(OUT PUSHORT AnsiCodePage,
+                     OUT PUSHORT OemCodePage)
 {
-       ULONG Size = 0;
-       ULONG i;
+  *AnsiCodePage = NlsAnsiCodePage;
+  *OemCodePage = NlsOemCodePage;
+}
 
-       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 = *MbString;
-#if 0
-                       *UnicodeString = NlsAnsiToUnicodeTable[*MbString];
-#endif
-
-                       UnicodeString++;
-                       MbString++;
-               }
-       }
-       else
-       {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
-       }
 
-       return STATUS_SUCCESS;
+/*
+ * @implemented
+ */
+VOID STDCALL
+RtlInitCodePageTable(IN PUSHORT TableBase,
+                    OUT PCPTABLEINFO CodePageTable)
+{
+  PNLS_FILE_HEADER NlsFileHeader;
+  PUSHORT Ptr;
+  USHORT Offset;
+
+  DPRINT("RtlInitCodePageTable() called\n");
+
+  NlsFileHeader = (PNLS_FILE_HEADER)TableBase;
+
+  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);
+
+  /* Set Pointer to start of multi byte table */
+  Ptr = (PUSHORT)((ULONG_PTR)TableBase + 2 * NlsFileHeader->HeaderSize);
+
+  /* Get offset to the wide char table */
+  Offset = (USHORT)(*Ptr++) + NlsFileHeader->HeaderSize + 1;
+
+  /* Set pointer to the multi byte table */
+  CodePageTable->MultiByteTable = Ptr;
+
+  /* Skip ANSI and OEM table */
+  Ptr += 256;
+  if (*Ptr++)
+    Ptr += 256;
+
+  /* Set pointer to DBCS ranges */
+  CodePageTable->DBCSRanges = (PUSHORT)Ptr;
+
+  if (*Ptr > 0)
+    {
+      CodePageTable->DBCSCodePage = 1;
+      CodePageTable->DBCSOffsets = (PUSHORT)++Ptr;
+    }
+  else
+    {
+      CodePageTable->DBCSCodePage = 0;
+      CodePageTable->DBCSOffsets = 0;
+    }
+
+  CodePageTable->WideCharTable = (PVOID)((ULONG_PTR)TableBase + 2 * Offset);
 }
 
 
-NTSTATUS
-STDCALL
-RtlMultiByteToUnicodeSize (
-       PULONG  UnicodeSize,
-       PCHAR   MbString,
-       ULONG   MbSize
-       )
+/*
+ * @implemented
+ */
+VOID STDCALL
+RtlInitNlsTables(IN PUSHORT AnsiTableBase,
+                IN PUSHORT OemTableBase,
+                IN PUSHORT CaseTableBase,
+                OUT PNLSTABLEINFO NlsTable)
 {
-       if (NlsMbCodePageTag == FALSE)
-       {
-               /* single-byte code page */
-               *UnicodeSize = MbSize * sizeof (WCHAR);
-       }
-       else
-       {
-               /* multi-byte code page */
-               /* FIXME */
+  DPRINT("RtlInitNlsTables()called\n");
 
-       }
+  if (AnsiTableBase == NULL ||
+      OemTableBase == NULL ||
+      CaseTableBase == NULL)
+    return;
+
+  RtlInitCodePageTable (AnsiTableBase,
+                       &NlsTable->AnsiTableInfo);
 
-       return STATUS_SUCCESS;
+  RtlInitCodePageTable (OemTableBase,
+                       &NlsTable->OemTableInfo);
+
+  NlsTable->UpperCaseTable = (PUSHORT)CaseTableBase + 2;
+  NlsTable->LowerCaseTable = (PUSHORT)CaseTableBase + *((PUSHORT)CaseTableBase + 1) + 2;
 }
 
 
-NTSTATUS
-STDCALL
-RtlOemToUnicodeN (
-       PWCHAR  UnicodeString,
-       ULONG   UnicodeSize,
-       PULONG  ResultSize,
-       PCHAR   OemString,
-       ULONG   OemSize
-       )
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlMultiByteToUnicodeN (IN OUT PWCHAR UnicodeString,
+                       IN ULONG UnicodeSize,
+                       OUT PULONG ResultSize,
+                       IN PCHAR MbString,
+                       IN ULONG MbSize)
 {
-       ULONG Size = 0;
-       ULONG i;
+  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 = *OemString;
-#if 0
-                       *UnicodeString = NlsOemToUnicodeTable[*OemString];
-#endif
-
-                       UnicodeString++;
-                       OemString++;
-               };
-       }
-       else
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
+         *UnicodeString = NlsAnsiToUnicodeTable[*((unsigned char *) MbString)];
+         UnicodeString++;
+         MbString++;
        }
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
+}
 
-       return STATUS_SUCCESS;
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+RtlMultiByteToUnicodeSize (OUT PULONG UnicodeSize,
+                          IN PCHAR MbString,
+                          IN ULONG MbSize)
+{
+  if (NlsMbCodePageTag == FALSE)
+    {
+      /* single-byte code page */
+      *UnicodeSize = MbSize * sizeof (WCHAR);
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
-STDCALL
-RtlUnicodeToCustomCPN (
-       PRTL_NLS_DATA   NlsData,
-       PCHAR           CustomString,
-       ULONG           CustomSize,
-       PULONG          ResultSize,
-       PWCHAR          UnicodeString,
-       ULONG           UnicodeSize
-       )
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlOemToUnicodeN (PWCHAR UnicodeString,
+                 ULONG UnicodeSize,
+                 PULONG ResultSize,
+                 PCHAR OemString,
+                 ULONG OemSize)
 {
-       ULONG Size = 0;
-       ULONG i;
+  ULONG Size = 0;
+  ULONG i;
 
-       if (NlsData->DbcsFlag == 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 = NlsData->UnicodeToMultiByte[*UnicodeString];
-                       CustomString++;
-                       UnicodeString++;
-               }
-       }
-       else
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
+         *UnicodeString = NlsOemToUnicodeTable[(INT)*OemString];
+         UnicodeString++;
+         OemString++;
        }
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
+}
 
-       return STATUS_SUCCESS;
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable)
+{
+  DPRINT("RtlResetRtlTranslations() called\n");
+
+  /* Set ANSI data */
+  NlsAnsiToUnicodeTable = NlsTable->AnsiTableInfo.MultiByteTable;
+  NlsUnicodeToAnsiTable = 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 = NlsTable->OemTableInfo.MultiByteTable;
+  NlsUnicodeToOemTable = 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;
 }
 
 
-NTSTATUS
-STDCALL
-RtlUnicodeToMultiByteN (
-       PCHAR   MbString,
-       ULONG   MbSize,
-       PULONG  ResultSize,
-       PWCHAR  UnicodeString,
-       ULONG   UnicodeSize
-       )
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlUnicodeToCustomCPN(IN PCPTABLEINFO CustomCP,
+                     PCHAR CustomString,
+                     ULONG CustomSize,
+                     PULONG ResultSize,
+                     PWCHAR UnicodeString,
+                     ULONG UnicodeSize)
 {
-       ULONG Size = 0;
-       ULONG i;
+  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++)
-               {
-                       *MbString = *UnicodeString;
-#if 0
-                       *MbString = UnicodeToAnsiTable[*UnicodeString];
-#endif
-
-                       MbString++;
-                       UnicodeString++;
-               }
-       }
-       else
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
+         *CustomString = ((PCHAR)CustomCP->WideCharTable)[*UnicodeString];
+         CustomString++;
+         UnicodeString++;
        }
-
-       return STATUS_SUCCESS;
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
-STDCALL
-RtlUnicodeToMultiByteSize (
-       PULONG  MbSize,
-       PWCHAR  UnicodeString,
-       ULONG   UnicodeSize
-       )
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlUnicodeToMultiByteN (PCHAR MbString,
+                       ULONG MbSize,
+                       PULONG ResultSize,
+                       PWCHAR UnicodeString,
+                       ULONG UnicodeSize)
 {
-       if (NlsMbCodePageTag == FALSE)
-       {
-               /* single-byte code page */
-               *MbSize = UnicodeSize / sizeof (WCHAR);
-       }
-       else
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    *MbSize = 0;
-    assert(FALSE);
+         *MbString = NlsUnicodeToAnsiTable[*UnicodeString];
+         MbString++;
+         UnicodeString++;
        }
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
+}
+
 
-       return STATUS_SUCCESS;
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlUnicodeToMultiByteSize (PULONG MbSize,
+                          PWCHAR UnicodeString,
+                          ULONG UnicodeSize)
+{
+  if (NlsMbCodePageTag == FALSE)
+    {
+      /* single-byte code page */
+      *MbSize = UnicodeSize / sizeof (WCHAR);
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      *MbSize = 0;
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
-STDCALL
-RtlUnicodeToOemN (
-       PCHAR   OemString,
-       ULONG   OemSize,
-       PULONG  ResultSize,
-       PWCHAR  UnicodeString,
-       ULONG   UnicodeSize
-       )
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlUnicodeToOemN (PCHAR OemString,
+                 ULONG OemSize,
+                 PULONG ResultSize,
+                 PWCHAR UnicodeString,
+                 ULONG UnicodeSize)
 {
-       ULONG Size = 0;
-       ULONG i;
+  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 = *UnicodeString;
-#if 0
-                       *OemString = UnicodeToOemTable[*UnicodeString];
-#endif
-
-                       OemString++;
-                       UnicodeString++;
-               };
-       }
-       else
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
+         *OemString = NlsUnicodeToOemTable[*UnicodeString];
+         OemString++;
+         UnicodeString++;
        }
-
-       return STATUS_SUCCESS;
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
-STDCALL
-RtlUpcaseUnicodeToCustomCPN (
-       PRTL_NLS_DATA   NlsData,
-       PCHAR           CustomString,
-       ULONG           CustomSize,
-       PULONG          ResultSize,
-       PWCHAR          UnicodeString,
-       ULONG           UnicodeSize
-       )
+/*
+ * @implemented
+ */
+WCHAR STDCALL
+RtlUpcaseUnicodeChar(IN WCHAR Source)
 {
-       WCHAR UpcaseChar;
-       ULONG Size = 0;
-       ULONG i;
+  USHORT Offset;
 
-       if (NlsData->DbcsFlag == 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 = NlsData->UnicodeToMultiByte[*UnicodeString];
-#if 0
-                       UpcaseChar = NlsUnicodeUpcaseTable[*UnicodeString];
-                       *CustomString = NlsData->UnicodeToMultiByte[UpcaseChar];
-#endif
-                       CustomString++;
-                       UnicodeString++;
-               }
-       }
-       else
-       {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
-       }
+  if (Source < L'a')
+    return Source;
+
+  if (Source <= L'z')
+    return (Source - (L'a' - L'A'));
 
-       return STATUS_SUCCESS;
+  Offset = ((USHORT)Source >> 8);
+  Offset = NlsUnicodeUpcaseTable[Offset];
+
+  Offset += (((USHORT)Source & 0x00F0) >> 4);
+  Offset = NlsUnicodeUpcaseTable[Offset];
+
+  Offset += ((USHORT)Source & 0x000F);
+  Offset = NlsUnicodeUpcaseTable[Offset];
+
+  return Source + (SHORT)Offset;
 }
 
 
-NTSTATUS
-STDCALL
-RtlUpcaseUnicodeToMultiByteN (
-       PCHAR   MbString,
-       ULONG   MbSize,
-       PULONG  ResultSize,
-       PWCHAR  UnicodeString,
-       ULONG   UnicodeSize
-       )
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlUpcaseUnicodeToCustomCPN (IN PCPTABLEINFO CustomCP,
+                            PCHAR CustomString,
+                            ULONG CustomSize,
+                            PULONG ResultSize,
+                            PWCHAR UnicodeString,
+                            ULONG UnicodeSize)
 {
-       WCHAR UpcaseChar;
-       ULONG Size = 0;
-       ULONG i;
-
-       if (NLS_MB_CODE_PAGE_TAG == 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++)
-               {
-                       *MbString = *UnicodeString;
-#if 0
-                       UpcaseChar = NlsUnicodeUpcaseTable[*UnicodeString];
-                       *MbString = NlsUnicodeToAnsiTable[UpcaseChar];
-#endif
-
-                       MbString++;
-                       UnicodeString++;
-               }
-       }
-       else
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
+         UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
+         *CustomString = ((PCHAR)CustomCP->WideCharTable)[UpcaseChar];
+         CustomString++;
+         UnicodeString++;
        }
-
-       return STATUS_SUCCESS;
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
-STDCALL
-RtlUpcaseUnicodeToOemN (
-       PCHAR   OemString,
-       ULONG   OemSize,
-       PULONG  ResultSize,
-       PWCHAR  UnicodeString,
-       ULONG   UnicodeSize
-       )
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlUpcaseUnicodeToMultiByteN (PCHAR MbString,
+                             ULONG MbSize,
+                             PULONG ResultSize,
+                             PWCHAR UnicodeString,
+                             ULONG UnicodeSize)
 {
-       WCHAR UpcaseChar;
-       ULONG Size = 0;
-       ULONG i;
-
-       if (NLS_MB_OEM_CODE_PAGE_TAG == FALSE)
+  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++)
        {
-               /* 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 = *UnicodeString;
-#if 0
-                       UpcaseChar = NlsUnicodeUpcaseTable[*UnicodeString];
-                       *OemString = UnicodeToOemTable[UpcaseChar];
-#endif
-
-                       OemString++;
-                       UnicodeString++;
-               }
+         UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
+         *MbString = NlsUnicodeToAnsiTable[UpcaseChar];
+         MbString++;
+         UnicodeString++;
        }
-       else
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
+}
+
+
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlUpcaseUnicodeToOemN (PCHAR OemString,
+                       ULONG OemSize,
+                       PULONG ResultSize,
+                       PWCHAR UnicodeString,
+                       ULONG UnicodeSize)
+{
+  WCHAR UpcaseChar;
+  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++)
        {
-               /* multi-byte code page */
-               /* FIXME */
-    assert(FALSE);
+         UpcaseChar = RtlUpcaseUnicodeChar(*UnicodeString);
+         *OemString = NlsUnicodeToOemTable[UpcaseChar];
+         OemString++;
+         UnicodeString++;
        }
+    }
+  else
+    {
+      /* multi-byte code page */
+      /* FIXME */
+      assert(FALSE);
+    }
+
+  return STATUS_SUCCESS;
+}
+
 
-       return STATUS_SUCCESS;
+/*
+ * @unimplemented
+ */
+CHAR STDCALL
+RtlUpperChar (IN CHAR Source)
+{
+  WCHAR Unicode;
+  CHAR Destination;
+
+  if (NlsMbCodePageTag == FALSE)
+    {
+      /* single-byte code page */
+
+      /* ansi->unicode */
+      Unicode = NlsAnsiToUnicodeTable[(INT)Source];
+
+      /* upcase conversion */
+      Unicode = RtlUpcaseUnicodeChar (Unicode);
+
+      /* unicode -> ansi */
+      Destination = NlsUnicodeToAnsiTable[Unicode];
+    }
+  else
+    {
+      /* single-byte code page */
+      /* FIXME: implement the multi-byte stuff!! */
+      Destination = Source;
+    }
+
+  return Destination;
 }
 
 /* EOF */