- Implement RtlpDidUnicodeToOemWork to check for unmapped characters. Based on a...
authorAleksey Bragin <aleksey@reactos.org>
Sat, 10 Oct 2009 13:22:41 +0000 (13:22 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Sat, 10 Oct 2009 13:22:41 +0000 (13:22 +0000)
See issue #4548 for more details.

svn path=/trunk/; revision=43363

reactos/lib/rtl/nls.c
reactos/lib/rtl/unicode.c

index 389297c..319cbcf 100644 (file)
@@ -33,6 +33,10 @@ PCHAR NlsUnicodeToOemTable =NULL;
 PWCHAR NlsDbcsUnicodeToOemTable = NULL;
 PUSHORT _NlsOemLeadByteInfo = NULL; /* exported */
 
+USHORT NlsOemDefaultChar = '\0';
+USHORT NlsUnicodeDefaultChar = 0;
+
+
 #define NlsOemLeadByteInfo              _NlsOemLeadByteInfo
 #define INIT_FUNCTION
 
@@ -435,6 +439,10 @@ RtlResetRtlTranslations(IN PNLSTABLEINFO NlsTable)
    /* 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;
 }
 
 
index cd7927c..c1f2358 100644 (file)
@@ -23,6 +23,9 @@ extern BOOLEAN NlsMbCodePageTag;
 extern BOOLEAN NlsMbOemCodePageTag;
 extern PUSHORT NlsLeadByteInfo;
 
+extern USHORT NlsOemDefaultChar;
+extern USHORT NlsUnicodeDefaultChar;
+
 /* FUNCTIONS *****************************************************************/
 
 /*
@@ -395,6 +398,45 @@ RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
     }
 }
 
+
+/*
+ * @implemented
+ * 
+ * NOTES
+ *  Check the oem-string to match the uincoded-string.
+ *
+ *  Functions who convert unicode strings to oem strings will set a DefaultChar from 
+ *  the OemCodepage when the character are unknown. So check it against the unicode string
+ *  and return false when the unicode string not contain an TransDefaultChar.
+ */
+BOOLEAN
+NTAPI
+RtlpDidUnicodeToOemWork(IN PCUNICODE_STRING UnicodeString,
+                        IN POEM_STRING OemString)
+{
+   ULONG i = 0;
+
+   /* Go through all characters of a string */
+   while ((OemString->Buffer[i] != 0) &&
+          (i < OemString->Length))
+   {
+       /* Check if it got translated into '?', but source char
+          wasn't '?' equivalent */
+       if ((OemString->Buffer[i] == NlsOemDefaultChar) &&
+           (UnicodeString->Buffer[i] != NlsUnicodeDefaultChar))
+       {
+           /* Yes, it means unmappable characters were found */
+           return FALSE;
+       }
+
+       /* Move to the next char */
+       i++;
+   }
+
+   /* All chars were translated successfuly */
+   return TRUE;
+}
+
 /*
 * @unimplemented
 */
@@ -1534,8 +1576,9 @@ RtlUnicodeStringToCountedOemString(
                               UniSource->Buffer,
                               UniSource->Length);
 
-    /* FIXME: Check if everything mapped correctly and
-     * return STATUS_UNMAPPABLE_CHARACTER */
+    /* Check for unmapped character */
+    if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+        Status = STATUS_UNMAPPABLE_CHARACTER;
 
     if (!NT_SUCCESS(Status) && AllocateDestinationString)
     {
@@ -1763,7 +1806,9 @@ RtlUpcaseUnicodeStringToCountedOemString(
                                     UniSource->Buffer,
                                     UniSource->Length);
 
-    /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+    /* Check for unmapped characters */
+    if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+        Status = STATUS_UNMAPPABLE_CHARACTER;
 
     if (!NT_SUCCESS(Status) && AllocateDestinationString)
     {
@@ -1816,7 +1861,9 @@ RtlUpcaseUnicodeStringToOemString (
                                     UniSource->Buffer,
                                     UniSource->Length);
 
-    /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+    /* Check for unmapped characters */
+    if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+        Status = STATUS_UNMAPPABLE_CHARACTER;
 
     if (!NT_SUCCESS(Status) && AllocateDestinationString)
     {