[NTFS] - In the NtfsAddFilenameToDirectory() function, rename DirectoryContext parame...
[reactos.git] / drivers / filesystems / ntfs / mft.c
index 62b2979..e83c33e 100644 (file)
@@ -195,10 +195,16 @@ AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord)
 * @param Vcb
 * Pointer to the VCB (DEVICE_EXTENSION) of the target volume.
 *
+*
+* @param CanWait
+* Boolean indicating if the function is allowed to wait for exclusive access to the master file table.
+* This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
+*
 * @return
 * STATUS_SUCCESS on success.
 * STATUS_INSUFFICIENT_RESOURCES if an allocation fails.
 * STATUS_INVALID_PARAMETER if there was an error reading the Mft's bitmap.
+* STATUS_CANT_WAIT if CanWait was FALSE and the function could not get immediate, exclusive access to the MFT.
 *
 * @remarks
 * Increases the size of the Master File Table by 8 records. Bitmap entries for the new records are cleared,
@@ -206,7 +212,7 @@ AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord)
 * This function will wait for exlusive access to the volume fcb.
 */
 NTSTATUS
-IncreaseMftSize(PDEVICE_EXTENSION Vcb)
+IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
 {
     PNTFS_ATTR_CONTEXT BitmapContext;
     LARGE_INTEGER BitmapSize;
@@ -221,10 +227,10 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb)
     ULONG LengthWritten;
     NTSTATUS Status;
 
-    DPRINT1("IncreaseMftSize(%p)\n", Vcb);
+    DPRINT1("IncreaseMftSize(%p, %s)\n", Vcb, CanWait ? "TRUE" : "FALSE");
 
     // We need exclusive access to the mft while we change its size
-    if (!ExAcquireResourceExclusiveLite(&(Vcb->DirResource), TRUE))
+    if (!ExAcquireResourceExclusiveLite(&(Vcb->DirResource), CanWait))
     {
         return STATUS_CANT_WAIT;
     }
@@ -1353,7 +1359,8 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
                      PUNICODE_STRING FileName,
                      BOOLEAN DirSearch,
                      ULONGLONG NewDataSize,
-                     ULONGLONG NewAllocationSize)
+                     ULONGLONG NewAllocationSize,
+                     BOOLEAN CaseSensitive)
 {
     PFILE_RECORD_HEADER MftRecord;
     PNTFS_ATTR_CONTEXT IndexRootCtx;
@@ -1363,7 +1370,14 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
     NTSTATUS Status;
     ULONG CurrentEntry = 0;
 
-    DPRINT("UpdateFileNameRecord(%p, %I64d, %wZ, %u, %I64u, %I64u)\n", Vcb, ParentMFTIndex, FileName, DirSearch, NewDataSize, NewAllocationSize);
+    DPRINT("UpdateFileNameRecord(%p, %I64d, %wZ, %u, %I64u, %I64u, %s)\n",
+           Vcb,
+           ParentMFTIndex,
+           FileName,
+           DirSearch,
+           NewDataSize,
+           NewAllocationSize,
+           CaseSensitive ? "TRUE" : "FALSE");
 
     MftRecord = ExAllocatePoolWithTag(NonPagedPool,
                                       Vcb->NtfsInfo.BytesPerFileRecord,
@@ -1415,7 +1429,8 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
                                           &CurrentEntry,
                                           DirSearch,
                                           NewDataSize,
-                                          NewAllocationSize);
+                                          NewAllocationSize,
+                                          CaseSensitive);
 
     ReleaseAttributeContext(IndexRootCtx);
     ExFreePoolWithTag(IndexRecord, TAG_NTFS);
@@ -1441,7 +1456,8 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb,
                              PULONG CurrentEntry,
                              BOOLEAN DirSearch,
                              ULONGLONG NewDataSize,
-                             ULONGLONG NewAllocatedSize)
+                             ULONGLONG NewAllocatedSize,
+                             BOOLEAN CaseSensitive)
 {
     NTSTATUS Status;
     ULONG RecordOffset;
@@ -1460,7 +1476,7 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb,
         if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) > 0x10 &&
             *CurrentEntry >= *StartEntry &&
             IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS &&
