Beispiel #1
0
VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
{
    PAGED_CODE();

    FSP_FILE_NODE_GET_FLAGS();
    FSP_FILE_NODE_ASSERT_FLAGS_SET();

    Owner = (PVOID)((UINT_PTR)Owner | 3);

    if (Flags & FspFileNodeAcquirePgio)
    {
        if (ExIsResourceAcquiredLite(FileNode->Header.PagingIoResource))
            ExReleaseResourceLite(FileNode->Header.PagingIoResource);
        else
            ExReleaseResourceForThreadLite(FileNode->Header.PagingIoResource, (ERESOURCE_THREAD)Owner);
    }

    if (Flags & FspFileNodeAcquireMain)
    {
        if (ExIsResourceAcquiredLite(FileNode->Header.Resource))
            ExReleaseResourceLite(FileNode->Header.Resource);
        else
            ExReleaseResourceForThreadLite(FileNode->Header.Resource, (ERESOURCE_THREAD)Owner);
    }

    FSP_FILE_NODE_CLR_FLAGS();
}
Beispiel #2
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdPnpCancelRemove (
    PRFSD_IRP_CONTEXT IrpContext,
    PRFSD_VCB         Vcb
    )
{
    NTSTATUS Status;

    PAGED_CODE();

    RfsdPrint((DBG_PNP, "RfsdPnpCancelRemove by RfsdPnp ...\n"));

    ExAcquireResourceExclusiveLite(
        &Vcb->MainResource,  TRUE );

    Status = RfsdUnlockVcb(Vcb, IrpContext->FileObject);

    ExReleaseResourceForThreadLite(
        &Vcb->MainResource,
        ExGetCurrentResourceThread());

    IoSkipCurrentIrpStackLocation(IrpContext->Irp);

    Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);

    IrpContext->Irp = NULL;

    return Status;
}
Beispiel #3
0
VOID
FFSFreeCcb(
	IN PFFS_CCB Ccb)
{
	ASSERT(Ccb != NULL);

	ASSERT((Ccb->Identifier.Type == FFSCCB) &&
			(Ccb->Identifier.Size == sizeof(FFS_CCB)));

	if (Ccb->DirectorySearchPattern.Buffer != NULL)
	{
		ExFreePool(Ccb->DirectorySearchPattern.Buffer);
	}

	if (FlagOn(Ccb->Flags, CCB_FROM_POOL))
	{
		ExFreePool(Ccb);
	}
	else
	{
		ExAcquireResourceExclusiveLite(
				&FFSGlobal->LAResource,
				TRUE);

		ExFreeToNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList), Ccb);

		ExReleaseResourceForThreadLite(
				&FFSGlobal->LAResource,
				ExGetCurrentResourceThread());
	}
}
Beispiel #4
0
__drv_mustHoldCriticalRegion
VOID
FFSFreeMcb(
	IN PFFS_MCB Mcb)
{
#ifndef __REACTOS__
    PFFS_MCB   Parent = Mcb->Parent;
#endif
    PAGED_CODE();

	ASSERT(Mcb != NULL);

	ASSERT((Mcb->Identifier.Type == FFSMCB) &&
			(Mcb->Identifier.Size == sizeof(FFS_MCB)));

	FFSPrint((DBG_INFO, "FFSFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer));

	if (Mcb->ShortName.Buffer)
		ExFreePool(Mcb->ShortName.Buffer);

	if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
	{
		ExFreePool(Mcb);
	}
	else
	{
		ExAcquireResourceExclusiveLite(
				&FFSGlobal->LAResource,
				TRUE);

		ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);

		ExReleaseResourceForThreadLite(
				&FFSGlobal->LAResource,
				ExGetCurrentResourceThread());
	}

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->CountResource,
			TRUE);

	FFSGlobal->McbAllocated--;

	ExReleaseResourceForThreadLite(
			&FFSGlobal->CountResource,
			ExGetCurrentResourceThread());
}
Beispiel #5
0
__drv_mustHoldCriticalRegion
PFFS_CCB
FFSAllocateCcb(
	VOID)
{
	PFFS_CCB Ccb;

    PAGED_CODE();

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->LAResource,
			TRUE);

	Ccb = (PFFS_CCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList)));

	ExReleaseResourceForThreadLite(
			&FFSGlobal->LAResource,
			ExGetCurrentResourceThread());

	if (Ccb == NULL)
	{
		Ccb = (PFFS_CCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_CCB), FFS_POOL_TAG);

		RtlZeroMemory(Ccb, sizeof(FFS_CCB));

		SetFlag(Ccb->Flags, CCB_FROM_POOL);
	}
	else
	{
		RtlZeroMemory(Ccb, sizeof(FFS_CCB));
	}

	if (!Ccb)
	{
		return NULL;
	}

	Ccb->Identifier.Type = FFSCCB;
	Ccb->Identifier.Size = sizeof(FFS_CCB);

	Ccb->CurrentByteOffset = 0;

	Ccb->DirectorySearchPattern.Length = 0;
	Ccb->DirectorySearchPattern.MaximumLength = 0;
	Ccb->DirectorySearchPattern.Buffer = 0;

	return Ccb;
}
Beispiel #6
0
__drv_mustHoldCriticalRegion
VOID
FFSFreeIrpContext(
	IN PFFS_IRP_CONTEXT IrpContext)
{
    PAGED_CODE();

	ASSERT(IrpContext != NULL);

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

	FFSUnpinRepinnedBcbs(IrpContext);

	//  Return the Irp context record to the region or to pool depending on
	//  its flag

	if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL))
	{
		IrpContext->Identifier.Type = 0;
		IrpContext->Identifier.Size = 0;

		ExFreePool(IrpContext);
	}
	else
	{
		IrpContext->Identifier.Type = 0;
		IrpContext->Identifier.Size = 0;

		ExAcquireResourceExclusiveLite(
				&FFSGlobal->LAResource,
				TRUE);

		ExFreeToNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList), IrpContext);

		ExReleaseResourceForThreadLite(
				&FFSGlobal->LAResource,
				ExGetCurrentResourceThread());

	}
}
Beispiel #7
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdPnpSurpriseRemove (
    PRFSD_IRP_CONTEXT IrpContext,
    PRFSD_VCB         Vcb      )
{
    NTSTATUS Status;
    KEVENT   Event;
    BOOLEAN  bDeleted;

    PAGED_CODE();

    _SEH2_TRY {

        RfsdPrint((DBG_PNP, "RfsdPnpSupriseRemove by RfsdPnp ...\n"));
#if (_WIN32_WINNT >= 0x0500)
        CcWaitForCurrentLazyWriterActivity();
#endif
        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource,  TRUE );

        Status = RfsdLockVcb(Vcb, IrpContext->FileObject);

        ExReleaseResourceForThreadLite(
            &Vcb->MainResource,
            ExGetCurrentResourceThread());

        //
        // Setup the Irp. We'll send it to the lower disk driver.
        //

        IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);

        KeInitializeEvent( &Event, NotificationEvent, FALSE );
        IoSetCompletionRoutine( IrpContext->Irp,
                                RfsdPnpCompletionRoutine,
                                &Event,
                                TRUE,
                                TRUE,
                                TRUE );

        Status = IoCallDriver( Vcb->TargetDeviceObject, 
                               IrpContext->Irp);

       if (Status == STATUS_PENDING) {

            KeWaitForSingleObject( &Event,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   NULL );

            Status = IrpContext->Irp->IoStatus.Status;
       }

        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource, TRUE );

        RfsdPurgeVolume(Vcb, FALSE);

        ExReleaseResourceForThreadLite(
            &Vcb->MainResource,
            ExGetCurrentResourceThread() );

        bDeleted = RfsdCheckDismount(IrpContext, Vcb, TRUE);

    } _SEH2_FINALLY {

        RfsdCompleteRequest(
            IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
            IO_DISK_INCREMENT : IO_NO_INCREMENT) );

        IrpContext->Irp = NULL;
    } _SEH2_END;

    return Status;
}
Beispiel #8
0
NTSTATUS
FFSWriteVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb  = NULL;
	PFFS_CCB            Ccb = NULL;
	PFFS_FCBVCB         FcbOrVcb  = NULL;
	PFILE_OBJECT        FileObject  = NULL;

	PDEVICE_OBJECT      DeviceObject  = NULL;

	PIRP                Irp  = NULL;
	PIO_STACK_LOCATION  IoStackLocation  = NULL;

	ULONG               Length;
	LARGE_INTEGER       ByteOffset;

	BOOLEAN             PagingIo;
	BOOLEAN             Nocache;
	BOOLEAN             SynchronousIo;
	BOOLEAN             MainResourceAcquired = FALSE;
	BOOLEAN             PagingIoResourceAcquired = FALSE;

	BOOLEAN             bDeferred = FALSE;

	PUCHAR              Buffer = NULL;

	__try
	{
		ASSERT(IrpContext);

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

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

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

		FileObject = IrpContext->FileObject;

		FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;

		ASSERT(FcbOrVcb);

		if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		Length = IoStackLocation->Parameters.Write.Length;
		ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

		PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
		Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
		SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

		FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
					ByteOffset.QuadPart, Length, PagingIo, Nocache));

		if (Length == 0)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_SUCCESS;
			__leave;
		}

		// For the case of "Direct Access Storage Device", we
		// need flush/purge the cache

		if (Ccb != NULL)
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			Status = FFSPurgeVolume(Vcb, TRUE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;

			if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO))
			{
				if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart)
				{
					Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
				}
			}

			{
				FFS_BDL BlockArray;

				if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
						(Length & (SECTOR_SIZE - 1)))
				{
					Status = STATUS_INVALID_PARAMETER;
					__leave;
				}

				Status = FFSLockUserBuffer(
							IrpContext->Irp,
							Length,
							IoReadAccess);

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

				BlockArray.Irp = NULL;
				BlockArray.Lba = ByteOffset.QuadPart;;
				BlockArray.Offset = 0;
				BlockArray.Length = Length;

				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							&BlockArray,
							Length,
							1,
							FALSE);
				Irp = IrpContext->Irp;

				__leave;
			}
		}                    

		if (Nocache &&
				(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
				 Length & (SECTOR_SIZE - 1)))
		{
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
		{
			ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
			Status = STATUS_PENDING;
			__leave;
		}

		if (ByteOffset.QuadPart >=
				Vcb->PartitionInformation.PartitionLength.QuadPart)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_END_OF_FILE;
			__leave;
		}

