Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dbcsname.c File Reference

#include "FsRtlP.h"

Go to the source code of this file.

Defines

#define Dbg   (0x10000000)
#define DavePrint   NOTHING
#define MODULE_POOL_TAG   ('drSF')
#define GetDbcs(BUF, OFFSET, DBCS_CHAR, LENGTH)
#define MATCHES_ARRAY_SIZE   16

Functions

BOOLEAN FsRtlIsFatDbcsLegal (IN ANSI_STRING DbcsName, IN BOOLEAN WildCardsPermissible, IN BOOLEAN PathNamePermissible, IN BOOLEAN LeadingBackslashPermissible)
BOOLEAN FsRtlIsHpfsDbcsLegal (IN ANSI_STRING DbcsName, IN BOOLEAN WildCardsPermissible, IN BOOLEAN PathNamePermissible, IN BOOLEAN LeadingBackslashPermissible)
VOID FsRtlDissectDbcs (IN ANSI_STRING Path, OUT PANSI_STRING FirstName, OUT PANSI_STRING RemainingName)
BOOLEAN FsRtlDoesDbcsContainWildCards (IN PANSI_STRING Name)
BOOLEAN FsRtlIsDbcsInExpression (IN PANSI_STRING Expression, IN PANSI_STRING Name)


Define Documentation

#define DavePrint   NOTHING
 

Definition at line 60 of file dbcsname.c.

#define Dbg   (0x10000000)
 

Definition at line 47 of file dbcsname.c.

#define GetDbcs BUF,
OFFSET,
DBCS_CHAR,
LENGTH   ) 
 

Value:

{ \ if (FsRtlIsLeadDbcsCharacter( (BUF)[(OFFSET)] )) { \ *(DBCS_CHAR) = (WCHAR)((BUF)[(OFFSET)] + \ 0x100 * (BUF)[(OFFSET) + 1]); \ *(LENGTH) = 2; \ } else { \ *(DBCS_CHAR) = (WCHAR)(BUF)[(OFFSET)]; \ *(LENGTH) = 1; \ } \ }

Definition at line 757 of file dbcsname.c.

Referenced by FsRtlIsDbcsInExpression().

#define MATCHES_ARRAY_SIZE   16
 

Definition at line 768 of file dbcsname.c.

Referenced by FsRtlIsDbcsInExpression(), and FsRtlIsNameInExpressionPrivate().

#define MODULE_POOL_TAG   ('drSF')
 

Definition at line 69 of file dbcsname.c.

Referenced by FsRtlpRegisterProviderWithMUP(), and FsRtlRegisterUncProvider().


Function Documentation

VOID FsRtlDissectDbcs IN ANSI_STRING  Path,
OUT PANSI_STRING  FirstName,
OUT PANSI_STRING  RemainingName
 

Definition at line 542 of file dbcsname.c.

References FsRtlIsLeadDbcsCharacter, NULL, PAGED_CODE, and USHORT.

Referenced by FsRtlIsFatDbcsLegal(), and FsRtlIsHpfsDbcsLegal().

00550 : 00551 00552 This routine takes an input Dbcs string and dissects it into two 00553 substrings. The first output string contains the name that appears at 00554 the beginning of the input string, the second output string contains the 00555 remainder of the input string. 00556 00557 In the input string backslashes are used to separate names. The input 00558 string must not start with a backslash. Both output strings will not 00559 begin with a backslash. 00560 00561 If the input string does not contain any names then both output strings 00562 are empty. If the input string contains only one name then the first 00563 output string contains the name and the second string is empty. 00564 00565 Note that both output strings use the same string buffer memory of the 00566 input string. 00567 00568 Example of its results are: 00569 00570 //. . InputString FirstPart RemainingPart 00571 // 00572 //. . empty empty empty 00573 // 00574 //. . A A empty 00575 // 00576 //. . A\B\C\D\E A B\C\D\E 00577 // 00578 //. . *A? *A? empty 00579 // 00580 //. . \A A empty 00581 // 00582 //. . A[,] A[,] empty 00583 // 00584 //. . A\\B+;\C A \B+;\C 00585 00586 Arguments: 00587 00588 InputName - Supplies the input string being dissected 00589 00590 Is8dot3 - Indicates if the first part of the input name must be 8.3 00591 or can be long file name. 00592 00593 FirstPart - Receives the first name in the input string 00594 00595 RemainingPart - Receives the remaining part of the input string 00596 00597 Return Value: 00598 00599 NONE 00600 00601 --*/ 00602 00603 { 00604 ULONG i = 0; 00605 ULONG PathLength; 00606 ULONG FirstNameStart; 00607 00608 PAGED_CODE(); 00609 00610 // 00611 // Make both output strings empty for now 00612 // 00613 00614 FirstName->Length = 0; 00615 FirstName->MaximumLength = 0; 00616 FirstName->Buffer = NULL; 00617 00618 RemainingName->Length = 0; 00619 RemainingName->MaximumLength = 0; 00620 RemainingName->Buffer = NULL; 00621 00622 PathLength = Path.Length; 00623 00624 // 00625 // Check for an empty input string 00626 // 00627 00628 if (PathLength == 0) { 00629 00630 return; 00631 } 00632 00633 // 00634 // Skip over a starting backslash, and make sure there is more. 00635 // 00636 00637 if ( Path.Buffer[0] == '\\' ) { 00638 00639 i = 1; 00640 } 00641 00642 // 00643 // Now run down the input string until we hit a backslash or the end 00644 // of the string, remembering where we started; 00645 // 00646 00647 for ( FirstNameStart = i; 00648 (i < PathLength) && (Path.Buffer[i] != '\\'); 00649 i += 1 ) { 00650 00651 // 00652 // If this is the first byte of a Dbcs character, skip over the 00653 // next byte as well. 00654 // 00655 00656 if ( FsRtlIsLeadDbcsCharacter( Path.Buffer[i] ) ) { 00657 00658 i += 1; 00659 } 00660 } 00661 00662 // 00663 // At this point all characters up to (but not including) i are 00664 // in the first part. So setup the first name 00665 // 00666 00667 FirstName->Length = (USHORT)(i - FirstNameStart); 00668 FirstName->MaximumLength = FirstName->Length; 00669 FirstName->Buffer = &Path.Buffer[FirstNameStart]; 00670 00671 // 00672 // Now the remaining part needs a string only if the first part didn't 00673 // exhaust the entire input string. We know that if anything is left 00674 // that is must start with a backslash. Note that if there is only 00675 // a trailing backslash, the length will get correctly set to zero. 00676 // 00677 00678 if (i < PathLength) { 00679 00680 RemainingName->Length = (USHORT)(PathLength - (i + 1)); 00681 RemainingName->MaximumLength = RemainingName->Length; 00682 RemainingName->Buffer = &Path.Buffer[i + 1]; 00683 } 00684 00685 // 00686 // And return to our caller 00687 // 00688 00689 return; 00690 }