-            CompareFileName(FileName, IndexEntry, DirSearch))
+            CompareFileName(FileName, IndexEntry, DirSearch, CaseSensitive))
         {
             *StartEntry = *CurrentEntry;
             IndexEntry->FileName.DataSize = NewDataSize;
@@ -1511,7 +1527,19 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb,
         LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries);
         ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize));
 
-        Status = UpdateIndexEntryFileNameSize(NULL, NULL, NULL, 0, FirstEntry, LastEntry, FileName, StartEntry, CurrentEntry, DirSearch, NewDataSize, NewAllocatedSize);
+        Status = UpdateIndexEntryFileNameSize(NULL,
+                                              NULL,
+                                              NULL,
+                                              0,
+                                              FirstEntry,
+                                              LastEntry,
+                                              FileName,
+                                              StartEntry,
+                                              CurrentEntry,
+                                              DirSearch,
+                                              NewDataSize,
+                                              NewAllocatedSize,
+                                              CaseSensitive);
         if (Status == STATUS_PENDING)
         {
             // write the index record back to disk
@@ -1638,17 +1666,22 @@ FixupUpdateSequenceArray(PDEVICE_EXTENSION Vcb,
 * @param DestinationIndex
 * Pointer to a ULONGLONG which will receive the MFT index where the file record was stored.
 *
+* @param CanWait
+* Boolean indicating if the function is allowed to wait for exclusive access to the master file table.
+* This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
+*
 * @return
 * STATUS_SUCCESS on success.
 * STATUS_OBJECT_NAME_NOT_FOUND if we can't find the MFT's $Bitmap or if we weren't able 
 * to read the attribute.
 * STATUS_INSUFFICIENT_RESOURCES if we can't allocate enough memory for a copy of $Bitmap.
-* 
+* STATUS_CANT_WAIT if CanWait was FALSE and the function could not get immediate, exclusive access to the MFT.
 */
 NTSTATUS
 AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
                PDEVICE_EXTENSION DeviceExt,
-               PULONGLONG DestinationIndex)
+               PULONGLONG DestinationIndex,
+               BOOLEAN CanWait)
 {
     NTSTATUS Status = STATUS_SUCCESS;
     ULONGLONG MftIndex;
@@ -1661,7 +1694,7 @@ AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
     LARGE_INTEGER BitmapBits;
     UCHAR SystemReservedBits;
 
-    DPRINT1("AddNewMftEntry(%p, %p, %p)\n", FileRecord, DeviceExt, DestinationIndex);
+    DPRINT1("AddNewMftEntry(%p, %p, %p, %s)\n", FileRecord, DeviceExt, DestinationIndex, CanWait ? "TRUE" : "FALSE");
 
     // First, we have to read the mft's $Bitmap attribute
     Status = FindAttribute(DeviceExt, DeviceExt->MasterFileTable, AttributeBitmap, L"", 0, &BitmapContext, NULL);
@@ -1717,14 +1750,14 @@ AddNewMftEntry(PFILE_RECORD_HEADER FileRecord,
         ReleaseAttributeContext(BitmapContext);
 
         // Couldn't find a free record in the MFT, add some blank records and try again
-        Status = IncreaseMftSize(DeviceExt);
+        Status = IncreaseMftSize(DeviceExt, CanWait);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("ERROR: Couldn't find space in MFT for file or increase MFT size!\n");
             return Status;
         }
 
-        return AddNewMftEntry(FileRecord, DeviceExt, DestinationIndex);
+        return AddNewMftEntry(FileRecord, DeviceExt, DestinationIndex, CanWait);
     }
 
     DPRINT1("Creating file record at MFT index: %I64u\n", MftIndex);
