* Sync up to trunk head (r65120).
[reactos.git] / drivers / filesystems / ntfs / fsctl.c
index b57e12a..7aab976 100644 (file)
@@ -526,6 +526,85 @@ NtfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
 }
 
 
+static
+NTSTATUS
+NtfsUserFsRequest(PDEVICE_OBJECT DeviceObject,
+                  PIRP Irp)
+{
+    NTSTATUS Status;
+    PIO_STACK_LOCATION Stack;
+    PDEVICE_EXTENSION DeviceExt;
+    PNTFS_VOLUME_DATA_BUFFER DataBuffer;
+    PNTFS_ATTR_RECORD Attribute;
+
+    DPRINT1("NtfsUserFsRequest(%p, %p)\n", DeviceObject, Irp);
+
+    Stack = IoGetCurrentIrpStackLocation(Irp);
+    switch (Stack->Parameters.FileSystemControl.FsControlCode)
+    {
+        case FSCTL_GET_NTFS_VOLUME_DATA:
+            DeviceExt = DeviceObject->DeviceExtension;
+            DataBuffer = (PNTFS_VOLUME_DATA_BUFFER)Irp->UserBuffer;
+
+            if (Stack->Parameters.FileSystemControl.OutputBufferLength < sizeof(NTFS_VOLUME_DATA_BUFFER) ||
+                Irp->UserBuffer == NULL)
+            {
+                DPRINT1("Invalid output! %d %p\n", Stack->Parameters.FileSystemControl.OutputBufferLength, Irp->UserBuffer);
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            DataBuffer->VolumeSerialNumber.QuadPart = DeviceExt->NtfsInfo.SerialNumber;
+            DataBuffer->NumberSectors.QuadPart = DeviceExt->NtfsInfo.SectorCount;
+            DataBuffer->TotalClusters.QuadPart = DeviceExt->NtfsInfo.SectorCount / DeviceExt->NtfsInfo.SectorsPerCluster;
+            DataBuffer->FreeClusters.QuadPart = NtfsGetFreeClusters(DeviceExt);
+            DataBuffer->TotalReserved.QuadPart = 0LL; // FIXME
+            DataBuffer->BytesPerSector = DeviceExt->NtfsInfo.BytesPerSector;
+            DataBuffer->BytesPerCluster = DeviceExt->NtfsInfo.BytesPerCluster;
+            DataBuffer->BytesPerFileRecordSegment = DeviceExt->NtfsInfo.BytesPerFileRecord;
+            DataBuffer->ClustersPerFileRecordSegment = DeviceExt->NtfsInfo.BytesPerFileRecord / DeviceExt->NtfsInfo.BytesPerCluster;
+            DataBuffer->MftStartLcn.QuadPart = DeviceExt->NtfsInfo.MftStart.QuadPart;
+            DataBuffer->Mft2StartLcn.QuadPart = DeviceExt->NtfsInfo.MftMirrStart.QuadPart;
+            DataBuffer->MftZoneStart.QuadPart = 0; // FIXME
+            DataBuffer->MftZoneEnd.QuadPart = 0; // FIXME
+
+            Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DeviceExt->MasterFileTable + DeviceExt->MasterFileTable->AttributeOffset);
+            while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)DeviceExt->MasterFileTable + DeviceExt->MasterFileTable->BytesInUse) &&
+                   Attribute->Type != AttributeEnd)
+            {
+                if (Attribute->Type == AttributeData)
+                {
+                    ASSERT(Attribute->IsNonResident);
+                    DataBuffer->MftValidDataLength.QuadPart = Attribute->NonResident.DataSize;
+
+                    break;
+                }
+
+                Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
+            }
+
+            if (Stack->Parameters.FileSystemControl.OutputBufferLength >= sizeof(NTFS_EXTENDED_VOLUME_DATA) + sizeof(NTFS_VOLUME_DATA_BUFFER))
+            {
+                PNTFS_EXTENDED_VOLUME_DATA ExtendedData = (PNTFS_EXTENDED_VOLUME_DATA)((ULONG_PTR)Irp->UserBuffer + sizeof(NTFS_VOLUME_DATA_BUFFER));
+
+                ExtendedData->ByteCount = sizeof(NTFS_EXTENDED_VOLUME_DATA);
+                ExtendedData->MajorVersion = DeviceExt->NtfsInfo.MajorVersion;
+                ExtendedData->MinorVersion = DeviceExt->NtfsInfo.MinorVersion;
+            }
+
+            Status = STATUS_SUCCESS;
+            break;
+
+        default:
+            DPRINT1("Invalid user request: %x\n", Stack->Parameters.FileSystemControl.FsControlCode);
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+    }
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 NtfsFsdFileSystemControl(PDEVICE_OBJECT DeviceObject,
@@ -541,11 +620,14 @@ NtfsFsdFileSystemControl(PDEVICE_OBJECT DeviceObject,
     switch (Stack->MinorFunction)
     {
         case IRP_MN_KERNEL_CALL:
-        case IRP_MN_USER_FS_REQUEST:
-            DPRINT("NTFS: IRP_MN_USER_FS_REQUEST/IRP_MN_KERNEL_CALL\n");
+            DPRINT1("NTFS: IRP_MN_USER_FS_REQUEST\n");
             Status = STATUS_INVALID_DEVICE_REQUEST;
             break;
 
+        case IRP_MN_USER_FS_REQUEST:
+            Status = NtfsUserFsRequest(DeviceObject, Irp);
+            break;
+
         case IRP_MN_MOUNT_VOLUME:
             DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n");
             Status = NtfsMountVolume(DeviceObject, Irp);
@@ -557,7 +639,7 @@ NtfsFsdFileSystemControl(PDEVICE_OBJECT DeviceObject,
             break;
 
         default:
-            DPRINT("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction);
+            DPRINT1("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction);
             Status = STATUS_INVALID_DEVICE_REQUEST;
             break;
     }