#if FALSE

		if (!Nocache)
		{
			BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
			BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
			BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

			if (!CcCanIWrite(
						FileObject,
						Length,
						(bWait && bQueue),
						bAgain))
			{
				SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

				CcDeferWrite(FileObject,
						(PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
						IrpContext,
						Irp,
						Length,
						bAgain);

				bDeferred = TRUE;

				FFSBreakPoint();

				Status = STATUS_PENDING;

				__leave;
			}
		}

#endif

		if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) 
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcFlushCache(&(Vcb->SectionObject),
					&ByteOffset,
					Length,
					&(Irp->IoStatus));

			if (!NT_SUCCESS(Irp->IoStatus.Status)) 
			{
				Status = Irp->IoStatus.Status;
				__leave;
			}

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcPurgeCacheSection(&(Vcb->SectionObject),
					(PLARGE_INTEGER)&(ByteOffset),
					Length,
					FALSE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;
		}

		if (!PagingIo)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Vcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			MainResourceAcquired = TRUE;
		}
		else
		{
			/*
			ULONG ResShCnt, ResExCnt; 
			ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource);
			ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource);

			FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous));
			*/

			if (Ccb)
			{
				if (!ExAcquireResourceSharedLite(
							&Vcb->PagingIoResource,
							IrpContext->IsSynchronous))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				PagingIoResourceAcquired = TRUE;
			}
		}

		if (!Nocache)
		{
			if ((ByteOffset.QuadPart + Length) >
					Vcb->PartitionInformation.PartitionLength.QuadPart
			)
			{
				Length = (ULONG) (
						Vcb->PartitionInformation.PartitionLength.QuadPart -
						ByteOffset.QuadPart);

				Length &= ~((ULONG)SECTOR_SIZE - 1);
			}

			if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
			{

				CcPrepareMdlWrite(
						Vcb->StreamObj,
						&ByteOffset,
						Length,
						&Irp->MdlAddress,
						&Irp->IoStatus);

				Status = Irp->IoStatus.Status;
			}
			else
			{
				Buffer = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)
				{
					FFSBreakPoint();

					Status = STATUS_INVALID_USER_BUFFER;
					__leave;
				}

				if (!CcCopyWrite(Vcb->StreamObj,
							(PLARGE_INTEGER)(&ByteOffset),
							Length,
							TRUE,
							Buffer))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				Status = Irp->IoStatus.Status;
				FFSAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
			}

			if (NT_SUCCESS(Status))
			{
				Irp->IoStatus.Information = Length;
			}
		}
		else
		{
			PFFS_BDL            ffs_bdl = NULL;
			ULONG               Blocks = 0;

			LONGLONG            DirtyStart;
			LONGLONG            DirtyLba;
			LONGLONG            DirtyLength;
			LONGLONG            RemainLength;

			if ((ByteOffset.QuadPart + Length) >
					Vcb->PartitionInformation.PartitionLength.QuadPart)
			{
				Length = (ULONG)(
						Vcb->PartitionInformation.PartitionLength.QuadPart -
						ByteOffset.QuadPart);

				Length &= ~((ULONG)SECTOR_SIZE - 1);
			}

			Status = FFSLockUserBuffer(
					IrpContext->Irp,
					Length,
					IoReadAccess);

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

			ffs_bdl = ExAllocatePool(PagedPool, 
					(Length / Vcb->BlockSize) *
					sizeof(FFS_BDL));

			if (!ffs_bdl)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				__leave;
			}

			DirtyLba = ByteOffset.QuadPart;
			RemainLength = (LONGLONG)Length;

			while (RemainLength > 0)
			{
				DirtyStart = DirtyLba;

				if (FFSLookupMcbEntry(Vcb, 
							DirtyStart,
							&DirtyLba,
							&DirtyLength,
							(PLONGLONG)NULL,
							(PLONGLONG)NULL,
							(PULONG)NULL))
				{

					if (DirtyLba == -1)
					{
						DirtyLba = DirtyStart + DirtyLength;

						RemainLength = ByteOffset.QuadPart + 
							(LONGLONG)Length -
							DirtyLba;
						continue;
					}

					ffs_bdl[Blocks].Irp = NULL;
					ffs_bdl[Blocks].Lba = DirtyLba;
					ffs_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length +
							DirtyStart -
							RemainLength - 
							DirtyLba);

					if (DirtyLba + DirtyLength > DirtyStart + RemainLength)
					{
						ffs_bdl[Blocks].Length = (ULONG)(DirtyStart +
								RemainLength -
								DirtyLba);
						RemainLength = 0;
					}
					else
					{
						ffs_bdl[Blocks].Length = (ULONG)DirtyLength;
						RemainLength =  (DirtyStart + RemainLength) -
							(DirtyLba + DirtyLength);
					}

					DirtyLba = DirtyStart + DirtyLength;
					Blocks++;
				}
				else
				{
					if (Blocks == 0)
					{
						if (ffs_bdl)
							ExFreePool(ffs_bdl);

						//
						// Lookup fails at the first time, ie. 
						// no dirty blocks in the run
						//

						FFSBreakPoint();

						if (RemainLength == (LONGLONG)Length)
							Status = STATUS_SUCCESS;
						else
							Status = STATUS_UNSUCCESSFUL;

						__leave;
					}
					else
					{
						break;
					}
				}
			}

			if (Blocks > 0)
			{
				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							ffs_bdl,
							Length,
							Blocks,
							FALSE);
				Irp = IrpContext->Irp;

				if (NT_SUCCESS(Status))
				{
					ULONG   i;

					for (i = 0; i < Blocks; i++)
					{
						FFSRemoveMcbEntry(Vcb,
								ffs_bdl[i].Lba,
								ffs_bdl[i].Length);
					}
				}

				if (ffs_bdl)
					ExFreePool(ffs_bdl);

				if (!Irp)
					__leave;

			}
			else
			{
				if (ffs_bdl)
					ExFreePool(ffs_bdl);

				Irp->IoStatus.Information = Length;

				Status = STATUS_SUCCESS;
				__leave;
			}
		}
	}

	__finally
	{
		if (PagingIoResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->PagingIoResource,
					ExGetCurrentResourceThread());
		}

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

		if (!IrpContext->ExceptionInProgress)
		{
			if (Irp)
			{
				if (Status == STATUS_PENDING)
				{
					if(!bDeferred)
					{
						Status = FFSLockUserBuffer(
								IrpContext->Irp,
								Length,
								IoReadAccess);

						if (NT_SUCCESS(Status))
						{
							Status = FFSQueueRequest(IrpContext);
						}
						else
						{
							FFSCompleteIrpContext(IrpContext, Status);
						}
					}
				}
				else
				{
					if (NT_SUCCESS(Status))
					{
						if (SynchronousIo && !PagingIo)
						{
							FileObject->CurrentByteOffset.QuadPart =
								ByteOffset.QuadPart + Irp->IoStatus.Information;
						}

						if (!PagingIo)
						{
							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
						}
					}

					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				FFSFreeIrpContext(IrpContext);
			}
		}
	}

	return Status;
}
Beispiel #9
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdCleanup (IN PRFSD_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_SUCCESS;
    PRFSD_VCB       Vcb = 0;
    BOOLEAN         VcbResourceAcquired = FALSE;
    PFILE_OBJECT    FileObject;
    PRFSD_FCB       Fcb = 0;
    BOOLEAN         FcbResourceAcquired = FALSE;
    BOOLEAN         FcbPagingIoAcquired = FALSE;
    PRFSD_CCB       Ccb;
    PIRP            Irp;

    PAGED_CODE();

    _SEH2_TRY {

        ASSERT(IrpContext != NULL);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        DeviceObject = IrpContext->DeviceObject;
        
        if (DeviceObject == RfsdGlobal->DeviceObject) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
        
        ASSERT(Vcb != NULL);
        
        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
            (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
        if (!ExAcquireResourceExclusiveLite(
                 &Vcb->MainResource,
                 IrpContext->IsSynchronous
                 ))  {
            Status = STATUS_PENDING;
            _SEH2_LEAVE;
        }

        VcbResourceAcquired = TRUE;
        
        FileObject = IrpContext->FileObject;
        
        Fcb = (PRFSD_FCB) FileObject->FsContext;
        
        if (!Fcb) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        if (Fcb->Identifier.Type == RFSDVCB) {
            if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
                (Vcb->LockFile == FileObject) ) {
                ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
                Vcb->LockFile = NULL;

                RfsdClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
            }

            Vcb->OpenHandleCount--;

            if (!Vcb->OpenHandleCount) {
                IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
            }

            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
            (Fcb->Identifier.Size == sizeof(RFSD_FCB)));

/*
        if ( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
             !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))
*/
        {
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
            if (!ExAcquireResourceExclusiveLite(
                     &Fcb->MainResource,
                     IrpContext->IsSynchronous
                     ))
            {
                Status = STATUS_PENDING;
                _SEH2_LEAVE;
            }

            FcbResourceAcquired = TRUE;
        }
        
        Ccb = (PRFSD_CCB) FileObject->FsContext2;

        if (!Ccb) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

        if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
            if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
                 IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
                 !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) {
                Status = RfsdFlushFile(Fcb);
            }
            _SEH2_LEAVE;
        }
        
        ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
            (Ccb->Identifier.Size == sizeof(RFSD_CCB)));        
        Irp = IrpContext->Irp;

        Fcb->OpenHandleCount--;

        if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED )) {
            Fcb->NonCachedOpenCount--;
        }

        Vcb->OpenFileHandleCount--;

        if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE))  {
            SetFlag(Fcb->Flags, FCB_DELETE_PENDING);

            if (IsDirectory(Fcb)) {
                FsRtlNotifyFullChangeDirectory(
                                            Vcb->NotifySync,
                                            &Vcb->NotifyList,
                                            Fcb,
                                            NULL,
                                            FALSE,
                                            FALSE,
                                            0,
                                            NULL,
                                            NULL,
                                            NULL );
            }
        }

        if (IsDirectory(Fcb)) {

            FsRtlNotifyCleanup(
                Vcb->NotifySync,
                &Vcb->NotifyList,
                Ccb   );

        } else {

            //
            // Drop any byte range locks this process may have on the file.
            //

            FsRtlFastUnlockAll(
                &Fcb->FileLockAnchor,
                FileObject,
                IoGetRequestorProcess(Irp),
                NULL  );

            //
            // If there are no byte range locks owned by other processes on the
            // file the fast I/O read/write functions doesn't have to check for
            // locks so we set IsFastIoPossible to FastIoIsPossible again.
            //
            if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
                if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
                    RfsdPrint((
                        DBG_INFO, ": %-16.16s %-31s %s\n",
                        RfsdGetCurrentProcessName(),
                        "FastIoIsPossible",
                        Fcb->AnsiFileName.Buffer
                        ));

                    Fcb->Header.IsFastIoPossible = FastIoIsPossible;
                }
            }
        }

        if ( IsFlagOn( FileObject->Flags, FO_CACHE_SUPPORTED) &&
             (Fcb->NonCachedOpenCount != 0) &&
             (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) &&
             (Fcb->SectionObject.DataSectionObject != NULL)) {

            if( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
                !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
                CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
            }

            ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE);
            ExReleaseResourceLite(&(Fcb->PagingIoResource));

            CcPurgeCacheSection( &Fcb->SectionObject,
                                 NULL,
                                 0,
                                 FALSE );
        }

        if (Fcb->OpenHandleCount == 0) {

            if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
                //
                //  Have to delete this file...
                //

#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
                if (!ExAcquireResourceExclusiveLite(
                         &Fcb->PagingIoResource,
                         IrpContext->IsSynchronous
                         )) {
                    Status = STATUS_PENDING;
                    _SEH2_LEAVE;
                }

                FcbPagingIoAcquired = TRUE;
DbgBreak();
#if DISABLED
                Status = RfsdDeleteFile(IrpContext, Vcb, Fcb);

                if (NT_SUCCESS(Status)) {
                    if (IsDirectory(Fcb)) {
                        RfsdNotifyReportChange( IrpContext, Vcb, Fcb,
                                                FILE_NOTIFY_CHANGE_DIR_NAME,
                                                FILE_ACTION_REMOVED );
                    } else {
                        RfsdNotifyReportChange( IrpContext, Vcb, Fcb,
                                                FILE_NOTIFY_CHANGE_FILE_NAME,
                                                FILE_ACTION_REMOVED );
                    }
                }
#endif
                if (CcIsFileCached(FileObject)) {

                    CcSetFileSizes(FileObject, 
                            (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }

                if (FcbPagingIoAcquired) {
                    ExReleaseResourceForThreadLite(
                        &Fcb->PagingIoResource,
                        ExGetCurrentResourceThread() );

                    FcbPagingIoAcquired = FALSE;
                }
            }
        }

        if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap) {
            RfsdPrint((DBG_INFO, "RfsdCleanup: CcUninitializeCacheMap is called for %s.\n",
                                  Fcb->AnsiFileName.Buffer ));

            CcUninitializeCacheMap(
                    FileObject,
                    (PLARGE_INTEGER)(&(Fcb->Header.FileSize)),
                    NULL );
        }

        if (!Fcb->OpenHandleCount) {
            IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
        }

        RfsdPrint((DBG_INFO, "RfsdCleanup: OpenCount: %u ReferCount: %u %s\n",
            Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer ));

        Status = STATUS_SUCCESS;

        if (FileObject) {
            SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
        }

    } _SEH2_FINALLY {
       
        if (FcbPagingIoAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->PagingIoResource,
                ExGetCurrentResourceThread() );
        }

        if (FcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread() );
        }
        
        if (VcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread());
        }
        
        if (!IrpContext->ExceptionInProgress) {
            if (Status == STATUS_PENDING) {
                RfsdQueueRequest(IrpContext);
            } else {
                IrpContext->Irp->IoStatus.Status = Status;
                RfsdCompleteIrpContext(IrpContext, Status);
            }
        }
    } _SEH2_END;
    
    return Status;
}
Beispiel #10
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdVerifyVolume (IN PRFSD_IRP_CONTEXT IrpContext)
{

    PDEVICE_OBJECT          DeviceObject;
    NTSTATUS                Status = STATUS_UNSUCCESSFUL;
    PRFSD_SUPER_BLOCK       rfsd_sb = NULL;
    PRFSD_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 == RFSDICX) &&
        (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));

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

        ExAcquireResourceExclusiveLite(
            &RfsdGlobal->Resource,
            TRUE );

        GlobalResourceAcquired = TRUE;

        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
        (Vcb->Identifier.Size == sizeof(RFSD_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 = RfsdDiskIoControl(
            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);

        rfsd_sb = RfsdLoadSuper(Vcb, TRUE);

        // FUTURE: use the volume name and uuid from the extended superblock to make this happen.
        // NOTE: The magic check will have to use the same thing as mount did!
        if ((rfsd_sb != NULL) /*&& (rfsd_sb->s_magic == RFSD_SUPER_MAGIC) &&
            (memcmp(rfsd_sb->s_uuid, SUPER_BLOCK->s_uuid, 16) == 0) &&
            (memcmp(rfsd_sb->s_volume_name, SUPER_BLOCK->s_volume_name, 16) ==0)*/) {
            ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);

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

            RfsdPrint((DBG_INFO, "RfsdVerifyVolume: Volume verify succeeded.\n"));

            Status = STATUS_SUCCESS;
        } else {
            Status = STATUS_WRONG_VOLUME;

            RfsdPurgeVolume(Vcb, FALSE);

            SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);

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

            RfsdPrint((DBG_INFO, "RfsdVerifyVolume: Volume verify failed.\n"));
        }

    } _SEH2_FINALLY {

        if (rfsd_sb)
            ExFreePool(rfsd_sb);

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

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

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

    return Status;
}
Beispiel #11
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdInvalidateVolumes ( IN PRFSD_IRP_CONTEXT IrpContext )
{
    NTSTATUS            Status;
    PIRP                Irp;
    PIO_STACK_LOCATION  IrpSp;

    HANDLE              Handle;

    PLIST_ENTRY         ListEntry;

    PFILE_OBJECT        FileObject;
    PDEVICE_OBJECT      DeviceObject;
    BOOLEAN             GlobalResourceAcquired = FALSE;

    LUID Privilege = {SE_TCB_PRIVILEGE, 0};

    _SEH2_TRY {

        Irp   = IrpContext->Irp;
        IrpSp = IoGetCurrentIrpStackLocation(Irp);

        if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) {
            Status = STATUS_PRIVILEGE_NOT_HELD;
            _SEH2_LEAVE;
        }

        if (
#ifndef _GNU_NTIFS_
            IrpSp->Parameters.FileSystemControl.InputBufferLength
#else
            ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))->
            Parameters.FileSystemControl.InputBufferLength
