Example #1
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSMountVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT              MainDeviceObject;
	BOOLEAN                     GlobalDataResourceAcquired = FALSE;
	PIRP                        Irp;
	PIO_STACK_LOCATION          IoStackLocation;
	PDEVICE_OBJECT              TargetDeviceObject;
	NTSTATUS                    Status = STATUS_UNRECOGNIZED_VOLUME;
	PDEVICE_OBJECT              VolumeDeviceObject = NULL;
	PFFS_VCB                    Vcb;
	PFFS_SUPER_BLOCK            FFSSb = NULL;
	ULONG                       dwBytes;
	DISK_GEOMETRY               DiskGeometry;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		MainDeviceObject = IrpContext->DeviceObject;

		//
		//  Make sure we can wait.
		//

		SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

		//
		// This request is only allowed on the main device object
		//
		if (MainDeviceObject != FFSGlobal->DeviceObject)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			_SEH2_LEAVE;
		}

		ExAcquireResourceExclusiveLite(
				&(FFSGlobal->Resource),
				TRUE);

		GlobalDataResourceAcquired = TRUE;

		if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING))
		{
			Status = STATUS_UNRECOGNIZED_VOLUME;
			_SEH2_LEAVE;
		}

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		TargetDeviceObject =
			IoStackLocation->Parameters.MountVolume.DeviceObject;

		dwBytes = sizeof(DISK_GEOMETRY);
		Status = FFSDiskIoControl(
					TargetDeviceObject,
					IOCTL_DISK_GET_DRIVE_GEOMETRY,
					NULL,
					0,
					&DiskGeometry,
					&dwBytes);

		if (!NT_SUCCESS(Status))
		{
			_SEH2_LEAVE;
		}

		Status = IoCreateDevice(
					MainDeviceObject->DriverObject,
					sizeof(FFS_VCB),
					NULL,
					FILE_DEVICE_DISK_FILE_SYSTEM,
					0,
					FALSE,
					&VolumeDeviceObject);

		if (!NT_SUCCESS(Status))
		{
			_SEH2_LEAVE;
		}

		VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);

		if (TargetDeviceObject->AlignmentRequirement > 
				VolumeDeviceObject->AlignmentRequirement)
		{

			VolumeDeviceObject->AlignmentRequirement = 
				TargetDeviceObject->AlignmentRequirement;
		}

		(IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject =
			VolumeDeviceObject;

		Vcb = (PFFS_VCB)VolumeDeviceObject->DeviceExtension;

		RtlZeroMemory(Vcb, sizeof(FFS_VCB));

		Vcb->Identifier.Type = FFSVCB;
		Vcb->Identifier.Size = sizeof(FFS_VCB);

		Vcb->TargetDeviceObject = TargetDeviceObject;
		Vcb->DiskGeometry = DiskGeometry;

		Status = FFSLoadDiskLabel(TargetDeviceObject, Vcb);

		if (!NT_SUCCESS(Status))
		{
			_SEH2_LEAVE;
		}


		FFSSb = Vcb->ffs_super_block;

		Vcb->BlockSize = FFSSb->fs_bsize;
		Vcb->SectorBits = FFSLog2(SECTOR_SIZE);

		Status = FFSInitializeVcb(IrpContext, Vcb, FFSSb, TargetDeviceObject, 
				VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb);

		if (NT_SUCCESS(Status))
		{
			if (FFSIsMediaWriteProtected(IrpContext, TargetDeviceObject))
			{
				SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
			}
			else
			{
				ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
			}

			SetFlag(Vcb->Flags, VCB_MOUNTED);

			FFSInsertVcb(Vcb);

			ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
		}
	}

	_SEH2_FINALLY
	{
		if (GlobalDataResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&FFSGlobal->Resource,
					ExGetCurrentResourceThread());
		}

		if (!NT_SUCCESS(Status))
		{
			if (FFSSb)
			{
				ExFreePool(FFSSb);
			}

			if (VolumeDeviceObject)
			{
				IoDeleteDevice(VolumeDeviceObject);
			}
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (NT_SUCCESS(Status))
			{
				ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
			}

			FFSCompleteIrpContext(IrpContext,  Status);
		}
	} _SEH2_END;

	return Status;
}
Example #2
0
NTSTATUS
FFSInitializeVcb(
	IN PFFS_IRP_CONTEXT IrpContext, 
	IN PFFS_VCB         Vcb, 
	IN PFFS_SUPER_BLOCK FFSSb,
	IN PDEVICE_OBJECT   TargetDevice,
	IN PDEVICE_OBJECT   VolumeDevice,
	IN PVPB             Vpb)
{
	BOOLEAN                     VcbResourceInitialized = FALSE;
	USHORT                      VolumeLabelLength;
	ULONG                       IoctlSize;
	BOOLEAN                     NotifySyncInitialized = FALSE;
	LONGLONG                    DiskSize;
	LONGLONG                    PartSize;
	NTSTATUS                    Status = STATUS_UNSUCCESSFUL;
	UNICODE_STRING              RootNode;
	USHORT                      Buffer[2];
	ULONG                       ChangeCount;

	__try
	{
		if (!Vpb)
		{
			Status = STATUS_DEVICE_NOT_READY;
			__leave;
		}

		Buffer[0] = L'\\';
		Buffer[1] = 0;

		RootNode.Buffer = Buffer;
		RootNode.MaximumLength = RootNode.Length = 2;

		Vcb->McbTree = FFSAllocateMcb(Vcb, &RootNode,
				FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL);

		if (!Vcb->McbTree)
		{
			__leave;
		}

#if FFS_READ_ONLY
		SetFlag(Vcb->Flags, VCB_READ_ONLY);
#endif //READ_ONLY

		if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA))
		{
			SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA);
		}

		if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE))
		{
			SetFlag(Vcb->Flags, VCB_FLOPPY_DISK);
		}
