ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dbcsname.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/fsrtl/name.c
00005  * PURPOSE:         Provides DBCS parsing and other support routines for FSDs
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  *                  Pierre Schweitzer (pierre.schweitzer@reactos.org)
00008  */
00009 
00010 /* INCLUDES ******************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* PUBLIC FUNCTIONS **********************************************************/
00017 
00018 /*++
00019  * @name FsRtlDissectDbcs
00020  * @implemented
00021  *
00022  * Dissects a given path name into first and remaining part.
00023  *
00024  * @param Name
00025  *        ANSI string to dissect.
00026  *
00027  * @param FirstPart
00028  *        Pointer to user supplied ANSI_STRING, that will later point
00029  *        to the first part of the original name.
00030  *
00031  * @param RemainingPart
00032  *        Pointer to user supplied ANSI_STRING, that will later point
00033  *        to the remaining part of the original name.
00034  *
00035  * @return None
00036  *
00037  * @remarks Example:
00038  *          Name:           \test1\test2\test3
00039  *          FirstPart:      test1
00040  *          RemainingPart:  test2\test3
00041  *
00042  *--*/
00043 VOID
00044 NTAPI
00045 FsRtlDissectDbcs(IN ANSI_STRING Name,
00046                  OUT PANSI_STRING FirstPart,
00047                  OUT PANSI_STRING RemainingPart)
00048 {
00049     USHORT FirstPosition, i;
00050     USHORT SkipFirstSlash = 0;
00051     PAGED_CODE();
00052 
00053     /* Zero the strings before continuing */
00054     RtlZeroMemory(FirstPart, sizeof(ANSI_STRING));
00055     RtlZeroMemory(RemainingPart, sizeof(ANSI_STRING));
00056 
00057     /* Just quit if the string is empty */
00058     if (!Name.Length) return;
00059 
00060     /* Find first backslash */
00061     FirstPosition = Name.Length;
00062     for (i = 0; i < Name.Length; i++)
00063     {
00064         /* First make sure the character it's not the Lead DBCS */
00065         if (FsRtlIsLeadDbcsCharacter(Name.Buffer[i]))
00066         {
00067             i++;
00068         }
00069         /* If we found one... */
00070         else if (Name.Buffer[i] == '\\')
00071         {
00072             /* If it begins string, just notice it and continue */
00073             if (i == 0)
00074             {
00075                 SkipFirstSlash = 1;
00076             }
00077             else
00078             {
00079                 /* Else, save its position and break out of the loop */
00080                 FirstPosition = i;
00081                 break;
00082             }
00083         }
00084     }
00085 
00086     /* Set up the first result string */
00087     FirstPart->Buffer = Name.Buffer + SkipFirstSlash;
00088     FirstPart->Length = (FirstPosition - SkipFirstSlash);
00089     FirstPart->MaximumLength = FirstPart->Length;
00090 
00091     /* And second one, if necessary */
00092     if (FirstPosition < (Name.Length))
00093     {
00094         RemainingPart->Buffer = Name.Buffer + FirstPosition + 1;
00095         RemainingPart->Length = Name.Length - (FirstPosition + 1);
00096         RemainingPart->MaximumLength = RemainingPart->Length;
00097     }
00098 }
00099 
00100 /*++
00101  * @name FsRtlDoesDbcsContainWildCards
00102  * @implemented
00103  *
00104  * Returns TRUE if the given DbcsName contains wildcards such as *, ?, 
00105  * ANSI_DOS_STAR, ANSI_DOS_DOT, and ANSI_DOS_QM
00106  *
00107  * @param Name
00108  *        The Name to check
00109  *
00110  * @return TRUE if there are wildcards, FALSE otherwise
00111  *
00112  * @remarks None
00113  *
00114  *--*/
00115 BOOLEAN
00116 NTAPI
00117 FsRtlDoesDbcsContainWildCards(IN PANSI_STRING Name)
00118 {
00119     USHORT i;
00120     PAGED_CODE();
00121 
00122     /* Check every character */
00123     for (i = 0; i < Name->Length; i++)
00124     {
00125         /* First make sure it's not the Lead DBCS */
00126         if (FsRtlIsLeadDbcsCharacter(Name->Buffer[i]))
00127         {
00128             i++;
00129         }
00130         else if (FsRtlIsAnsiCharacterWild(Name->Buffer[i]))
00131         {
00132             /* Now return if it has a wildcard */
00133             return TRUE;
00134         }
00135     }
00136 
00137     /* We didn't return above...so none found */
00138     return FALSE;
00139 }
00140 
00141 /*++
00142  * @name FsRtlIsDbcsInExpression
00143  * @implemented
00144  *
00145  * Check if the Name string is in the Expression string.
00146  *
00147  * @param Expression
00148  *        The string in which we've to find Name. It can contains wildcards
00149  *
00150  * @param Name
00151  *        The string to find. It cannot contain wildcards.
00152  *
00153  * @return TRUE if Name is found in Expression, FALSE otherwise
00154  *
00155  * @remarks
00156  *
00157  *--*/
00158 BOOLEAN
00159 NTAPI
00160 FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
00161                         IN PANSI_STRING Name)
00162 {
00163     SHORT StarFound = -1;
00164     PUSHORT BackTracking = NULL;
00165     USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars;
00166     PAGED_CODE();
00167 
00168     ASSERT(Name->Length);
00169     ASSERT(Expression->Length);
00170     ASSERT(!FsRtlDoesDbcsContainWildCards(Name));
00171 
00172     while (NamePosition < Name->Length && ExpressionPosition < Expression->Length)
00173     {
00174         /* Basic check to test if chars are equal */
00175         if ((Expression->Buffer[ExpressionPosition] == Name->Buffer[NamePosition]))
00176         {
00177             NamePosition++;
00178             ExpressionPosition++;
00179         }
00180         /* Check cases that eat one char */
00181         else if ((Expression->Buffer[ExpressionPosition] == '?') || (Expression->Buffer[ExpressionPosition] == ANSI_DOS_QM) ||
00182                  (Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT && Name->Buffer[NamePosition] == '.'))
00183         {
00184             NamePosition++;
00185             ExpressionPosition++;
00186         }
00187         /* Test star */
00188         else if (Expression->Buffer[ExpressionPosition] == '*')
00189         {
00190             /* Skip contigous stars */
00191             while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == '*')
00192             {
00193                 ExpressionPosition++;
00194             }
00195 
00196             /* Save star position */
00197             if (!BackTracking)
00198             {
00199                 BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
00200                                                      Expression->Length * sizeof(USHORT), 'nrSF');
00201             }
00202             BackTracking[++StarFound] = ExpressionPosition++;
00203 
00204             /* If star is at the end, then eat all rest and leave */
00205             if (ExpressionPosition == Expression->Length)
00206             {
00207                 NamePosition = Name->Length;
00208                 break;
00209             }
00210             else if (Expression->Buffer[ExpressionPosition] != '?')
00211             {
00212                 NamePosition++;
00213             }
00214         }
00215         /* Check DOS_STAR */
00216         else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
00217         {
00218             MatchingChars = NamePosition;
00219             while (MatchingChars < Name->Length)
00220             {
00221                 if (Name->Buffer[MatchingChars] == '.')
00222                 {
00223                     NamePosition = MatchingChars;
00224                 }
00225                 MatchingChars++;
00226             }
00227             ExpressionPosition++;
00228         }
00229         /* If nothing match, try to backtrack */
00230         else if (StarFound >= 0)
00231         {
00232             ExpressionPosition = BackTracking[StarFound--];
00233         }
00234         /* Otherwise, fail */
00235         else
00236         {
00237             break;
00238         }
00239 
00240         /* Under certain circumstances, expression is over, but name isn't
00241          * and we can backtrack, then, backtrack */
00242         if (ExpressionPosition == Expression->Length &&
00243             NamePosition != Name->Length && StarFound >= 0)
00244         {
00245             ExpressionPosition = BackTracking[StarFound--];
00246         }
00247     }
00248     if (ExpressionPosition + 1 == Expression->Length && NamePosition == Name->Length &&
00249         Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT)
00250     {
00251         ExpressionPosition++;
00252     }
00253 
00254     if (BackTracking)
00255     {
00256         ExFreePoolWithTag(BackTracking, 'nrSF');
00257     }
00258 
00259     return (ExpressionPosition == Expression->Length && NamePosition == Name->Length);
00260 }
00261 
00262 /*++
00263  * @name FsRtlIsFatDbcsLegal
00264  * @implemented
00265  *
00266  * Returns TRUE if the given DbcsName is a valid FAT filename (in 8.3)
00267  *
00268  * @param DbcsName
00269  *        The filename to check. It can also contains pathname.
00270  *
00271  * @param WildCardsPermissible
00272  *        If this is set to FALSE and if filename contains wildcard, the function 
00273  *        will fail
00274  *
00275  * @param PathNamePermissible
00276  *        If this is set to FALSE and if the filename comes with a pathname, the
00277  *        function will fail
00278  *
00279  * @param LeadingBackslashPermissible
00280  *        If this is set to FALSE and if the filename starts with a backslash, the
00281  *        function will fail
00282  *
00283  * @return TRUE if the DbcsName is legal, FALSE otherwise
00284  *
00285  * @remarks None
00286  *
00287  *--*/
00288 BOOLEAN
00289 NTAPI
00290 FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName,
00291                     IN BOOLEAN WildCardsPermissible,
00292                     IN BOOLEAN PathNamePermissible,
00293                     IN BOOLEAN LeadingBackslashPermissible)
00294 {
00295     ANSI_STRING FirstPart, RemainingPart, Name;
00296     BOOLEAN LastDot;
00297     USHORT i;
00298     PAGED_CODE();
00299 
00300     /* Just quit if the string is empty */
00301     if (!DbcsName.Length)
00302         return FALSE;
00303 
00304     /* DbcsName wasn't supposed to be started with \ */
00305     if (!LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
00306         return FALSE;
00307     /* DbcsName was allowed to be started with \, but now, remove it */
00308     else if (LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
00309     {
00310         DbcsName.Buffer = DbcsName.Buffer + 1;
00311         DbcsName.Length = DbcsName.Length - 1;
00312         DbcsName.MaximumLength = DbcsName.MaximumLength - 1;
00313     }
00314 
00315     /* Extract first part of the DbcsName to work on */
00316     FsRtlDissectDbcs(DbcsName, &FirstPart, &RemainingPart);
00317     while (FirstPart.Length > 0)
00318     {
00319         /* Reset dots count */
00320         LastDot = FALSE;
00321 
00322         /* Accept special filename if wildcards are allowed */
00323         if (WildCardsPermissible && (FirstPart.Length == 1 || FirstPart.Length == 2) && FirstPart.Buffer[0] == '.')
00324         {
00325             if (FirstPart.Length == 2)
00326             {
00327                 if (FirstPart.Buffer[1] == '.')
00328                 {
00329                     goto EndLoop;
00330                 }
00331             }
00332             else
00333             {
00334                 goto EndLoop;
00335             }
00336         }
00337 
00338         /* Filename must be 8.3 filename */
00339         if (FirstPart.Length < 3 || FirstPart.Length > 12)
00340             return FALSE;
00341 
00342         /* Now, we will parse the filename to find everything bad in */
00343         for (i = 0; i < FirstPart.Length; i++)
00344         {
00345             /* First make sure the character it's not the Lead DBCS */
00346             if (FsRtlIsLeadDbcsCharacter(FirstPart.Buffer[i]))
00347             {
00348                 if (i == (FirstPart.Length) - 1)
00349                     return FALSE;
00350                 i++;
00351             }
00352             /* Then check for bad characters */
00353             else if (!FsRtlIsAnsiCharacterLegalFat(FirstPart.Buffer[i], WildCardsPermissible))
00354             {
00355                 return FALSE;
00356             }
00357             else if (FirstPart.Buffer[i] == '.')
00358             {
00359                 /* Filename can only contain one dot */
00360                 if (LastDot)
00361                     return FALSE;
00362 
00363                 LastDot = TRUE;
00364 
00365                 /* We mustn't have spaces before dot or at the end of the filename
00366                  * and no dot at the beginning of the filename */
00367                 if ((i == (FirstPart.Length) - 1) || i == 0)
00368                     return FALSE;
00369 
00370                 if (i > 0)
00371                     if (FirstPart.Buffer[i - 1] == ' ')
00372                         return FALSE;
00373 
00374                 /* Filename must be 8.3 filename and not 3.8 filename */
00375                 if ((FirstPart.Length - 1) - i > 3)
00376                     return FALSE;
00377             }
00378         }
00379 
00380         /* Filename mustn't finish with a space */
00381         if (FirstPart.Buffer[FirstPart.Length - 1] == ' ')
00382             return FALSE;
00383 
00384         EndLoop:
00385         /* Preparing next loop */
00386         Name.Buffer = RemainingPart.Buffer;
00387         Name.Length = RemainingPart.Length;
00388         Name.MaximumLength = RemainingPart.MaximumLength;
00389 
00390         /* Call once again our dissect function */
00391         FsRtlDissectDbcs(Name, &FirstPart, &RemainingPart);
00392 
00393         /* We found a pathname, it wasn't allowed */
00394         if (FirstPart.Length > 0 && !PathNamePermissible)
00395             return FALSE;
00396     }
00397     return TRUE;
00398 }
00399 
00400 /*++
00401  * @name FsRtlIsHpfsDbcsLegal
00402  * @implemented
00403  *
00404  * Returns TRUE if the given DbcsName is a valid HPFS filename
00405  *
00406  * @param DbcsName
00407  *        The filename to check. It can also contains pathname.
00408  *
00409  * @param WildCardsPermissible
00410  *        If this is set to FALSE and if filename contains wildcard, the function 
00411  *        will fail
00412  *
00413  * @param PathNamePermissible
00414  *        If this is set to FALSE and if the filename comes with a pathname, the
00415  *        function will fail
00416  *
00417  * @param LeadingBackslashPermissible
00418  *        If this is set to FALSE and if the filename starts with a backslash, the
00419  *        function will fail
00420  *
00421  * @return TRUE if the DbcsName is legal, FALSE otherwise
00422  *
00423  * @remarks None
00424  *
00425  *--*/
00426 BOOLEAN
00427 NTAPI
00428 FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName,
00429                      IN BOOLEAN WildCardsPermissible,
00430                      IN BOOLEAN PathNamePermissible,
00431                      IN BOOLEAN LeadingBackslashPermissible)
00432 {
00433     ANSI_STRING FirstPart, RemainingPart, Name;
00434     USHORT i;
00435     PAGED_CODE();
00436 
00437     /* Just quit if the string is empty */
00438     if (!DbcsName.Length)
00439         return FALSE;
00440 
00441     /* DbcsName wasn't supposed to be started with \ */
00442     if (!LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
00443         return FALSE;
00444     /* DbcsName was allowed to be started with \, but now, remove it */
00445     else if (LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
00446     {
00447         DbcsName.Buffer = DbcsName.Buffer + 1;
00448         DbcsName.Length = DbcsName.Length - 1;
00449         DbcsName.MaximumLength = DbcsName.MaximumLength - 1;
00450     }
00451 
00452     /* Extract first part of the DbcsName to work on */
00453     FsRtlDissectDbcs(DbcsName, &FirstPart, &RemainingPart);
00454     while (FirstPart.Length > 0)
00455     {
00456         /* Accept special filename if wildcards are allowed */
00457         if (WildCardsPermissible && (FirstPart.Length == 1 || FirstPart.Length == 2) && FirstPart.Buffer[0] == '.')
00458         {
00459             if (FirstPart.Length == 2)
00460             {
00461                 if (FirstPart.Buffer[1] == '.')
00462                 {
00463                     goto EndLoop;
00464                 }
00465             }
00466             else
00467             {
00468                 goto EndLoop;
00469             }
00470         }
00471 
00472         /* Filename must be 255 bytes maximum */
00473         if (FirstPart.Length > 255)
00474             return FALSE;
00475 
00476         /* Now, we will parse the filename to find everything bad in */
00477         for (i = 0; i < FirstPart.Length; i++)
00478         {
00479             /* First make sure the character it's not the Lead DBCS */
00480             if (FsRtlIsLeadDbcsCharacter(FirstPart.Buffer[i]))
00481             {
00482                 if (i == (FirstPart.Length) - 1)
00483                     return FALSE;
00484                 i++;
00485             }
00486             /* Then check for bad characters */
00487             else if (!FsRtlIsAnsiCharacterLegalHpfs(FirstPart.Buffer[i], WildCardsPermissible))
00488             {
00489                 return FALSE;
00490             }
00491         }
00492 
00493         /* Filename mustn't finish with a space or a dot */
00494         if ((FirstPart.Buffer[FirstPart.Length - 1] == ' ') ||
00495             (FirstPart.Buffer[FirstPart.Length - 1] == '.'))
00496             return FALSE;
00497 
00498         EndLoop:
00499         /* Preparing next loop */
00500         Name.Buffer = RemainingPart.Buffer;
00501         Name.Length = RemainingPart.Length;
00502         Name.MaximumLength = RemainingPart.MaximumLength;
00503 
00504         /* Call once again our dissect function */
00505         FsRtlDissectDbcs(Name, &FirstPart, &RemainingPart);
00506 
00507         /* We found a pathname, it wasn't allowed */
00508         if (FirstPart.Length > 0 && !PathNamePermissible)
00509             return FALSE;
00510     }
00511     return TRUE;
00512 }

Generated on Sun May 27 2012 04:37:10 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.