[NTFS]
[reactos.git] / reactos / drivers / filesystems / ntfs / dirctl.c
index 638935e..c19bf6b 100644 (file)
 /* FUNCTIONS ****************************************************************/
 
 
+ULONGLONG
+NtfsGetFileSize(PDEVICE_EXTENSION DeviceExt,
+                PFILE_RECORD_HEADER FileRecord,
+                PCWSTR Stream,
+                ULONG StreamLength,
+                PULONGLONG AllocatedSize)
+{
+    ULONGLONG Size = 0ULL;
+    ULONGLONG Allocated = 0ULL;
+    NTSTATUS Status;
+    PNTFS_ATTR_CONTEXT DataContext;
+
+    Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext);
+    if (NT_SUCCESS(Status))
+    {
+        Size = AttributeDataLength(&DataContext->Record);
+        Allocated = AttributeAllocatedLength(&DataContext->Record);
+        ReleaseAttributeContext(DataContext);
+    }
+
+    if (AllocatedSize != NULL) *AllocatedSize = Allocated;
+
+    return Size;
+}
+
+
 static NTSTATUS
 NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt,
                        PFILE_RECORD_HEADER FileRecord,
@@ -47,11 +73,11 @@ NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt,
 
     DPRINT("NtfsGetNameInformation() called\n");
 
-    FileName = GetBestFileNameFromRecord(FileRecord);
+    FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
     if (FileName == NULL)
     {
         DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
-        NtfsDumpFileAttributes(FileRecord);
+        NtfsDumpFileAttributes(DeviceExt, FileRecord);
         return STATUS_OBJECT_NAME_NOT_FOUND;
     }
 
@@ -81,15 +107,15 @@ NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
 
     DPRINT("NtfsGetDirectoryInformation() called\n");
 
-    FileName = GetBestFileNameFromRecord(FileRecord);
+    FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
     if (FileName == NULL)
     {
         DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
-        NtfsDumpFileAttributes(FileRecord);
+        NtfsDumpFileAttributes(DeviceExt, FileRecord);
         return STATUS_OBJECT_NAME_NOT_FOUND;
     }
 
-    StdInfo = GetStandardInformationFromRecord(FileRecord);
+    StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
     ASSERT(StdInfo != NULL);
 
     Length = FileName->NameLength * sizeof (WCHAR);
@@ -109,8 +135,7 @@ NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
     /* Convert file flags */
     NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
 
-    Info->EndOfFile.QuadPart = FileName->AllocatedSize;
-    Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
+    Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
 
     Info->FileIndex = MFTIndex;
 
@@ -131,15 +156,15 @@ NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
 
     DPRINT("NtfsGetFullDirectoryInformation() called\n");
 
-    FileName = GetBestFileNameFromRecord(FileRecord);
+    FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
     if (FileName == NULL)
     {
         DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
-        NtfsDumpFileAttributes(FileRecord);
+        NtfsDumpFileAttributes(DeviceExt, FileRecord);
         return STATUS_OBJECT_NAME_NOT_FOUND;
     }
 
-    StdInfo = GetStandardInformationFromRecord(FileRecord);
+    StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
     ASSERT(StdInfo != NULL);
 
     Length = FileName->NameLength * sizeof (WCHAR);
@@ -159,8 +184,7 @@ NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
     /* Convert file flags */
     NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
 
-    Info->EndOfFile.QuadPart = FileName->AllocatedSize;
-    Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
+    Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
 
     Info->FileIndex = MFTIndex;
     Info->EaSize = 0;
@@ -182,16 +206,16 @@ NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
 
     DPRINT("NtfsGetBothDirectoryInformation() called\n");
 
-    FileName = GetBestFileNameFromRecord(FileRecord);
+    FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
     if (FileName == NULL)
     {
         DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
-        NtfsDumpFileAttributes(FileRecord);
+        NtfsDumpFileAttributes(DeviceExt, FileRecord);
         return STATUS_OBJECT_NAME_NOT_FOUND;
     }
-    ShortFileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
+    ShortFileName = GetFileNameFromRecord(DeviceExt, FileRecord, NTFS_FILE_NAME_DOS);
 
-    StdInfo = GetStandardInformationFromRecord(FileRecord);
+    StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
     ASSERT(StdInfo != NULL);
 
     Length = FileName->NameLength * sizeof (WCHAR);
@@ -224,8 +248,7 @@ NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
     /* Convert file flags */
     NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
 
-    Info->EndOfFile.QuadPart = FileName->AllocatedSize;
-    Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
+    Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
 
     Info->FileIndex = MFTIndex;
     Info->EaSize = 0;
@@ -275,6 +298,19 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
     FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
     FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
 
+    if (NtfsFCBIsCompressed(Fcb))
+    {
+        DPRINT1("Compressed directory!\n");
+        UNIMPLEMENTED;
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    if (!ExAcquireResourceSharedLite(&Fcb->MainResource,
+                                     BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
+    {
+        return STATUS_PENDING;
+    }
+
     if (SearchPattern != NULL)
     {
         if (!Ccb->DirectorySearchPattern)
@@ -286,6 +322,7 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
                 ExAllocatePoolWithTag(NonPagedPool, Pattern.MaximumLength, TAG_NTFS);
             if (!Ccb->DirectorySearchPattern)
             {
+                ExReleaseResourceLite(&Fcb->MainResource);
                 return STATUS_INSUFFICIENT_RESOURCES;
             }
 
@@ -299,6 +336,7 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
         Ccb->DirectorySearchPattern = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), TAG_NTFS);
         if (!Ccb->DirectorySearchPattern)
         {
+            ExReleaseResourceLite(&Fcb->MainResource);
             return STATUS_INSUFFICIENT_RESOURCES;
         }
 
@@ -341,7 +379,7 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
              */
             if (MFTRecord == OldMFTRecord)
             {
-                DPRINT("Ignoring duplicate MFT entry 0x%x\n", MFTRecord);
+                DPRINT1("Ignoring duplicate MFT entry 0x%x\n", MFTRecord);
                 Ccb->Entry++;
                 ExFreePoolWithTag(FileRecord, TAG_NTFS);
                 continue;
@@ -431,6 +469,8 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
         Buffer0->NextEntryOffset = 0;
     }
 
+    ExReleaseResourceLite(&Fcb->MainResource);
+
     if (FileIndex > 0)
     {
         Status = STATUS_SUCCESS;
@@ -463,6 +503,11 @@ NtfsDirectoryControl(PNTFS_IRP_CONTEXT IrpContext)
             break;
     }
 
+    if (Status == STATUS_PENDING && IrpContext->Flags & IRPCONTEXT_COMPLETE)
+    {
+        return NtfsMarkIrpContextForQueue(IrpContext);
+    }
+
     IrpContext->Irp->IoStatus.Information = 0;
 
     return Status;