Author: pschweitzer
Date: Sun Dec 14 18:13:57 2014
New Revision: 65645

URL: http://svn.reactos.org/svn/reactos?rev=65645&view=rev
Log:
[NTFS]
Implement GetVolumeBitmap().

This allows NFI to find which file is at which LCN: 
http://www.heisspiter.net/~Pierre/rostests/NTFS_NFI_LCN.png

So far, NFI is not as verbose as it is on Windows in such cases, because 
FILE_OPEN_BY_FILE_ID is *still* unimplemented (you should consider implementing 
it Pierre ;-)).
I checked with Windows, the correct file is found though!

CORE-8725

Modified:
    trunk/reactos/drivers/filesystems/ntfs/fsctl.c

Modified: trunk/reactos/drivers/filesystems/ntfs/fsctl.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/fsctl.c?rev=65645&r1=65644&r2=65645&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/fsctl.c      [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/fsctl.c      [iso-8859-1] Sun Dec 14 
18:13:57 2014
@@ -666,6 +666,11 @@
     PIO_STACK_LOCATION Stack;
     PVOLUME_BITMAP_BUFFER BitmapBuffer;
     LONGLONG StartingLcn;
+    PFILE_RECORD_HEADER BitmapRecord;
+    PNTFS_ATTR_CONTEXT DataContext;
+    ULONGLONG TotalClusters;
+    ULONGLONG ToCopy;
+    BOOLEAN Overflow = FALSE;
 
     DPRINT1("GetVolumeBitmap(%p, %p)\n", DeviceExt, Irp);
 
@@ -722,8 +727,59 @@
         return STATUS_INVALID_PARAMETER;
     }
 
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    /* Round down to a multiple of 8 */
+    StartingLcn = StartingLcn & ~7;
+    TotalClusters = DeviceExt->NtfsInfo.ClusterCount - StartingLcn;
+    ToCopy = TotalClusters / 8;
+    if ((ToCopy + FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer)) > 
Stack->Parameters.FileSystemControl.OutputBufferLength)
+    {
+        DPRINT1("Buffer too small: %x, needed: %x\n", 
Stack->Parameters.FileSystemControl.OutputBufferLength, (ToCopy + 
FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer)));
+        Overflow = TRUE;
+        ToCopy = Stack->Parameters.FileSystemControl.OutputBufferLength - 
FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer);
+    }
+
+    BitmapRecord = ExAllocatePoolWithTag(NonPagedPool,
+                                         
DeviceExt->NtfsInfo.BytesPerFileRecord,
+                                         TAG_NTFS);
+    if (BitmapRecord == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    Status = ReadFileRecord(DeviceExt, NTFS_FILE_BITMAP, BitmapRecord);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed reading volume bitmap: %lx\n", Status);
+        ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
+        return Status;
+    }
+
+    Status = FindAttribute(DeviceExt, BitmapRecord, AttributeData, L"", 0, 
&DataContext);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed find $DATA for bitmap: %lx\n", Status);
+        ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
+        return Status;
+    }
+
+    BitmapBuffer->StartingLcn.QuadPart = StartingLcn;
+    BitmapBuffer->BitmapSize.QuadPart = ToCopy * 8;
+
+    Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer);
+    _SEH2_TRY
+    {
+        Irp->IoStatus.Information += ReadAttribute(DeviceExt, DataContext, 
StartingLcn / 8, (PCHAR)BitmapBuffer->Buffer, ToCopy);
+        Status = (Overflow ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+    ReleaseAttributeContext(DataContext);
+    ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
+
+    return STATUS_SUCCESS;
 }
 
 


Reply via email to