#endif
            != sizeof(HANDLE)) {

            Status = STATUS_INVALID_PARAMETER;

            _SEH2_LEAVE;
        }

        Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;

        Status = ObReferenceObjectByHandle( Handle,
        0,
        *IoFileObjectType,
        KernelMode,
        (void **)&FileObject,
        NULL );

        if (!NT_SUCCESS(Status)) {
            _SEH2_LEAVE;
        } else {
            ObDereferenceObject(FileObject);
            DeviceObject = FileObject->DeviceObject;
        }

        RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: FileObject=%xh ...\n", FileObject));

        ExAcquireResourceExclusiveLite(
            &RfsdGlobal->Resource,
            TRUE );

        GlobalResourceAcquired = TRUE;

        ListEntry = RfsdGlobal->VcbList.Flink;

        while (ListEntry != &RfsdGlobal->VcbList)  {

            PRFSD_VCB Vcb;

            Vcb = CONTAINING_RECORD(ListEntry, RFSD_VCB, Next);

            ListEntry = ListEntry->Flink;

            RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb));
            if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject))
            {
                ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
                RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdPurgeVolume...\n"));
                RfsdPurgeVolume(Vcb, FALSE);
                ClearFlag(Vcb->Flags, VCB_MOUNTED);
                ExReleaseResourceLite(&Vcb->MainResource);

                //
                // Vcb is still attached on the list ......
                //

                if (ListEntry->Blink == &Vcb->Next)
                {
                    RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdCheckDismount...\n"));
                    RfsdCheckDismount(IrpContext, Vcb, FALSE);
                }
            }
        }

    } _SEH2_FINALLY {

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

        RfsdCompleteIrpContext(IrpContext, Status);
    } _SEH2_END;

    return Status;
}
Beispiel #12
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdPurgeVolume (IN PRFSD_VCB Vcb,
                 IN BOOLEAN  FlushBeforePurge )
{
    PRFSD_FCB       Fcb;
    LIST_ENTRY      FcbList;
    PLIST_ENTRY     ListEntry;
    PFCB_LIST_ENTRY FcbListEntry;

    PAGED_CODE();

    _SEH2_TRY {

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
        (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
        IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
            FlushBeforePurge = FALSE;
        }

        FcbListEntry= NULL;
        InitializeListHead(&FcbList);

        for (ListEntry = Vcb->FcbList.Flink;
        ListEntry != &Vcb->FcbList;
        ListEntry = ListEntry->Flink  ) {

            Fcb = CONTAINING_RECORD(ListEntry, RFSD_FCB, Next);

            Fcb->ReferenceCount++;

            RfsdPrint((DBG_INFO, "RfsdPurgeVolume: %s refercount=%xh\n", Fcb->AnsiFileName.Buffer, Fcb->ReferenceCount));

            FcbListEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FCB_LIST_ENTRY), RFSD_POOL_TAG);

            if (FcbListEntry) {

                FcbListEntry->Fcb = Fcb;

                InsertTailList(&FcbList, &FcbListEntry->Next);
            } else {
                RfsdPrint((DBG_ERROR, "RfsdPurgeVolume: Error allocating FcbListEntry ...\n"));
            }
        }

        while (!IsListEmpty(&FcbList)) {

            ListEntry = RemoveHeadList(&FcbList);

            FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);

            Fcb = FcbListEntry->Fcb;

            if (ExAcquireResourceExclusiveLite(
                        &Fcb->MainResource,
                        TRUE )) {

                RfsdPurgeFile(Fcb, FlushBeforePurge);

                if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1) {
                    RemoveEntryList(&Fcb->Next);
                    RfsdFreeFcb(Fcb);
                } else {
                    ExReleaseResourceForThreadLite(
                        &Fcb->MainResource,
                        ExGetCurrentResourceThread());
                }
            }

            ExFreePool(FcbListEntry);
        }

        if (FlushBeforePurge) {
            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResourceLite(&Vcb->PagingIoResource);

            CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL);
        }

        if (Vcb->SectionObject.ImageSectionObject) {
            MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
        }

        if (Vcb->SectionObject.DataSectionObject) {
            CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
        }

        RfsdPrint((DBG_INFO, "RfsdPurgeVolume: Volume flushed and purged.\n"));

    } _SEH2_FINALLY {
        // Nothing
    } _SEH2_END;

    return STATUS_SUCCESS;
}
Beispiel #13
0
PFFS_MCB
FFSAllocateMcb(
	PFFS_VCB        Vcb,
	PUNICODE_STRING FileName,
	ULONG           FileAttr)
{
	PFFS_MCB    Mcb = NULL;
	PLIST_ENTRY List = NULL;

	ULONG       Extra = 0;

#define MCB_NUM_SHIFT   0x04

	if (FFSGlobal->McbAllocated > (FFSGlobal->MaxDepth << MCB_NUM_SHIFT))
		Extra = FFSGlobal->McbAllocated - 
			(FFSGlobal->MaxDepth << MCB_NUM_SHIFT) +
			FFSGlobal->MaxDepth;

	FFSPrint((DBG_INFO,
				"FFSAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n", 
				FFSGlobal->McbAllocated,
				FFSGlobal->MaxDepth << MCB_NUM_SHIFT,
				FFSGlobal->FcbAllocated,
				FileName->Buffer));

	List = Vcb->McbList.Flink;

	while ((List != &(Vcb->McbList)) && (Extra > 0))
	{
		Mcb = CONTAINING_RECORD(List, FFS_MCB, Link);
		List = List->Flink;

		if ((Mcb->Inode != 2) && (Mcb->Child == NULL) &&
				(Mcb->FFSFcb == NULL) && (!IsMcbUsed(Mcb)))
		{
			FFSPrint((DBG_INFO, "FFSAllocateMcb: Mcb %S will be freed.\n",
						Mcb->ShortName.Buffer));

			if (FFSDeleteMcbNode(Vcb, Vcb->McbTree, Mcb))
			{
				FFSFreeMcb(Mcb);

				Extra--;
			}
		}
	}

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->LAResource,
			TRUE);

	Mcb = (PFFS_MCB)(ExAllocateFromPagedLookasideList(
				&(FFSGlobal->FFSMcbLookasideList)));

	ExReleaseResourceForThreadLite(
			&FFSGlobal->LAResource,
			ExGetCurrentResourceThread());

	if (Mcb == NULL)
	{
		Mcb = (PFFS_MCB)ExAllocatePool(PagedPool, sizeof(FFS_MCB));

		RtlZeroMemory(Mcb, sizeof(FFS_MCB));

		SetFlag(Mcb->Flags, MCB_FROM_POOL);
	}
	else
	{
		RtlZeroMemory(Mcb, sizeof(FFS_MCB));
	}

	if (!Mcb)
	{
		return NULL;
	}

	Mcb->Identifier.Type = FFSMCB;
	Mcb->Identifier.Size = sizeof(FFS_MCB);

	if (FileName && FileName->Length)
	{
		Mcb->ShortName.Length = FileName->Length;
		Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2;

		Mcb->ShortName.Buffer = ExAllocatePool(PagedPool, Mcb->ShortName.MaximumLength);

		if (!Mcb->ShortName.Buffer)
			goto errorout;

		RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength);
		RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length);
	} 

	Mcb->FileAttr = FileAttr;

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->CountResource,
			TRUE);

	FFSGlobal->McbAllocated++;

	ExReleaseResourceForThreadLite(
			&FFSGlobal->CountResource,
			ExGetCurrentResourceThread());

	return Mcb;

