[NTFS]
[reactos.git] / reactos / drivers / filesystems / ntfs / rw.c
index a5b5f74..e74d5a6 100644 (file)
@@ -57,6 +57,7 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt,
     ULONG ToRead;
     BOOLEAN AllocatedBuffer = FALSE;
     PCHAR ReadBuffer = (PCHAR)Buffer;
+    ULONGLONG StreamSize;
 
     DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt, FileObject, Buffer, Length, ReadOffset, IrpFlags, LengthRead);
 
@@ -70,31 +71,11 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt,
 
     Fcb = (PNTFS_FCB)FileObject->FsContext;
 
-    if (ReadOffset >= Fcb->Entry.AllocatedSize)
+    if (NtfsFCBIsCompressed(Fcb))
     {
-        DPRINT1("Reading beyond file end!\n");
-        return STATUS_END_OF_FILE;
-    }
-
-    ToRead = Length;
-    if (ReadOffset + Length > Fcb->Entry.AllocatedSize)
-        ToRead = Fcb->Entry.AllocatedSize - ReadOffset;
-
-    RealReadOffset = ReadOffset;
-    RealLength = ToRead;
-
-    if ((ReadOffset % DeviceExt->NtfsInfo.BytesPerSector) != 0 || (ToRead % DeviceExt->NtfsInfo.BytesPerSector) != 0)
-    {
-        RealReadOffset = ROUND_DOWN(ReadOffset, DeviceExt->NtfsInfo.BytesPerSector);
-        RealLength = ROUND_UP(ToRead, DeviceExt->NtfsInfo.BytesPerSector);
-
-        ReadBuffer = ExAllocatePoolWithTag(NonPagedPool, RealLength + DeviceExt->NtfsInfo.BytesPerSector, TAG_NTFS);
-        if (ReadBuffer == NULL)
-        {
-            DPRINT1("Not enough memory!\n");
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-        AllocatedBuffer = TRUE;
+        DPRINT1("Compressed file!\n");
+        UNIMPLEMENTED;
+        return STATUS_NOT_IMPLEMENTED;
     }
 
     FileRecord = ExAllocatePoolWithTag(NonPagedPool, DeviceExt->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
@@ -112,17 +93,77 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt,
         return Status;
     }
 
-    Status = FindAttribute(DeviceExt, FileRecord, AttributeData, L"", 0, &DataContext);
+
+    Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Fcb->Stream, wcslen(Fcb->Stream), &DataContext);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("No data associated with file!\n");
+        NTSTATUS BrowseStatus;
+        FIND_ATTR_CONTXT Context;
+        PNTFS_ATTR_RECORD Attribute;
+
+        DPRINT1("No '%S' data stream associated with file!\n", Fcb->Stream);
+
+        BrowseStatus = FindFirstAttribute(&Context, DeviceExt, FileRecord, FALSE, &Attribute);
+        while (NT_SUCCESS(BrowseStatus))
+        {
+            if (Attribute->Type == AttributeData)
+            {
+                UNICODE_STRING Name;
+
+                Name.Length = Attribute->NameLength * sizeof(WCHAR);
+                Name.MaximumLength = Name.Length;
+                Name.Buffer = (PWCHAR)((ULONG_PTR)Attribute + Attribute->NameOffset);
+                DPRINT1("Data stream: '%wZ' available\n", &Name);
+            }
+
+            BrowseStatus = FindNextAttribute(&Context, &Attribute);
+        }
+        FindCloseAttribute(&Context);
+
+        ReleaseAttributeContext(DataContext);
         ExFreePoolWithTag(FileRecord, TAG_NTFS);
         return Status;
     }
 
-    DPRINT1("Effective read: %lu at %lu\n", RealLength, RealReadOffset);
+    StreamSize = AttributeDataLength(&DataContext->Record);
+    if (ReadOffset >= StreamSize)
+    {
+        DPRINT1("Reading beyond stream end!\n");
+        ReleaseAttributeContext(DataContext);
+        ExFreePoolWithTag(FileRecord, TAG_NTFS);
+        return STATUS_END_OF_FILE;
+    }
+
+    ToRead = Length;
+    if (ReadOffset + Length > StreamSize)
+        ToRead = StreamSize - ReadOffset;
+
+    RealReadOffset = ReadOffset;
+    RealLength = ToRead;
+
+    if ((ReadOffset % DeviceExt->NtfsInfo.BytesPerSector) != 0 || (ToRead % DeviceExt->NtfsInfo.BytesPerSector) != 0)
+    {
+        RealReadOffset = ROUND_DOWN(ReadOffset, DeviceExt->NtfsInfo.BytesPerSector);
+        RealLength = ROUND_UP(ToRead, DeviceExt->NtfsInfo.BytesPerSector);
+        /* do we need to extend RealLength by one sector? */
+        if (RealLength + RealReadOffset < ReadOffset + Length)
+            RealLength += DeviceExt->NtfsInfo.BytesPerSector;
+
+
+        ReadBuffer = ExAllocatePoolWithTag(NonPagedPool, RealLength + (DeviceExt->NtfsInfo.BytesPerSector * 2), TAG_NTFS);
+        if (ReadBuffer == NULL)
+        {
+            DPRINT1("Not enough memory!\n");
+            ReleaseAttributeContext(DataContext);
+            ExFreePoolWithTag(FileRecord, TAG_NTFS);
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+        AllocatedBuffer = TRUE;
+    }
+
+    DPRINT1("Effective read: %lu at %lu for stream '%S'\n", RealLength, RealReadOffset, Fcb->Stream);
     RealLengthRead = ReadAttribute(DeviceExt, DataContext, RealReadOffset, (PCHAR)ReadBuffer, RealLength);
-    if (RealLengthRead != RealLength)
+    if (RealLengthRead == 0)
     {
         DPRINT1("Read failure!\n");
         ReleaseAttributeContext(DataContext);
@@ -174,7 +215,7 @@ NtfsRead(PNTFS_IRP_CONTEXT IrpContext)
     PIRP Irp;
     PDEVICE_OBJECT DeviceObject;
 
-    DPRINT("NtfsRead(DeviceObject %p)\n", IrpContext);
+    DPRINT("NtfsRead(IrpContext %p)\n", IrpContext);
 
     DeviceObject = IrpContext->DeviceObject;
     Irp = IrpContext->Irp;
@@ -184,7 +225,7 @@ NtfsRead(PNTFS_IRP_CONTEXT IrpContext)
     DeviceExt = DeviceObject->DeviceExtension;
     ReadLength = Stack->Parameters.Read.Length;
     ReadOffset = Stack->Parameters.Read.ByteOffset;
-    Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+    Buffer = NtfsGetUserBuffer(Irp, BooleanFlagOn(Irp->Flags, IRP_PAGING_IO));
 
     Status = NtfsReadFile(DeviceExt,
                           FileObject,
@@ -213,14 +254,11 @@ NtfsRead(PNTFS_IRP_CONTEXT IrpContext)
 
 
 NTSTATUS
-NTAPI
-NtfsFsdWrite(PDEVICE_OBJECT DeviceObject,
-             PIRP Irp)
+NtfsWrite(PNTFS_IRP_CONTEXT IrpContext)
 {
-    DPRINT("NtfwWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+    DPRINT("NtfsWrite(IrpContext %p)\n",IrpContext);
 
-    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-    Irp->IoStatus.Information = 0;
+    IrpContext->Irp->IoStatus.Information = 0;
     return STATUS_NOT_SUPPORTED;
 }