mirror of
https://github.com/reactos/reactos.git
synced 2025-04-18 03:34:11 +00:00
- 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:
parent
063bd518b1
commit
c9a794eb0e
6 changed files with 548 additions and 646 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue