2002-06-25 22:23:06 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
|
|
|
* Copyright (C) 2002 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2008-03-08 21:45:51 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-06-25 22:23:06 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
2007-12-28 21:56:19 +00:00
|
|
|
* FILE: drivers/filesystems/ntfs/fsctl.c
|
2002-06-25 22:23:06 +00:00
|
|
|
* PURPOSE: NTFS filesystem driver
|
|
|
|
* PROGRAMMER: Eric Kohl
|
2008-02-24 10:06:37 +00:00
|
|
|
* Valentin Verkhovsky
|
|
|
|
* Pierre Schweitzer
|
2002-06-25 22:23:06 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2005-06-17 12:29:33 +00:00
|
|
|
#include "ntfs.h"
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2005-07-20 02:52:52 +00:00
|
|
|
#define NDEBUG
|
2002-06-25 22:23:06 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2005-07-20 02:52:52 +00:00
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
|
2002-06-25 22:23:06 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
|
|
|
|
/*
|
2005-05-08 02:16:32 +00:00
|
|
|
* FUNCTION: Tests if the device contains a filesystem that can be mounted
|
2002-06-25 22:23:06 +00:00
|
|
|
* by this fsd
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
PARTITION_INFORMATION PartitionInfo;
|
|
|
|
DISK_GEOMETRY DiskGeometry;
|
|
|
|
PBOOT_SECTOR BootSector;
|
|
|
|
NTSTATUS Status;
|
2008-02-24 10:06:37 +00:00
|
|
|
ULONG Size, k;
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
DPRINT1("NtfsHasFileSystem() called\n");
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Size = sizeof(DISK_GEOMETRY);
|
|
|
|
Status = NtfsDeviceIoControl(DeviceToMount,
|
2008-01-01 18:55:52 +00:00
|
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&DiskGeometry,
|
|
|
|
&Size,
|
|
|
|
TRUE);
|
2002-06-25 22:23:06 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
DPRINT1("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DiskGeometry.MediaType == FixedMedia)
|
|
|
|
{
|
|
|
|
/* We have found a hard disk */
|
|
|
|
Size = sizeof(PARTITION_INFORMATION);
|
|
|
|
Status = NtfsDeviceIoControl(DeviceToMount,
|
|
|
|
IOCTL_DISK_GET_PARTITION_INFO,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&PartitionInfo,
|
|
|
|
&Size,
|
|
|
|
TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2002-06-25 22:23:06 +00:00
|
|
|
{
|
2003-11-12 15:30:21 +00:00
|
|
|
DPRINT1("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
|
2002-06-25 22:23:06 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
2008-01-01 18:55:52 +00:00
|
|
|
if (PartitionInfo.PartitionType != PARTITION_IFS)
|
2002-06-25 22:23:06 +00:00
|
|
|
{
|
2008-01-01 18:55:52 +00:00
|
|
|
DPRINT1("Invalid partition type\n");
|
|
|
|
return(STATUS_UNRECOGNIZED_VOLUME);
|
2002-06-25 22:23:06 +00:00
|
|
|
}
|
2008-01-01 18:55:52 +00:00
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
DPRINT1("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
|
2008-01-13 11:36:54 +00:00
|
|
|
BootSector = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
DiskGeometry.BytesPerSector, TAG_NTFS);
|
2002-06-25 22:23:06 +00:00
|
|
|
if (BootSector == NULL)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
Status = NtfsReadSectors (DeviceToMount,
|
2008-01-01 18:55:52 +00:00
|
|
|
0,
|
|
|
|
1,
|
|
|
|
DiskGeometry.BytesPerSector,
|
|
|
|
(PVOID)BootSector,
|
|
|
|
TRUE);
|
2008-02-24 10:06:37 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check values of different fields. If those fields have not expected
|
|
|
|
* values, we fail, to avoid mounting partitions that Windows won't mount.
|
|
|
|
*/
|
|
|
|
/* OEMID: this field must be NTFS */
|
|
|
|
if (RtlCompareMemory(BootSector->OEMID, "NTFS ", 8) != 8)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed with NTFS-identifier: [%.8s]\n", BootSector->OEMID);
|
|
|
|
Status = STATUS_UNRECOGNIZED_VOLUME;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
/* Unused0: this field must be COMPLETELY null */
|
|
|
|
for (k=0; k<7; k++)
|
|
|
|
{
|
|
|
|
if (BootSector->BPB.Unused0[k] != 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed in field Unused0: [%.7s]\n", BootSector->BPB.Unused0);
|
|
|
|
Status = STATUS_UNRECOGNIZED_VOLUME;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Unused3: this field must be COMPLETELY null */
|
|
|
|
for (k=0; k<4; k++)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
2008-02-24 10:06:37 +00:00
|
|
|
if (BootSector->BPB.Unused3[k] != 0)
|
2002-06-25 22:23:06 +00:00
|
|
|
{
|
2008-02-24 10:06:37 +00:00
|
|
|
DPRINT1("Failed in field Unused3: [%.4s]\n", BootSector->BPB.Unused3);
|
2008-01-01 18:55:52 +00:00
|
|
|
Status = STATUS_UNRECOGNIZED_VOLUME;
|
2008-02-24 10:06:37 +00:00
|
|
|
goto ByeBye;
|
2002-06-25 22:23:06 +00:00
|
|
|
}
|
2008-01-01 18:55:52 +00:00
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2008-02-24 10:06:37 +00:00
|
|
|
ByeBye:
|
2002-06-25 22:23:06 +00:00
|
|
|
ExFreePool(BootSector);
|
2008-02-24 10:06:37 +00:00
|
|
|
return Status;
|
2002-06-25 22:23:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
|
2004-06-05 08:28:37 +00:00
|
|
|
PDEVICE_EXTENSION DeviceExt)
|
2002-06-25 22:23:06 +00:00
|
|
|
{
|
|
|
|
DISK_GEOMETRY DiskGeometry;
|
2003-11-12 15:30:21 +00:00
|
|
|
PFILE_RECORD_HEADER MftRecord;
|
|
|
|
PFILE_RECORD_HEADER VolumeRecord;
|
|
|
|
PVOLINFO_ATTRIBUTE VolumeInfo;
|
|
|
|
PBOOT_SECTOR BootSector;
|
|
|
|
PATTRIBUTE Attribute;
|
2002-06-25 22:23:06 +00:00
|
|
|
ULONG Size;
|
|
|
|
NTSTATUS Status;
|
2004-06-05 08:28:37 +00:00
|
|
|
PNTFS_INFO NtfsInfo = &DeviceExt->NtfsInfo;
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
DPRINT("NtfsGetVolumeData() called\n");
|
|
|
|
|
|
|
|
Size = sizeof(DISK_GEOMETRY);
|
|
|
|
Status = NtfsDeviceIoControl(DeviceObject,
|
2008-01-01 18:55:52 +00:00
|
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&DiskGeometry,
|
|
|
|
&Size,
|
|
|
|
TRUE);
|
2002-06-25 22:23:06 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
|
|
|
|
return(Status);
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
|
2008-01-13 11:36:54 +00:00
|
|
|
BootSector = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
DiskGeometry.BytesPerSector, TAG_NTFS);
|
2002-06-25 22:23:06 +00:00
|
|
|
if (BootSector == NULL)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
Status = NtfsReadSectors(DeviceObject,
|
2008-01-01 18:55:52 +00:00
|
|
|
0, /* Partition boot sector */
|
|
|
|
1,
|
|
|
|
DiskGeometry.BytesPerSector,
|
|
|
|
(PVOID)BootSector,
|
|
|
|
TRUE);
|
2003-11-12 15:30:21 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
ExFreePool(BootSector);
|
|
|
|
return Status;
|
|
|
|
}
|
2003-11-12 15:30:21 +00:00
|
|
|
|
|
|
|
/* Read data from the bootsector */
|
2007-12-28 21:56:19 +00:00
|
|
|
NtfsInfo->BytesPerSector = BootSector->BPB.BytesPerSector;
|
|
|
|
NtfsInfo->SectorsPerCluster = BootSector->BPB.SectorsPerCluster;
|
|
|
|
NtfsInfo->BytesPerCluster = BootSector->BPB.BytesPerSector * BootSector->BPB.SectorsPerCluster;
|
|
|
|
NtfsInfo->SectorCount = BootSector->EBPB.SectorCount;
|
|
|
|
|
|
|
|
NtfsInfo->MftStart.QuadPart = BootSector->EBPB.MftLocation;
|
|
|
|
NtfsInfo->MftMirrStart.QuadPart = BootSector->EBPB.MftMirrLocation;
|
|
|
|
NtfsInfo->SerialNumber = BootSector->EBPB.SerialNumber;
|
|
|
|
if (BootSector->EBPB.ClustersPerMftRecord > 0)
|
|
|
|
NtfsInfo->BytesPerFileRecord = BootSector->EBPB.ClustersPerMftRecord * NtfsInfo->BytesPerCluster;
|
2004-06-05 08:28:37 +00:00
|
|
|
else
|
2007-12-28 21:56:19 +00:00
|
|
|
NtfsInfo->BytesPerFileRecord = 1 << (-BootSector->EBPB.ClustersPerMftRecord);
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2008-02-24 10:06:37 +00:00
|
|
|
DPRINT("Boot sector information:\n");
|
|
|
|
DPRINT(" BytesPerSector: %hu\n", BootSector->BPB.BytesPerSector);
|
|
|
|
DPRINT(" SectorsPerCluster: %hu\n", BootSector->BPB.SectorsPerCluster);
|
|
|
|
DPRINT(" SectorCount: %I64u\n", BootSector->EBPB.SectorCount);
|
|
|
|
DPRINT(" MftStart: %I64u\n", BootSector->EBPB.MftLocation);
|
|
|
|
DPRINT(" MftMirrStart: %I64u\n", BootSector->EBPB.MftMirrLocation);
|
|
|
|
DPRINT(" ClustersPerMftRecord: %lx\n", BootSector->EBPB.ClustersPerMftRecord);
|
|
|
|
DPRINT(" ClustersPerIndexRecord: %lx\n", BootSector->EBPB.ClustersPerIndexRecord);
|
|
|
|
DPRINT(" SerialNumber: %I64x\n", BootSector->EBPB.SerialNumber);
|
2002-07-15 15:37:33 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
ExFreePool(BootSector);
|
2002-07-15 15:37:33 +00:00
|
|
|
|
2008-01-13 11:36:54 +00:00
|
|
|
MftRecord = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
NtfsInfo->BytesPerFileRecord, TAG_NTFS);
|
2003-11-12 15:30:21 +00:00
|
|
|
if (MftRecord == NULL)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
Status = NtfsReadSectors(DeviceObject,
|
2008-01-01 18:55:52 +00:00
|
|
|
NtfsInfo->MftStart.u.LowPart * NtfsInfo->SectorsPerCluster,
|
|
|
|
NtfsInfo->BytesPerFileRecord / NtfsInfo->BytesPerSector,
|
|
|
|
NtfsInfo->BytesPerSector,
|
|
|
|
(PVOID)MftRecord,
|
|
|
|
TRUE);
|
2003-11-12 15:30:21 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
ExFreePool (MftRecord);
|
|
|
|
return Status;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2008-01-13 11:36:54 +00:00
|
|
|
VolumeRecord = ExAllocatePoolWithTag(NonPagedPool, NtfsInfo->BytesPerFileRecord, TAG_NTFS);
|
2004-06-05 08:28:37 +00:00
|
|
|
if (VolumeRecord == NULL)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
ExFreePool (MftRecord);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
2003-11-12 15:30:21 +00:00
|
|
|
|
2004-06-05 08:28:37 +00:00
|
|
|
/* Read Volume File (MFT index 3) */
|
|
|
|
DeviceExt->StorageDevice = DeviceObject;
|
|
|
|
Status = ReadFileRecord(DeviceExt, 3, VolumeRecord, MftRecord);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
ExFreePool (MftRecord);
|
|
|
|
return Status;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
/* Enumerate attributes */
|
|
|
|
NtfsDumpFileAttributes (MftRecord);
|
|
|
|
|
|
|
|
/* Enumerate attributes */
|
|
|
|
NtfsDumpFileAttributes (VolumeRecord);
|
|
|
|
|
|
|
|
/* Get volume name */
|
|
|
|
Attribute = FindAttribute (VolumeRecord, AttributeVolumeName, NULL);
|
|
|
|
DPRINT("Attribute %p\n", Attribute);
|
|
|
|
|
|
|
|
if (Attribute != NULL && ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength != 0)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
DPRINT("Data length %lu\n", AttributeDataLength (Attribute));
|
|
|
|
NtfsInfo->VolumeLabelLength =
|
|
|
|
min (((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength, MAXIMUM_VOLUME_LABEL_LENGTH);
|
|
|
|
RtlCopyMemory (NtfsInfo->VolumeLabel,
|
|
|
|
(PVOID)((ULONG_PTR)Attribute + ((PRESIDENT_ATTRIBUTE)Attribute)->ValueOffset),
|
|
|
|
NtfsInfo->VolumeLabelLength);
|
|
|
|
}
|
2003-11-12 15:30:21 +00:00
|
|
|
else
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
NtfsInfo->VolumeLabelLength = 0;
|
|
|
|
}
|
2003-11-12 15:30:21 +00:00
|
|
|
|
|
|
|
/* Get volume information */
|
|
|
|
Attribute = FindAttribute (VolumeRecord, AttributeVolumeInformation, NULL);
|
|
|
|
DPRINT("Attribute %p\n", Attribute);
|
|
|
|
|
|
|
|
if (Attribute != NULL && ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength != 0)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
DPRINT("Data length %lu\n", AttributeDataLength (Attribute));
|
|
|
|
VolumeInfo = (PVOID)((ULONG_PTR)Attribute + ((PRESIDENT_ATTRIBUTE)Attribute)->ValueOffset);
|
2003-11-12 15:30:21 +00:00
|
|
|
|
2008-01-01 18:55:52 +00:00
|
|
|
NtfsInfo->MajorVersion = VolumeInfo->MajorVersion;
|
|
|
|
NtfsInfo->MinorVersion = VolumeInfo->MinorVersion;
|
|
|
|
NtfsInfo->Flags = VolumeInfo->Flags;
|
|
|
|
}
|
2003-11-12 15:30:21 +00:00
|
|
|
|
|
|
|
ExFreePool (MftRecord);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
NtfsMountVolume(PDEVICE_OBJECT DeviceObject,
|
2008-01-01 18:55:52 +00:00
|
|
|
PIRP Irp)
|
2002-06-25 22:23:06 +00:00
|
|
|
{
|
|
|
|
PDEVICE_EXTENSION DeviceExt = NULL;
|
|
|
|
PDEVICE_OBJECT NewDeviceObject = NULL;
|
|
|
|
PDEVICE_OBJECT DeviceToMount;
|
|
|
|
PIO_STACK_LOCATION Stack;
|
2008-03-15 08:51:47 +00:00
|
|
|
PNTFS_FCB Fcb = NULL;
|
|
|
|
PNTFS_CCB Ccb = NULL;
|
2002-06-25 22:23:06 +00:00
|
|
|
PVPB Vpb;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
DPRINT1("NtfsMountVolume() called\n");
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
if (DeviceObject != NtfsGlobalData->DeviceObject)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
DeviceToMount = Stack->Parameters.MountVolume.DeviceObject;
|
|
|
|
Vpb = Stack->Parameters.MountVolume.Vpb;
|
|
|
|
|
|
|
|
Status = NtfsHasFileSystem(DeviceToMount);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Status = IoCreateDevice(NtfsGlobalData->DriverObject,
|
2008-01-01 18:55:52 +00:00
|
|
|
sizeof(DEVICE_EXTENSION),
|
|
|
|
NULL,
|
|
|
|
FILE_DEVICE_FILE_SYSTEM,
|
|
|
|
// FILE_DEVICE_DISK_FILE_SYSTEM,
|
|
|
|
0,
|
|
|
|
FALSE,
|
|
|
|
&NewDeviceObject);
|
2002-06-25 22:23:06 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
goto ByeBye;
|
|
|
|
|
|
|
|
NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO;
|
|
|
|
DeviceExt = (PVOID)NewDeviceObject->DeviceExtension;
|
|
|
|
RtlZeroMemory(DeviceExt,
|
2008-01-01 18:55:52 +00:00
|
|
|
sizeof(DEVICE_EXTENSION));
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Status = NtfsGetVolumeData(DeviceToMount,
|
2008-01-01 18:55:52 +00:00
|
|
|
DeviceExt);
|
2002-06-25 22:23:06 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
goto ByeBye;
|
|
|
|
|
|
|
|
NewDeviceObject->Vpb = DeviceToMount->Vpb;
|
|
|
|
|
|
|
|
DeviceExt->StorageDevice = DeviceToMount;
|
|
|
|
DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject;
|
|
|
|
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
|
|
|
|
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
|
|
|
|
NewDeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
|
|
|
|
NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
|
|
|
|
DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL,
|
2008-01-01 18:55:52 +00:00
|
|
|
DeviceExt->StorageDevice);
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
Fcb = NtfsCreateFCB(NULL);
|
|
|
|
if (Fcb == NULL)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Ccb = ExAllocatePoolWithTag(NonPagedPool,
|
2008-03-15 08:51:47 +00:00
|
|
|
sizeof(NTFS_CCB),
|
2008-01-01 18:55:52 +00:00
|
|
|
TAG_CCB);
|
2002-06-25 22:23:06 +00:00
|
|
|
if (Ccb == NULL)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto ByeBye;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
RtlZeroMemory(Ccb,
|
2008-03-15 08:51:47 +00:00
|
|
|
sizeof(NTFS_CCB));
|
2002-06-25 22:23:06 +00:00
|
|
|
|
2003-02-13 22:24:19 +00:00
|
|
|
DeviceExt->StreamFileObject->FsContext = Fcb;
|
2002-06-25 22:23:06 +00:00
|
|
|
DeviceExt->StreamFileObject->FsContext2 = Ccb;
|
2003-06-07 Casper S. Hornstrup <chorns@users.sourceforge.net>
Changes for compiling with w32api
* include/ddk/cctypes.h (PREACTOS_COMMON_FCB_HEADER): Remove.
(FSRTL_COMMON_FCB_HEADER): Add.
* include/ddk/iotypes.h (FILE_OBJECT): Rename field
SectionObjectPointers to SectionObjectPointer.
* ntoskrnl/cc/copy.c, ntoskrnl/cc/misc.c, ntoskrnl/cc/pin.c,
ntoskrnl/cc/view.c, ntoskrnl/io/rawfs.c, ntoskrnl/mm/section.c,
drivers/fs/cdfs/cleanup.c, drivers/fs/cdfs/fcb.c,
drivers/fs/cdfs/fsctl.c, drivers/fs/ntfs/fcb.c, drivers/fs/ntfs/fsctl.c,
drivers/fs/vfat/close.c, drivers/fs/vfat/create.c,
drivers/fs/vfat/finfo.c, drivers/fs/vfat/fcb.c, drivers/fs/vfat/fsctl.c:
Use new FILE_OBJECT structure.
* drivers/fs/cdfs/cdfs.h, drivers/fs/ntfs/ntfs.h, drivers/fs/vfat/vfat.h:
Use new FSRTL_COMMON_FCB_HEADER structure.
* drivers/net/afd/include/afd.h (FSRTL_COMMON_FCB_HEADER): Remove.
* include/ddk/ketypes.h (KQUEUE): Match w32api structure.
* ntoskrnl/ke/queue.c, ntoskrnl/ke/wait.c: Use new structure.
* ntoskrnl/ke/spinlock.c (KeAcquireSpinLockAtDpcLevel,
KeReleaseSpinLockFromDpcLevel): Undefine before declaring.
svn path=/trunk/; revision=4865
2003-06-07 11:34:36 +00:00
|
|
|
DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
|
2002-06-25 22:23:06 +00:00
|
|
|
DeviceExt->StreamFileObject->PrivateCacheMap = NULL;
|
|
|
|
DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb;
|
|
|
|
Ccb->PtrFileObject = DeviceExt->StreamFileObject;
|
|
|
|
Fcb->FileObject = DeviceExt->StreamFileObject;
|
|
|
|
Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice;
|
|
|
|
|
|
|
|
Fcb->Flags = FCB_IS_VOLUME_STREAM;
|
|
|
|
|
|
|
|
Fcb->RFCB.FileSize.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector;
|
|
|
|
Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector;
|
|
|
|
Fcb->RFCB.AllocationSize.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector; /* Correct? */
|
|
|
|
|
|
|
|
// Fcb->Entry.ExtentLocationL = 0;
|
|
|
|
// Fcb->Entry.DataLengthL = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE;
|
2008-03-08 12:14:41 +00:00
|
|
|
|
2005-02-13 17:23:41 +00:00
|
|
|
CcInitializeCacheMap(DeviceExt->StreamFileObject,
|
|
|
|
(PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
|
|
|
|
FALSE,
|
2008-03-08 13:17:48 +00:00
|
|
|
&(NtfsGlobalData->CacheMgrCallbacks),
|
|
|
|
Fcb);
|
2008-03-08 12:14:41 +00:00
|
|
|
|
2002-06-25 22:23:06 +00:00
|
|
|
ExInitializeResourceLite(&DeviceExt->DirResource);
|
|
|
|
// ExInitializeResourceLite(&DeviceExt->FatResource);
|
|
|
|
|
|
|
|
KeInitializeSpinLock(&DeviceExt->FcbListLock);
|
|
|
|
InitializeListHead(&DeviceExt->FcbListHead);
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
/* Get serial number */
|
2002-06-25 22:23:06 +00:00
|
|
|
NewDeviceObject->Vpb->SerialNumber = DeviceExt->NtfsInfo.SerialNumber;
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
/* Get volume label */
|
|
|
|
NewDeviceObject->Vpb->VolumeLabelLength = DeviceExt->NtfsInfo.VolumeLabelLength;
|
|
|
|
RtlCopyMemory (NewDeviceObject->Vpb->VolumeLabel,
|
2008-01-01 18:55:52 +00:00
|
|
|
DeviceExt->NtfsInfo.VolumeLabel,
|
|
|
|
DeviceExt->NtfsInfo.VolumeLabelLength);
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
ByeBye:
|
|
|
|
if (!NT_SUCCESS(Status))
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
/* Cleanup */
|
|
|
|
if (DeviceExt && DeviceExt->StreamFileObject)
|
|
|
|
ObDereferenceObject(DeviceExt->StreamFileObject);
|
|
|
|
if (Fcb)
|
|
|
|
ExFreePool(Fcb);
|
|
|
|
if (Ccb)
|
|
|
|
ExFreePool(Ccb);
|
|
|
|
if (NewDeviceObject)
|
|
|
|
IoDeleteDevice(NewDeviceObject);
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
DPRINT("NtfsMountVolume() done (Status: %lx)\n", Status);
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
return Status;
|
2002-06-25 22:23:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static NTSTATUS
|
|
|
|
NtfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
|
2008-01-01 18:55:52 +00:00
|
|
|
PIRP Irp)
|
2002-06-25 22:23:06 +00:00
|
|
|
{
|
|
|
|
DPRINT1("NtfsVerifyVolume() called\n");
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
return STATUS_WRONG_VOLUME;
|
2002-06-25 22:23:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-10 11:20:29 +00:00
|
|
|
NTSTATUS NTAPI
|
|
|
|
NtfsFsdFileSystemControl(PDEVICE_OBJECT DeviceObject,
|
2008-01-01 18:55:52 +00:00
|
|
|
PIRP Irp)
|
2002-06-25 22:23:06 +00:00
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION Stack;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
DPRINT1("NtfsFileSystemControl() called\n");
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
switch (Stack->MinorFunction)
|
2008-01-01 18:55:52 +00:00
|
|
|
{
|
|
|
|
case IRP_MN_USER_FS_REQUEST:
|
|
|
|
DPRINT("NTFS: IRP_MN_USER_FS_REQUEST\n");
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_MOUNT_VOLUME:
|
|
|
|
DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n");
|
|
|
|
Status = NtfsMountVolume(DeviceObject, Irp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_VERIFY_VOLUME:
|
|
|
|
DPRINT1("NTFS: IRP_MN_VERIFY_VOLUME\n");
|
|
|
|
Status = NtfsVerifyVolume(DeviceObject, Irp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
DPRINT("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction);
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
break;
|
|
|
|
}
|
2002-06-25 22:23:06 +00:00
|
|
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|