#if 0
		if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
		{
			if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
			{
				ClearFlag(Vcb->Flags, VCB_READ_ONLY);
			}
			else
			{
				SetFlag(Vcb->Flags, VCB_READ_ONLY);
			}
		}
		else
#endif
		{
			SetFlag(Vcb->Flags, VCB_READ_ONLY);
		}

		ExInitializeResourceLite(&Vcb->MainResource);
		ExInitializeResourceLite(&Vcb->PagingIoResource);

		ExInitializeResourceLite(&Vcb->McbResource);

		VcbResourceInitialized = TRUE;

		Vcb->McbTree->Inode = FFS_ROOT_INO;

		Vcb->Vpb = Vpb;

		Vcb->RealDevice = Vpb->RealDevice;
		Vpb->DeviceObject = VolumeDevice;

		{
			UNICODE_STRING      LabelName;
			OEM_STRING          OemName;

			LabelName.MaximumLength = 16 * 2;
			LabelName.Length    = 0;
			LabelName.Buffer    = Vcb->Vpb->VolumeLabel;

			RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength);

			VolumeLabelLength = 16;

			while((VolumeLabelLength > 0) &&
					((FFSSb->fs_volname[VolumeLabelLength-1] == 0x00) ||
					 (FFSSb->fs_volname[VolumeLabelLength-1] == 0x20)))
			{
				VolumeLabelLength--;
			}

			OemName.Buffer = FFSSb->fs_volname;
			OemName.MaximumLength = 16;
			OemName.Length = VolumeLabelLength;

			Status = FFSOEMToUnicode(&LabelName,
					&OemName);

			if (!NT_SUCCESS(Status))
			{
				__leave;
			}

			Vpb->VolumeLabelLength = LabelName.Length;
		}

		Vpb->SerialNumber = ((ULONG*)FFSSb->fs_id)[0] + ((ULONG*)FFSSb->fs_id)[1] +
			((ULONG*)FFSSb->fs_id)[2];


		Vcb->StreamObj = IoCreateStreamFileObject(NULL, Vcb->Vpb->RealDevice);

		if (Vcb->StreamObj)
		{
			Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject);
			Vcb->StreamObj->Vpb = Vcb->Vpb;
			Vcb->StreamObj->ReadAccess = TRUE;
			if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
			{
				Vcb->StreamObj->WriteAccess = TRUE;
				Vcb->StreamObj->DeleteAccess = TRUE;
			}
			else
			{
				Vcb->StreamObj->WriteAccess = TRUE;
				Vcb->StreamObj->DeleteAccess = TRUE;
			}
			Vcb->StreamObj->FsContext = (PVOID) Vcb;
			Vcb->StreamObj->FsContext2 = NULL;
			Vcb->StreamObj->Vpb = Vcb->Vpb;

			SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING);
		}
		else
		{
			__leave;
		}

		InitializeListHead(&Vcb->FcbList);

		InitializeListHead(&Vcb->NotifyList);

		FsRtlNotifyInitializeSync(&Vcb->NotifySync);

		NotifySyncInitialized = TRUE;

		Vcb->DeviceObject = VolumeDevice;

		Vcb->TargetDeviceObject = TargetDevice;

		Vcb->OpenFileHandleCount = 0;

		Vcb->ReferenceCount = 0;

		Vcb->ffs_super_block = FFSSb;

		Vcb->Header.NodeTypeCode = (USHORT) FFSVCB;
		Vcb->Header.NodeByteSize = sizeof(FFS_VCB);
		Vcb->Header.IsFastIoPossible = FastIoIsNotPossible;
		Vcb->Header.Resource = &(Vcb->MainResource);
		Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource);

		Vcb->Vpb->SerialNumber = 'PS';

		DiskSize =
			Vcb->DiskGeometry.Cylinders.QuadPart *
			Vcb->DiskGeometry.TracksPerCylinder *
			Vcb->DiskGeometry.SectorsPerTrack *
			Vcb->DiskGeometry.BytesPerSector;

		IoctlSize = sizeof(PARTITION_INFORMATION);

		Status = FFSDiskIoControl(
					TargetDevice,
					IOCTL_DISK_GET_PARTITION_INFO,
					NULL,
					0,
					&Vcb->PartitionInformation,
					&IoctlSize);

		PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart;

		if (!NT_SUCCESS(Status))
		{
			Vcb->PartitionInformation.StartingOffset.QuadPart = 0;

			Vcb->PartitionInformation.PartitionLength.QuadPart =
				DiskSize;

			PartSize = DiskSize;

			Status = STATUS_SUCCESS;
		}

		IoctlSize = sizeof(ULONG);
		Status = FFSDiskIoControl(
					TargetDevice,
					IOCTL_DISK_CHECK_VERIFY,
					NULL,
					0,
					&ChangeCount,
					&IoctlSize);

		if (!NT_SUCCESS(Status))
		{
			__leave;
		}

		Vcb->ChangeCount = ChangeCount;

		Vcb->Header.AllocationSize.QuadPart =
			Vcb->Header.FileSize.QuadPart = PartSize;

		Vcb->Header.ValidDataLength.QuadPart = 
			(LONGLONG)(0x7fffffffffffffff);
		/*
		Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(ffs_super_block->s_blocks_count - ffs_super_block->s_free_blocks_count)
			* (FFS_MIN_BLOCK << ffs_super_block->s_log_block_size);
			Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart;
			Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart;
		*/

		{
			CC_FILE_SIZES FileSizes;

			FileSizes.AllocationSize.QuadPart =
				FileSizes.FileSize.QuadPart =
				Vcb->Header.AllocationSize.QuadPart;

			FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff);

			CcInitializeCacheMap(Vcb->StreamObj,
					&FileSizes,
					TRUE,
					&(FFSGlobal->CacheManagerNoOpCallbacks),
					Vcb);
		}