BOOLEAN FsRtlDoesDbcsContainWildCards IN PANSI_STRING  Name  ) 
 

Definition at line 694 of file dbcsname.c.

References FALSE, FsRtlIsAnsiCharacterWild, FsRtlIsLeadDbcsCharacter, Name, PAGED_CODE, and TRUE.

Referenced by FsRtlIsDbcsInExpression(), and FsRtlIsFatDbcsLegal().

00700 : 00701 00702 This routine checks if the input Dbcs name contains any wild card 00703 characters (i.e., *, ?, ANSI_DOS_STAR, or ANSI_DOS_QM). 00704 00705 Arguments: 00706 00707 Name - Supplies the name to examine 00708 00709 Return Value: 00710 00711 BOOLEAN - TRUE if the input name contains any wildcard characters and 00712 FALSE otherwise. 00713 00714 --*/ 00715 00716 { 00717 CLONG i; 00718 00719 PAGED_CODE(); 00720 00721 // 00722 // Check each character in the name to see if it's a wildcard 00723 // character 00724 // 00725 00726 for (i = 0; i < Name->Length; i += 1) { 00727 00728 // 00729 // check for dbcs character because we'll just skip over those 00730 // 00731 00732 if (FsRtlIsLeadDbcsCharacter( Name->Buffer[i] )) { 00733 00734 i += 1; 00735 00736 // 00737 // else check for a wild card character 00738 // 00739 00740 } else if (FsRtlIsAnsiCharacterWild( Name->Buffer[i] )) { 00741 00742 // 00743 // Tell caller that this name contains wild cards 00744 // 00745 00746 return TRUE; 00747 } 00748 } 00749 00750 // 00751 // No wildcard characters were found, so return to our caller 00752 // 00753 00754 return FALSE; 00755 }

BOOLEAN FsRtlIsDbcsInExpression IN PANSI_STRING  Expression,
IN PANSI_STRING  Name
 

Definition at line 771 of file dbcsname.c.

References ASSERT, Dbg, DebugTrace, ExFreePool(), FALSE, FsRtlDoesDbcsContainWildCards(), FsRtlIsLeadDbcsCharacter, FsRtlpAllocatePool, GetDbcs, MATCHES_ARRAY_SIZE, Name, NlsMbOemCodePageTag, NULL, Offset, PAGED_CODE, PagedPool, TRUE, and USHORT.

00778 : 00779 00780 This routine compares a Dbcs name and an expression and tells the caller 00781 if the name is in the language defined by the expression. The input name 00782 cannot contain wildcards, while the expression may contain wildcards. 00783 00784 Expression wild cards are evaluated as shown in the nondeterministic 00785 finite automatons below. Note that ~* and ~? are DOS_STAR and DOS_QM. 00786 00787 00788 ~* is DOS_STAR, ~? is DOS_QM, and ~. is DOS_DOT 00789 00790 00791 S 00792 <-----< 00793 X | | e Y 00794 X * Y == (0)----->-(1)->-----(2)-----(3) 00795 00796 00797 S-. 00798 <-----< 00799 X | | e Y 00800 X ~* Y == (0)----->-(1)->-----(2)-----(3) 00801 00802 00803 00804 X S S Y 00805 X ?? Y == (0)---(1)---(2)---(3)---(4) 00806 00807 00808 00809 X . . Y 00810 X ~.~. Y == (0)---(1)----(2)------(3)---(4) 00811 | |________| 00812 | ^ | 00813 |_______________| 00814 ^EOF or .^ 00815 00816 00817 X S-. S-. Y 00818 X ~?~? Y == (0)---(1)-----(2)-----(3)---(4) 00819 | |________| 00820 | ^ | 00821 |_______________| 00822 ^EOF or .^ 00823 00824 00825 00826 where S is any single character 00827 00828 S-. is any single character except the final . 00829 00830 e is a null character transition 00831 00832 EOF is the end of the name string 00833 00834 In words: 00835 00836 * matches 0 or more characters. 00837 00838 ? matches exactly 1 character. 00839 00840 DOS_STAR matches 0 or more characters until encountering and matching 00841 the final . in the name. 00842 00843 DOS_QM matches any single character, or upon encountering a period or 00844 end of name string, advances the expression to the end of the 00845 set of contiguous DOS_QMs. 00846 00847 DOS_DOT matches either a . or zero characters beyond name string. 00848 00849 Arguments: 00850 00851 Expression - Supplies the input expression to check against 00852 00853 Name - Supplies the input name to check for. 00854 00855 Return Value: 00856 00857 BOOLEAN - TRUE if Name is an element in the set of strings denoted 00858 by the input Expression and FALSE otherwise. 00859 00860 --*/ 00861 00862 { 00863 USHORT NameOffset; 00864 USHORT ExprOffset; 00865 USHORT Length; 00866 00867 ULONG SrcCount; 00868 ULONG DestCount; 00869 ULONG PreviousDestCount; 00870 ULONG MatchesCount; 00871 00872 WCHAR NameChar, ExprChar; 00873 00874 USHORT LocalBuffer[MATCHES_ARRAY_SIZE * 2]; 00875 00876 USHORT *AuxBuffer = NULL; 00877 USHORT *PreviousMatches; 00878 USHORT *CurrentMatches; 00879 00880 USHORT MaxState; 00881 USHORT CurrentState; 00882 00883 BOOLEAN NameFinished = FALSE; 00884 00885 // 00886 // The idea behind the algorithm is pretty simple. We keep track of 00887 // all possible locations in the regular expression that are matching 00888 // the name. If when the name has been exhausted one of the locations 00889 // in the expression is also just exhausted, the name is in the language 00890 // defined by the regular expression. 00891 // 00892 00893 PAGED_CODE(); 00894 00895 DebugTrace(+1, Dbg, "FsRtlIsDbcsInExpression\n", 0); 00896 DebugTrace( 0, Dbg, " Expression = %Z\n", Expression ); 00897 DebugTrace( 0, Dbg, " Name = %Z\n", Name ); 00898 00899 ASSERT( Name->Length != 0 ); 00900 ASSERT( Expression->Length != 0 ); 00901 00902 // 00903 // If one string is empty return FALSE. If both are empty return TRUE. 00904 // 00905 00906 if ( (Name->Length == 0) || (Expression->Length == 0) ) { 00907 00908 return (BOOLEAN)(!(Name->Length + Expression->Length)); 00909 } 00910 00911 // 00912 // Special case by far the most common wild card search of * 00913 // 00914 00915 if ((Expression->Length == 1) && (Expression->Buffer[0] == '*')) { 00916 00917 return TRUE; 00918 } 00919 00920 ASSERT( FsRtlDoesDbcsContainWildCards( Expression ) ); 00921 00922 // 00923 // Also special case expressions of the form *X. With this and the prior 00924 // case we have covered virtually all normal queries. 00925 // 00926 00927 if (Expression->Buffer[0] == '*') { 00928 00929 ANSI_STRING LocalExpression; 00930 00931 LocalExpression = *Expression; 00932 00933 LocalExpression.Buffer += 1; 00934 LocalExpression.Length -= 1; 00935 00936 // 00937 // Only special case an expression with a single * 00938 // 00939 00940 if ( !FsRtlDoesDbcsContainWildCards( &LocalExpression ) ) { 00941 00942 ULONG StartingNameOffset; 00943 00944 if (Name->Length < (USHORT)(Expression->Length - 1)) { 00945 00946 return FALSE; 00947 } 00948 00949 StartingNameOffset = Name->Length - LocalExpression.Length; 00950 00951 // 00952 // FsRtlIsDbcsInExpression(): bug fix "expression[0] == *" case 00953 // 00954 // StatingNameOffset must not bisect DBCS characters. 00955 // 00956 00957 if (NlsMbOemCodePageTag) { 00958 00959 ULONG i = 0; 00960 00961 while ( i < StartingNameOffset ) { 00962 00963 i += FsRtlIsLeadDbcsCharacter( Name->Buffer[i] ) ? 2 : 1; 00964 } 00965 00966 if ( i > StartingNameOffset ) { 00967 00968 return FALSE; 00969 } 00970 } 00971 00972 // 00973 // Do a simple memory compare if case sensitive, otherwise 00974 // we have got to check this one character at a time. 00975 // 00976 00977 return (BOOLEAN) RtlEqualMemory( LocalExpression.Buffer, 00978 Name->Buffer + StartingNameOffset, 00979 LocalExpression.Length ); 00980 } 00981 } 00982 00983 // 00984 // Walk through the name string, picking off characters. We go one 00985 // character beyond the end because some wild cards are able to match 00986 // zero characters beyond the end of the string. 00987 // 00988 // With each new name character we determine a new set of states that 00989 // match the name so far. We use two arrays that we swap back and forth 00990 // for this purpose. One array lists the possible expression states for 00991 // all name characters up to but not including the current one, and other 00992 // array is used to build up the list of states considering the current 00993 // name character as well. The arrays are then switched and the process 00994 // repeated. 00995 // 00996 // There is not a one-to-one correspondence between state number and 00997 // offset into the expression. This is evident from the NFAs in the 00998 // initial comment to this function. State numbering is not continuous. 00999 // This allows a simple conversion between state number and expression 01000 // offset. Each character in the expression can represent one or two 01001 // states. * and DOS_STAR generate two states: ExprOffset*2 and 01002 // ExprOffset*2 + 1. All other expreesion characters can produce only 01003 // a single state. Thus ExprOffset = State/2. 01004 // 01005 // 01006 // Here is a short description of the variables involved: 01007 // 01008 // NameOffset - The offset of the current name char being processed. 01009 // 01010 // ExprOffset - The offset of the current expression char being processed. 01011 // 01012 // SrcCount - Prior match being investigated with current name char 01013 // 01014 // DestCount - Next location to put a matching assuming current name char 01015 // 01016 // NameFinished - Allows one more itteration through the Matches array 01017 // after the name is exhusted (to come *s for example) 01018 // 01019 // PreviousDestCount - This is used to prevent entry duplication, see coment 01020 // 01021 // PreviousMatches - Holds the previous set of matches (the Src array) 01022 // 01023 // CurrentMatches - Holds the current set of matches (the Dest array) 01024 // 01025 // AuxBuffer, LocalBuffer - the storage for the Matches arrays 01026 // 01027 01028 // 01029 // Set up the initial variables 01030 // 01031 01032 PreviousMatches = &LocalBuffer[0]; 01033 CurrentMatches = &LocalBuffer[MATCHES_ARRAY_SIZE]; 01034 01035 PreviousMatches[0] = 0; 01036 MatchesCount = 1; 01037 01038 NameOffset = 0; 01039 01040 MaxState = (USHORT)(Expression->Length * 2); 01041 01042 while ( !NameFinished ) { 01043 01044 if ( NameOffset < Name->Length ) { 01045 01046 GetDbcs( Name->Buffer, NameOffset, &NameChar, &Length ); 01047 NameOffset += Length; 01048 01049 } else { 01050 01051 NameFinished = TRUE; 01052 01053 // 01054 // if we have already exhasted the expression, cool. Don't 01055 // continue. 01056 // 01057 01058 if ( PreviousMatches[MatchesCount-1] == MaxState ) { 01059 01060 break; 01061 } 01062 } 01063 01064 01065 // 01066 // Now, for each of the previous stored expression matches, see what 01067 // we can do with this name character. 01068 // 01069 01070 SrcCount = 0; 01071 DestCount = 0; 01072 PreviousDestCount = 0; 01073 01074 while ( SrcCount < MatchesCount ) { 01075 01076 // 01077 // We have to carry on our expression analysis as far as possible 01078 // for each character of name, so we loop here until the 01079 // expression stops matching. A clue here is that expression 01080 // cases that can match zero or more characters end with a 01081 // continue, while those that can accept only a single character 01082 // end with a break. 01083 // 01084 01085 ExprOffset = (USHORT)((PreviousMatches[SrcCount++] + 1) / 2); 01086 01087 Length = 0; 01088 01089 01090 while ( TRUE ) { 01091 01092 if ( ExprOffset == Expression->Length ) { 01093 01094 break; 01095 } 01096 01097 // 01098 // The first time through the loop we don't want 01099 // to increment ExprOffset. 01100 // 01101 01102 ExprOffset += Length; 01103 01104 CurrentState = (USHORT)(ExprOffset * 2); 01105 01106 if ( ExprOffset == Expression->Length ) { 01107 01108 CurrentMatches[DestCount++] = MaxState; 01109 break; 01110 } 01111 01112 GetDbcs(Expression->Buffer, ExprOffset, &ExprChar, &Length); 01113 01114 ASSERT( !((ExprChar >= 'a') && (ExprChar <= 'z')) ); 01115 01116 // 01117 // Before we get started, we have to check for something 01118 // really gross. We may be about to exhaust the local 01119 // space for ExpressionMatches[][], so we have to allocate 01120 // some pool if this is the case. Yuk! 01121 // 01122 01123 if ( (DestCount >= MATCHES_ARRAY_SIZE - 2) && 01124 (AuxBuffer == NULL) ) { 01125 01126 AuxBuffer = FsRtlpAllocatePool( PagedPool, 01127 (Expression->Length+1) * 01128 sizeof(USHORT)*2*2 ); 01129 01130 RtlCopyMemory( AuxBuffer, 01131 CurrentMatches, 01132 MATCHES_ARRAY_SIZE * sizeof(USHORT) ); 01133 01134 CurrentMatches = AuxBuffer; 01135 01136 RtlCopyMemory( AuxBuffer + (Expression->Length+1)*2, 01137 PreviousMatches, 01138 MATCHES_ARRAY_SIZE * sizeof(USHORT) ); 01139 01140 PreviousMatches = AuxBuffer + (Expression->Length+1)*2; 01141 01142 } 01143 01144 // 01145 // * matches any character zero or more times. 01146 // 01147 01148 if (ExprChar == '*') { 01149 01150 CurrentMatches[DestCount++] = CurrentState; 01151 CurrentMatches[DestCount++] = CurrentState + 1; 01152 continue; 01153 } 01154 01155 // 01156 // DOS_STAR matches any character except . zero or more times. 01157 // 01158 01159 if (ExprChar == ANSI_DOS_STAR) { 01160 01161 BOOLEAN ICanEatADot = FALSE; 01162 01163 // 01164 // If we are at a period, determine if we are allowed to 01165 // consume it, ie. make sure it is not the last one. 01166 // 01167 01168 if ( !NameFinished && (NameChar == '.') ) { 01169 01170 WCHAR NameChar; 01171 USHORT Offset; 01172 USHORT Length; 01173 01174 for ( Offset = NameOffset; 01175 Offset < Name->Length; 01176 Offset += Length ) { 01177 01178 GetDbcs( Name->Buffer, Offset, &NameChar, &Length ); 01179 01180 if (NameChar == '.') { 01181 01182 ICanEatADot = TRUE; 01183 break; 01184 } 01185 } 01186 } 01187 01188 if (NameFinished || (NameChar != '.') || ICanEatADot) { 01189 01190 CurrentMatches[DestCount++] = CurrentState; 01191 CurrentMatches[DestCount++] = CurrentState + 1; 01192 continue; 01193 01194 } else { 01195 01196 // 01197 // We are at a period. We can only match zero 01198 // characters (ie. the epsilon transition). 01199 // 01200 01201 CurrentMatches[DestCount++] = CurrentState + 1; 01202 continue; 01203 } 01204 } 01205 01206 // 01207 // The following expreesion characters all match by consuming 01208 // a character, thus force the expression, and thus state 01209 // forward. 01210 // 01211 01212 CurrentState += (USHORT)(Length * 2); 01213 01214 // 01215 // DOS_QM is the most complicated. If the name is finished, 01216 // we can match zero characters. If this name is a '.', we 01217 // don't match, but look at the next expression. Otherwise 01218 // we match a single character. 01219 // 01220 01221 if ( ExprChar == ANSI_DOS_QM ) { 01222 01223 if ( NameFinished || (NameChar == '.') ) { 01224 01225 continue; 01226 } 01227 01228 CurrentMatches[DestCount++] = CurrentState; 01229 break; 01230 } 01231 01232 // 01233 // A DOS_DOT can match either a period, or zero characters 01234 // beyond the end of name. 01235 // 01236 01237 if (ExprChar == DOS_DOT) { 01238 01239 if ( NameFinished ) { 01240 01241 continue; 01242 } 01243 01244 if (NameChar == '.') { 01245 01246 CurrentMatches[DestCount++] = CurrentState; 01247 break; 01248 } 01249 } 01250 01251 // 01252 // From this point on a name character is required to even 01253 // continue, let alone make a match. 01254 // 01255 01256 if ( NameFinished ) { 01257 01258 break; 01259 } 01260 01261 // 01262 // If this expression was a '?' we can match it once. 01263 // 01264 01265 if (ExprChar == '?') { 01266 01267 CurrentMatches[DestCount++] = CurrentState; 01268 break; 01269 } 01270 01271 // 01272 // Finally, check if the expression char matches the name char 01273 // 01274 01275 if (ExprChar == NameChar) { 01276 01277 CurrentMatches[DestCount++] = CurrentState; 01278 break; 01279 } 01280 01281 // 01282 // The expression didn't match so go look at the next 01283 // previous match. 01284 // 01285 01286 break; 01287 } 01288 01289 01290 // 01291 // Prevent duplication in the destination array. 01292 // 01293 // Each of the arrays is montonically increasing and non- 01294 // duplicating, thus we skip over any source element in the src 01295 // array if we just added the same element to the destination 01296 // array. This guarentees non-duplication in the dest. array. 01297 // 01298 01299 if ((SrcCount < MatchesCount) && 01300 (PreviousDestCount < DestCount) ) { 01301 01302 while (PreviousDestCount < DestCount) { 01303 01304 while ( PreviousMatches[SrcCount] < 01305 CurrentMatches[PreviousDestCount] ) { 01306 01307 01308 SrcCount += 1; 01309 } 01310 01311 PreviousDestCount += 1; 01312 } 01313 } 01314 } 01315 01316 // 01317 // If we found no matches in the just finished itteration, it's time 01318 // to bail. 01319 // 01320 01321 if ( DestCount == 0 ) { 01322 01323 01324 if (AuxBuffer != NULL) { ExFreePool( AuxBuffer ); } 01325 01326 return FALSE; 01327 } 01328 01329 // 01330 // Swap the meaning the two arrays 01331 // 01332 01333 { 01334 USHORT *Tmp; 01335 01336 Tmp = PreviousMatches; 01337 01338 PreviousMatches = CurrentMatches; 01339 01340 CurrentMatches = Tmp; 01341 } 01342 01343 MatchesCount = DestCount; 01344 } 01345 01346 01347 CurrentState = PreviousMatches[MatchesCount-1]; 01348 01349 if (AuxBuffer != NULL) { ExFreePool( AuxBuffer ); } 01350 01351 01352 return (BOOLEAN)(CurrentState == MaxState); 01353 } }

BOOLEAN FsRtlIsFatDbcsLegal IN ANSI_STRING  DbcsName,
IN BOOLEAN  WildCardsPermissible,
IN BOOLEAN  PathNamePermissible,
IN BOOLEAN  LeadingBackslashPermissible
 

Definition at line 81 of file dbcsname.c.

References ASSERT, FALSE, FsRtlDissectDbcs(), FsRtlDoesDbcsContainWildCards(), FsRtlIsAnsiCharacterLegalFat, FsRtlIsLeadDbcsCharacter, Index, PAGED_CODE, and TRUE.

Referenced by UdfIs8dot3Name().

00090 : 00091 00092 This routine simple returns whether the specified file names conforms 00093 to the file system specific rules for legal file names. This routine 00094 will check the single name, or if PathNamePermissible is specified as 00095 TRUE, whether the whole path is a legal name. 00096 00097 For FAT, the following rules apply: 00098 00099 A. A Fat file name may not contain any of the following characters: 00100 00101 0x00-0x1F " / : | + , ; = [ ] 00102 00103 B. A Fat file name is either of the form N.E or just N, where N is a 00104 string of 1-8 bytes and E is a string of 1-3 bytes conformant to 00105 rule A above. In addition, neither N nor E may contain a period 00106 character or end with a space character. 00107 00108 Incidently, N corresponds to name and E to extension. 00109 00110 Case: Lower case characters are taken as valid, but are up-shifted upon 00111 receipt, ie. Fat only deals with upper case file names. 00112 00113 For example, the files ".foo", "foo.", and "foo .b" are illegal, while 00114 "foo. b" and " bar" are legal. 00115 00116 Arguments: 00117 00118 DbcsName - Supllies the name/path to check. 00119 00120 WildCardsPermissible - Specifies if Nt wild card characters are to be 00121 considered considered legal. 00122 00123 PathNamePermissible - Spcifes if Name may be a path name separated by 00124 backslash characters, or just a simple file name. 00125 00126 LeadingBackSlashPermissible - Specifies if a single leading backslash 00127 is permissible in the file/path name. 00128 00129 Return Value: 00130 00131 BOOLEAN - TRUE if the name is legal, FALSE otherwise. 00132 00133 --*/ 00134 { 00135 BOOLEAN ExtensionPresent = FALSE; 00136 00137 ULONG Index; 00138 00139 UCHAR Char; 00140 00141 PAGED_CODE(); 00142 00143 // 00144 // Empty names are not valid. 00145 // 00146 00147 if ( DbcsName.Length == 0 ) { return FALSE; } 00148 00149 // 00150 // If Wild Cards are OK, then for directory enumeration to work 00151 // correctly we have to accept . and .. 00152 // 00153 00154 if ( WildCardsPermissible && 00155 ( ( (DbcsName.Length == 1) && 00156 ((DbcsName.Buffer[0] == '.') || 00157 (DbcsName.Buffer[0] == ANSI_DOS_DOT)) ) 00158 || 00159 ( (DbcsName.Length == 2) && 00160 ( ((DbcsName.Buffer[0] == '.') && 00161 (DbcsName.Buffer[1] == '.')) || 00162 ((DbcsName.Buffer[0] == ANSI_DOS_DOT) && 00163 (DbcsName.Buffer[1] == ANSI_DOS_DOT)) ) ) ) ) { 00164 00165 return TRUE; 00166 } 00167 00168 // 00169 // If a leading \ is OK, skip over it (if there's more) 00170 // 00171 00172 if ( DbcsName.Buffer[0] == '\\' ) { 00173 00174 if ( LeadingBackslashPermissible ) { 00175 00176 if ( (DbcsName.Length > 1) ) { 00177 00178 DbcsName.Buffer += 1; 00179 DbcsName.Length -= 1; 00180 00181 } else { return TRUE; } 00182 00183 } else { return FALSE; } 00184 } 00185 00186 // 00187 // If we got a path name, check each componant. 00188 // 00189 00190 if ( PathNamePermissible ) { 00191 00192 ANSI_STRING FirstName; 00193 ANSI_STRING RemainingName; 00194 00195 RemainingName = DbcsName; 00196 00197 while ( RemainingName.Length != 0 ) { 00198 00199 // 00200 // This will catch the case of an illegal double backslash. 00201 // 00202 00203 if ( RemainingName.Buffer[0] == '\\' ) { return FALSE; } 00204 00205 FsRtlDissectDbcs(RemainingName, &FirstName, &RemainingName); 00206 00207 if ( !FsRtlIsFatDbcsLegal( FirstName, 00208 WildCardsPermissible, 00209 FALSE, 00210 FALSE) ) { 00211 00212 return FALSE; 00213 } 00214 } 00215 00216 // 00217 // All the componants were OK, so the path is OK. 00218 // 00219 00220 return TRUE; 00221 } 00222 00223 // 00224 // If this name contains wild cards, just check for invalid characters. 00225 // 00226 00227 if ( WildCardsPermissible && FsRtlDoesDbcsContainWildCards(&DbcsName) ) { 00228 00229 for ( Index = 0; Index < DbcsName.Length; Index += 1 ) { 00230 00231 Char = DbcsName.Buffer[ Index ]; 00232 00233 // 00234 // Skip over any Dbcs chacters 00235 // 00236 00237 if ( FsRtlIsLeadDbcsCharacter( Char ) ) { 00238 00239 ASSERT( Index != (ULONG)(DbcsName.Length - 1) ); 00240 Index += 1; 00241 continue; 00242 } 00243 00244 // 00245 // Make sure this character is legal, and if a wild card, that 00246 // wild cards are permissible. 00247 // 00248 00249 if ( !FsRtlIsAnsiCharacterLegalFat(Char, WildCardsPermissible) ) { 00250 return FALSE; 00251 } 00252 } 00253 00254 return TRUE; 00255 } 00256 00257 00258 // 00259 // At this point we should only have a single name, which can't have 00260 // more than 12 characters (including a single period) 00261 // 00262 00263 if ( DbcsName.Length > 12 ) { return FALSE; } 00264 00265 for ( Index = 0; Index < DbcsName.Length; Index += 1 ) { 00266 00267 Char = DbcsName.Buffer[ Index ]; 00268 00269 // 00270 // Skip over and Dbcs chacters 00271 // 00272 00273 if ( FsRtlIsLeadDbcsCharacter( Char ) ) { 00274 00275 // 00276 // FsRtlIsFatDbcsLegal(): fat name part and extension part dbcs check 00277 // 00278 // 1) if we're looking at base part ( !ExtensionPresent ) and the 8th byte 00279 // is in the dbcs leading byte range, it's error ( Index == 7 ). If the 00280 // length of base part is more than 8 ( Index > 7 ), it's definitely error. 00281 // 00282 // 2) if the last byte ( Index == DbcsName.Length - 1 ) is in the dbcs leading 00283 // byte range, it's error 00284 // 00285 00286 if ( (!ExtensionPresent && (Index >= 7)) || 00287 ( Index == (ULONG)(DbcsName.Length - 1) ) ) { 00288 return FALSE; 00289 } 00290 00291 Index += 1; 00292 00293 continue; 00294 } 00295 00296 // 00297 // Make sure this character is legal, and if a wild card, that 00298 // wild cards are permissible. 00299 // 00300 00301 if ( !FsRtlIsAnsiCharacterLegalFat(Char, WildCardsPermissible) ) { 00302 00303 return FALSE; 00304 } 00305 00306 if ( (Char == '.') || (Char == ANSI_DOS_DOT) ) { 00307 00308 // 00309 // We stepped onto a period. We require the following things: 00310 // 00311 // - It can't be the first character 00312 // - There can only be one 00313 // - There can't be more than three characters following 00314 // - The previous character can't be a space. 00315 // 00316 00317 if ( (Index == 0) || 00318 ExtensionPresent || 00319 (DbcsName.Length - (Index + 1) > 3) || 00320 (DbcsName.Buffer[Index - 1] == ' ') ) { 00321 00322 return FALSE; 00323 } 00324 00325 ExtensionPresent = TRUE; 00326 } 00327 00328 // 00329 // The base part of the name can't be more than 8 characters long. 00330 // 00331 00332 if ( (Index >= 8) && !ExtensionPresent ) { return FALSE; } 00333 } 00334 00335 // 00336 // The name cannot end in a space or a period. 00337 // 00338 00339 if ( (Char == ' ') || (Char == '.') || (Char == ANSI_DOS_DOT)) { return FALSE; } 00340 00341 return TRUE; 00342 }

BOOLEAN FsRtlIsHpfsDbcsLegal IN ANSI_STRING  DbcsName,
IN BOOLEAN  WildCardsPermissible,
IN BOOLEAN  PathNamePermissible,
IN BOOLEAN  LeadingBackslashPermissible
 

Definition at line 345 of file dbcsname.c.

References FALSE, FsRtlDissectDbcs(), FsRtlIsAnsiCharacterLegalHpfs, FsRtlIsLeadDbcsCharacter, Index, PAGED_CODE, and TRUE.

00354 : 00355 00356 This routine simple returns whether the specified file names conforms 00357 to the file system specific rules for legal file names. This routine 00358 will check the single name, or if PathNamePermissible is specified as 00359 TRUE, whether the whole path is a legal name. 00360 00361 For HPFS, the following rules apply: 00362 00363 A. An HPFS file name may not contain any of the following characters: 00364 00365 0x0000 - 0x001F " / : < > ? | * 00366 00367 B. An HPFS file name may not end in a period or a space. 00368 00369 C. An HPFS file name must contain no more than 255 bytes. 00370 00371 Case: HPFS is case preserving, but not case sensitive. Case is 00372 preserved on creates, but not checked for on file name compares. 00373 00374 For example, the files "foo " and "foo." are illegal, while ".foo", 00375 " foo" and "foo.bar.foo" are legal. 00376 00377 Arguments: 00378 00379 DbcsName - Supllies the name/path to check. 00380 00381 WildCardsPermissible - Specifies if Nt wild card characters are to be 00382 considered considered legal. 00383 00384 PathNamePermissible - Spcifes if Name may be a path name separated by 00385 backslash characters, or just a simple file name. 00386 00387 LeadingBackSlashPermissible - Specifies if a single leading backslash 00388 is permissible in the file/path name. 00389 00390 Return Value: 00391 00392 BOOLEAN - TRUE if the name is legal, FALSE otherwise. 00393 00394 --*/ 00395 { 00396 BOOLEAN ExtensionPresent = FALSE; 00397 00398 ULONG Index; 00399 00400 UCHAR Char; 00401 00402 PAGED_CODE(); 00403 00404 // 00405 // Empty names are not valid. 00406 // 00407 00408 if ( DbcsName.Length == 0 ) { return FALSE; } 00409 00410 // 00411 // If Wild Cards are OK, then for directory enumeration to work 00412 // correctly we have to accept . and .. 00413 // 00414 00415 if ( WildCardsPermissible && 00416 ( ( (DbcsName.Length == 1) && 00417 ((DbcsName.Buffer[0] == '.') || 00418 (DbcsName.Buffer[0] == ANSI_DOS_DOT)) ) 00419 || 00420 ( (DbcsName.Length == 2) && 00421 ( ((DbcsName.Buffer[0] == '.') && 00422 (DbcsName.Buffer[1] == '.')) || 00423 ((DbcsName.Buffer[0] == ANSI_DOS_DOT) && 00424 (DbcsName.Buffer[1] == ANSI_DOS_DOT)) ) ) ) ) { 00425 00426 return TRUE; 00427 } 00428 00429 // 00430 // If a leading \ is OK, skip over it (if there's more) 00431 // 00432 00433 if ( DbcsName.Buffer[0] == '\\' ) { 00434 00435 if ( LeadingBackslashPermissible ) { 00436 00437 if ( (DbcsName.Length > 1) ) { 00438 00439 DbcsName.Buffer += 1; 00440 DbcsName.Length -= 1; 00441 00442 } else { return TRUE; } 00443 00444 } else { return FALSE; } 00445 } 00446 00447 // 00448 // If we got a path name, check each componant. 00449 // 00450 00451 if ( PathNamePermissible ) { 00452 00453 ANSI_STRING FirstName; 00454 ANSI_STRING RemainingName; 00455 00456 RemainingName = DbcsName; 00457 00458 while ( RemainingName.Length != 0 ) { 00459 00460 // 00461 // This will catch the case of an illegal double backslash. 00462 // 00463 00464 if ( RemainingName.Buffer[0] == '\\' ) { return FALSE; } 00465 00466 FsRtlDissectDbcs(RemainingName, &FirstName, &RemainingName); 00467 00468 if ( !FsRtlIsHpfsDbcsLegal( FirstName, 00469 WildCardsPermissible, 00470 FALSE, 00471 FALSE) ) { 00472 00473 return FALSE; 00474 } 00475 } 00476 00477 // 00478 // All the componants were OK, so the path is OK. 00479 // 00480 00481 return TRUE; 00482 } 00483 00484 // 00485 // At this point we should only have a single name, which can't have 00486 // more than 255 characters 00487 // 00488 00489 if ( DbcsName.Length > 255 ) { return FALSE; } 00490 00491 for ( Index = 0; Index < DbcsName.Length; Index += 1 ) { 00492 00493 Char = DbcsName.Buffer[ Index ]; 00494 00495 // 00496 // Skip over and Dbcs chacters 00497 // 00498 00499 if ( FsRtlIsLeadDbcsCharacter( Char ) ) { 00500 00501 // 00502 // FsRtlIsHpfsDbcsLegal () hpfs dbcs check 00503 // 00504 // If the last byte ( Index == DbcsName.Length - 1 ) is in the 00505 // dbcs leading byte range, it's error. 00506 // 00507 00508 if ( Index == (ULONG)(DbcsName.Length - 1) ) { 00509 00510 return FALSE; 00511 } 00512 00513 Index += 1; 00514 continue; 00515 } 00516 00517 // 00518 // Make sure this character is legal, and if a wild card, that 00519 // wild cards are permissible. 00520 // 00521 00522 if ( !FsRtlIsAnsiCharacterLegalHpfs(Char, WildCardsPermissible) ) { 00523 00524 return FALSE; 00525 } 00526 } 00527 00528 // 00529 // The name cannot end in a space or a period. 00530 // 00531 00532 if ( (Char == ' ') || (Char == '.') || (Char == ANSI_DOS_DOT) ) { 00533 00534 return FALSE; 00535 } 00536 00537 return TRUE; 00538 }


Generated on Sat May 15 19:43:23 2004 for test by doxygen 1.3.7