@@ -1816,7 +1849,8 @@ ReadLCN(PDEVICE_EXTENSION Vcb,
 BOOLEAN
 CompareFileName(PUNICODE_STRING FileName,
                 PINDEX_ENTRY_ATTRIBUTE IndexEntry,
-                BOOLEAN DirSearch)
+                BOOLEAN DirSearch,
+                BOOLEAN CaseSensitive)
 {
     BOOLEAN Ret, Alloc = FALSE;
     UNICODE_STRING EntryName;
@@ -1828,7 +1862,7 @@ CompareFileName(PUNICODE_STRING FileName,
     if (DirSearch)
     {
         UNICODE_STRING IntFileName;
-        if (IndexEntry->FileName.NameType != NTFS_FILE_NAME_POSIX)
+        if (!CaseSensitive)
         {
             NT_VERIFY(NT_SUCCESS(RtlUpcaseUnicodeString(&IntFileName, FileName, TRUE)));
             Alloc = TRUE;
@@ -1838,7 +1872,7 @@ CompareFileName(PUNICODE_STRING FileName,
             IntFileName = *FileName;
         }
 
-        Ret = FsRtlIsNameInExpression(&IntFileName, &EntryName, (IndexEntry->FileName.NameType != NTFS_FILE_NAME_POSIX), NULL);
+        Ret = FsRtlIsNameInExpression(&IntFileName, &EntryName, !CaseSensitive, NULL);
 
         if (Alloc)
         {
@@ -1849,7 +1883,7 @@ CompareFileName(PUNICODE_STRING FileName,
     }
     else
     {
-        return (RtlCompareUnicodeString(FileName, &EntryName, (IndexEntry->FileName.NameType != NTFS_FILE_NAME_POSIX)) == 0);
+        return (RtlCompareUnicodeString(FileName, &EntryName, !CaseSensitive) == 0);
     }
 }
 
@@ -1889,6 +1923,7 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
                    PULONG StartEntry,
                    PULONG CurrentEntry,
                    BOOLEAN DirSearch,
+                   BOOLEAN CaseSensitive,
                    ULONGLONG *OutMFTIndex)
 {
     NTSTATUS Status;
@@ -1898,7 +1933,19 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
     ULONGLONG IndexAllocationSize;
     PINDEX_BUFFER IndexBuffer;
 
-    DPRINT("BrowseIndexEntries(%p, %p, %p, %u, %p, %p, %wZ, %u, %u, %u, %p)\n", Vcb, MftRecord, IndexRecord, IndexBlockSize, FirstEntry, LastEntry, FileName, *StartEntry, *CurrentEntry, DirSearch, OutMFTIndex);
+    DPRINT("BrowseIndexEntries(%p, %p, %p, %u, %p, %p, %wZ, %u, %u, %s, %s, %p)\n",
+           Vcb,
+           MftRecord,
+           IndexRecord,
+           IndexBlockSize,
+           FirstEntry,
+           LastEntry,
+           FileName,
+           *StartEntry,
+           *CurrentEntry,
+           DirSearch ? "TRUE" : "FALSE",
+           CaseSensitive ? "TRUE" : "FALSE",
+           OutMFTIndex);
 
     IndexEntry = FirstEntry;
     while (IndexEntry < LastEntry &&
@@ -1907,7 +1954,7 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
         if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) >= 0x10 &&
             *CurrentEntry >= *StartEntry &&
             IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS &&
-            CompareFileName(FileName, IndexEntry, DirSearch))
+            CompareFileName(FileName, IndexEntry, DirSearch, CaseSensitive))
         {
             *StartEntry = *CurrentEntry;
             *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
@@ -1956,7 +2003,18 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
         LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries);
         ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize));
 
