}
+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,
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);
break;
default:
- DPRINT("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction);
+ DPRINT1("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}