[NTOSKRNL] Unify buffer size calculation in FsRtlIs{Name,Dbcs}InExpression
[reactos.git] / ntoskrnl / fsrtl / dbcsname.c
index b7bf7f0..3b1afd8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * PROJECT:         ReactOS Kernel
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/fsrtl/name.c
+ * FILE:            ntoskrnl/fsrtl/dbcsname.c
  * PURPOSE:         Provides DBCS parsing and other support routines for FSDs
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  *                  Pierre Schweitzer (pierre.schweitzer@reactos.org)
@@ -160,9 +160,16 @@ NTAPI
 FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
                         IN PANSI_STRING Name)
 {
-    SHORT StarFound = -1, DosStarFound = -1;
-    PUSHORT BackTracking = NULL, DosBackTracking = NULL;
-    USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, LastDot;
+    USHORT Offset, Position, BackTrackingPosition, OldBackTrackingPosition;
+    USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
+    PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer;
+    ULONG BackTrackingBufferSize = RTL_NUMBER_OF(BackTrackingBuffer);
+    PVOID AllocatedBuffer = NULL;
+    USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1;
+    USHORT NameChar = 0, ExpressionChar;
+    BOOLEAN EndOfName = FALSE;
+    BOOLEAN Result;
+    BOOLEAN DontSkipDot;
     PAGED_CODE();
 
     ASSERT(Name->Length);
@@ -232,170 +239,200 @@ FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
         }
     }
 
-    while (NamePosition < Name->Length && ExpressionPosition < Expression->Length)
+    /* Name parsing loop */
+    for (; !EndOfName; MatchingChars = BackTrackingPosition)
     {
-        /* Basic check to test if chars are equal */
-        if ((Expression->Buffer[ExpressionPosition] == Name->Buffer[NamePosition]))
-        {
-            NamePosition++;
-            ExpressionPosition++;
-        }
-        /* Check cases that eat one char */
-        else if (Expression->Buffer[ExpressionPosition] == '?')
+        /* Reset positions */
+        OldBackTrackingPosition = BackTrackingPosition = 0;
+
+        if (NamePosition >= Name->Length)
         {
-            NamePosition++;
-            ExpressionPosition++;
+            EndOfName = TRUE;
+            if (OldBackTracking[MatchingChars - 1] == Expression->Length * 2)
+                break;
         }
-        /* Test star */
-        else if (Expression->Buffer[ExpressionPosition] == '*')
+        else
         {
-            /* Skip contigous stars */
-            while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == '*')
-            {
-                ExpressionPosition++;
-            }
-
-            /* Save star position */
-            if (!BackTracking)
-            {
-                BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
-                                                     Expression->Length * sizeof(USHORT), 'nrSF');
-            }
-            BackTracking[++StarFound] = ExpressionPosition++;
-
-            /* If star is at the end, then eat all rest and leave */
-            if (ExpressionPosition == Expression->Length)
+            /* If lead byte present */
+            if (FsRtlIsLeadDbcsCharacter(Name->Buffer[NamePosition]))
             {
-                NamePosition = Name->Length;
-                break;
+                NameChar = Name->Buffer[NamePosition] +
+                           (0x100 * Name->Buffer[NamePosition + 1]);
+                NamePosition += sizeof(USHORT);
             }
-            /* Allow null matching */
-            else if (Expression->Buffer[ExpressionPosition] != '?' &&
-                     Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition])
+            else
             {
-                NamePosition++;
+                NameChar = Name->Buffer[NamePosition];
+                NamePosition += sizeof(UCHAR);
             }
         }
-        /* Check DOS_STAR */
-        else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
+
+        while (MatchingChars > OldBackTrackingPosition)
         {
-            /* Skip contigous stars */
-            while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == ANSI_DOS_STAR)
-            {
-                ExpressionPosition++;
-            }
+            ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2;
 
