-/*\r
- * PROJECT: ReactOS Kernel\r
- * LICENSE: GPL - See COPYING in the top level directory\r
- * FILE: ntoskrnl/fsrtl/name.c\r
- * PURPOSE: Provides name parsing and other support routines for FSDs\r
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
- * Filip Navara (navaraf@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-/* PUBLIC FUNCTIONS **********************************************************/\r
-\r
-/*++\r
- * @name FsRtlAreNamesEqual\r
- * @implemented\r
- *\r
- * FILLME\r
- *\r
- * @param Name1\r
- * FILLME\r
- *\r
- * @param Name2\r
- * FILLME\r
- *\r
- * @param IgnoreCase\r
- * FILLME\r
- *\r
- * @param UpcaseTable\r
- * FILLME\r
- *\r
- * @return None\r
- *\r
- * @remarks From Bo Branten's ntifs.h v25.\r
- *\r
- *--*/\r
-BOOLEAN\r
-NTAPI\r
-FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1,\r
- IN PCUNICODE_STRING Name2,\r
- IN BOOLEAN IgnoreCase,\r
- IN PCWCH UpcaseTable OPTIONAL)\r
-{\r
- UNICODE_STRING UpcaseName1;\r
- UNICODE_STRING UpcaseName2;\r
- BOOLEAN StringsAreEqual, MemoryAllocated = FALSE;\r
- ULONG i;\r
- NTSTATUS Status;\r
-\r
- /* Well, first check their size */\r
- if (Name1->Length != Name2->Length) return FALSE;\r
-\r
- /* Check if the caller didn't give an upcase table */\r
- if ((IgnoreCase) && !(UpcaseTable))\r
- {\r
- /* Upcase the string ourselves */\r
- Status = RtlUpcaseUnicodeString(&UpcaseName1, Name1, TRUE);\r
- if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status);\r
-\r
- /* Upcase the second string too */\r
- RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);\r
- Name1 = &UpcaseName1;\r
- Name2 = &UpcaseName2;\r
-\r
- /* Make sure we go through the path below, but free the strings */\r
- IgnoreCase = FALSE;\r
- MemoryAllocated = TRUE;\r
- }\r
-\r
- /* Do a case-sensitive search */\r
- if (!IgnoreCase)\r
- {\r
- /* Use a raw memory compare */\r
- StringsAreEqual = RtlEqualMemory(Name1->Buffer,\r
- Name2->Buffer,\r
- Name1->Length);\r
-\r
- /* Check if we allocated strings */\r
- if (MemoryAllocated)\r
- {\r
- /* Free them */\r
- RtlFreeUnicodeString(&UpcaseName1);\r
- RtlFreeUnicodeString(&UpcaseName2);\r
- }\r
-\r
- /* Return the equality */\r
- return StringsAreEqual;\r
- }\r
- else\r
- {\r
- /* Case in-sensitive search */\r
- for (i = 0; i < Name1->Length / sizeof(WCHAR); i++)\r
- {\r
- /* Check if the character matches */\r
- if (UpcaseTable[Name1->Buffer[i]] != UpcaseTable[Name2->Buffer[i]])\r
- {\r
- /* Non-match found! */\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* We finished the loop so we are equal */\r
- return TRUE;\r
- }\r
-}\r
-\r
-/*++\r
- * @name FsRtlDissectName\r
- * @implemented\r
- *\r
- * Dissects a given path name into first and remaining part.\r
- *\r
- * @param Name\r
- * Unicode string to dissect.\r
- *\r
- * @param FirstPart\r
- * Pointer to user supplied UNICODE_STRING, that will later point\r
- * to the first part of the original name.\r
- *\r
- * @param RemainingPart\r
- * Pointer to user supplied UNICODE_STRING, that will later point\r
- * to the remaining part of the original name.\r
- *\r
- * @return None\r
- *\r
- * @remarks Example:\r
- * Name: \test1\test2\test3\r
- * FirstPart: test1\r
- * RemainingPart: test2\test3\r
- *\r
- *--*/\r
-VOID\r
-NTAPI\r
-FsRtlDissectName(IN UNICODE_STRING Name,\r
- OUT PUNICODE_STRING FirstPart,\r
- OUT PUNICODE_STRING RemainingPart)\r
-{\r
- KEBUGCHECK(0);\r
-}\r
-\r
-/*++\r
- * @name FsRtlDoesNameContainWildCards\r
- * @implemented\r
- *\r
- * FILLME\r
- *\r
- * @param Name\r
- * Pointer to a UNICODE_STRING containing Name to examine\r
- *\r
- * @return TRUE if Name contains wildcards, FALSE otherwise\r
- *\r
- * @remarks From Bo Branten's ntifs.h v12.\r
- *\r
- *--*/\r
-BOOLEAN\r
-NTAPI\r
-FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)\r
-{\r
- PWCHAR Ptr;\r
-\r
- /* Loop through every character */\r
- if (Name->Length)\r
- {\r
- Ptr = Name->Buffer + (Name->Length / sizeof(WCHAR)) - 1;\r
- while ((Ptr >= Name->Buffer) && (*Ptr != L'\\'))\r
- {\r
- /* Check for Wildcard */\r
- if (FsRtlIsUnicodeCharacterWild(*Ptr)) return TRUE;\r
- Ptr--;\r
- }\r
- }\r
-\r
- /* Nothing Found */\r
- return FALSE;\r
-}\r
-\r
-/*++\r
- * @name FsRtlIsNameInExpression\r
- * @implemented\r
- *\r
- * FILLME\r
- *\r
- * @param DeviceObject\r
- * FILLME\r
- *\r
- * @param Irp\r
- * FILLME\r
- *\r
- * @return TRUE if Name is in Expression, FALSE otherwise\r
- *\r
- * @remarks From Bo Branten's ntifs.h v12. This function should be\r
- * rewritten to avoid recursion and better wildcard handling\r
- * should be implemented (see FsRtlDoesNameContainWildCards).\r
- *\r
- *--*/\r
-BOOLEAN\r
-NTAPI\r
-FsRtlIsNameInExpression(IN PUNICODE_STRING Expression,\r
- IN PUNICODE_STRING Name,\r
- IN BOOLEAN IgnoreCase,\r
- IN PWCHAR UpcaseTable OPTIONAL)\r
-{\r
- USHORT ExpressionPosition, NamePosition;\r
- UNICODE_STRING TempExpression, TempName;\r
-\r
- ExpressionPosition = 0;\r
- NamePosition = 0;\r
- while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&\r
- NamePosition < (Name->Length / sizeof(WCHAR)))\r
- {\r
- if (Expression->Buffer[ExpressionPosition] == L'*')\r
- {\r
- ExpressionPosition++;\r
- if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)))\r
- {\r
- return TRUE;\r
- }\r
- while (NamePosition < (Name->Length / sizeof(WCHAR)))\r
- {\r
- TempExpression.Length =\r
- TempExpression.MaximumLength =\r
- Expression->Length - (ExpressionPosition * sizeof(WCHAR));\r
- TempExpression.Buffer = Expression->Buffer + ExpressionPosition;\r
- TempName.Length =\r
- TempName.MaximumLength =\r
- Name->Length - (NamePosition * sizeof(WCHAR));\r
- TempName.Buffer = Name->Buffer + NamePosition;\r
- /* FIXME: Rewrite to get rid of recursion */\r
- if (FsRtlIsNameInExpression(&TempExpression, &TempName,\r
- IgnoreCase, UpcaseTable))\r
- {\r
- return TRUE;\r
- }\r
- NamePosition++;\r
- }\r
- }\r
- else\r
- {\r
- /* FIXME: Take UpcaseTable into account! */\r
- if (Expression->Buffer[ExpressionPosition] == L'?' ||\r
- (IgnoreCase &&\r
- RtlUpcaseUnicodeChar(Expression->Buffer[ExpressionPosition]) ==\r
- RtlUpcaseUnicodeChar(Name->Buffer[NamePosition])) ||\r
- (!IgnoreCase &&\r
- Expression->Buffer[ExpressionPosition] ==\r
- Name->Buffer[NamePosition]))\r
- {\r
- NamePosition++;\r
- ExpressionPosition++;\r
- }\r
- else\r
- {\r
- return FALSE;\r
- }\r
- }\r
- }\r
-\r
- /* Handle matching of "f0_*.*" expression to "f0_000" file name. */\r
- if (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&\r
- Expression->Buffer[ExpressionPosition] == L'.')\r
- {\r
- while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&\r
- (Expression->Buffer[ExpressionPosition] == L'.' ||\r
- Expression->Buffer[ExpressionPosition] == L'*' ||\r
- Expression->Buffer[ExpressionPosition] == L'?'))\r
- {\r
- ExpressionPosition++;\r
- }\r
- }\r
-\r
- if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)) &&\r
- NamePosition == (Name->Length / sizeof(WCHAR)))\r
- {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/fsrtl/name.c
+ * PURPOSE: Provides name parsing and other support routines for FSDs
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Filip Navara (navaraf@reactos.org)
+ * Pierre Schweitzer (pierre.schweitzer@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* PRIVATE FUNCTIONS *********************************************************/
+BOOLEAN
+NTAPI
+FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
+ IN PUNICODE_STRING Name,
+ IN BOOLEAN IgnoreCase,
+ IN PWCHAR UpcaseTable OPTIONAL)
+{
+ USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, StarFound = MAXUSHORT;
+ PAGED_CODE();
+
+ ASSERT(!IgnoreCase || UpcaseTable);
+
+ while (NamePosition < Name->Length / sizeof(WCHAR) && ExpressionPosition < Expression->Length / sizeof(WCHAR))
+ {
+ if ((Expression->Buffer[ExpressionPosition] == (IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition])))
+ {
+ NamePosition++;
+ ExpressionPosition++;
+ }
+ else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) ||
+ (Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.'))
+ {
+ NamePosition++;
+ ExpressionPosition++;
+ StarFound = MAXUSHORT;
+ }
+ else if (Expression->Buffer[ExpressionPosition] == L'*')
+ {
+ StarFound = ExpressionPosition++;
+ if (StarFound < (Expression->Length / sizeof(WCHAR) - 1))
+ {
+ while ((IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition]) != Expression->Buffer[ExpressionPosition] &&
+ NamePosition < Name->Length / sizeof(WCHAR))
+ {
+ NamePosition++;
+ }
+ }
+ else
+ {
+ NamePosition = Name->Length / sizeof(WCHAR);
+ }
+ }
+ else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
+ {
+ StarFound = MAXUSHORT;
+ MatchingChars = NamePosition;
+ while (MatchingChars < Name->Length / sizeof(WCHAR))
+ {
+ if (Name->Buffer[MatchingChars] == L'.')
+ {
+ NamePosition = MatchingChars;
+ }
+ MatchingChars++;
+ }
+ ExpressionPosition++;
+ }
+ else if (StarFound != MAXUSHORT)
+ {
+ ExpressionPosition = StarFound + 1;
+ while ((IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition]) != Expression->Buffer[ExpressionPosition] &&
+ NamePosition < Name->Length / sizeof(WCHAR))
+ {
+ NamePosition++;
+ }
+ }
+ else
+ {
+ NamePosition = Name->Length / sizeof(WCHAR);
+ }
+ }
+ if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR) &&
+ Expression->Buffer[ExpressionPosition] == DOS_DOT)
+ {
+ ExpressionPosition++;
+ }
+
+ return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*++
+ * @name FsRtlAreNamesEqual
+ * @implemented
+ *
+ * Compare two strings to check if they match
+ *
+ * @param Name1
+ * First unicode string to compare
+ *
+ * @param Name2
+ * Second unicode string to compare
+ *
+ * @param IgnoreCase
+ * If TRUE, Case will be ignored when comparing strings
+ *
+ * @param UpcaseTable
+ * Table for upcase letters. If NULL is given, system one will be used
+ *
+ * @return TRUE if the strings are equal
+ *
+ * @remarks From Bo Branten's ntifs.h v25.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1,
+ IN PCUNICODE_STRING Name2,
+ IN BOOLEAN IgnoreCase,
+ IN PCWCH UpcaseTable OPTIONAL)
+{
+ UNICODE_STRING UpcaseName1;
+ UNICODE_STRING UpcaseName2;
+ BOOLEAN StringsAreEqual, MemoryAllocated = FALSE;
+ ULONG i;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Well, first check their size */
+ if (Name1->Length != Name2->Length) return FALSE;
+
+ /* Check if the caller didn't give an upcase table */
+ if ((IgnoreCase) && !(UpcaseTable))
+ {
+ /* Upcase the string ourselves */
+ Status = RtlUpcaseUnicodeString(&UpcaseName1, Name1, TRUE);
+ if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status);
+
+ /* Upcase the second string too */
+ RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
+ Name1 = &UpcaseName1;
+ Name2 = &UpcaseName2;
+
+ /* Make sure we go through the path below, but free the strings */
+ IgnoreCase = FALSE;
+ MemoryAllocated = TRUE;
+ }
+
+ /* Do a case-sensitive search */
+ if (!IgnoreCase)
+ {
+ /* Use a raw memory compare */
+ StringsAreEqual = RtlEqualMemory(Name1->Buffer,
+ Name2->Buffer,
+ Name1->Length);
+
+ /* Check if we allocated strings */
+ if (MemoryAllocated)
+ {
+ /* Free them */
+ RtlFreeUnicodeString(&UpcaseName1);
+ RtlFreeUnicodeString(&UpcaseName2);
+ }
+
+ /* Return the equality */
+ return StringsAreEqual;
+ }
+ else
+ {
+ /* Case in-sensitive search */
+ for (i = 0; i < Name1->Length / sizeof(WCHAR); i++)
+ {
+ /* Check if the character matches */
+ if (UpcaseTable[Name1->Buffer[i]] != UpcaseTable[Name2->Buffer[i]])
+ {
+ /* Non-match found! */
+ return FALSE;
+ }
+ }
+
+ /* We finished the loop so we are equal */
+ return TRUE;
+ }
+}
+
+/*++
+ * @name FsRtlDissectName
+ * @implemented
+ *
+ * Dissects a given path name into first and remaining part.
+ *
+ * @param Name
+ * Unicode string to dissect.
+ *
+ * @param FirstPart
+ * Pointer to user supplied UNICODE_STRING, that will later point
+ * to the first part of the original name.
+ *
+ * @param RemainingPart
+ * Pointer to user supplied UNICODE_STRING, that will later point
+ * to the remaining part of the original name.
+ *
+ * @return None
+ *
+ * @remarks Example:
+ * Name: \test1\test2\test3
+ * FirstPart: test1
+ * RemainingPart: test2\test3
+ *
+ *--*/
+VOID
+NTAPI
+FsRtlDissectName(IN UNICODE_STRING Name,
+ OUT PUNICODE_STRING FirstPart,
+ OUT PUNICODE_STRING RemainingPart)
+{
+ ULONG FirstPosition, i;
+ ULONG SkipFirstSlash = 0;
+ PAGED_CODE();
+
+ /* Zero the strings before continuing */
+ RtlZeroMemory(FirstPart, sizeof(UNICODE_STRING));
+ RtlZeroMemory(RemainingPart, sizeof(UNICODE_STRING));
+
+ /* Just quit if the string is empty */
+ if (!Name.Length) return;
+
+ /* Find first backslash */
+ FirstPosition = Name.Length / sizeof(WCHAR) ;
+ for (i = 0; i < Name.Length / sizeof(WCHAR); i++)
+ {
+ /* If we found one... */
+ if (Name.Buffer[i] == L'\\')
+ {
+ /* If it begins string, just notice it and continue */
+ if (i == 0)
+ {
+ SkipFirstSlash = 1;
+ }
+ else
+ {
+ /* Else, save its position and break out of the loop */
+ FirstPosition = i;
+ break;
+ }
+ }
+ }
+
+ /* Set up the first result string */
+ FirstPart->Buffer = Name.Buffer + SkipFirstSlash;
+ FirstPart->Length = (FirstPosition - SkipFirstSlash) * sizeof(WCHAR);
+ FirstPart->MaximumLength = FirstPart->Length;
+
+ /* And second one, if necessary */
+ if (FirstPosition < (Name.Length / sizeof(WCHAR)))
+ {
+ RemainingPart->Buffer = Name.Buffer + FirstPosition + 1;
+ RemainingPart->Length = Name.Length - (FirstPosition + 1) * sizeof(WCHAR);
+ RemainingPart->MaximumLength = RemainingPart->Length;
+ }
+}
+
+/*++
+ * @name FsRtlDoesNameContainWildCards
+ * @implemented
+ *
+ * Checks if the given string contains WildCards
+ *
+ * @param Name
+ * Pointer to a UNICODE_STRING containing Name to examine
+ *
+ * @return TRUE if Name contains wildcards, FALSE otherwise
+ *
+ * @remarks From Bo Branten's ntifs.h v12.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
+{
+ PWCHAR Ptr;
+ PAGED_CODE();
+
+ /* Loop through every character */
+ if (Name->Length)
+ {
+ Ptr = Name->Buffer + (Name->Length / sizeof(WCHAR)) - 1;
+ while ((Ptr >= Name->Buffer) && (*Ptr != L'\\'))
+ {
+ /* Check for Wildcard */
+ if (FsRtlIsUnicodeCharacterWild(*Ptr)) return TRUE;
+ Ptr--;
+ }
+ }
+
+ /* Nothing Found */
+ return FALSE;
+}
+
+/*++
+ * @name FsRtlIsNameInExpression
+ * @implemented
+ *
+ * Check if the Name string is in the Expression string.
+ *
+ * @param Expression
+ * The string in which we've to find Name. It can contain wildcards.
+ * If IgnoreCase is set to TRUE, this string MUST BE uppercase.
+ *
+ * @param Name
+ * The string to find. It cannot contain wildcards
+ *
+ * @param IgnoreCase
+ * If set to TRUE, case will be ignore with upcasing both strings
+ *
+ * @param UpcaseTable
+ * If not NULL, and if IgnoreCase is set to TRUE, it will be used to
+ * upcase the both strings
+ *
+ * @return TRUE if Name is in Expression, FALSE otherwise
+ *
+ * @remarks From Bo Branten's ntifs.h v12. This function should be
+ * rewritten to avoid recursion and better wildcard handling
+ * should be implemented (see FsRtlDoesNameContainWildCards).
+ *
+ *--*/
+BOOLEAN
+NTAPI
+FsRtlIsNameInExpression(IN PUNICODE_STRING Expression,
+ IN PUNICODE_STRING Name,
+ IN BOOLEAN IgnoreCase,
+ IN PWCHAR UpcaseTable OPTIONAL)
+{
+ BOOLEAN Result;
+ NTSTATUS Status;
+ UNICODE_STRING IntName;
+
+ if (IgnoreCase && !UpcaseTable)
+ {
+ Status = RtlUpcaseUnicodeString(&IntName, Name, TRUE);
+ if (Status != STATUS_SUCCESS)
+ {
+ ExRaiseStatus(Status);
+ }
+ Name = &IntName;
+ IgnoreCase = FALSE;
+ }
+ else
+ {
+ IntName.Buffer = NULL;
+ }
+
+ Result = FsRtlIsNameInExpressionPrivate(Expression, Name, IgnoreCase, UpcaseTable);
+
+ if (IntName.Buffer != NULL)
+ {
+ RtlFreeUnicodeString(&IntName);
+ }
+
+ return Result;
+}