Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendbcsname.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
1.7.6.1
|