-            /* Look for last dot */
-            MatchingChars = 0;
-            LastDot = (USHORT)-1;
-            while (MatchingChars < Name->Length)
+            /* Expression parsing loop */
+            for (Offset = 0; ExpressionPosition < Expression->Length; )
             {
-                if (Name->Buffer[MatchingChars] == '.')
+                ExpressionPosition += Offset;
+
+                if (ExpressionPosition == Expression->Length)
                 {
-                    LastDot = MatchingChars;
-                    if (LastDot > NamePosition)
-                        break;
+                    BackTracking[BackTrackingPosition++] = Expression->Length * 2;
+                    break;
                 }
 
-                MatchingChars++;
-            }
+                /* If buffer too small */
+                if (BackTrackingPosition > BackTrackingBufferSize - 3)
+                {
+                    /* We should only ever get here once! */
+                    ASSERT(AllocatedBuffer == NULL);
+                    ASSERT((BackTracking == BackTrackingBuffer) || (BackTracking == OldBackTrackingBuffer));
+                    ASSERT((OldBackTracking == BackTrackingBuffer) || (OldBackTracking == OldBackTrackingBuffer));
+
+                    /* Calculate buffer size */
+                    BackTrackingBufferSize = Expression->Length * 2 + 1;
+
+                    /* Allocate memory for both back-tracking buffers */
+                    AllocatedBuffer = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
+                                                            2 * BackTrackingBufferSize * sizeof(USHORT),
+                                                            'nrSF');
+                    if (AllocatedBuffer == NULL)
+                    {
+                        DPRINT1("Failed to allocate BackTracking buffer. BackTrackingBufferSize = =x%lx\n",
+                                BackTrackingBufferSize);
+                        Result = FALSE;
+                        goto Exit;
+                    }
+
+                    /* Copy BackTracking content. Note that it can point to either BackTrackingBuffer or OldBackTrackingBuffer */
+                    RtlCopyMemory(AllocatedBuffer,
+                                  BackTracking,
+                                  RTL_NUMBER_OF(BackTrackingBuffer) * sizeof(USHORT));
+
+                    /* Place current Backtracking is at the start of the new buffer */
+                    BackTracking = AllocatedBuffer;
+
+                    /* Copy OldBackTracking content */
+                    RtlCopyMemory(&BackTracking[BackTrackingBufferSize],
+                                  OldBackTracking,
+                                  RTL_NUMBER_OF(OldBackTrackingBuffer) * sizeof(USHORT));
+
+                    /* Place current OldBackTracking after current BackTracking in the buffer */
+                    OldBackTracking = &BackTracking[BackTrackingBufferSize];
+                }
 
-            /* If we don't have dots or we didn't find last yet
-             * start eating everything
-             */
-            if (MatchingChars != Name->Length || LastDot == (USHORT)-1)
-            {
-                if (!DosBackTracking) DosBackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
-                                                                              Expression->Length * sizeof(USHORT), 'nrSF');
-                DosBackTracking[++DosStarFound] = ExpressionPosition++;
+                /* If lead byte present */
+                if (FsRtlIsLeadDbcsCharacter(Expression->Buffer[ExpressionPosition]))
+                {
+                    ExpressionChar = Expression->Buffer[ExpressionPosition] +
+                                     (0x100 * Expression->Buffer[ExpressionPosition + 1]);
+                    Offset = sizeof(USHORT);
+                }
+                else
+                {
+                    ExpressionChar = Expression->Buffer[ExpressionPosition];
+                    Offset = sizeof(UCHAR);
+                }
 