#if 0 //	LoadGroup XXX
		if (!FFSLoadGroup(Vcb))
		{
			Status = STATUS_UNSUCCESSFUL;
			__leave;
		}
#endif
		FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool);
		InitializeListHead(&(Vcb->McbList));

		if (IsFlagOn(FFSGlobal->Flags, FFS_CHECKING_BITMAP))
		{
			FFSCheckBitmapConsistency(IrpContext, Vcb);
		}

		{
			ULONG   dwData[FFS_BLOCK_TYPES] = {NDADDR, 1, 1, 1};
			ULONG   dwMeta[FFS_BLOCK_TYPES] = {0, 0, 0, 0};
			ULONG   i;

			if (FS_VERSION == 1)
			{
				for (i = 0; i < FFS_BLOCK_TYPES; i++)
				{
					dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i);

					if (i > 0)
					{
						dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2));
					}

					Vcb->dwData[i] = dwData[i];
					Vcb->dwMeta[i] = dwMeta[i];
				}
			}
			else
			{
				for (i = 0; i < FFS_BLOCK_TYPES; i++)
				{
					dwData[i] = dwData[i] << ((BLOCK_BITS - 3) * i);

					if (i > 0)
					{
						dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 3));
					}

					Vcb->dwData[i] = dwData[i];
					Vcb->dwMeta[i] = dwMeta[i];
				}
			}
		}

		SetFlag(Vcb->Flags, VCB_INITIALIZED);
	}

	__finally
	{
		if (!NT_SUCCESS(Status))
		{
			if (NotifySyncInitialized)
			{
				FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
			}

			if (Vcb->ffs_super_block)
			{
				ExFreePool(Vcb->ffs_super_block);
				Vcb->ffs_super_block = NULL;
			}

			if (VcbResourceInitialized)
			{
				ExDeleteResourceLite(&Vcb->MainResource);
				ExDeleteResourceLite(&Vcb->PagingIoResource);
			}
		}
	}

	return Status;
}
Example #3
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSVerifyVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT          DeviceObject;
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	PFFS_SUPER_BLOCK        FFSSb = NULL;
	PFFS_VCB                Vcb = 0;
	BOOLEAN                 VcbResourceAcquired = FALSE;
	BOOLEAN                 GlobalResourceAcquired = FALSE;
	PIRP                    Irp;
	PIO_STACK_LOCATION      IoStackLocation;
	ULONG                   ChangeCount;
	ULONG                   dwReturn;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;
		//
		// This request is not allowed on the main device object
		//
		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			_SEH2_LEAVE;
		}

		ExAcquireResourceExclusiveLite(
				&FFSGlobal->Resource,
				TRUE);

		GlobalResourceAcquired = TRUE;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		ExAcquireResourceExclusiveLite(
				&Vcb->MainResource,
				TRUE);

		VcbResourceAcquired = TRUE;

		if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME))
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		if (!IsMounted(Vcb))
		{
			Status = STATUS_WRONG_VOLUME;
			_SEH2_LEAVE;
		}

		dwReturn = sizeof(ULONG);
		Status = FFSDiskIoControl(
				Vcb->TargetDeviceObject,
				IOCTL_DISK_CHECK_VERIFY,
				NULL,
				0,
				&ChangeCount,
				&dwReturn);

		if (ChangeCount != Vcb->ChangeCount)
		{
			Status = STATUS_WRONG_VOLUME;
			_SEH2_LEAVE;
		}

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		if (((((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS1)) != NULL) && (FFSSb->fs_magic == FS_UFS1_MAGIC)) ||
			 (((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS2)) != NULL) && (FFSSb->fs_magic == FS_UFS2_MAGIC))) &&
				(memcmp(FFSSb->fs_id, SUPER_BLOCK->fs_id, 8) == 0) &&
				(memcmp(FFSSb->fs_volname, SUPER_BLOCK->fs_volname, 16) == 0))
		{
			ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);

			if (FFSIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject))
			{
				SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
			}
			else
			{
				ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
			}

			FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify succeeded.\n"));

			Status = STATUS_SUCCESS;
		}
		else
		{
			Status = STATUS_WRONG_VOLUME;

			FFSPurgeVolume(Vcb, FALSE);

			SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);

			ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);

			FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify failed.\n"));
		}
	}

	_SEH2_FINALLY
	{
		if (FFSSb)
			ExFreePool(FFSSb);

		if (VcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (GlobalResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&FFSGlobal->Resource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			FFSCompleteIrpContext(IrpContext,  Status);
		}
	} _SEH2_END;

	return Status;
}