- Cleaned up some of the mess that was caused by a previous patch

- Support verify override
- Read volume name

svn path=/trunk/; revision=6629
This commit is contained in:
Eric Kohl 2003-11-12 15:30:21 +00:00
parent 063bd518b1
commit c9a794eb0e
6 changed files with 548 additions and 646 deletions

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: attrib.c,v 1.6 2003/09/15 16:01:16 ea Exp $
/* $Id: attrib.c,v 1.7 2003/11/12 15:30:21 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -32,7 +32,7 @@
#include <ntos.h>
//#define NDEBUG
#define NDEBUG
#include <debug.h>
#include "ntfs.h"
@ -42,17 +42,19 @@
ULONG RunLength(PUCHAR run)
ULONG
RunLength(PUCHAR run)
{
return(*run & 0x0f) + ((*run >> 4) & 0x0f) + 1;
}
LONGLONG RunLCN(PUCHAR run)
LONGLONG
RunLCN(PUCHAR run)
{
UCHAR n1 = *run & 0x0f;
UCHAR n2 = (*run >> 4) & 0x0f;
LONGLONG lcn = n2 == 0 ? 0 : (CHAR)(run[n1 + n2]);
LONGLONG lcn = (n2 == 0) ? 0 : (CHAR)(run[n1 + n2]);
LONG i = 0;
for (i = n1 +n2 - 1; i > n1; i--)
@ -62,7 +64,8 @@ LONGLONG RunLCN(PUCHAR run)
ULONGLONG RunCount(PUCHAR run)
ULONGLONG
RunCount(PUCHAR run)
{
UCHAR n = *run & 0xf;
ULONGLONG count = 0;
@ -74,13 +77,51 @@ ULONGLONG RunCount(PUCHAR run)
}
VOID
BOOLEAN
FindRun (PNONRESIDENT_ATTRIBUTE NresAttr,
ULONGLONG vcn,
PULONGLONG lcn,
PULONGLONG count)
{
PUCHAR run;
ULONGLONG base = NresAttr->StartVcn;
if (vcn < NresAttr->StartVcn || vcn > NresAttr->LastVcn)
return FALSE;
*lcn = 0;
for (run = (PUCHAR)((ULONG)NresAttr + NresAttr->RunArrayOffset);
*run != 0; run += RunLength(run))
{
*lcn += RunLCN(run);
*count = RunCount(run);
if (base <= vcn && vcn < base + *count)
{
*lcn = (RunLCN(run) == 0) ? 0 : *lcn + vcn - base;
*count -= (ULONG)(vcn - base);
return TRUE;
}
else
{
base += *count;
}
}
return FALSE;
}
static VOID
NtfsDumpFileNameAttribute(PATTRIBUTE Attribute)
{
PRESIDENT_ATTRIBUTE ResAttr;
PFILENAME_ATTRIBUTE FileNameAttr;
DbgPrint(" FILE_NAME ");
DbgPrint(" $FILE_NAME ");
ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
// DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
@ -90,7 +131,7 @@ NtfsDumpFileNameAttribute(PATTRIBUTE Attribute)
}
VOID
static VOID
NtfsDumpVolumeNameAttribute(PATTRIBUTE Attribute)
{
PRESIDENT_ATTRIBUTE ResAttr;
@ -102,11 +143,11 @@ NtfsDumpVolumeNameAttribute(PATTRIBUTE Attribute)
// DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
VolumeName = (PWCHAR)((PVOID)ResAttr + ResAttr->ValueOffset);
DbgPrint(" '%.*S' ", ResAttr->ValueLength/2, VolumeName);
DbgPrint(" '%.*S' ", ResAttr->ValueLength / sizeof(WCHAR), VolumeName);
}
VOID
static VOID
NtfsDumpVolumeInformationAttribute(PATTRIBUTE Attribute)
{
PRESIDENT_ATTRIBUTE ResAttr;
@ -125,26 +166,22 @@ NtfsDumpVolumeInformationAttribute(PATTRIBUTE Attribute)
}
BOOL
NtfsDumpAttribute(PATTRIBUTE Attribute)
static VOID
NtfsDumpAttribute (PATTRIBUTE Attribute)
{
PNONRESIDENT_ATTRIBUTE NresAttr;
PRESIDENT_ATTRIBUTE ResAttr;
UNICODE_STRING Name;
PUCHAR Ptr;
UCHAR RunHeader;
ULONG RunLength;
ULONG RunStart;
ULONGLONG lcn;
ULONGLONG runcount;
switch (Attribute->AttributeType)
{
case AttributeFileName:
case AttributeFileName:
NtfsDumpFileNameAttribute(Attribute);
break;
case AttributeStandardInformation:
DbgPrint(" $STANDARD_INFORMATION ");
break;
@ -153,8 +190,6 @@ NtfsDumpAttribute(PATTRIBUTE Attribute)
DbgPrint(" $ATTRIBUTE_LIST ");
break;
case AttributeObjectId:
DbgPrint(" $OBJECT_ID ");
break;
@ -225,25 +260,33 @@ NtfsDumpAttribute(PATTRIBUTE Attribute)
DbgPrint("(%s)\n",
Attribute->Nonresident ? "non-resident" : "resident");
if (Attribute->Nonresident != 0)
if (Attribute->Nonresident)
{
NresAttr = (PNONRESIDENT_ATTRIBUTE)Attribute;
return TRUE;
}
return FALSE;
FindRun (NresAttr,0,&lcn, &runcount);
DbgPrint (" AllocatedSize %I64u DataSize %I64u\n",
NresAttr->AllocatedSize, NresAttr->DataSize);
DbgPrint (" logical clusters: %I64u - %I64u\n",
lcn, lcn + runcount - 1);
}
}
VOID
NtfsDumpFileAttributes (PFILE_RECORD_HEADER FileRecord)
{
PATTRIBUTE Attribute;
Attribute = (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
while (Attribute->AttributeType !=-1)
{
NtfsDumpAttribute (Attribute);
Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
}
}
/* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: blockdev.c,v 1.1 2002/06/25 22:23:05 ekohl Exp $
/* $Id: blockdev.c,v 1.2 2003/11/12 15:30:21 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -42,88 +42,8 @@ NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN ULONG SectorSize,
IN OUT PUCHAR Buffer)
{
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER Offset;
ULONG BlockSize;
KEVENT Event;
PIRP Irp;
NTSTATUS Status;
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
BlockSize = SectorCount * SectorSize;
DPRINT("NtfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n",
DeviceObject, DiskSector, Buffer);
DPRINT("Offset %I64x BlockSize %ld\n",
Offset.QuadPart,
BlockSize);
DPRINT("Building synchronous FSD Request...\n");
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
DeviceObject,
Buffer,
BlockSize,
&Offset,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("IoBuildSynchronousFsdRequest failed\n");
return(STATUS_INSUFFICIENT_RESOURCES);
}
DPRINT("Calling IO Driver... with irp %x\n", Irp);
Status = IoCallDriver(DeviceObject, Irp);
DPRINT("Waiting for IO Operation for %x\n", Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
DPRINT("Getting IO Status... for %x\n", Irp);
Status = IoStatus.Status;
}
if (!NT_SUCCESS(Status))
{
if (Status == STATUS_VERIFY_REQUIRED)
{
PDEVICE_OBJECT DeviceToVerify;
NTSTATUS NewStatus;
DPRINT1("STATUS_VERIFY_REQUIRED\n");
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
NewStatus = IoVerifyVolume(DeviceToVerify, FALSE);
DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus);
}
DPRINT("NtfsReadSectors() failed (Status %x)\n", Status);
DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n",
DeviceObject, DiskSector, Buffer,
Offset.QuadPart);
return(Status);
}
DPRINT("Block request succeeded for %x\n", Irp);
return(STATUS_SUCCESS);
}
NTSTATUS
NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN ULONG SectorSize,
IN OUT PUCHAR Buffer)
IN OUT PUCHAR Buffer,
IN BOOLEAN Override)
{
PIO_STACK_LOCATION Stack;
IO_STATUS_BLOCK IoStatus;
@ -157,11 +77,14 @@ NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject,
if (Irp == NULL)
{
DPRINT("IoBuildSynchronousFsdRequest failed\n");
return(STATUS_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
// Stack = IoGetCurrentIrpStackLocation(Irp);
// Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
if (Override)
{
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
}
DPRINT("Calling IO Driver... with irp %x\n", Irp);
Status = IoCallDriver(DeviceObject, Irp);
@ -175,18 +98,9 @@ NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject,
Status = IoStatus.Status;
}
if (!NT_SUCCESS(Status))
{
DPRINT("NtfsReadSectors() failed (Status %x)\n", Status);
DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n",
DeviceObject, DiskSector, Buffer,
Offset.QuadPart);
return(Status);
}
DPRINT("NtfsReadSectors() done (Status %x)\n", Status);
DPRINT("Block request succeeded for %x\n", Irp);
return(STATUS_SUCCESS);
return Status;
}
@ -196,26 +110,16 @@ NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG OutputBufferSize)
IN OUT PULONG OutputBufferSize,
IN BOOLEAN Override)
{
ULONG BufferSize = 0;
PKEVENT Event;
PIRP Irp;
PIO_STACK_LOCATION Stack;
IO_STATUS_BLOCK IoStatus;
KEVENT Event;
PIRP Irp;
NTSTATUS Status;
if (OutputBufferSize != NULL)
{
BufferSize = *OutputBufferSize;
}
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
if (Event == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
KeInitializeEvent(Event, NotificationEvent, FALSE);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
DPRINT("Building device I/O control request ...\n");
Irp = IoBuildDeviceIoControlRequest(ControlCode,
@ -223,33 +127,36 @@ NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
BufferSize,
(OutputBufferSize) ? *OutputBufferSize : 0,
FALSE,
Event,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("IoBuildDeviceIoControlRequest() failed\n");
ExFreePool(Event);
return(STATUS_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (Override)
{
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
}
DPRINT("Calling IO Driver... with irp %x\n", Irp);
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL);
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (OutputBufferSize)
{
*OutputBufferSize = BufferSize;
*OutputBufferSize = IoStatus.Information;
}
ExFreePool(Event);
return(Status);
return Status;
}
/* EOF */