-                /* Not the same char, start exploring */
-                if (Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition])
-                    NamePosition++;
-            }
-            else
-            {
-                /* Else, if we are at last dot, eat it - otherwise, null match */
-                if (Name->Buffer[NamePosition] == '.')
-                    NamePosition++;
+                /* Basic check to test if chars are equal */
+                if (ExpressionChar == NameChar && !EndOfName)
+                {
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+                /* Check cases that eat one char */
+                else if (ExpressionChar == '?' && !EndOfName)
+                {
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+                /* Test star */
+                else if (ExpressionChar == '*')
+                {
+                    BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 1;
+                    continue;
+                }
+                /* Check DOS_STAR */
+                else if (ExpressionChar == ANSI_DOS_STAR)
+                {
+                    /* Look for last dot */
+                    DontSkipDot = TRUE;
+                    if (!EndOfName && NameChar == '.')
+                    {
+                        for (Position = NamePosition; Position < Name->Length; )
+                        {
+                            /* If lead byte not present */
+                            if (!FsRtlIsLeadDbcsCharacter(Name->Buffer[Position]))
+                            {
+                                if (Name->Buffer[Position] == '.')
+                                {
+                                    DontSkipDot = FALSE;
+                                    break;
+                                }
+
+                                Position += sizeof(UCHAR);
+                            }
+                            else
+                            {
+                                Position += sizeof(USHORT);
+                            }
+                        }
+                    }
+
+                    if (EndOfName || NameChar != '.' || !DontSkipDot)
+                        BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
+
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 1;
+                    continue;
+                }
+                /* Check DOS_DOT */
+                else if (ExpressionChar == ANSI_DOS_DOT)
+                {
+                    if (EndOfName) continue;
 
-                 ExpressionPosition++;
-            }
-        }
-        /* Check DOS_DOT */
-        else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT)
-        {
-            /* We only match dots */
-            if (Name->Buffer[NamePosition] == '.')
-            {
-                NamePosition++;
-            }
-            /* Try to explore later on for null matching */
-            else if (ExpressionPosition + 1 < Expression->Length &&
-                     Name->Buffer[NamePosition] == Expression->Buffer[ExpressionPosition + 1])
-            {
-                NamePosition++;
-            }
-            ExpressionPosition++;
-        }
-        /* Check DOS_QM */
-        else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_QM)
-        {
-            /* We match everything except dots */
-            if (Name->Buffer[NamePosition] != '.')
-            {
-                NamePosition++;
+                    if (NameChar == '.')
+                        BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+                /* Check DOS_QM */
+                else if (ExpressionChar == ANSI_DOS_QM)
+                {
+                    if (EndOfName || NameChar == '.') continue;
+
+                    BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2;
+                }
+
+                /* Leave from loop */
+                break;
             }
-            ExpressionPosition++;
-        }
-        /* If nothing match, try to backtrack */
-        else if (StarFound >= 0)
-        {
-            ExpressionPosition = BackTracking[StarFound--];
-        }
-        else if (DosStarFound >= 0)
-        {
-            ExpressionPosition = DosBackTracking[DosStarFound--];
-        }
-        /* Otherwise, fail */
-        else
-        {
-            break;
-        }
 
-        /* Under certain circumstances, expression is over, but name isn't
-         * and we can backtrack, then, backtrack */
-        if (ExpressionPosition == Expression->Length &&
-            NamePosition != Name->Length && StarFound >= 0)
-        {
-            ExpressionPosition = BackTracking[StarFound--];
-        }
-    }
-    /* If we have nullable matching wc at the end of the string, eat them */
-    if (ExpressionPosition != Expression->Length && NamePosition == Name->Length)
-    {
-        while (ExpressionPosition < Expression->Length)
-        {
-            if (Expression->Buffer[ExpressionPosition] != ANSI_DOS_DOT &&
-                Expression->Buffer[ExpressionPosition] != '*' &&
-                Expression->Buffer[ExpressionPosition] != ANSI_DOS_STAR)
+            for (Position = 0; MatchingChars > OldBackTrackingPosition && Position < BackTrackingPosition; Position++)
             {
-                break;
+                while (MatchingChars > OldBackTrackingPosition &&
+                       BackTracking[Position] > OldBackTracking[OldBackTrackingPosition])
+                {
+                    ++OldBackTrackingPosition;
+                }
             }
-            ExpressionPosition++;
         }
-    }
 
-    if (BackTracking)
-    {
-        ExFreePoolWithTag(BackTracking, 'nrSF');
+        /* Swap pointers */
+        BackTrackingSwap = BackTracking;
+        BackTracking = OldBackTracking;
+        OldBackTracking = BackTrackingSwap;
     }