-        Status = BrowseIndexEntries(NULL, NULL, NULL, 0, FirstEntry, LastEntry, FileName, StartEntry, CurrentEntry, DirSearch, OutMFTIndex);
+        Status = BrowseIndexEntries(NULL,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    FirstEntry,
+                                    LastEntry,
+                                    FileName,
+                                    StartEntry,
+                                    CurrentEntry,
+                                    DirSearch,
+                                    CaseSensitive,
+                                    OutMFTIndex);
         if (NT_SUCCESS(Status))
         {
             break;
@@ -1973,7 +2031,8 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
                   PUNICODE_STRING FileName,
                   PULONG FirstEntry,
                   BOOLEAN DirSearch,
-                  ULONGLONG *OutMFTIndex)
+                  ULONGLONG *OutMFTIndex,
+                  BOOLEAN CaseSensitive)
 {
     PFILE_RECORD_HEADER MftRecord;
     PNTFS_ATTR_CONTEXT IndexRootCtx;
@@ -2025,7 +2084,18 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
 
     DPRINT("IndexRecordSize: %x IndexBlockSize: %x\n", Vcb->NtfsInfo.BytesPerIndexRecord, IndexRoot->SizeOfEntry);
 
-    Status = BrowseIndexEntries(Vcb, MftRecord, IndexRecord, IndexRoot->SizeOfEntry, IndexEntry, IndexEntryEnd, FileName, FirstEntry, &CurrentEntry, DirSearch, OutMFTIndex);
+    Status = BrowseIndexEntries(Vcb,
+                                MftRecord,
+                                IndexRecord,
+                                IndexRoot->SizeOfEntry,
+                                IndexEntry,
+                                IndexEntryEnd,
+                                FileName,
+                                FirstEntry,
+                                &CurrentEntry,
+                                DirSearch,
+                                CaseSensitive,
+                                OutMFTIndex);
 
     ExFreePoolWithTag(IndexRecord, TAG_NTFS);
     ExFreePoolWithTag(MftRecord, TAG_NTFS);
@@ -2036,6 +2106,7 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
 NTSTATUS
 NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
                  PUNICODE_STRING PathName,
+                 BOOLEAN CaseSensitive,
                  PFILE_RECORD_HEADER *FileRecord,
                  PULONGLONG MFTIndex,
                  ULONGLONG CurrentMFTIndex)
@@ -2044,7 +2115,13 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
     NTSTATUS Status;
     ULONG FirstEntry = 0;
 
-    DPRINT("NtfsLookupFileAt(%p, %wZ, %p, %I64x)\n", Vcb, PathName, FileRecord, CurrentMFTIndex);
+    DPRINT("NtfsLookupFileAt(%p, %wZ, %s, %p, %p, %I64x)\n",
+           Vcb,
+           PathName,
+           CaseSensitive ? "TRUE" : "FALSE",
+           FileRecord,
+           MFTIndex,
+           CurrentMFTIndex);
 
     FsRtlDissectName(*PathName, &Current, &Remaining);
 
@@ -2052,7 +2129,7 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
     {
         DPRINT("Current: %wZ\n", &Current);
 
-        Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, &Current, &FirstEntry, FALSE, &CurrentMFTIndex);
+        Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, &Current, &FirstEntry, FALSE, &CurrentMFTIndex, CaseSensitive);
         if (!NT_SUCCESS(Status))
         {
             return Status;
@@ -2087,10 +2164,11 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
 NTSTATUS
 NtfsLookupFile(PDEVICE_EXTENSION Vcb,
                PUNICODE_STRING PathName,
+               BOOLEAN CaseSensitive,
                PFILE_RECORD_HEADER *FileRecord,
                PULONGLONG MFTIndex)
 {
-    return NtfsLookupFileAt(Vcb, PathName, FileRecord, MFTIndex, NTFS_FILE_ROOT);
+    return NtfsLookupFileAt(Vcb, PathName, CaseSensitive, FileRecord, MFTIndex, NTFS_FILE_ROOT);
 }
 
 /**
@@ -2139,13 +2217,21 @@ NtfsFindFileAt(PDEVICE_EXTENSION Vcb,
                PULONG FirstEntry,
                PFILE_RECORD_HEADER *FileRecord,
                PULONGLONG MFTIndex,
-               ULONGLONG CurrentMFTIndex)
+               ULONGLONG CurrentMFTIndex,
+               BOOLEAN CaseSensitive)
 {
     NTSTATUS Status;
 
-    DPRINT("NtfsFindFileAt(%p, %wZ, %u, %p, %p, %I64x)\n", Vcb, SearchPattern, *FirstEntry, FileRecord, MFTIndex, CurrentMFTIndex);
+    DPRINT("NtfsFindFileAt(%p, %wZ, %u, %p, %p, %I64x, %s)\n",
+           Vcb,
+           SearchPattern,
+           *FirstEntry,
+           FileRecord,
+           MFTIndex,
+           CurrentMFTIndex,
+           (CaseSensitive ? "TRUE" : "FALSE"));
 
-    Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, SearchPattern, FirstEntry, TRUE, &CurrentMFTIndex);
+    Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, SearchPattern, FirstEntry, TRUE, &CurrentMFTIndex, CaseSensitive);
     if (!NT_SUCCESS(Status))
     {
         DPRINT("NtfsFindFileAt: NtfsFindMftRecord() failed with status 0x%08lx\n", Status);