View file

@ -16,19 +16,20 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: fsctl.c,v 1.8 2003/09/15 16:01:16 ea Exp $
/* $Id: fsctl.c,v 1.9 2003/11/12 15:30:21 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ntfs/fsctl.c
* PURPOSE: NTFS filesystem driver
* PROGRAMMER: Eric Kohl
* Updated by Valentin Verkhovsky 2003/09/12
* Updated by Valentin Verkhovsky 2003/09/12
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <ntos/minmax.h>
#define NDEBUG
#include <debug.h>
@ -50,7 +51,7 @@ NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
PBOOT_SECTOR BootSector;
NTSTATUS Status;
DPRINT("NtfsHasFileSystem() called\n");
DPRINT1("NtfsHasFileSystem() called\n");
Size = sizeof(DISK_GEOMETRY);
Status = NtfsDeviceIoControl(DeviceToMount,
@ -58,10 +59,11 @@ NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
NULL,
0,
&DiskGeometry,
&Size);
&Size,
TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
DPRINT1("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
return(Status);
}
@ -74,20 +76,22 @@ NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
NULL,
0,
&PartitionInfo,
&Size);
&Size,
TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
DPRINT1("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
return(Status);
}
if (PartitionInfo.PartitionType != PARTITION_IFS)
{
DPRINT1("Invalid partition type\n");
return(STATUS_UNRECOGNIZED_VOLUME);
}
}
DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
DPRINT1("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
BootSector = ExAllocatePool(NonPagedPool,
DiskGeometry.BytesPerSector);
if (BootSector == NULL)
@ -95,14 +99,15 @@ NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
return(STATUS_INSUFFICIENT_RESOURCES);
}
Status = NtfsReadRawSectors(DeviceToMount,
0,
1,
DiskGeometry.BytesPerSector,
(PVOID)BootSector);
Status = NtfsReadSectors (DeviceToMount,
0,
1,
DiskGeometry.BytesPerSector,
(PVOID)BootSector,
TRUE);
if (NT_SUCCESS(Status))
{
DPRINT("NTFS-identifier: [%.8s]\n", BootSector->OemName);
DPRINT1("NTFS-identifier: [%.8s]\n", BootSector->OemName);
if (strncmp(BootSector->OemName, "NTFS ", 8) != 0)
{
Status = STATUS_UNRECOGNIZED_VOLUME;
@ -117,13 +122,17 @@ NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
static NTSTATUS
NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
PDEVICE_EXTENSION Vcb)
PNTFS_INFO NtfsInfo)
{
DISK_GEOMETRY DiskGeometry;
// PUCHAR Buffer;
PFILE_RECORD_HEADER MftRecord;
PFILE_RECORD_HEADER VolumeRecord;
PVOLINFO_ATTRIBUTE VolumeInfo;
PBOOT_SECTOR BootSector;
PATTRIBUTE Attribute;
ULONG FileRecordSize;
ULONG Size;
NTSTATUS Status;
PBOOT_SECTOR BootSector;
DPRINT("NtfsGetVolumeData() called\n");
@ -133,7 +142,8 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
NULL,
0,
&DiskGeometry,
&Size);
&Size,
TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
@ -148,49 +158,151 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
return(STATUS_INSUFFICIENT_RESOURCES);
}
Status = NtfsReadRawSectors(DeviceObject,
0, /* Partition boot sector */
1,
DiskGeometry.BytesPerSector,
(PVOID)BootSector);
if (NT_SUCCESS(Status))
Status = NtfsReadSectors(DeviceObject,
0, /* Partition boot sector */
1,
DiskGeometry.BytesPerSector,
(PVOID)BootSector,
TRUE);
if (!NT_SUCCESS(Status))
{
/* Read data from the bootsector */
Vcb->NtfsInfo.BytesPerSector = BootSector->BytesPerSector;
Vcb->NtfsInfo.SectorsPerCluster = BootSector->SectorsPerCluster;
Vcb->NtfsInfo.BytesPerCluster = BootSector->BytesPerSector * BootSector->SectorsPerCluster;
Vcb->NtfsInfo.SectorCount = BootSector->SectorCount;
Vcb->NtfsInfo.MftStart.QuadPart = BootSector->MftLocation;
Vcb->NtfsInfo.MftMirrStart.QuadPart = BootSector->MftMirrLocation;
Vcb->NtfsInfo.SerialNumber = BootSector->SerialNumber;
Vcb->NtfsInfo.ClustersPerFileRecord = BootSector->ClustersPerMftRecord;
//#indef NDEBUG
DbgPrint("Boot sector information:\n");
DbgPrint(" BytesPerSector: %hu\n", BootSector->BytesPerSector);
DbgPrint(" SectorsPerCluster: %hu\n", BootSector->SectorsPerCluster);
DbgPrint(" SectorCount: %I64u\n", BootSector->SectorCount);
DbgPrint(" MftStart: %I64u\n", BootSector->MftLocation);
DbgPrint(" MftMirrStart: %I64u\n", BootSector->MftMirrLocation);
DbgPrint(" ClustersPerMftRecord: %lx\n", BootSector->ClustersPerMftRecord);
DbgPrint(" ClustersPerIndexRecord: %lx\n", BootSector->ClustersPerIndexRecord);
DbgPrint(" SerialNumber: %I64x\n", BootSector->SerialNumber);
//#endif
NtfsOpenMft(DeviceObject, Vcb);
ExFreePool(BootSector);
return Status;
}
/* Read data from the bootsector */
NtfsInfo->BytesPerSector = BootSector->BytesPerSector;
NtfsInfo->SectorsPerCluster = BootSector->SectorsPerCluster;
NtfsInfo->BytesPerCluster = BootSector->BytesPerSector * BootSector->SectorsPerCluster;
NtfsInfo->SectorCount = BootSector->SectorCount;
NtfsInfo->MftStart.QuadPart = BootSector->MftLocation;
NtfsInfo->MftMirrStart.QuadPart = BootSector->MftMirrLocation;
NtfsInfo->SerialNumber = BootSector->SerialNumber;
NtfsInfo->ClustersPerFileRecord = BootSector->ClustersPerMftRecord;
//#ifndef NDEBUG
DbgPrint("Boot sector information:\n");
DbgPrint(" BytesPerSector: %hu\n", BootSector->BytesPerSector);
DbgPrint(" SectorsPerCluster: %hu\n", BootSector->SectorsPerCluster);
DbgPrint(" SectorCount: %I64u\n", BootSector->SectorCount);
DbgPrint(" MftStart: %I64u\n", BootSector->MftLocation);
DbgPrint(" MftMirrStart: %I64u\n", BootSector->MftMirrLocation);
DbgPrint(" ClustersPerMftRecord: %lx\n", BootSector->ClustersPerMftRecord);
DbgPrint(" ClustersPerIndexRecord: %lx\n", BootSector->ClustersPerIndexRecord);
DbgPrint(" SerialNumber: %I64x\n", BootSector->SerialNumber);
//#endif
ExFreePool(BootSector);
return(Status);
}
if (NtfsInfo->ClustersPerFileRecord == 0xF6)
FileRecordSize = NtfsInfo->ClustersPerFileRecord * NtfsInfo->BytesPerCluster;
else
FileRecordSize = NtfsInfo->BytesPerCluster;
MftRecord = ExAllocatePool(NonPagedPool,
FileRecordSize);
if (MftRecord == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = NtfsReadSectors(DeviceObject,
NtfsInfo->MftStart.u.LowPart * NtfsInfo->SectorsPerCluster,
FileRecordSize / NtfsInfo->BytesPerSector,
NtfsInfo->BytesPerSector,
(PVOID)MftRecord,
TRUE);
if (!NT_SUCCESS(Status))
{
ExFreePool (MftRecord);
return Status;
}
if (NtfsInfo->ClustersPerFileRecord == 0xF6)
{
VolumeRecord = (PVOID)((ULONG_PTR)MftRecord + 3 * (NtfsInfo->BytesPerCluster / 4));
}
else
{
VolumeRecord = ExAllocatePool(NonPagedPool,
FileRecordSize);
if (VolumeRecord == NULL)
{
ExFreePool (MftRecord);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Read cluster MftStart + 3 (Volume File) */
Status = NtfsReadSectors(DeviceObject,
(NtfsInfo->MftStart.u.LowPart + 3) * NtfsInfo->SectorsPerCluster,
FileRecordSize / NtfsInfo->BytesPerSector,
NtfsInfo->BytesPerSector,
(PVOID)VolumeRecord,
TRUE);
if (!NT_SUCCESS(Status))
{
ExFreePool (MftRecord);
return Status;
}
}
#ifndef NDEBUG
DbgPrint("\n\n");
/* Enumerate attributes */
NtfsDumpFileAttributes (MftRecord);
DbgPrint("\n\n");
DbgPrint("\n\n");
/* Enumerate attributes */
NtfsDumpFileAttributes (VolumeRecord);
DbgPrint("\n\n");
#endif
/* Get volume name */
Attribute = FindAttribute (VolumeRecord, AttributeVolumeName, NULL);
DPRINT("Attribute %p\n", Attribute);
DPRINT("Data length %lu\n", AttributeDataLength (Attribute));
if (Attribute != NULL && ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength != 0)
{
NtfsInfo->VolumeLabelLength =
min (((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength, MAXIMUM_VOLUME_LABEL_LENGTH);
RtlCopyMemory (NtfsInfo->VolumeLabel,
(PVOID)((ULONG_PTR)Attribute + ((PRESIDENT_ATTRIBUTE)Attribute)->ValueOffset),
NtfsInfo->VolumeLabelLength);
}
else
{
NtfsInfo->VolumeLabelLength = 0;
}
/* Get volume information */
Attribute = FindAttribute (VolumeRecord, AttributeVolumeInformation, NULL);
DPRINT("Attribute %p\n", Attribute);
DPRINT("Data length %lu\n", AttributeDataLength (Attribute));
if (Attribute != NULL && ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength != 0)
{
VolumeInfo = (PVOID)((ULONG_PTR)Attribute + ((PRESIDENT_ATTRIBUTE)Attribute)->ValueOffset);
NtfsInfo->MajorVersion = VolumeInfo->MajorVersion;
NtfsInfo->MinorVersion = VolumeInfo->MinorVersion;
NtfsInfo->Flags = VolumeInfo->Flags;
}
if (NtfsInfo->ClustersPerFileRecord != 0xF6)
{
ExFreePool (VolumeRecord);
}
ExFreePool (MftRecord);
return Status;
}
static NTSTATUS
@ -206,7 +318,7 @@ NtfsMountVolume(PDEVICE_OBJECT DeviceObject,
PVPB Vpb;
NTSTATUS Status;
DPRINT("NtfsMountVolume() called\n");
DPRINT1("NtfsMountVolume() called\n");
if (DeviceObject != NtfsGlobalData->DeviceObject)
{
@ -241,7 +353,7 @@ NtfsMountVolume(PDEVICE_OBJECT DeviceObject,
sizeof(DEVICE_EXTENSION));
Status = NtfsGetVolumeData(DeviceToMount,
DeviceExt);
&DeviceExt->NtfsInfo);
if (!NT_SUCCESS(Status))
goto ByeBye;
@ -309,12 +421,14 @@ NtfsMountVolume(PDEVICE_OBJECT DeviceObject,
KeInitializeSpinLock(&DeviceExt->FcbListLock);
InitializeListHead(&DeviceExt->FcbListHead);
/* Read serial number */
/* Get serial number */
NewDeviceObject->Vpb->SerialNumber = DeviceExt->NtfsInfo.SerialNumber;
/* Read volume label */
// NtfsReadVolumeLabel(DeviceExt,
// NewDeviceObject->Vpb);
/* Get volume label */
NewDeviceObject->Vpb->VolumeLabelLength = DeviceExt->NtfsInfo.VolumeLabelLength;
RtlCopyMemory (NewDeviceObject->Vpb->VolumeLabel,
DeviceExt->NtfsInfo.VolumeLabel,
DeviceExt->NtfsInfo.VolumeLabelLength);
Status = STATUS_SUCCESS;
@ -334,7 +448,7 @@ ByeBye:
DPRINT("NtfsMountVolume() done (Status: %lx)\n", Status);
return(Status);
return Status;
}
@ -342,95 +456,9 @@ static NTSTATUS
NtfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
#if 0
PDEVICE_OBJECT DeviceToVerify;
PIO_STACK_LOCATION Stack;
PUCHAR Buffer;
ULONG Sector;
ULONG i;
NTSTATUS Status;
union
{
ULONG Value;
UCHAR Part[4];
} Serial;
#endif
DPRINT1("NtfsVerifyVolume() called\n");
#if 0
Stack = IoGetCurrentIrpStackLocation(Irp);
DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject;
DPRINT("Device object %p Device to verify %p\n", DeviceObject, DeviceToVerify);
Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION;
Buffer = ExAllocatePool(NonPagedPool,
CDFS_BASIC_SECTOR);
if (Buffer == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
do
{
/* Read the Primary Volume Descriptor (PVD) */
Status = CdfsReadRawSectors(DeviceToVerify,
Sector,
1,
Buffer);
DPRINT("CdfsReadRawSectors() status %lx\n", Status);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
}
if (Buffer[0] == 1 &&
Buffer[1] == 'C' &&
Buffer[2] == 'D' &&
Buffer[3] == '0' &&
Buffer[4] == '0' &&
Buffer[5] == '1')
{
break;
}
Sector++;
}
while (Buffer[0] != 255);
if (Buffer[0] == 255)
goto ByeBye;
Status = STATUS_WRONG_VOLUME;
/* Calculate the volume serial number */
Serial.Value = 0;
for (i = 0; i < 2048; i += 4)
{
/* DON'T optimize this to ULONG!!! (breaks overflow) */
Serial.Part[0] += Buffer[i+3];
Serial.Part[1] += Buffer[i+2];
Serial.Part[2] += Buffer[i+1];
Serial.Part[3] += Buffer[i+0];
}
DPRINT("Current serial number %08lx Vpb serial number %08lx\n",
Serial.Value, DeviceToVerify->Vpb->SerialNumber);
if (Serial.Value == DeviceToVerify->Vpb->SerialNumber)
Status = STATUS_SUCCESS;
ByeBye:
ExFreePool(Buffer);
DPRINT("CdfsVerifyVolume() done (Status: %lx)\n", Status);
return(Status);
#endif
return(STATUS_UNSUCCESSFUL);
return STATUS_WRONG_VOLUME;
}
@ -441,7 +469,7 @@ NtfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
PIO_STACK_LOCATION Stack;
NTSTATUS Status;
DPRINT("NtfsFileSystemControl() called\n");
DPRINT1("NtfsFileSystemControl() called\n");
Stack = IoGetCurrentIrpStackLocation(Irp);

View file

@ -16,19 +16,20 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: mft.c,v 1.2 2003/09/15 16:01:16 ea Exp $
/* $Id: mft.c,v 1.3 2003/11/12 15:30:21 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ntfs/mft.c
* PURPOSE: NTFS filesystem driver
* PROGRAMMER: Eric Kohl
* Updated by Valentin Verkhovsky 2003/09/12
* PROGRAMMER: Eric Kohl
* Updated by Valentin Verkhovsky 2003/09/12
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <ntos/minmax.h>
//#define NDEBUG
#include <debug.h>
@ -36,306 +37,236 @@
#include "ntfs.h"
#define __min(a,b) (((a) < (b)) ? (a) : (b))
//#define __min(a,b) (((a) < (b)) ? (a) : (b))
/* FUNCTIONS ****************************************************************/
NTSTATUS
NtfsOpenMft(PDEVICE_OBJECT DeviceObject,
PDEVICE_EXTENSION Vcb)
NtfsOpenMft (PDEVICE_EXTENSION Vcb)
{
PVOID Buffer;
PVOID Bitmap;
// PVOID Bitmap;
PFILE_RECORD_HEADER MftRecord;
PFILE_RECORD_HEADER file;
PATTRIBUTE Attribute;
PATTRIBUTE AttrData;
PRESIDENT_ATTRIBUTE ResAttr;
PFILE_RECORD_HEADER FileRecord;
// PATTRIBUTE Attribute;
// PATTRIBUTE AttrData;
// PRESIDENT_ATTRIBUTE ResAttr;
NTSTATUS Status;
ULONG BytesPerFileRecord;
DPRINT1("NtfsOpenMft() called\n");
ULONG n = 0;
ULONG BytesPerFileRecord;
ULONG n;
ULONG i;
BytesPerFileRecord = Vcb->NtfsInfo.ClustersPerFileRecord *
Vcb->NtfsInfo.BytesPerCluster;
Buffer = ExAllocatePool(NonPagedPool,
BytesPerFileRecord);
if (Buffer == NULL)
DPRINT1("NtfsOpenMft() called\n");
BytesPerFileRecord =
Vcb->NtfsInfo.ClustersPerFileRecord * Vcb->NtfsInfo.BytesPerCluster;
MftRecord = ExAllocatePool(NonPagedPool,
BytesPerFileRecord);
if (MftRecord == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = NtfsReadSectors(Vcb->StorageDevice,
Vcb->NtfsInfo.MftStart.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
BytesPerFileRecord / Vcb->NtfsInfo.BytesPerSector,
Vcb->NtfsInfo.BytesPerSector,
(PVOID)MftRecord,
FALSE);
if (!NT_SUCCESS(Status))
{
ExFreePool(MftRecord);
return Status;
}
FixupUpdateSequenceArray(MftRecord);
// Attribute = FindAttribute(MftRecord, AttributeBitmap, 0);
/* Get number of file records*/
n = AttributeDataLength (FindAttribute (MftRecord, AttributeData, 0))
/ BytesPerFileRecord;
FileRecord = ExAllocatePool(NonPagedPool, BytesPerFileRecord);
if (FileRecord == NULL)
{
ExFreePool(MftRecord);
return(STATUS_INSUFFICIENT_RESOURCES);
}
Status = NtfsReadRawSectors(DeviceObject,
Vcb->NtfsInfo.MftStart.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
BytesPerFileRecord / Vcb->NtfsInfo.BytesPerSector,
Vcb->NtfsInfo.BytesPerSector,
(PVOID)Buffer);
if (NT_SUCCESS(Status))
/* Enumerate MFT Records */
DPRINT("Enumerate MFT records\n");
for ( i=0; i < n; i++)
{
DbgPrint("Enumerate MFT \n");
MftRecord = Buffer;
ReadFileRecord(Vcb, i, FileRecord, MftRecord);
FixupUpdateSequenceArray(MftRecord);
ULONG i;
Attribute = FindAttribute(MftRecord, AttributeBitmap, 0);
/* Get number of file records*/
n = AttributeLength(FindAttribute(MftRecord, AttributeData,0))
/ BytesPerFileRecord;
file = ExAllocatePool(NonPagedPool, BytesPerFileRecord);
if (file == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
/* Enumerate MFT Records */
for ( i=0; i < n; i++)
{
ReadFileRecord(i, file, Vcb, MftRecord, DeviceObject);
if (file->Ntfs.Type == 'ELIF' && (file->Flags & 1) != 0)
{
DbgPrint("\n");
DbgPrint("File %lu\n", i);
DbgPrint("\n");
/* Enumerate attributtes */
if (FileRecord->Ntfs.Type == NRH_FILE_TYPE && (FileRecord->Flags & FRH_IN_USE))
{
DPRINT("\nFile %lu\n\n", i);
EnumerAttribute(file, Vcb, DeviceObject);
DbgPrint("\n");
DbgPrint("\n");
}
/* Enumerate attributtes */
NtfsDumpFileAttributes (FileRecord);
DbgPrint("\n\n");
}
}
}
ExFreePool(FileRecord);
ExFreePool(MftRecord);
}
ExFreePool(Buffer);
ExFreePool(file);
return(Status);
return Status;
}
PATTRIBUTE FindAttribute(PFILE_RECORD_HEADER file,
ATTRIBUTE_TYPE type, PWSTR name)
PATTRIBUTE
FindAttribute (PFILE_RECORD_HEADER FileRecord,
ATTRIBUTE_TYPE Type,
PWSTR name)
{
PATTRIBUTE attr = (PATTRIBUTE)((PVOID)file + file->AttributeOffset);
while (attr->AttributeType !=-1)
PATTRIBUTE Attribute;
Attribute = (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
while (Attribute->AttributeType != -1)
{
if (Attribute->AttributeType == Type)
{
if(attr->AttributeType == type) {
return attr;
}
attr = (PATTRIBUTE)((ULONG)attr + attr->Length);
return Attribute;
}
return 0;
Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
}
return NULL;
}
ULONG AttributeLengthAllocated(PATTRIBUTE attr)
ULONG
AttributeAllocatedLength (PATTRIBUTE Attribute)
{
PRESIDENT_ATTRIBUTE ResAttr;
PNONRESIDENT_ATTRIBUTE NresAttr;
if(attr->Nonresident == FALSE)
{
ResAttr = (PRESIDENT_ATTRIBUTE)attr;
return ResAttr->ValueLength;
}
else
{
NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
return NresAttr->AllocatedSize;
}
if (Attribute->Nonresident)
{
return ((PNONRESIDENT_ATTRIBUTE)Attribute)->AllocatedSize;
}
return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
}
VOID ReadAttribute(PATTRIBUTE attr, PVOID buffer, PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject)
ULONG
AttributeDataLength (PATTRIBUTE Attribute)
{
if(attr->Nonresident == FALSE)
{
PRESIDENT_ATTRIBUTE ResAttr = (PRESIDENT_ATTRIBUTE)attr;
memcpy(buffer, (PRESIDENT_ATTRIBUTE)((PVOID)ResAttr + ResAttr->ValueOffset),
ResAttr->ValueLength);
if (Attribute->Nonresident)
{
return ((PNONRESIDENT_ATTRIBUTE)Attribute)->DataSize;
}
}
PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
ReadExternalAttribute(NresAttr, 0, (ULONG)(NresAttr->LastVcn) + 1,
buffer, Vcb, DeviceObject);
return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
}
VOID
ReadAttribute (PATTRIBUTE attr,
PVOID buffer,
PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject)
{
if (attr->Nonresident == FALSE)
{
memcpy (buffer,
(PVOID)((ULONG_PTR)attr + ((PRESIDENT_ATTRIBUTE)attr)->ValueOffset),
((PRESIDENT_ATTRIBUTE)attr)->ValueLength);
}
PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
ReadExternalAttribute(Vcb, NresAttr, 0, (ULONG)(NresAttr->LastVcn) + 1,
buffer);
}
ULONG AttributeLength(PATTRIBUTE attr)
VOID
ReadFileRecord (PDEVICE_EXTENSION Vcb,
ULONG index,
PFILE_RECORD_HEADER file,
PFILE_RECORD_HEADER Mft)
{
PRESIDENT_ATTRIBUTE ResAttr;
PNONRESIDENT_ATTRIBUTE NresAttr;
if(attr->Nonresident == FALSE)
{
ResAttr = (PRESIDENT_ATTRIBUTE)attr;
return ResAttr->ValueLength;
}
PVOID p;
ULONG clusters = Vcb->NtfsInfo.ClustersPerFileRecord;
ULONG BytesPerFileRecord = clusters * Vcb->NtfsInfo.BytesPerCluster;
else
{
NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
return NresAttr->DataSize;
}
p = ExAllocatePool(NonPagedPool, BytesPerFileRecord);
ULONGLONG vcn = index * BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster;
ReadVCN (Vcb, Mft, AttributeData, vcn, clusters, p);
LONG m = (Vcb->NtfsInfo.BytesPerCluster / BytesPerFileRecord) - 1;
ULONG n = m > 0 ? (index & m) : 0;
memcpy(file, p + n * BytesPerFileRecord, BytesPerFileRecord);
ExFreePool(p);
FixupUpdateSequenceArray(file);
}
VOID ReadFileRecord(ULONG index, PFILE_RECORD_HEADER file,
PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER Mft,
PDEVICE_OBJECT DeviceObject)
VOID
ReadExternalAttribute (PDEVICE_EXTENSION Vcb,
PNONRESIDENT_ATTRIBUTE NresAttr,
ULONGLONG vcn,
ULONG count,
PVOID buffer)
{
PVOID p;
ULONG clusters = Vcb->NtfsInfo.ClustersPerFileRecord;
ULONG BytesPerFileRecord = clusters * Vcb->NtfsInfo.BytesPerCluster;
p = ExAllocatePool(NonPagedPool, BytesPerFileRecord);
ULONGLONG vcn = index * BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster;
ReadVCN(Mft, AttributeData, vcn, clusters, p, Vcb,DeviceObject);
LONG m = (Vcb->NtfsInfo.BytesPerCluster / BytesPerFileRecord) - 1;
ULONG n = m > 0 ? (index & m) : 0;
memcpy(file, p + n * BytesPerFileRecord, BytesPerFileRecord);
ExFreePool(p);
FixupUpdateSequenceArray(file);
}
VOID ReadExternalAttribute(PNONRESIDENT_ATTRIBUTE NresAttr,
ULONGLONG vcn, ULONG count, PVOID buffer,
PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject)
{
ULONGLONG lcn, runcount;
ULONG readcount, left;
ULONGLONG lcn;
ULONGLONG runcount;
ULONG readcount;
ULONG left;
PUCHAR bytes = (PUCHAR)buffer;
for (left = count; left>0; left -=readcount)
{
for (left = count; left>0; left -=readcount)
{
FindRun(NresAttr, vcn, &lcn, &runcount);
readcount = (ULONG)(__min(runcount, left));
// readcount = (ULONG)(__min(runcount, left));
readcount = (ULONG)min (runcount, left);
ULONG n = readcount * Vcb->NtfsInfo.BytesPerCluster;
if (lcn == 0)
memset(bytes, 0, n);
else
ReadLCN(lcn, readcount, bytes, Vcb, DeviceObject);
ReadLCN(Vcb, lcn, readcount, bytes);
vcn += readcount;
bytes += n;
}
}
}
BOOL FindRun(PNONRESIDENT_ATTRIBUTE NresAttr, ULONGLONG vcn,
PULONGLONG lcn, PULONGLONG count)
VOID
ReadVCN (PDEVICE_EXTENSION Vcb,
PFILE_RECORD_HEADER file,
ATTRIBUTE_TYPE type,
ULONGLONG vcn,
ULONG count,
PVOID buffer)
{
PUCHAR run;
ULONGLONG base = NresAttr->StartVcn;
if (vcn < NresAttr->StartVcn || vcn > NresAttr->LastVcn)
return FALSE;
*lcn = 0;
for (run = (PUCHAR)((ULONG)NresAttr + NresAttr->RunArrayOffset);
*run != 0; run += RunLength(run)) {
*lcn += RunLCN(run);
*count = RunCount(run);
if(base <= vcn && vcn < base + *count)
{
*lcn = RunLCN(run) == 0 ? 0 : *lcn + vcn - base;
*count -= (ULONG)(vcn - base);
return TRUE;
}
else
base += *count;
}
return FALSE;
}
VOID ReadVCN(PFILE_RECORD_HEADER file, ATTRIBUTE_TYPE type,
ULONGLONG vcn, ULONG count, PVOID buffer,
PDEVICE_EXTENSION Vcb, PDEVICE_OBJECT DeviceObject)
{
PNONRESIDENT_ATTRIBUTE NresAttr;
PATTRIBUTE attr;
attr = FindAttribute(file, type,0);
attr = FindAttribute(file, type, 0);
NresAttr = (PNONRESIDENT_ATTRIBUTE) attr;
@ -347,11 +278,10 @@ VOID ReadVCN(PFILE_RECORD_HEADER file, ATTRIBUTE_TYPE type,
//KeDebugCheck(0);
}
ReadExternalAttribute(NresAttr, vcn, count, buffer, Vcb, DeviceObject);
ReadExternalAttribute(Vcb, NresAttr, vcn, count, buffer);
}
BOOL bitset(PUCHAR bitmap, ULONG i)
{
return (bitmap[i>>3] & (1 << (i & 7))) !=0;
@ -374,52 +304,22 @@ VOID FixupUpdateSequenceArray(PFILE_RECORD_HEADER file)
}
VOID ReadLCN(ULONGLONG lcn, ULONG count, PVOID buffer, PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject)
NTSTATUS
ReadLCN (PDEVICE_EXTENSION Vcb,
ULONGLONG lcn,
ULONG count,
PVOID buffer)
{
LARGE_INTEGER DiskSector;
DiskSector.QuadPart = lcn;
NtfsReadRawSectors(DeviceObject, DiskSector.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
count * Vcb->NtfsInfo.SectorsPerCluster, Vcb->NtfsInfo.BytesPerSector, buffer);
LARGE_INTEGER DiskSector;
DiskSector.QuadPart = lcn;
return NtfsReadSectors (Vcb->StorageDevice,
DiskSector.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
count * Vcb->NtfsInfo.SectorsPerCluster,
Vcb->NtfsInfo.BytesPerSector,
buffer,
FALSE);
}
VOID EnumerAttribute(PFILE_RECORD_HEADER file, PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject)
{
ULONGLONG lcn;
ULONGLONG runcount;
ULONG size;
PATTRIBUTE attr = (PATTRIBUTE)((PVOID)file + file->AttributeOffset);
while (attr->AttributeType !=-1)
{
if(NtfsDumpAttribute(attr))
{
PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
FindRun(NresAttr,0,&lcn, &runcount);
DbgPrint(" AllocatedSize %I64d DataSize %I64d\n", NresAttr->AllocatedSize, NresAttr->DataSize);
DbgPrint(" logical sectors: %lu", lcn);
DbgPrint("-%lu\n", lcn + runcount -1);
}
attr = (PATTRIBUTE)((ULONG)attr + attr->Length);
}
}
/* EOF */
/* EOF */

View file

@ -49,9 +49,15 @@ typedef struct _NTFS_INFO
ULONGLONG SectorCount;
ULARGE_INTEGER MftStart;
ULARGE_INTEGER MftMirrStart;
ULONGLONG SerialNumber;
ULONG ClustersPerFileRecord;
ULONGLONG SerialNumber;
USHORT VolumeLabelLength;
WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH];
UCHAR MajorVersion;
UCHAR MinorVersion;
USHORT Flags;
} NTFS_INFO, *PNTFS_INFO;
@ -155,10 +161,14 @@ typedef struct
{
ULONG Type; /* Magic number 'FILE' */
USHORT UsaOffset; /* Offset to the update sequence */
USHORT UsaCount; /* Size in words of Update Sequence Number & Array (S) */
USHORT UsaCount; /* Size in words of Update Sequence Number & Array (S) */
ULONGLONG Lsn; /* $LogFile Sequence Number (LSN) */
} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;
/* NTFS_RECORD_HEADER.Type */
#define NRH_FILE_TYPE 0x454C4946 /* 'FILE' */
typedef struct
{
NTFS_RECORD_HEADER Ntfs;
@ -176,10 +186,10 @@ typedef struct
/* Flags in FILE_RECORD_HEADER */
#define FRH_IN_USE 0x01 /* Record is in use */
#define FRH_DIRECTORY 0x02 /* Record is a directory */
#define FRH_UNKNOWN1 0x04 /* Don't know */
#define FRH_UNKNOWN2 0x08 /* Don't know */
#define FRH_IN_USE 0x0001 /* Record is in use */
#define FRH_DIRECTORY 0x0002 /* Record is a directory */
#define FRH_UNKNOWN1 0x0004 /* Don't know */
#define FRH_UNKNOWN2 0x0008 /* Don't know */
typedef struct
{
@ -281,12 +291,14 @@ extern PNTFS_GLOBAL_DATA NtfsGlobalData;
/* attrib.c */
BOOL
NtfsDumpAttribute(PATTRIBUTE Attribute);
//VOID
//NtfsDumpAttribute(PATTRIBUTE Attribute);
LONGLONG RunLCN(PUCHAR run);
//LONGLONG RunLCN(PUCHAR run);
ULONG RunLength(PUCHAR run);
//ULONG RunLength(PUCHAR run);
VOID
NtfsDumpFileAttributes (PFILE_RECORD_HEADER FileRecord);
/* blockdev.c */
@ -295,14 +307,8 @@ NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN ULONG SectorSize,
IN OUT PUCHAR Buffer);
NTSTATUS
NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN ULONG SectorSize,
IN OUT PUCHAR Buffer);
IN OUT PUCHAR Buffer,
IN BOOLEAN Override);
NTSTATUS
NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
@ -310,7 +316,8 @@ NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG OutputBufferSize);
IN OUT PULONG OutputBufferSize,
IN BOOLEAN Override);
/* close.c */
@ -399,45 +406,59 @@ NtfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
/* mft.c */
NTSTATUS
NtfsOpenMft(PDEVICE_OBJECT DeviceObject,
PDEVICE_EXTENSION Vcb);
NtfsOpenMft (PDEVICE_EXTENSION Vcb);
VOID ReadAttribute(PATTRIBUTE attr, PVOID buffer, PDEVICE_EXTENSION Vcb,
VOID
ReadAttribute(PATTRIBUTE attr, PVOID buffer, PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject);
ULONG AttributeLength(PATTRIBUTE attr);
ULONG
AttributeDataLength(PATTRIBUTE attr);
VOID ReadFileRecord(ULONG index, PFILE_RECORD_HEADER file,
PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER Mft,
PDEVICE_OBJECT DeviceObject);
VOID
ReadFileRecord (PDEVICE_EXTENSION Vcb,
ULONG index,
PFILE_RECORD_HEADER file,
PFILE_RECORD_HEADER Mft);
PATTRIBUTE
FindAttribute(PFILE_RECORD_HEADER file,
ATTRIBUTE_TYPE type,
PWSTR name);
PATTRIBUTE FindAttribute(PFILE_RECORD_HEADER file,
ULONG
AttributeLengthAllocated(PATTRIBUTE attr);
ATTRIBUTE_TYPE type, PWSTR name);
ULONG AttributeLengthAllocated(PATTRIBUTE attr);
VOID ReadVCN(PFILE_RECORD_HEADER file, ATTRIBUTE_TYPE type,
ULONGLONG vcn, ULONG count, PVOID buffer,
PDEVICE_EXTENSION Vcb, PDEVICE_OBJECT DeviceObject);
VOID
ReadVCN (PDEVICE_EXTENSION Vcb,
PFILE_RECORD_HEADER file,
ATTRIBUTE_TYPE type,
ULONGLONG vcn,
ULONG count,
PVOID buffer);
VOID FixupUpdateSequenceArray(PFILE_RECORD_HEADER file);
VOID ReadExternalAttribute(PNONRESIDENT_ATTRIBUTE NresAttr,
ULONGLONG vcn, ULONG count, PVOID buffer,
PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject);
VOID
ReadExternalAttribute (PDEVICE_EXTENSION Vcb,
PNONRESIDENT_ATTRIBUTE NresAttr,
ULONGLONG vcn,
ULONG count,
PVOID buffer);
VOID ReadLCN(ULONGLONG lcn, ULONG count, PVOID buffer, PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject);
NTSTATUS
ReadLCN (PDEVICE_EXTENSION Vcb,
ULONGLONG lcn,
ULONG count,
PVOID buffer);
VOID EnumerAttribute(PFILE_RECORD_HEADER file,PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject );
VOID
EnumerAttribute(PFILE_RECORD_HEADER file,
PDEVICE_EXTENSION Vcb,
PDEVICE_OBJECT DeviceObject);
#if 0
/* misc.c */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: volinfo.c,v 1.2 2003/07/17 13:31:39 chorns Exp $
/* $Id: volinfo.c,v 1.3 2003/11/12 15:30:21 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -42,40 +42,43 @@ NtfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
PULONG BufferLength)
{
ULONG LabelLength;
DPRINT("NtfsGetFsVolumeInformation() called\n");
DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
DPRINT("BufferLength %lu\n", *BufferLength);
DPRINT("Vpb %p\n", DeviceObject->Vpb);
LabelLength = DeviceObject->Vpb->VolumeLabelLength;
DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)));
DPRINT("LabelLength %lu\n", LabelLength);
DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel);
DPRINT("Required length %lu\n",
sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength);
DPRINT("LabelLength %hu\n",
DeviceObject->Vpb->VolumeLabelLength);
DPRINT("Label %*.S\n",
DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR),
DeviceObject->Vpb->VolumeLabel);
if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
return(STATUS_INFO_LENGTH_MISMATCH);
return STATUS_INFO_LENGTH_MISMATCH;
if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)))
return(STATUS_BUFFER_OVERFLOW);
if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength))
return STATUS_BUFFER_OVERFLOW;
/* valid entries */
FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR);
wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
memcpy(FsVolumeInfo->VolumeLabel,
DeviceObject->Vpb->VolumeLabel,
DeviceObject->Vpb->VolumeLabelLength);
/* dummy entries */
FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
FsVolumeInfo->SupportsObjects = FALSE;
*BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR));
*BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength);
DPRINT("BufferLength %lu\n", *BufferLength);
DPRINT("NtfsGetFsVolumeInformation() done\n");
return(STATUS_SUCCESS);
return STATUS_SUCCESS;
}