-    if (DosBackTracking)
+
+    /* Store result value */
+    Result = (OldBackTracking[MatchingChars - 1] == Expression->Length * 2);
+
+Exit:
+
+    /* Frees the memory if necessary */
+    if (AllocatedBuffer != NULL)
     {
-        ExFreePoolWithTag(DosBackTracking, 'nrSF');
+        ExFreePoolWithTag(AllocatedBuffer, 'nrSF');
     }
 
-    return (ExpressionPosition == Expression->Length && NamePosition == Name->Length);
+    return Result;
 }
 
 /*++
@@ -431,7 +468,7 @@ FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName,
                     IN BOOLEAN PathNamePermissible,
                     IN BOOLEAN LeadingBackslashPermissible)
 {
-    ANSI_STRING FirstPart, RemainingPart, Name;
+    ANSI_STRING FirstPart, RemainingPart;
     BOOLEAN LastDot;
     USHORT i;
     PAGED_CODE();
@@ -440,6 +477,20 @@ FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName,
     if (!DbcsName.Length)
         return FALSE;
 
+    /* Accept special filename if wildcards are allowed */
+    if (WildCardsPermissible && (DbcsName.Length == 1 || DbcsName.Length == 2) && DbcsName.Buffer[0] == '.')
+    {
+        if (DbcsName.Length == 2)
+        {
+            if (DbcsName.Buffer[1] == '.')
+                return TRUE;
+        }
+        else
+        {
+            return TRUE;
+        }
+    }
+
     /* DbcsName wasn't supposed to be started with \ */
     if (!LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
         return FALSE;
@@ -451,88 +502,108 @@ FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName,
         DbcsName.MaximumLength = DbcsName.MaximumLength - 1;
     }
 
-    /* Extract first part of the DbcsName to work on */
-    FsRtlDissectDbcs(DbcsName, &FirstPart, &RemainingPart);
-    while (FirstPart.Length > 0)
+    if (PathNamePermissible)
     {
-        /* Reset dots count */
-        LastDot = FALSE;
+        /* We copy the buffer for FsRtlDissectDbcs call */
+        RemainingPart.Buffer = DbcsName.Buffer;
+        RemainingPart.Length = DbcsName.Length;
+        RemainingPart.MaximumLength = DbcsName.MaximumLength;
 
-        /* Accept special filename if wildcards are allowed */
-        if (WildCardsPermissible && (FirstPart.Length == 1 || FirstPart.Length == 2) && FirstPart.Buffer[0] == '.')
+        while (RemainingPart.Length > 0)
         {
-            if (FirstPart.Length == 2)
-            {
-                if (FirstPart.Buffer[1] == '.')
-                {
-                    goto EndLoop;
-                }
-            }
-            else
+            if (RemainingPart.Buffer[0] == '\\')
+                return FALSE;
+
+            /* Call once again our dissect function */
+            FsRtlDissectDbcs(RemainingPart, &FirstPart, &RemainingPart);
+
+            if (!FsRtlIsFatDbcsLegal(FirstPart,
+                                     WildCardsPermissible,
+                                     FALSE,
+                                     FALSE))
             {
-                goto EndLoop;
+                return FALSE;
             }
         }
 
-        /* Filename must be 8.3 filename */
-        if (FirstPart.Length < 3 || FirstPart.Length > 12)
-            return FALSE;
+        return TRUE;
+    }
 