errorout:

	if (Mcb)
	{
		if (Mcb->ShortName.Buffer)
			ExFreePool(Mcb->ShortName.Buffer);

		if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
		{
			ExFreePool(Mcb);
		}
		else
		{
			ExAcquireResourceExclusiveLite(
					&FFSGlobal->LAResource,
					TRUE);

			ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);

			ExReleaseResourceForThreadLite(
					&FFSGlobal->LAResource,
					ExGetCurrentResourceThread());
		}
	}

	return NULL;
}
Beispiel #14
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;
}
Beispiel #15
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSClose(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT  DeviceObject;
	NTSTATUS        Status = STATUS_SUCCESS;
	PFFS_VCB        Vcb = 0;
	BOOLEAN         VcbResourceAcquired = FALSE;
	PFILE_OBJECT    FileObject;
	PFFS_FCB        Fcb = 0;
	BOOLEAN         FcbResourceAcquired = FALSE;
	PFFS_CCB        Ccb;
	BOOLEAN         FreeVcb = FALSE;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

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

		DeviceObject = IrpContext->DeviceObject;

		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		Vcb = (PFFS_VCB) DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

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

		ASSERT(IsMounted(Vcb));

		if (!ExAcquireResourceExclusiveLite(
					&Vcb->MainResource,
					IrpContext->IsSynchronous))
		{
			FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n",
						Vcb->OpenFileHandleCount, Vcb->ReferenceCount));

			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		VcbResourceAcquired = TRUE;

		FileObject = IrpContext->FileObject;

		if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
		{
			Fcb = IrpContext->Fcb;
			Ccb = IrpContext->Ccb;
		}
		else
		{
			Fcb = (PFFS_FCB)FileObject->FsContext;

			if (!Fcb)
			{
				Status = STATUS_SUCCESS;
				_SEH2_LEAVE;
			}

			ASSERT(Fcb != NULL);

			Ccb = (PFFS_CCB)FileObject->FsContext2;
		}

		if (Fcb->Identifier.Type == FFSVCB)
		{
			Vcb->ReferenceCount--;

			if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
			{
				FreeVcb = TRUE;
			}

			if (Ccb)
			{
				FFSFreeCcb(Ccb);
				if (FileObject)
				{
					FileObject->FsContext2 = Ccb = NULL;
				}
			}

			Status = STATUS_SUCCESS;

			_SEH2_LEAVE;
		}

		if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB))
		{
#if DBG
			FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n"));
			ExAcquireResourceExclusiveLite(
					&FFSGlobal->CountResource,
					TRUE);

			FFSGlobal->IRPCloseCount++;

			ExReleaseResourceForThreadLite(
					&FFSGlobal->CountResource,
					ExGetCurrentResourceThread());
#endif
			_SEH2_LEAVE;
		}

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		/*        
			  if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) && 
			  (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)))
			  */
		{
			if (!ExAcquireResourceExclusiveLite(
						&Fcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				_SEH2_LEAVE;
			}

			FcbResourceAcquired = TRUE;
		}

		if (!Ccb)
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		ASSERT((Ccb->Identifier.Type == FFSCCB) &&
				(Ccb->Identifier.Size == sizeof(FFS_CCB)));

		Fcb->ReferenceCount--;
		Vcb->ReferenceCount--;

		if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
		{
			FreeVcb = TRUE;
		}

		FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n",
					Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));

		if (Ccb)
		{
			FFSFreeCcb(Ccb);

			if (FileObject)
			{
				FileObject->FsContext2 = Ccb = NULL;
			}
		}

		if (!Fcb->ReferenceCount)
		{
			//
			// Remove Fcb from Vcb->FcbList ...
			//

			RemoveEntryList(&Fcb->Next);

			FFSFreeFcb(Fcb);

			FcbResourceAcquired = FALSE;
		}

		Status = STATUS_SUCCESS;
	}

	_SEH2_FINALLY
	{
		if (FcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

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

		if (!IrpContext->ExceptionInProgress)
		{
			if (Status == STATUS_PENDING)
			{
				FFSQueueCloseRequest(IrpContext);
#if 0
/*
				Status = STATUS_SUCCESS;

				if (IrpContext->Irp != NULL)
				{
					IrpContext->Irp->IoStatus.Status = Status;

					FFSCompleteRequest(
							IrpContext->Irp,
							(BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED),
							(CCHAR)
							(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));

					IrpContext->Irp = NULL;
				}
*/
#endif
			}
			else
			{
				FFSCompleteIrpContext(IrpContext, Status);

				if (FreeVcb)
				{
					ExAcquireResourceExclusiveLite(
							&FFSGlobal->Resource, TRUE);

					FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);

					FFSRemoveVcb(Vcb);

					ExReleaseResourceForThreadLite(
							&FFSGlobal->Resource,
							ExGetCurrentResourceThread());

					FFSFreeVcb(Vcb);
				}
			}
		}
	} _SEH2_END;

	return Status;
}
Beispiel #16
0
VOID
FFSFreeFcb(
	IN PFFS_FCB Fcb)
{
	PFFS_VCB       Vcb;
	ASSERT(Fcb != NULL);

	ASSERT((Fcb->Identifier.Type == FFSFCB) &&
			(Fcb->Identifier.Size == sizeof(FFS_FCB)));

	Vcb = Fcb->Vcb;

	FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);

	ExDeleteResourceLite(&Fcb->MainResource);

	ExDeleteResourceLite(&Fcb->PagingIoResource);

	Fcb->FFSMcb->FFSFcb = NULL;

	if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
	{
		if (Fcb->FFSMcb)
		{
			FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
			FFSFreeMcb(Fcb->FFSMcb);
		}
	}

	if (Fcb->LongName.Buffer)
	{
		ExFreePool(Fcb->LongName.Buffer);
		Fcb->LongName.Buffer = NULL;
	}

#if DBG    
	ExFreePool(Fcb->AnsiFileName.Buffer);
#endif

	if (FS_VERSION == 1)
	{
		ExFreePool(Fcb->dinode1);
	}
	else
	{
		ExFreePool(Fcb->dinode2);
	}

	Fcb->Header.NodeTypeCode = (SHORT)0xCCCC;
	Fcb->Header.NodeByteSize = (SHORT)0xC0C0;

	if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
	{
		ExFreePool(Fcb);
	}
	else
	{
		ExAcquireResourceExclusiveLite(
				&FFSGlobal->LAResource,
				TRUE);

		ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);

		ExReleaseResourceForThreadLite(
				&FFSGlobal->LAResource,
				ExGetCurrentResourceThread());
	}

#if DBG

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->CountResource,
			TRUE);

	FFSGlobal->FcbAllocated--;

	ExReleaseResourceForThreadLite(
			&FFSGlobal->CountResource,
			ExGetCurrentResourceThread());
#endif

}
Beispiel #17
0
__drv_mustHoldCriticalRegion
BOOLEAN
FFSCheckDismount(
	IN PFFS_IRP_CONTEXT  IrpContext,
	IN PFFS_VCB          Vcb,
	IN BOOLEAN           bForce)
{
	KIRQL   Irql;
	PVPB    Vpb = Vcb->Vpb;
	BOOLEAN bDeleted = FALSE;
	ULONG   UnCleanCount = 0;

    PAGED_CODE();

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->Resource, TRUE);

	ExAcquireResourceExclusiveLite(
			&Vcb->MainResource, TRUE);

	if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
			(IrpContext->RealDevice == Vcb->RealDevice))
	{
		UnCleanCount = 3;
	}
	else
	{
		UnCleanCount = 2;
	}

	IoAcquireVpbSpinLock(&Irql);

	if ((Vpb->ReferenceCount == UnCleanCount) || bForce)
	{

		if ((Vpb->ReferenceCount != UnCleanCount) && bForce)
		{
			FFSBreakPoint();
		}

		ClearFlag(Vpb->Flags, VPB_MOUNTED);
		ClearFlag(Vpb->Flags, VPB_LOCKED);

		if ((Vcb->RealDevice != Vpb->RealDevice) &&
#ifdef _MSC_VER
#pragma prefast( suppress: 28175, "allowed in file system drivers" )
#endif
				(Vcb->RealDevice->Vpb == Vpb))
		{
			SetFlag(Vcb->RealDevice->Flags, DO_DEVICE_INITIALIZING);
			SetFlag(Vpb->Flags, VPB_PERSISTENT);
		}

		FFSRemoveVcb(Vcb);

		ClearFlag(Vpb->Flags, VPB_MOUNTED);
		SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);

		Vpb->DeviceObject = NULL;

		bDeleted = TRUE;
	}

#if 0

	else if ((Vpb->RealDevice->Vpb == Vpb) && bForce)
	{
		PVPB NewVpb;

#define TAG_VPB                         ' bpV'

		NewVpb = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 
				sizeof(VPB), TAG_VPB);

		NewVpb->Type = IO_TYPE_VPB;
		NewVpb->Size = sizeof(VPB);
		NewVpb->RealDevice = Vcb->Vpb->RealDevice;

		NewVpb->RealDevice->Vpb = NewVpb;

		NewVpb->Flags = FlagOn(Vcb->Vpb->Flags, VPB_REMOVE_PENDING);

		NewVpb = NULL;

		ClearFlag(Vcb->Flags, VCB_MOUNTED);
		ClearFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);
	}

#endif

	IoReleaseVpbSpinLock(Irql);

	ExReleaseResourceForThreadLite(
			&Vcb->MainResource,
			ExGetCurrentResourceThread());

	ExReleaseResourceForThreadLite(
			&FFSGlobal->Resource,
			ExGetCurrentResourceThread());

	if (bDeleted)
	{
#if 0
		FFSBreakPoint(); /* XP에서 브레이크 포인트 발생 */
#endif

		FFSFreeVcb(Vcb);
	}

	return bDeleted;
}
Beispiel #18
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSLockVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PIO_STACK_LOCATION IrpSp;
	PDEVICE_OBJECT     DeviceObject;
	PFFS_VCB           Vcb = 0;
	NTSTATUS           Status;
	BOOLEAN VcbResourceAcquired = FALSE;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

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

		DeviceObject = IrpContext->DeviceObject;

		Status = STATUS_UNSUCCESSFUL;

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

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

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

		ASSERT(IsMounted(Vcb));

		IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);

#if (_WIN32_WINNT >= 0x0500)
		CcWaitForCurrentLazyWriterActivity();
#endif
		ExAcquireResourceExclusiveLite(
				&Vcb->MainResource,
				TRUE);

		VcbResourceAcquired = TRUE;

		Status = FFSLockVcb(Vcb, IrpSp->FileObject);        
	}

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

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

	return Status;
}
Beispiel #19
0
__drv_mustHoldCriticalRegion
BOOLEAN
RfsdCheckDismount (
    IN PRFSD_IRP_CONTEXT IrpContext,
    IN PRFSD_VCB         Vcb,
    IN BOOLEAN           bForce   )
{
    KIRQL   Irql;
    PVPB    Vpb = Vcb->Vpb;
    BOOLEAN bDeleted = FALSE;
    ULONG   UnCleanCount = 0;

    PAGED_CODE();

    ExAcquireResourceExclusiveLite(
        &RfsdGlobal->Resource, TRUE );

    ExAcquireResourceExclusiveLite(
        &Vcb->MainResource, TRUE );

    if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
            (IrpContext->RealDevice == Vcb->RealDevice)) {
        UnCleanCount = 3;
    } else {
        UnCleanCount = 2;
    }

    IoAcquireVpbSpinLock (&Irql);

    if ((Vpb->ReferenceCount == UnCleanCount) || bForce) {

        if ((Vpb->ReferenceCount != UnCleanCount) && bForce) {
            KdPrint(("RfsdCheckDismount: force dismount ...\n"));
        }

        ClearFlag( Vpb->Flags, VPB_MOUNTED );
        ClearFlag( Vpb->Flags, VPB_LOCKED );

#ifdef _MSC_VER
#pragma prefast( suppress: 28175, "allowed in file system drivers" )
#endif
        if ((Vcb->RealDevice != Vpb->RealDevice) &&
                (Vcb->RealDevice->Vpb == Vpb)) {
            SetFlag( Vcb->RealDevice->Flags, DO_DEVICE_INITIALIZING );
            SetFlag( Vpb->Flags, VPB_PERSISTENT );
        }

        RfsdRemoveVcb(Vcb);

        ClearFlag(Vpb->Flags, VPB_MOUNTED);
        SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);

        Vpb->DeviceObject = NULL;

        bDeleted = TRUE;
    }

    IoReleaseVpbSpinLock(Irql);

    ExReleaseResourceForThreadLite(
        &Vcb->MainResource,
        ExGetCurrentResourceThread() );

    ExReleaseResourceForThreadLite(
        &RfsdGlobal->Resource,
        ExGetCurrentResourceThread() );

    if (bDeleted) {
        KdPrint(("RfsdCheckDismount: now free the vcb ...\n"));
        RfsdFreeVcb(Vcb);
    }

    return bDeleted;
}
Beispiel #20
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;
}
Beispiel #21
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdUnlockVolume (
    IN PRFSD_IRP_CONTEXT IrpContext
)
{
    PIO_STACK_LOCATION IrpSp;
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status;
    PRFSD_VCB       Vcb = 0;
    BOOLEAN         VcbResourceAcquired = FALSE;

    PAGED_CODE();

    _SEH2_TRY {

        ASSERT(IrpContext != NULL);

        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
        (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;

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

        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
        (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        ASSERT(IsMounted(Vcb));

        IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);

        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource,
            TRUE );

        VcbResourceAcquired = TRUE;

        Status = RfsdUnlockVcb(Vcb, IrpSp->FileObject);

    } _SEH2_FINALLY {

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

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

    return Status;
}
Beispiel #22
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSQueryDirectory(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT          DeviceObject;
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	PFFS_VCB                Vcb = 0;
	PFILE_OBJECT            FileObject;
	PFFS_FCB                Fcb = 0;
	PFFS_CCB                Ccb;
	PIRP                    Irp;
	PIO_STACK_LOCATION      IoStackLocation;
	FILE_INFORMATION_CLASS  FileInformationClass;
	ULONG                   Length;
	PUNICODE_STRING         FileName;
	ULONG                   FileIndex;
	BOOLEAN                 RestartScan;
	BOOLEAN                 ReturnSingleEntry;
	BOOLEAN                 IndexSpecified;
	PUCHAR                  Buffer;
	BOOLEAN                 FirstQuery;
	PFFSv1_INODE            dinode1 = NULL;
	PFFSv2_INODE            dinode2 = NULL;
	BOOLEAN                 FcbResourceAcquired = FALSE;
	ULONG                   UsedLength = 0;
	USHORT                  InodeFileNameLength;
	UNICODE_STRING          InodeFileName;
	PFFS_DIR_ENTRY          pDir = NULL;
	ULONG                   dwBytes;
	ULONG                   dwTemp = 0;
	ULONG                   dwSize = 0;
	ULONG                   dwReturn = 0;
	BOOLEAN                 bRun = TRUE;
	ULONG                   ByteOffset;

    PAGED_CODE();

	InodeFileName.Buffer = NULL;

	_SEH2_TRY
	{
		ASSERT(IrpContext);

		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;
		}

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

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

		ASSERT(IsMounted(Vcb));

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		ASSERT(Fcb);

		//
		// This request is not allowed on volumes
		//
		if (Fcb->Identifier.Type == FFSVCB)
		{
			Status = STATUS_INVALID_PARAMETER;
			_SEH2_LEAVE;
		}

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		if (!IsDirectory(Fcb))
		{
			Status = STATUS_INVALID_PARAMETER;
			_SEH2_LEAVE;
		}

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		ASSERT(Ccb);

		ASSERT((Ccb->Identifier.Type == FFSCCB) &&
				(Ccb->Identifier.Size == sizeof(FFS_CCB)));

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)

		FileInformationClass =
			IoStackLocation->Parameters.QueryDirectory.FileInformationClass;

		Length = IoStackLocation->Parameters.QueryDirectory.Length;

		FileName = IoStackLocation->Parameters.QueryDirectory.FileName;

		FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex;

#else // _GNU_NTIFS_

		FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION)
				IoStackLocation)->Parameters.QueryDirectory.FileInformationClass;

		Length = ((PEXTENDED_IO_STACK_LOCATION)
				IoStackLocation)->Parameters.QueryDirectory.Length;

		FileName = ((PEXTENDED_IO_STACK_LOCATION)
				IoStackLocation)->Parameters.QueryDirectory.FileName;

		FileIndex = ((PEXTENDED_IO_STACK_LOCATION)
				IoStackLocation)->Parameters.QueryDirectory.FileIndex;

