}
+static
+ULONG
+NtfsQueryMftZoneReservation(VOID)
+{
+ ULONG ZoneReservation = 1;
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[0].Name = L"NtfsMftZoneReservation";
+ QueryTable[0].EntryContext = &ZoneReservation;
+
+ RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+ L"FileSystem",
+ QueryTable,
+ NULL,
+ NULL);
+
+ return ZoneReservation;
+}
+
+
static
NTSTATUS
NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
NtfsInfo->SectorsPerCluster = BootSector->BPB.SectorsPerCluster;
NtfsInfo->BytesPerCluster = BootSector->BPB.BytesPerSector * BootSector->BPB.SectorsPerCluster;
NtfsInfo->SectorCount = BootSector->EBPB.SectorCount;
+ NtfsInfo->ClusterCount = DeviceExt->NtfsInfo.SectorCount / (ULONGLONG)DeviceExt->NtfsInfo.SectorsPerCluster;
NtfsInfo->MftStart.QuadPart = BootSector->EBPB.MftLocation;
NtfsInfo->MftMirrStart.QuadPart = BootSector->EBPB.MftMirrLocation;
}
/* Enumerate attributes */
- NtfsDumpFileAttributes(DeviceExt->MasterFileTable);
+ NtfsDumpFileAttributes(DeviceExt, DeviceExt->MasterFileTable);
/* Enumerate attributes */
- NtfsDumpFileAttributes(VolumeRecord);
+ NtfsDumpFileAttributes(DeviceExt, VolumeRecord);
/* Get volume name */
Status = FindAttribute(DeviceExt, VolumeRecord, AttributeVolumeName, L"", 0, &AttrCtxt);
VolumeNameU = L"\0";
}
- VolumeFcb = NtfsCreateFCB(VolumeNameU, DeviceExt);
+ if (NT_SUCCESS(Status))
+ {
+ ReleaseAttributeContext(AttrCtxt);
+ }
+
+ VolumeFcb = NtfsCreateFCB(VolumeNameU, NULL, DeviceExt);
if (VolumeFcb == NULL)
{
DPRINT1("Failed allocating volume FCB\n");
NtfsInfo->Flags = VolumeInfo->Flags;
}
+ if (NT_SUCCESS(Status))
+ {
+ ReleaseAttributeContext(AttrCtxt);
+ }
+
ExFreePool(VolumeRecord);
+ NtfsInfo->MftZoneReservation = NtfsQueryMftZoneReservation();
+
return Status;
}
InitializeListHead(&Vcb->FcbListHead);
- Fcb = NtfsCreateFCB(NULL, Vcb);
+ Fcb = NtfsCreateFCB(NULL, NULL, Vcb);
if (Fcb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
// Fcb->Entry.ExtentLocationL = 0;
// Fcb->Entry.DataLengthL = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE;
- CcInitializeCacheMap(Vcb->StreamFileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- FALSE,
- &(NtfsGlobalData->CacheMgrCallbacks),
- Fcb);
+ _SEH2_TRY
+ {
+ CcInitializeCacheMap(Vcb->StreamFileObject,
+ (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
+ TRUE,
+ &(NtfsGlobalData->CacheMgrCallbacks),
+ Fcb);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ goto ByeBye;
+ }
+ _SEH2_END;
ExInitializeResourceLite(&Vcb->DirResource);
Vcb->NtfsInfo.VolumeLabel,
Vcb->NtfsInfo.VolumeLabelLength);
+ FsRtlNotifyVolumeEvent(Vcb->StreamFileObject, FSRTL_VOLUME_MOUNT);
+
Status = STATUS_SUCCESS;
ByeBye:
ObDereferenceObject(Vcb->StreamFileObject);
if (Fcb)
- ExFreePool(Fcb);
+ NtfsDestroyFCB(Fcb);
if (Ccb)
ExFreePool(Ccb);
PIO_STACK_LOCATION Stack;
PNTFS_VOLUME_DATA_BUFFER DataBuffer;
PNTFS_ATTR_RECORD Attribute;
+ FIND_ATTR_CONTXT Context;
+ NTSTATUS Status;
- DataBuffer = (PNTFS_VOLUME_DATA_BUFFER)Irp->UserBuffer;
+ DataBuffer = (PNTFS_VOLUME_DATA_BUFFER)Irp->AssociatedIrp.SystemBuffer;
Stack = IoGetCurrentIrpStackLocation(Irp);
if (Stack->Parameters.FileSystemControl.OutputBufferLength < sizeof(NTFS_VOLUME_DATA_BUFFER) ||
DataBuffer->VolumeSerialNumber.QuadPart = DeviceExt->NtfsInfo.SerialNumber;
DataBuffer->NumberSectors.QuadPart = DeviceExt->NtfsInfo.SectorCount;
- DataBuffer->TotalClusters.QuadPart = DeviceExt->NtfsInfo.SectorCount / DeviceExt->NtfsInfo.SectorsPerCluster;
+ DataBuffer->TotalClusters.QuadPart = DeviceExt->NtfsInfo.ClusterCount;
DataBuffer->FreeClusters.QuadPart = NtfsGetFreeClusters(DeviceExt);
DataBuffer->TotalReserved.QuadPart = 0LL; // FIXME
DataBuffer->BytesPerSector = DeviceExt->NtfsInfo.BytesPerSector;
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)
+ Status = FindFirstAttribute(&Context, DeviceExt, DeviceExt->MasterFileTable, FALSE, &Attribute);
+ while (NT_SUCCESS(Status))
{
if (Attribute->Type == AttributeData)
{
break;
}
- Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
+ Status = FindNextAttribute(&Context, &Attribute);
}
+ FindCloseAttribute(&Context);
+
+ Irp->IoStatus.Information = sizeof(NTFS_VOLUME_DATA_BUFFER);
if (Stack->Parameters.FileSystemControl.OutputBufferLength >= sizeof(NTFS_EXTENDED_VOLUME_DATA) + sizeof(NTFS_VOLUME_DATA_BUFFER))
{
ExtendedData->ByteCount = sizeof(NTFS_EXTENDED_VOLUME_DATA);
ExtendedData->MajorVersion = DeviceExt->NtfsInfo.MajorVersion;
ExtendedData->MinorVersion = DeviceExt->NtfsInfo.MinorVersion;
+ Irp->IoStatus.Information += sizeof(NTFS_EXTENDED_VOLUME_DATA);
}
return STATUS_SUCCESS;
InputBuffer = (PNTFS_FILE_RECORD_INPUT_BUFFER)Irp->AssociatedIrp.SystemBuffer;
MFTRecord = InputBuffer->FileReferenceNumber.QuadPart;
- Status = ReadFileRecord(DeviceExt, MFTRecord, FileRecord);
- if (!NT_SUCCESS(Status))
+ DPRINT1("Requesting: %I64x\n", MFTRecord);
+
+ do
{
- DPRINT1("Failed reading record: %I64x\n", MFTRecord);
- ExFreePoolWithTag(FileRecord, TAG_NTFS);
- return Status;
- }
+ Status = ReadFileRecord(DeviceExt, MFTRecord, FileRecord);
+ if (NT_SUCCESS(Status))
+ {
+ if (FileRecord->Flags & FRH_IN_USE)
+ {
+ break;
+ }
+ }
+ --MFTRecord;
+ } while (TRUE);
+
+ DPRINT1("Returning: %I64x\n", MFTRecord);
OutputBuffer = (PNTFS_FILE_RECORD_OUTPUT_BUFFER)Irp->AssociatedIrp.SystemBuffer;
OutputBuffer->FileReferenceNumber.QuadPart = MFTRecord;
OutputBuffer->FileRecordLength = DeviceExt->NtfsInfo.BytesPerFileRecord;
ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ Irp->IoStatus.Information = FIELD_OFFSET(NTFS_FILE_RECORD_OUTPUT_BUFFER, FileRecordBuffer) + DeviceExt->NtfsInfo.BytesPerFileRecord;
+
return STATUS_SUCCESS;
}
+static
+NTSTATUS
+GetVolumeBitmap(PDEVICE_EXTENSION DeviceExt,
+ PIRP Irp)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ 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);
+
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+
+ if (Stack->Parameters.FileSystemControl.InputBufferLength < sizeof(STARTING_LCN_INPUT_BUFFER))
+ {
+ DPRINT1("Invalid input! %d\n", Stack->Parameters.FileSystemControl.InputBufferLength);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (Stack->Parameters.FileSystemControl.OutputBufferLength < sizeof(VOLUME_BITMAP_BUFFER))
+ {
+ DPRINT1("Invalid output! %d\n", Stack->Parameters.FileSystemControl.OutputBufferLength);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ BitmapBuffer = NtfsGetUserBuffer(Irp, FALSE);
+ if (Irp->RequestorMode == UserMode)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead(Stack->Parameters.FileSystemControl.Type3InputBuffer,
+ Stack->Parameters.FileSystemControl.InputBufferLength,
+ sizeof(CHAR));
+ ProbeForWrite(BitmapBuffer, Stack->Parameters.FileSystemControl.OutputBufferLength,
+ sizeof(CHAR));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ if (Stack->Parameters.FileSystemControl.Type3InputBuffer == NULL ||
+ BitmapBuffer == NULL)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Invalid buffer! %p %p\n", Stack->Parameters.FileSystemControl.Type3InputBuffer, BitmapBuffer);
+ return Status;
+ }
+
+ StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)Stack->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn.QuadPart;
+ if (StartingLcn > DeviceExt->NtfsInfo.ClusterCount)
+ {
+ DPRINT1("Requested bitmap start beyond partition end: %I64x %I64x\n", DeviceExt->NtfsInfo.ClusterCount, StartingLcn);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* 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;
+}
+
+
static
NTSTATUS
NtfsUserFsRequest(PDEVICE_OBJECT DeviceObject,
DeviceExt = DeviceObject->DeviceExtension;
switch (Stack->Parameters.FileSystemControl.FsControlCode)
{
+ case FSCTL_CREATE_USN_JOURNAL:
+ case FSCTL_DELETE_USN_JOURNAL:
+ case FSCTL_ENUM_USN_DATA:
+ case FSCTL_EXTEND_VOLUME:
+ //case FSCTL_GET_RETRIEVAL_POINTER_BASE:
+ case FSCTL_GET_RETRIEVAL_POINTERS:
+ case FSCTL_LOCK_VOLUME:
+ //case FSCTL_LOOKUP_STREAM_FROM_CLUSTER:
+ case FSCTL_MARK_HANDLE:
+ case FSCTL_MOVE_FILE:
+ case FSCTL_QUERY_USN_JOURNAL:
+ case FSCTL_READ_FILE_USN_DATA:
+ case FSCTL_READ_USN_JOURNAL:
+ //case FSCTL_SHRINK_VOLUME:
+ case FSCTL_UNLOCK_VOLUME:
+ case FSCTL_WRITE_USN_CLOSE_RECORD:
+ UNIMPLEMENTED;
+ DPRINT1("Unimplemented user request: %x\n", Stack->Parameters.FileSystemControl.FsControlCode);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
case FSCTL_GET_NTFS_VOLUME_DATA:
Status = GetNfsVolumeData(DeviceExt, Irp);
break;
Status = GetNtfsFileRecord(DeviceExt, Irp);
break;
+ case FSCTL_GET_VOLUME_BITMAP:
+ Status = GetVolumeBitmap(DeviceExt, Irp);
+ break;
+
default:
- DPRINT1("Invalid user request: %x\n", Stack->Parameters.FileSystemControl.FsControlCode);
+ DPRINT("Invalid user request: %x\n", Stack->Parameters.FileSystemControl.FsControlCode);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
NTSTATUS
-NTAPI
-NtfsFsdFileSystemControl(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+NtfsFileSystemControl(PNTFS_IRP_CONTEXT IrpContext)
{
- PIO_STACK_LOCATION Stack;
NTSTATUS Status;
+ PIRP Irp;
+ PDEVICE_OBJECT DeviceObject;
DPRINT1("NtfsFileSystemControl() called\n");
- Stack = IoGetCurrentIrpStackLocation(Irp);
+ DeviceObject = IrpContext->DeviceObject;
+ Irp = IrpContext->Irp;
+ Irp->IoStatus.Information = 0;
- switch (Stack->MinorFunction)
+ switch (IrpContext->MinorFunction)
{
case IRP_MN_KERNEL_CALL:
DPRINT1("NTFS: IRP_MN_USER_FS_REQUEST\n");
break;
default:
- DPRINT1("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction);
+ DPRINT1("NTFS FSC: MinorFunction %d\n", IrpContext->MinorFunction);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
return Status;
}