-        /* Now, we will parse the filename to find everything bad in */
-        for (i = 0; i < FirstPart.Length; i++)
+    if (WildCardsPermissible && FsRtlDoesDbcsContainWildCards(&DbcsName))
+    {
+        for (i = 0; i < DbcsName.Length; i++)
         {
             /* First make sure the character it's not the Lead DBCS */
-            if (FsRtlIsLeadDbcsCharacter(FirstPart.Buffer[i]))
+            if (FsRtlIsLeadDbcsCharacter(DbcsName.Buffer[i]))
             {
-                if (i == (FirstPart.Length) - 1)
-                    return FALSE;
                 i++;
             }
             /* Then check for bad characters */
-            else if (!FsRtlIsAnsiCharacterLegalFat(FirstPart.Buffer[i], WildCardsPermissible))
+            else if (!FsRtlIsAnsiCharacterLegalFat(DbcsName.Buffer[i], TRUE))
             {
                 return FALSE;
             }
-            else if (FirstPart.Buffer[i] == '.')
-            {
-                /* Filename can only contain one dot */
-                if (LastDot)
-                    return FALSE;
+        }
 
-                LastDot = TRUE;
+        return TRUE;
+    }
 
-                /* We mustn't have spaces before dot or at the end of the filename
-                 * and no dot at the beginning of the filename */
-                if ((i == (FirstPart.Length) - 1) || i == 0)
-                    return FALSE;
+    /* Filename must be 8.3 filename */
+    if (DbcsName.Length > 12)
+        return FALSE;
 
-                if (i > 0)
-                    if (FirstPart.Buffer[i - 1] == ' ')
-                        return FALSE;
+    /* Reset dots count */
+    LastDot = FALSE;
 
-                /* Filename must be 8.3 filename and not 3.8 filename */
-                if ((FirstPart.Length - 1) - i > 3)
-                    return FALSE;
-            }
-        }
+    for (i = 0; i < DbcsName.Length; i++)
+    {
+        /* First make sure the character it's not the Lead DBCS */
+        if (FsRtlIsLeadDbcsCharacter(DbcsName.Buffer[i]))
+        {
+            if (!LastDot && (i >= 7))
+                return FALSE;
 
-        /* Filename mustn't finish with a space */
-        if (FirstPart.Buffer[FirstPart.Length - 1] == ' ')
+            if (i == (DbcsName.Length - 1))
+                return FALSE;
+
+            i++;
+            continue;
+        }
+        /* Then check for bad characters */
+        else if (!FsRtlIsAnsiCharacterLegalFat(DbcsName.Buffer[i], WildCardsPermissible))
+        {
             return FALSE;
+        }
+        else if (DbcsName.Buffer[i] == '.')
+        {
+            /* Filename can only contain one dot */
+            if (LastDot)
+                return FALSE;
+
+            LastDot = TRUE;
+
+            /* We mustn't have spaces before dot or at the end of the filename
+             * and no dot at the beginning of the filename */
+            if (i == (DbcsName.Length - 1) || i == 0)
+                return FALSE;
 
-        EndLoop:
-        /* Preparing next loop */
-        Name.Buffer = RemainingPart.Buffer;
-        Name.Length = RemainingPart.Length;
-        Name.MaximumLength = RemainingPart.MaximumLength;
+            /* Filename must be 8.3 filename and not 3.8 filename */
+            if ((DbcsName.Length - 1) - i > 3)
+                return FALSE;
 
-        /* Call once again our dissect function */
-        FsRtlDissectDbcs(Name, &FirstPart, &RemainingPart);
+            if ((i > 0) && DbcsName.Buffer[i - 1] == ' ')
+                return FALSE;
+        }
+        /* Filename mustn't finish with a space */
+        else if (DbcsName.Buffer[i] == ' ' && i == (DbcsName.Length - 1))
+        {
+            return FALSE;
+        }
 
-        /* We found a pathname, it wasn't allowed */
-        if (FirstPart.Length > 0 && !PathNamePermissible)
+        if (!LastDot && (i >= 8))
             return FALSE;
     }
+
     return TRUE;
 }
 