#endif // _GNU_NTIFS_

		RestartScan = FlagOn(IoStackLocation->Flags, SL_RESTART_SCAN);
		ReturnSingleEntry = FlagOn(IoStackLocation->Flags, SL_RETURN_SINGLE_ENTRY);
		IndexSpecified = FlagOn(IoStackLocation->Flags, SL_INDEX_SPECIFIED);
		/*
		if (!Irp->MdlAddress && Irp->UserBuffer)
		{
			ProbeForWrite(Irp->UserBuffer, Length, 1);
		}
		*/
		Buffer = FFSGetUserBuffer(Irp);

		if (Buffer == NULL)
		{
			FFSBreakPoint();
			Status = STATUS_INVALID_USER_BUFFER;
			_SEH2_LEAVE;
		}

		if (!IrpContext->IsSynchronous)
		{
			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		if (!ExAcquireResourceSharedLite(
					&Fcb->MainResource,
					IrpContext->IsSynchronous))
		{
			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		FcbResourceAcquired = TRUE;

		if (FileName != NULL)
		{
			if (Ccb->DirectorySearchPattern.Buffer != NULL)
			{
				FirstQuery = FALSE;
			}
			else
			{
				FirstQuery = TRUE;

				Ccb->DirectorySearchPattern.Length =
					Ccb->DirectorySearchPattern.MaximumLength =
					FileName->Length;

				Ccb->DirectorySearchPattern.Buffer =
					ExAllocatePoolWithTag(PagedPool, FileName->Length, FFS_POOL_TAG);

				if (Ccb->DirectorySearchPattern.Buffer == NULL)
				{
					Status = STATUS_INSUFFICIENT_RESOURCES;
					_SEH2_LEAVE;
				}

				Status = RtlUpcaseUnicodeString(
						&(Ccb->DirectorySearchPattern),
						FileName,
						FALSE);

				if (!NT_SUCCESS(Status))
					_SEH2_LEAVE;
			}
		}
		else if (Ccb->DirectorySearchPattern.Buffer != NULL)
		{
			FirstQuery = FALSE;
			FileName = &Ccb->DirectorySearchPattern;
		}
		else
		{
			FirstQuery = TRUE;

			Ccb->DirectorySearchPattern.Length =
				Ccb->DirectorySearchPattern.MaximumLength = 2;

			Ccb->DirectorySearchPattern.Buffer =
				ExAllocatePoolWithTag(PagedPool, 2, FFS_POOL_TAG);

			if (Ccb->DirectorySearchPattern.Buffer == NULL)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				_SEH2_LEAVE;
			}

			RtlCopyMemory(
					Ccb->DirectorySearchPattern.Buffer,
					L"*\0", 2);
		}

		if (!IndexSpecified)
		{
			if (RestartScan || FirstQuery)
			{
				FileIndex = Fcb->FFSMcb->DeOffset = 0;
			}
			else
			{
				FileIndex = Ccb->CurrentByteOffset;
			}
		}

		if (FS_VERSION == 1)
		{
			dinode1 = (PFFSv1_INODE)ExAllocatePoolWithTag(
					PagedPool,
					DINODE1_SIZE, FFS_POOL_TAG);

			if (dinode1 == NULL)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				_SEH2_LEAVE;
			}

			RtlZeroMemory(Buffer, Length);

			if (Fcb->dinode1->di_size <= FileIndex)
			{
				Status = STATUS_NO_MORE_FILES;
				_SEH2_LEAVE;
			}
		}
		else
		{
			dinode2 = (PFFSv2_INODE)ExAllocatePoolWithTag(
					PagedPool,
					DINODE2_SIZE, FFS_POOL_TAG);

			if (dinode2 == NULL)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				_SEH2_LEAVE;
			}

			RtlZeroMemory(Buffer, Length);

			if (Fcb->dinode2->di_size <= FileIndex)
			{
				Status = STATUS_NO_MORE_FILES;
				_SEH2_LEAVE;
			}
		}

		pDir = ExAllocatePoolWithTag(PagedPool,
				sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG);
		if (!pDir)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			_SEH2_LEAVE;
		}


		if (FS_VERSION == 1)
		{
			dwBytes = 0;
			dwSize = (ULONG)Fcb->dinode1->di_size - FileIndex -
				(sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);

			ByteOffset = FileIndex;

			dwTemp = 0;

			while (bRun && UsedLength < Length  && dwBytes < dwSize)
			{
				OEM_STRING  OemName;

				RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));

				Status = FFSv1ReadInode(
							NULL,
							Vcb,
							Fcb->dinode1,
							ByteOffset,
							(PVOID)pDir,
							sizeof(FFS_DIR_ENTRY),
							&dwReturn);

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

				if (!pDir->d_ino)
				{
					if (pDir->d_reclen == 0)
					{
						FFSBreakPoint();
						_SEH2_LEAVE;
					}

					goto ProcessNextEntryv1;
				}

				OemName.Buffer = pDir->d_name;
				OemName.Length = (pDir->d_namlen & 0xff);
				OemName.MaximumLength = OemName.Length;

#if 0
/*
				//
				// We could not filter the files: "." and ".."
				//

				if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
				{
					if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
					{
					}
					else
					{
						goto ProcessNextEntry1;
					}
				}
*/
#endif

				InodeFileNameLength = (USHORT)
					RtlOemStringToUnicodeSize(&OemName);

				InodeFileName.Length = 0;
				InodeFileName.MaximumLength = InodeFileNameLength + 2;

				if (InodeFileNameLength <= 0)
				{
					break;
				}

				InodeFileName.Buffer = ExAllocatePoolWithTag(
						PagedPool,
						InodeFileNameLength + 2, FFS_POOL_TAG);

				if (!InodeFileName.Buffer)
				{
					Status = STATUS_INSUFFICIENT_RESOURCES;
					_SEH2_LEAVE;
				}

				RtlZeroMemory(
						InodeFileName.Buffer, 
						InodeFileNameLength + 2);

				Status = FFSOEMToUnicode(&InodeFileName,
						&OemName);

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

				if (FsRtlDoesNameContainWildCards(
							&(Ccb->DirectorySearchPattern)) ?
						FsRtlIsNameInExpression(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE,
							NULL) :
						!RtlCompareUnicodeString(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE))
				{
					dwReturn = FFSProcessDirEntry(
							Vcb, FileInformationClass,
							pDir->d_ino,
							Buffer,
							UsedLength, 
							Length - UsedLength,
							(FileIndex + dwBytes),
							&InodeFileName,
							ReturnSingleEntry);

					if (dwReturn <= 0)
					{
						bRun = FALSE;
					}
					else
					{
						dwTemp = UsedLength;
						UsedLength += dwReturn;
					}
				}

				if (InodeFileName.Buffer != NULL)
				{
					ExFreePool(InodeFileName.Buffer);
					InodeFileName.Buffer = NULL;
				}

ProcessNextEntryv1:

				if (bRun)
				{
					dwBytes +=pDir->d_reclen;
					Ccb->CurrentByteOffset = FileIndex + dwBytes;
				}

				if (UsedLength && ReturnSingleEntry)
				{
					Status = STATUS_SUCCESS;
					_SEH2_LEAVE;
				}

				ByteOffset = FileIndex + dwBytes;
			}
		}
		else
		{
			dwBytes = 0;
			dwSize = (ULONG)Fcb->dinode2->di_size - FileIndex -
				(sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);

			ByteOffset = FileIndex;

			dwTemp = 0;

			while (bRun && UsedLength < Length  && dwBytes < dwSize)
			{
				OEM_STRING  OemName;

				RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));

				Status = FFSv2ReadInode(
							NULL,
							Vcb,
							Fcb->dinode2,
							ByteOffset,
							(PVOID)pDir,
							sizeof(FFS_DIR_ENTRY),
							&dwReturn);

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

				if (!pDir->d_ino)
				{
					if (pDir->d_reclen == 0)
					{
						FFSBreakPoint();
						_SEH2_LEAVE;
					}

					goto ProcessNextEntryv2;
				}

				OemName.Buffer = pDir->d_name;
				OemName.Length = (pDir->d_namlen & 0xff);
				OemName.MaximumLength = OemName.Length;
#if 0
/*
				//
				// We could not filter the files: "." and ".."
				//

				if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
				{
					if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
					{
					}
					else
					{
						goto ProcessNextEntry2;
					}
				}
*/
#endif

				InodeFileNameLength = (USHORT)
					RtlOemStringToUnicodeSize(&OemName);

				InodeFileName.Length = 0;
				InodeFileName.MaximumLength = InodeFileNameLength + 2;

				if (InodeFileNameLength <= 0)
				{
					break;
				}

				InodeFileName.Buffer = ExAllocatePoolWithTag(
						PagedPool,
						InodeFileNameLength + 2, FFS_POOL_TAG);

				if (!InodeFileName.Buffer)
				{
					Status = STATUS_INSUFFICIENT_RESOURCES;
					_SEH2_LEAVE;
				}

				RtlZeroMemory(
						InodeFileName.Buffer, 
						InodeFileNameLength + 2);

				Status = FFSOEMToUnicode(&InodeFileName,
						&OemName);

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

				if (FsRtlDoesNameContainWildCards(
							&(Ccb->DirectorySearchPattern)) ?
						FsRtlIsNameInExpression(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE,
							NULL) :
						!RtlCompareUnicodeString(
							&(Ccb->DirectorySearchPattern),
							&InodeFileName,
							TRUE))
				{
					dwReturn = FFSProcessDirEntry(
							Vcb, FileInformationClass,
							pDir->d_ino,
							Buffer,
							UsedLength, 
							Length - UsedLength,
							(FileIndex + dwBytes),
							&InodeFileName,
							ReturnSingleEntry);

					if (dwReturn <= 0)
					{
						bRun = FALSE;
					}
					else
					{
						dwTemp = UsedLength;
						UsedLength += dwReturn;
					}
				}

				if (InodeFileName.Buffer != NULL)
				{
					ExFreePool(InodeFileName.Buffer);
					InodeFileName.Buffer = NULL;
				}