@@ -569,7 +640,7 @@ FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName,
                      IN BOOLEAN PathNamePermissible,
                      IN BOOLEAN LeadingBackslashPermissible)
 {
-    ANSI_STRING FirstPart, RemainingPart, Name;
+    ANSI_STRING FirstPart, RemainingPart;
     USHORT i;
     PAGED_CODE();
 
@@ -577,6 +648,20 @@ FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName,
     if (!DbcsName.Length)
         return FALSE;
 
+    /* Accept special filename if wildcards are allowed */
+    if (WildCardsPermissible && (DbcsName.Length == 1 || DbcsName.Length == 2) && DbcsName.Buffer[0] == '.')
+    {
+        if (DbcsName.Length == 2)
+        {
+            if (DbcsName.Buffer[1] == '.')
+                return TRUE;
+        }
+        else
+        {
+            return TRUE;
+        }
+    }
+
     /* DbcsName wasn't supposed to be started with \ */
     if (!LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
         return FALSE;
@@ -588,64 +673,56 @@ FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName,
         DbcsName.MaximumLength = DbcsName.MaximumLength - 1;
     }
 
-    /* Extract first part of the DbcsName to work on */
-    FsRtlDissectDbcs(DbcsName, &FirstPart, &RemainingPart);
-    while (FirstPart.Length > 0)
+    if (PathNamePermissible)
     {
-        /* Accept special filename if wildcards are allowed */
-        if (WildCardsPermissible && (FirstPart.Length == 1 || FirstPart.Length == 2) && FirstPart.Buffer[0] == '.')
+        /* We copy the buffer for FsRtlDissectDbcs call */
+        RemainingPart.Buffer = DbcsName.Buffer;
+        RemainingPart.Length = DbcsName.Length;
+        RemainingPart.MaximumLength = DbcsName.MaximumLength;
+
+        while (RemainingPart.Length > 0)
         {
-            if (FirstPart.Length == 2)
-            {
-                if (FirstPart.Buffer[1] == '.')
-                {
-                    goto EndLoop;
-                }
-            }
-            else
-            {
-                goto EndLoop;
-            }
-        }
+            if (RemainingPart.Buffer[0] == '\\')
+                return FALSE;
 
-        /* Filename must be 255 bytes maximum */
-        if (FirstPart.Length > 255)
-            return FALSE;
+            /* Call once again our dissect function */
+            FsRtlDissectDbcs(RemainingPart, &FirstPart, &RemainingPart);
 
-        /* Now, we will parse the filename to find everything bad in */
-        for (i = 0; i < FirstPart.Length; i++)
-        {
-            /* First make sure the character it's not the Lead DBCS */
-            if (FsRtlIsLeadDbcsCharacter(FirstPart.Buffer[i]))
-            {
-                if (i == (FirstPart.Length) - 1)
-                    return FALSE;
-                i++;
-            }
-            /* Then check for bad characters */
-            else if (!FsRtlIsAnsiCharacterLegalHpfs(FirstPart.Buffer[i], WildCardsPermissible))
+            if (!FsRtlIsHpfsDbcsLegal(FirstPart,
+                                      WildCardsPermissible,
+                                      FALSE,
+                                      FALSE))
             {
                 return FALSE;
             }
         }
 
-        /* Filename mustn't finish with a space or a dot */
-        if ((FirstPart.Buffer[FirstPart.Length - 1] == ' ') ||
-            (FirstPart.Buffer[FirstPart.Length - 1] == '.'))
-            return FALSE;
-
-        EndLoop:
-        /* Preparing next loop */
-        Name.Buffer = RemainingPart.Buffer;
-        Name.Length = RemainingPart.Length;
-        Name.MaximumLength = RemainingPart.MaximumLength;
+        return TRUE;
+    }
 
-        /* Call once again our dissect function */
-        FsRtlDissectDbcs(Name, &FirstPart, &RemainingPart);
+    if (DbcsName.Length > 255)
+        return FALSE;
 
-        /* We found a pathname, it wasn't allowed */
-        if (FirstPart.Length > 0 && !PathNamePermissible)
+    for (i = 0; i < DbcsName.Length; i++)
+    {
+        /* First make sure the character it's not the Lead DBCS */
+        if (FsRtlIsLeadDbcsCharacter(DbcsName.Buffer[i]))
+        {
+            if (i == (DbcsName.Length - 1))
+                return FALSE;
+            i++;
+        }
+        /* Then check for bad characters */
+        else if (!FsRtlIsAnsiCharacterLegalHpfs(DbcsName.Buffer[i], WildCardsPermissible))
+        {
+            return FALSE;
+        }
+        /* Filename mustn't finish with a space or a dot */
+        else if ((DbcsName.Buffer[i] == ' ' || DbcsName.Buffer[i] == '.') && i == (DbcsName.Length - 1))
+        {
             return FALSE;
+        }
     }
+
     return TRUE;
 }