ProcessNextEntryv2:

				if (bRun)
				{
					dwBytes +=pDir->d_reclen;
					Ccb->CurrentByteOffset = FileIndex + dwBytes;
				}

				if (UsedLength && ReturnSingleEntry)
				{
					Status = STATUS_SUCCESS;
					_SEH2_LEAVE;
				}

				ByteOffset = FileIndex + dwBytes;
			}
		}

		FileIndex += dwBytes;

		((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0;

		if (!UsedLength)
		{
			if (FirstQuery)
			{
				Status = STATUS_NO_SUCH_FILE;
			}
			else
			{
				Status = STATUS_NO_MORE_FILES;
			}
		}
		else
		{
			Status = STATUS_SUCCESS;
		}
	}

	_SEH2_FINALLY
	{

		if (FcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (FS_VERSION == 1)
		{
			if (dinode1 != NULL)
			{
				ExFreePool(dinode1);
			}
		}
		else
		{
			if (dinode2 != NULL)
			{
				ExFreePool(dinode2);
			}
		}

		if (pDir != NULL)
		{
			ExFreePool(pDir);
			pDir = NULL;
		}

		if (InodeFileName.Buffer != NULL)
		{
			ExFreePool(InodeFileName.Buffer);
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Status == STATUS_PENDING)
			{
				Status = FFSLockUserBuffer(
						IrpContext->Irp,
						Length,
						IoWriteAccess);

				if (NT_SUCCESS(Status))
				{
					Status = FFSQueueRequest(IrpContext);
				}
				else
				{
					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				IrpContext->Irp->IoStatus.Information = UsedLength;
				FFSCompleteIrpContext(IrpContext, Status);
			}
		}
	} _SEH2_END;

	return Status;
}
Beispiel #23
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdMountVolume (IN PRFSD_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;
    PRFSD_VCB                   Vcb;
    PRFSD_SUPER_BLOCK           RfsdSb = NULL;
    ULONG                       dwBytes;
    DISK_GEOMETRY               DiskGeometry;

    PAGED_CODE();

    _SEH2_TRY {


        ASSERT(IrpContext != NULL);

        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
        (IrpContext->Identifier.Size == sizeof(RFSD_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 != RfsdGlobal->DeviceObject) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            _SEH2_LEAVE;
        }

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

        GlobalDataResourceAcquired = TRUE;

        if (FlagOn(RfsdGlobal->Flags, RFSD_UNLOAD_PENDING)) {
            Status = STATUS_UNRECOGNIZED_VOLUME;
            _SEH2_LEAVE;
        }

        Irp = IrpContext->Irp;

        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        TargetDeviceObject =
        IoStackLocation->Parameters.MountVolume.DeviceObject;

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

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

        Status = IoCreateDevice(
            MainDeviceObject->DriverObject,
            sizeof(RFSD_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 = (PRFSD_VCB) VolumeDeviceObject->DeviceExtension;

        RtlZeroMemory(Vcb, sizeof(RFSD_VCB));

        Vcb->Identifier.Type = RFSDVCB;
        Vcb->Identifier.Size = sizeof(RFSD_VCB);

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

        RfsdSb = RfsdLoadSuper(Vcb, FALSE);

        if (RfsdSb) {
            if ( SuperblockContainsMagicKey(RfsdSb) ) {
                RfsdPrint((DBG_INFO, "Volume of ReiserFS rfsd file system is found.\n"));
                Status = STATUS_SUCCESS;
            } else  {
                Status = STATUS_UNRECOGNIZED_VOLUME;
            }
        }

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

        Vcb->BlockSize = RfsdSb->s_blocksize;		// NOTE: FFS also does this here, since LoadGroup is not called in the non-ext2 drivers
        Vcb->GroupDesc = NULL;						// NOTE: GroupDesc is not used for ReiserFS.  Setting it to NULL will keep other code from barfing.
        // Vcb->SectorBits = RFSDLog(SECTOR_SIZE);	// NOTE: SectorBits are unused for ReiserFS

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

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

            SetFlag(Vcb->Flags, VCB_MOUNTED);

            RfsdInsertVcb(Vcb);

            ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
        }

    } _SEH2_FINALLY {

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

        if (!NT_SUCCESS(Status)) {

            if (RfsdSb) {
                ExFreePool(RfsdSb);
            }

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

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

    return Status;
}
Beispiel #24
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSNotifyChangeDirectory(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT      DeviceObject;
	BOOLEAN             CompleteRequest;
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;
	PFFS_VCB            Vcb;
	PFILE_OBJECT        FileObject;
	PFFS_FCB            Fcb = 0;
	PIRP                Irp;
	PIO_STACK_LOCATION  IrpSp;
	ULONG               CompletionFilter;
	BOOLEAN             WatchTree;

	BOOLEAN             bFcbAcquired = FALSE;

	PUNICODE_STRING     FullName;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext);

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

		//
		//  Always set the wait flag in the Irp context for the original request.
		//

		SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

		DeviceObject = IrpContext->DeviceObject;

		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			CompleteRequest = TRUE;
			Status = STATUS_INVALID_DEVICE_REQUEST;
			_SEH2_LEAVE;
		}

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

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

		ASSERT(IsMounted(Vcb));

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		ASSERT(Fcb);

		if (Fcb->Identifier.Type == FFSVCB)
		{
			FFSBreakPoint();
			CompleteRequest = TRUE;
			Status = STATUS_INVALID_PARAMETER;
			_SEH2_LEAVE;
		}

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		if (!IsDirectory(Fcb))
		{
			FFSBreakPoint();
			CompleteRequest = TRUE;
			Status = STATUS_INVALID_PARAMETER;
			_SEH2_LEAVE;
		}

		if (ExAcquireResourceExclusiveLite(
					&Fcb->MainResource,
					TRUE))
		{
			bFcbAcquired = TRUE;
		}
		else
		{
			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		Irp = IrpContext->Irp;

		IrpSp = IoGetCurrentIrpStackLocation(Irp);

#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)

		CompletionFilter =
			IrpSp->Parameters.NotifyDirectory.CompletionFilter;

#else // _GNU_NTIFS_

		CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION)
				IrpSp)->Parameters.NotifyDirectory.CompletionFilter;

#endif // _GNU_NTIFS_

		WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE);

		if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
		{
			Status = STATUS_DELETE_PENDING;
			_SEH2_LEAVE;
		}

		FullName = &Fcb->LongName;

		if (FullName->Buffer == NULL)
		{
			if (!FFSGetFullFileName(Fcb->FFSMcb, FullName))
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				_SEH2_LEAVE;
			}
		}

		FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
				&Vcb->NotifyList,
				FileObject->FsContext2,
				(PSTRING)FullName,
				WatchTree,
				FALSE,
				CompletionFilter,
				Irp,
				NULL,
				NULL);

		CompleteRequest = FALSE;

		Status = STATUS_PENDING;

		/*
		   Currently the driver is read-only but here is an example on how to use the
		   FsRtl-functions to report a change:

		   ANSI_STRING TestString;
		   USHORT      FileNamePartLength;

		   RtlInitAnsiString(&TestString, "\\ntifs.h");

		   FileNamePartLength = 7;

		   FsRtlNotifyReportChange(
		   Vcb->NotifySync,            // PNOTIFY_SYNC NotifySync
		   &Vcb->NotifyList,           // PLIST_ENTRY  NotifyList
		   &TestString,                // PSTRING      FullTargetName
		   &FileNamePartLength,        // PUSHORT      FileNamePartLength
		   FILE_NOTIFY_CHANGE_NAME     // ULONG        FilterMatch
		   );

		   or

		   ANSI_STRING TestString;

		   RtlInitAnsiString(&TestString, "\\ntifs.h");

		   FsRtlNotifyFullReportChange(
		   Vcb->NotifySync,            // PNOTIFY_SYNC NotifySync
		   &Vcb->NotifyList,           // PLIST_ENTRY  NotifyList
		   &TestString,                // PSTRING      FullTargetName
		   1,                          // USHORT       TargetNameOffset
		   NULL,                       // PSTRING      StreamName OPTIONAL
		   NULL,                       // PSTRING      NormalizedParentName OPTIONAL
		   FILE_NOTIFY_CHANGE_NAME,    // ULONG        FilterMatch
		   0,                          // ULONG        Action
		   NULL                        // PVOID        TargetContext
		   );
		   */

	}
	_SEH2_FINALLY
	{
		if (bFcbAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (!CompleteRequest)
			{
				IrpContext->Irp = NULL;
			}

			FFSCompleteIrpContext(IrpContext, Status);
		}
	} _SEH2_END;

	return Status;
}
Beispiel #25
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdDismountVolume (IN PRFSD_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;
    PRFSD_VCB       Vcb = 0;
    BOOLEAN         VcbResourceAcquired = FALSE;

    PAGED_CODE();

    _SEH2_TRY {

        ASSERT(IrpContext != NULL);

        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
        (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;

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

        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
        (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        ASSERT(IsMounted(Vcb));

        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource,
            TRUE );

        VcbResourceAcquired = TRUE;

        if ( IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
            Status = STATUS_VOLUME_DISMOUNTED;
            _SEH2_LEAVE;
        }

        /*
                if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
                    RfsdPrint((DBG_ERROR, "RfsdDismount: Volume is not locked.\n"));

                    Status = STATUS_ACCESS_DENIED;

                    _SEH2_LEAVE;
                }
        */
#if DISABLED
        RfsdFlushFiles(Vcb, FALSE);

        RfsdFlushVolume(Vcb, FALSE);

        RfsdPurgeVolume(Vcb, TRUE);
#endif
        ExReleaseResourceForThreadLite(
            &Vcb->MainResource,
            ExGetCurrentResourceThread() );

        VcbResourceAcquired = FALSE;

        RfsdCheckDismount(IrpContext, Vcb, TRUE);

        RfsdPrint((DBG_INFO, "RfsdDismount: Volume dismount pending.\n"));

        Status = STATUS_SUCCESS;

    } _SEH2_FINALLY {

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

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

    return Status;
}
Beispiel #26
0
PFFS_IRP_CONTEXT
FFSAllocateIrpContext(
	IN PDEVICE_OBJECT   DeviceObject,
	IN PIRP             Irp)
{
	PIO_STACK_LOCATION  IoStackLocation;
	PFFS_IRP_CONTEXT    IrpContext;

	ASSERT(DeviceObject != NULL);
	ASSERT(Irp != NULL);

	IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->LAResource,
			TRUE);

	IrpContext = (PFFS_IRP_CONTEXT)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList)));

	ExReleaseResourceForThreadLite(
			&FFSGlobal->LAResource,
			ExGetCurrentResourceThread());

	if (IrpContext == NULL)
	{
		IrpContext = ExAllocatePool(NonPagedPool, sizeof(FFS_IRP_CONTEXT));

		//
		//  Zero out the irp context and indicate that it is from pool and
		//  not region allocated
		//

		RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT));

		SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL);
	}
	else
	{
		//
		//  Zero out the irp context and indicate that it is from zone and
		//  not pool allocated
		//

		RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT));
	}

	if (!IrpContext)
	{
		return NULL;
	}

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

	IrpContext->Irp = Irp;

	IrpContext->MajorFunction = IoStackLocation->MajorFunction;
	IrpContext->MinorFunction = IoStackLocation->MinorFunction;

	IrpContext->DeviceObject = DeviceObject;

	IrpContext->FileObject = IoStackLocation->FileObject;

	if (IrpContext->FileObject != NULL)
	{
		IrpContext->RealDevice = IrpContext->FileObject->DeviceObject;
	}
	else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
	{
		if (IoStackLocation->Parameters.MountVolume.Vpb)
		{
			IrpContext->RealDevice = 
				IoStackLocation->Parameters.MountVolume.Vpb->RealDevice;
		}
	}

	if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
			IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
			IrpContext->MajorFunction == IRP_MJ_SHUTDOWN)
	{
		IrpContext->IsSynchronous = TRUE;
	}
	else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP ||
			IrpContext->MajorFunction == IRP_MJ_CLOSE)
	{
		IrpContext->IsSynchronous = FALSE;
	}
#if (_WIN32_WINNT >= 0x0500)
	else if (IrpContext->MajorFunction == IRP_MJ_PNP)
	{
		if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL)
		{
			IrpContext->IsSynchronous = TRUE;
		}
		else
		{
			IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
		}
	}
#endif //(_WIN32_WINNT >= 0x0500)
	else
	{
		IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
	}

#if 0    
	//
	// Temporary workaround for a bug in close that makes it reference a
	// fileobject when it is no longer valid.
	//
	if (IrpContext->MajorFunction == IRP_MJ_CLOSE)
	{
		IrpContext->IsSynchronous = TRUE;
	}
#endif

	IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);

	IrpContext->ExceptionInProgress = FALSE;

	return IrpContext;
}
Beispiel #27
0
NTSTATUS
Ext2FsdQueryVolumeInformation (IN PFSD_IRP_CONTEXT IrpContext)
{
   PDEVICE_OBJECT DeviceObject = NULL;
   NTSTATUS Status = STATUS_UNSUCCESSFUL;
   PFSD_VCB Vcb = NULL;
   PIRP Irp = NULL;
   PIO_STACK_LOCATION IrpSp = NULL;
   FS_INFORMATION_CLASS FsInformationClass;
   ULONG Length;
   PVOID SystemBuffer = NULL;
   BOOLEAN VcbResourceAcquired = FALSE;

   __try
   {
      ASSERT (IrpContext != NULL);

      ASSERT ((IrpContext->Identifier.Type == ICX)
              && (IrpContext->Identifier.Size == sizeof (FSD_IRP_CONTEXT)));

      DeviceObject = IrpContext->DeviceObject;

      ASSERT (DeviceObject);

      if (DeviceObject == FsdGlobalData.DeviceObject)
      {
         Status = STATUS_INVALID_DEVICE_REQUEST;
         __leave;
      }

      Vcb = (PFSD_VCB) DeviceObject->DeviceExtension;

      ASSERT (Vcb != NULL);

      ASSERT ((Vcb->Identifier.Type == VCB)
              && (Vcb->Identifier.Size == sizeof (FSD_VCB)));

      if (!ExAcquireResourceSharedLite
          (&Vcb->MainResource, IrpContext->IsSynchronous))
      {
         Status = STATUS_PENDING;
         __leave;
      }

      VcbResourceAcquired = TRUE;

      Irp = IrpContext->Irp;
      ASSERT (Irp);

      IrpSp = IoGetCurrentIrpStackLocation (Irp);
      ASSERT (IrpSp);

      FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;

      Length = IrpSp->Parameters.QueryVolume.Length;

      SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
      ASSERT (SystemBuffer);

      RtlZeroMemory (SystemBuffer, Length);

      switch (FsInformationClass)
      {
      case FileFsVolumeInformation:
         {
            PFILE_FS_VOLUME_INFORMATION Buffer;
            ULONG VolumeLabelLength;
            ULONG RequiredLength;

            if (Length < sizeof (FILE_FS_VOLUME_INFORMATION))
            {
               Status = STATUS_INFO_LENGTH_MISMATCH;
               __leave;
            }
#ifdef TRACE
            DbgPrint
               ("Ext2FsdQueryVolumeInformation : FileFsVolumeInformation\n");
#endif

            Buffer = (PFILE_FS_VOLUME_INFORMATION) SystemBuffer;

            Buffer->VolumeCreationTime.QuadPart = 0;
            Buffer->VolumeSerialNumber = 0xAFFE;        //It's a joke!

            VolumeLabelLength = 4 + 1;  //Ext2 doesn't have a volume label, so we take 'ext2'
            Buffer->VolumeLabelLength = VolumeLabelLength * 2;

            // I don't know what this means.
            Buffer->SupportsObjects = FALSE;

            RequiredLength =
               sizeof (FILE_FS_VOLUME_INFORMATION) + VolumeLabelLength * 2 -
               sizeof (WCHAR);

            if (Length < RequiredLength)
            {
               DbgPrint ("Ext2FsdQueryVolumeInformation[1] : L=%i RL=%i\n",
                         Length, RequiredLength);
               Irp->IoStatus.Information = sizeof (FILE_FS_VOLUME_INFORMATION);
               Status = STATUS_BUFFER_OVERFLOW;
               __leave;
            }

            FsdCharToWchar (Buffer->VolumeLabel, "ext2", VolumeLabelLength);

            Irp->IoStatus.Information = RequiredLength;
            Status = STATUS_SUCCESS;
            __leave;
         }

      case FileFsSizeInformation:
         {
            PFILE_FS_SIZE_INFORMATION Buffer;

#ifdef TRACE
            DbgPrint
               ("Ext2FsdQueryVolumeInformation : FileFsSizeInformation\n");
#endif

            if (Length < sizeof (FILE_FS_SIZE_INFORMATION))
            {
               Status = STATUS_INFO_LENGTH_MISMATCH;
               __leave;
            }

            Buffer = (PFILE_FS_SIZE_INFORMATION) SystemBuffer;

            // On a readonly filesystem total size is the size of the
            // contents and available size is zero

            Buffer->TotalAllocationUnits.QuadPart = 0;  //Vcb->ext2->superblock.s_blocks_count;
            Buffer->AvailableAllocationUnits.QuadPart = 0;      //Vcb->ext2->block_size;

            Buffer->SectorsPerAllocationUnit =
               Vcb->ext2->block_size / Vcb->DiskGeometry.BytesPerSector;

            Buffer->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;

            Irp->IoStatus.Information = sizeof (FILE_FS_SIZE_INFORMATION);
            Status = STATUS_SUCCESS;
            __leave;
         }

      case FileFsDeviceInformation:
         {
            PFILE_FS_DEVICE_INFORMATION Buffer;

#ifdef TRACE
            DbgPrint
               ("Ext2FsdQueryVolumeInformation : FileFsDeviceInformation\n");
#endif

            if (Length < sizeof (FILE_FS_DEVICE_INFORMATION))
            {
               Status = STATUS_INFO_LENGTH_MISMATCH;
               __leave;
            }

            Buffer = (PFILE_FS_DEVICE_INFORMATION) SystemBuffer;

            Buffer->DeviceType = Vcb->TargetDeviceObject->DeviceType;

            Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;


            SetFlag (Buffer->Characteristics, FILE_READ_ONLY_DEVICE);

            Irp->IoStatus.Information = sizeof (FILE_FS_DEVICE_INFORMATION);
            Status = STATUS_SUCCESS;
            __leave;
         }

      case FileFsAttributeInformation:
         {
            PFILE_FS_ATTRIBUTE_INFORMATION Buffer;
            ULONG RequiredLength;

#ifdef TRACE
            DbgPrint
               ("Ext2FsdQueryVolumeInformation : FileFsAttributeInformation\n");
#endif

            if (Length < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
            {
               Status = STATUS_INFO_LENGTH_MISMATCH;
               __leave;
            }

            Buffer = (PFILE_FS_ATTRIBUTE_INFORMATION) SystemBuffer;

            Buffer->FileSystemAttributes =
               FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
               FILE_READ_ONLY_VOLUME;

            Buffer->MaximumComponentNameLength = EXT2_NAME_LEN;

            RequiredLength =
               sizeof (FILE_FS_ATTRIBUTE_INFORMATION) +
               sizeof (DRIVER_NAME) * 2 - sizeof (WCHAR);

            if (Length < RequiredLength)
            {
               Buffer->FileSystemNameLength = 0;
               Irp->IoStatus.Information =
                  sizeof (FILE_FS_ATTRIBUTE_INFORMATION);
               DbgPrint ("Ext2FsdQueryVolumeInformation[1] : L=%i RL=%i\n",
                         Length, RequiredLength);
               //Status = STATUS_BUFFER_OVERFLOW;
               //__leave;
            }
            else
            {
               Buffer->FileSystemNameLength = sizeof (DRIVER_NAME) * 2;
               FsdCharToWchar (Buffer->FileSystemName, DRIVER_NAME,
                               sizeof (DRIVER_NAME));

               Irp->IoStatus.Information = RequiredLength;
            }

            Status = STATUS_SUCCESS;
            __leave;
         }

      case FileFsFullSizeInformation:
         {
            PFILE_FS_FULL_SIZE_INFORMATION Buffer;

#ifdef TRACE
            DbgPrint
               ("Ext2FsdQueryVolumeInformation : FileFsFullSizeInformation\n");
#endif

            if (Length < sizeof (FILE_FS_FULL_SIZE_INFORMATION))
            {
               Status = STATUS_INFO_LENGTH_MISMATCH;
               __leave;
            }

            Buffer = (PFILE_FS_FULL_SIZE_INFORMATION) SystemBuffer;

            // On a readonly filesystem total size is the size of the
            // contents and available size is zero

            Buffer->TotalAllocationUnits.QuadPart = 0;  //Vcb->ext2->superblock.s_blocks_count;

            Buffer->CallerAvailableAllocationUnits.QuadPart = 0;
            Buffer->ActualAvailableAllocationUnits.QuadPart = 0;

            Buffer->SectorsPerAllocationUnit =
               Vcb->ext2->block_size / Vcb->DiskGeometry.BytesPerSector;

            Buffer->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;

            Irp->IoStatus.Information = sizeof (FILE_FS_FULL_SIZE_INFORMATION);
            Status = STATUS_SUCCESS;
            __leave;
         }
      default:
         Status = STATUS_INVALID_INFO_CLASS;
      }
   }
   __finally
   {
      if (VcbResourceAcquired)
      {
         ExReleaseResourceForThreadLite (&Vcb->MainResource,
                                         ExGetCurrentResourceThread ());
      }

      if (!IrpContext->ExceptionInProgress)
      {
         if (Status == STATUS_PENDING)
         {
            FsdQueueRequest (IrpContext);
         }
         else
         {
            IrpContext->Irp->IoStatus.Status = Status;

            FsdCompleteRequest (IrpContext->Irp,
                                (CCHAR) (NT_SUCCESS (Status) ? IO_DISK_INCREMENT
                                         : IO_NO_INCREMENT));

            Ext2FsdFreeIrpContext (IrpContext);
         }
      }
   }

   return Status;
}
Beispiel #28
0
PFFS_FCB
FFSv2AllocateFcb(
	IN PFFS_VCB           Vcb,
	IN PFFS_MCB           FFSMcb,
	IN PFFSv2_INODE       dinode2)
{
	PFFS_FCB Fcb;

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->LAResource,
			TRUE);

	Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList)));

	ExReleaseResourceForThreadLite(
			&FFSGlobal->LAResource,
			ExGetCurrentResourceThread());

	if (Fcb == NULL)
	{
		Fcb = (PFFS_FCB)ExAllocatePool(NonPagedPool, sizeof(FFS_FCB));

		RtlZeroMemory(Fcb, sizeof(FFS_FCB));

		SetFlag(Fcb->Flags, FCB_FROM_POOL);
	}
	else
	{
		RtlZeroMemory(Fcb, sizeof(FFS_FCB));
	}

	if (!Fcb)
	{
		return NULL;
	}

	Fcb->Identifier.Type = FFSFCB;
	Fcb->Identifier.Size = sizeof(FFS_FCB);

	FsRtlInitializeFileLock(
			&Fcb->FileLockAnchor,
			NULL,
			NULL);

	Fcb->OpenHandleCount = 0;
	Fcb->ReferenceCount = 0;

	Fcb->Vcb = Vcb;

#if DBG    

	Fcb->AnsiFileName.MaximumLength = (USHORT)
		RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1;

	Fcb->AnsiFileName.Buffer = (PUCHAR) 
		ExAllocatePool(PagedPool, Fcb->AnsiFileName.MaximumLength);

	if (!Fcb->AnsiFileName.Buffer)
	{
		goto errorout;
	}

	RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength);

	FFSUnicodeToOEM(&(Fcb->AnsiFileName),
			&(FFSMcb->ShortName));

#endif

	FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL;

	if ((dinode2->di_mode & IFMT) == IFDIR)
	{
		SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
	}

	if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || 
			FFSIsReadOnly(dinode2->di_mode))
	{
		SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
	}

	Fcb->dinode2 = dinode2;

	Fcb->FFSMcb = FFSMcb;
	FFSMcb->FFSFcb = Fcb;

	RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER));

	Fcb->Header.NodeTypeCode = (USHORT)FFSFCB;
	Fcb->Header.NodeByteSize = sizeof(FFS_FCB);
	Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
	Fcb->Header.Resource = &(Fcb->MainResource);
	Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource);

	{
		ULONG Totalblocks = (ULONG)(Fcb->dinode2->di_blocks);
		Fcb->Header.AllocationSize.QuadPart = 
			(((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
	}

	Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode2->di_size);
	Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);

	Fcb->SectionObject.DataSectionObject = NULL;
	Fcb->SectionObject.SharedCacheMap = NULL;
	Fcb->SectionObject.ImageSectionObject = NULL;

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

	InsertTailList(&Vcb->FcbList, &Fcb->Next);

#if DBG

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->CountResource,
			TRUE);

	FFSGlobal->FcbAllocated++;

	ExReleaseResourceForThreadLite(
			&FFSGlobal->CountResource,
			ExGetCurrentResourceThread());
#endif

	return Fcb;

#if DBG
errorout:
#endif

	if (Fcb)
	{

#if DBG
		if (Fcb->AnsiFileName.Buffer)
			ExFreePool(Fcb->AnsiFileName.Buffer);
#endif

		if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
		{
			ExFreePool(Fcb);
		}
		else
		{
			ExAcquireResourceExclusiveLite(
					&FFSGlobal->LAResource,
					TRUE);

			ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);

			ExReleaseResourceForThreadLite(
					&FFSGlobal->LAResource,
					ExGetCurrentResourceThread());
		}

	}

	return NULL;
}
Beispiel #29
0
NTSTATUS
FFSWriteFile(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb  = NULL;
	PFFS_FCB            Fcb  = NULL;
	PFFS_CCB            Ccb =  NULL;
	PFILE_OBJECT        FileObject  = NULL;
	PFILE_OBJECT        CacheObject;

	PDEVICE_OBJECT      DeviceObject  = NULL;

	PIRP                Irp  = NULL;
	PIO_STACK_LOCATION  IoStackLocation  = NULL;

	ULONG               Length;
	ULONG               ReturnedLength = 0;
	LARGE_INTEGER       ByteOffset;

	BOOLEAN             PagingIo;
	BOOLEAN             Nocache;
	BOOLEAN             SynchronousIo;
	BOOLEAN             MainResourceAcquired = FALSE;
	BOOLEAN             PagingIoResourceAcquired = FALSE;

	BOOLEAN             bNeedExtending = FALSE;
	BOOLEAN             bAppendFile = FALSE;

	BOOLEAN             bDeferred = FALSE;

	PUCHAR              Buffer = NULL;

	__try
	{
		ASSERT(IrpContext);

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

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

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

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		ASSERT(Fcb);

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		Length = IoStackLocation->Parameters.Write.Length;
		ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

		PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
		Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
		SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

		FFSPrint((DBG_INFO, "FFSWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
					ByteOffset.QuadPart, Length, PagingIo, Nocache));

		/*
		if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
		{
			Status = STATUS_FILE_DELETED;
			__leave;
		}

		if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
		{
			Status = STATUS_DELETE_PENDING;
			__leave;
		}
		*/

		if (Length == 0)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_SUCCESS;
			__leave;
		}

		if (Nocache &&
				(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
				 Length & (SECTOR_SIZE - 1)))
		{
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
		{
			ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
			Status = STATUS_PENDING;
			__leave;
		}

#if FALSE
		if (!Nocache)
		{
			BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
			BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
			BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

			if (!CcCanIWrite(
						FileObject,
						Length,
						(bWait && bQueue),
						bAgain))
			{
				SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

				CcDeferWrite(FileObject,
						(PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
						IrpContext,
						Irp,
						Length,
						bAgain);

				bDeferred = TRUE;

				FFSBreakPoint();

				Status = STATUS_PENDING;
				__leave;
			}
		}

#endif

		if (IsEndOfFile(ByteOffset))
		{
			bAppendFile = TRUE;
			ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
		}

		if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		//
		//  Do flushing for such cases
		//
		if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) 
		{
			ExAcquireResourceExclusive(&Fcb->MainResource, 
					IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));

			MainResourceAcquired = TRUE;

			ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
			ExReleaseResource(&Fcb->PagingIoResource);

			CcFlushCache(&(Fcb->SectionObject),
					&ByteOffset,
					Length,
					&(Irp->IoStatus));
			ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);

			if (!NT_SUCCESS(Irp->IoStatus.Status)) 
			{
				Status = Irp->IoStatus.Status;
				__leave;
			}

			ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
			ExReleaseResource(&Fcb->PagingIoResource);

			CcPurgeCacheSection(&(Fcb->SectionObject),
					(PLARGE_INTEGER)&(ByteOffset),
					Length,
					FALSE);

			ExReleaseResource(&Fcb->MainResource);
			MainResourceAcquired = FALSE;
		}

		if (!PagingIo)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Fcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			MainResourceAcquired = TRUE;
		}
		else
		{
			/*
			ULONG ResShCnt, ResExCnt; 
			ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
			ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);

			FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n",
			Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous));
			*/
			if (!ExAcquireResourceSharedLite(
						&Fcb->PagingIoResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			PagingIoResourceAcquired = TRUE;
		}

		if (!PagingIo)
		{
			if (!FsRtlCheckLockForWriteAccess(
						&Fcb->FileLockAnchor,
						Irp))
			{
				Status = STATUS_FILE_LOCK_CONFLICT;
				__leave;
			}
		}

		if (Nocache)
		{
			if ((ByteOffset.QuadPart + Length) >
					Fcb->Header.AllocationSize.QuadPart)
			{
				if (ByteOffset.QuadPart >= 
						Fcb->Header.AllocationSize.QuadPart)
				{
					Status = STATUS_SUCCESS;
					Irp->IoStatus.Information = 0;
					__leave;
				}
				else
				{
					if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart
								- ByteOffset.QuadPart))
					{
						Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart
								- ByteOffset.QuadPart);
					}
				}
			}
		}

		if (!Nocache)
		{
			if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
			{
				__leave;
			}

			if (FileObject->PrivateCacheMap == NULL)
			{
				CcInitializeCacheMap(
						FileObject,
						(PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
						FALSE,
						&FFSGlobal->CacheManagerCallbacks,
						Fcb);

				CcSetReadAheadGranularity(
						FileObject,
						READ_AHEAD_GRANULARITY);

				CcSetFileSizes(
						FileObject, 
						(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
			}

			CacheObject = FileObject;

			//
			//  Need extending the size of inode ?
			//
			if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) >
						(ULONG)(Fcb->Header.FileSize.QuadPart)))
			{

				LARGE_INTEGER   ExtendSize;
				LARGE_INTEGER   FileSize;

				bNeedExtending = TRUE;
				FileSize = Fcb->Header.FileSize;
				ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);

				if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
				{
					if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize))
					{
						Status = STATUS_INSUFFICIENT_RESOURCES;
						__leave;
					}
				}

				{
					Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart;
					Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart;
				}

				if (FileObject->PrivateCacheMap)
				{
					CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));

					if (ByteOffset.QuadPart > FileSize.QuadPart)
					{
						FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, 
								ByteOffset.QuadPart - FileSize.QuadPart);
					}

					if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart)
					{
						FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, 
								Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart);
					}
				}

				if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1))
				{
					Status = STATUS_SUCCESS;
				}

				FFSNotifyReportChange(
						IrpContext,
						Vcb,
						Fcb,
						FILE_NOTIFY_CHANGE_SIZE,
						FILE_ACTION_MODIFIED);
			}

			if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
			{
				CcPrepareMdlWrite(
						CacheObject,
						(&ByteOffset),
						Length,
						&Irp->MdlAddress,
						&Irp->IoStatus);

				Status = Irp->IoStatus.Status;
			}
			else
			{
				Buffer = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)
				{
					FFSBreakPoint();
					Status = STATUS_INVALID_USER_BUFFER;
					__leave;
				}

				if (!CcCopyWrite(
							CacheObject,
							(PLARGE_INTEGER)&ByteOffset,
							Length,
							IrpContext->IsSynchronous,
							Buffer))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				Status = Irp->IoStatus.Status;
			}

			if (NT_SUCCESS(Status))
			{
				Irp->IoStatus.Information = Length;

				if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
				{
					FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n"));
					FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject);
				}
			}
		}
		else
		{
			ReturnedLength = Length;

			Status = FFSLockUserBuffer(
					IrpContext->Irp,
					Length,
					IoReadAccess);

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

			Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = Length;

			Status = 
				FFSv1WriteInode(
						IrpContext,
						Vcb,
						Fcb->dinode1,
						(ULONGLONG)(ByteOffset.QuadPart),
						NULL,
						Length,
						TRUE,
						&ReturnedLength);

			Irp = IrpContext->Irp;

		}
	}

	__finally
	{
		if (PagingIoResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->PagingIoResource,
					ExGetCurrentResourceThread());
		}

		if (MainResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Irp)
			{
				if (Status == STATUS_PENDING)
				{
					if (!bDeferred)
					{
						Status = FFSLockUserBuffer(
									IrpContext->Irp,
									Length,
									IoReadAccess);

						if (NT_SUCCESS(Status))
						{
							Status = FFSQueueRequest(IrpContext);
						}
						else
						{
							FFSCompleteIrpContext(IrpContext, Status);
						}
					}
				}
				else
				{
					if (NT_SUCCESS(Status))
					{
						if (SynchronousIo && !PagingIo)
						{
							FileObject->CurrentByteOffset.QuadPart =
								ByteOffset.QuadPart + Irp->IoStatus.Information;
						}

						if (!PagingIo)
						{
							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
							SetFlag(Fcb->Flags, FCB_FILE_MODIFIED);
						}
					}

					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				FFSFreeIrpContext(IrpContext);
			}
		}
	}

	return Status;

}
Beispiel #30
0
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdPnpQueryRemove (
    PRFSD_IRP_CONTEXT IrpContext,
    PRFSD_VCB         Vcb
    )

{
    NTSTATUS Status;
    KEVENT   Event;
    BOOLEAN  bDeleted = FALSE;
    BOOLEAN  VcbAcquired = FALSE;

    PAGED_CODE();

    _SEH2_TRY {

        RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove by RfsdPnp ...\n"));

        RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdFlushVolume ...\n"));

#if (_WIN32_WINNT >= 0x0500)
        CcWaitForCurrentLazyWriterActivity();
#endif

        ExAcquireResourceExclusiveLite(
            &Vcb->MainResource, TRUE );
        VcbAcquired = TRUE;

        RfsdFlushFiles(Vcb, FALSE);

        RfsdFlushVolume(Vcb, FALSE);

        RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdLockVcb: Vcb=%xh FileObject=%xh ...\n",
                            Vcb, IrpContext->FileObject));
        Status = RfsdLockVcb(Vcb, IrpContext->FileObject);

        RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdPurgeVolume ...\n"));
        RfsdPurgeVolume(Vcb, TRUE);

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

        ExReleaseResourceForThreadLite(
            &Vcb->MainResource,
            ExGetCurrentResourceThread() );
        VcbAcquired = FALSE;

        IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);

        KeInitializeEvent( &Event, NotificationEvent, FALSE );
        IoSetCompletionRoutine( IrpContext->Irp,
                                RfsdPnpCompletionRoutine,
                                &Event,
                                TRUE,
                                TRUE,
                                TRUE );

        RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: Call lower level driver...\n"));
        Status = IoCallDriver( Vcb->TargetDeviceObject, 
                                   IrpContext->Irp);

        if (Status == STATUS_PENDING) {

            KeWaitForSingleObject( &Event,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   NULL );

            Status = IrpContext->Irp->IoStatus.Status;
        }

        if (NT_SUCCESS(Status)) {
            RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdCheckDismount ...\n"));
            bDeleted = RfsdCheckDismount(IrpContext, Vcb, TRUE);
            RfsdPrint((DBG_PNP, "RfsdPnpQueryRemove: RfsdFlushVolume bDelted=%xh ...\n", bDeleted));
        }

        ASSERT( !(NT_SUCCESS(Status) && !bDeleted));

    } _SEH2_FINALLY {

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

        RfsdCompleteRequest(
            IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
            IO_DISK_INCREMENT : IO_NO_INCREMENT) );

        IrpContext->Irp = NULL;
    } _SEH2_END;
    
    return Status;
}