Beispiel #1
0
VOID
NpReleaseCcb (
    IN PNONPAGED_CCB NonpagedCcb
    )

/*++

Routine Description:

    This routine releases access to the Ccb

Arguments:

    Ccb - Supplies the Ccb being released

Return Value:

    None.

--*/

{
    PAGED_CODE();

    DebugTrace(0, Dbg, "NpReleaseCcb, NonpagedCcb = %08lx\n", NonpagedCcb);

    ExReleaseResource( &(NonpagedCcb->Resource) );
    ExReleaseResource( &(NpVcb->Resource) );

    return;
}
Beispiel #2
0
VOID
NtfsReleaseScbFromLazyWrite (
    IN PVOID OpaqueScb
    )

/*++

Routine Description:

    The address of this routine is specified when creating a CacheMap for
    a file.  It is subsequently called by the Lazy Writer after its
    performing lazy writes to the file.

Arguments:

    Scb - The Scb which was specified as a context parameter for this
          routine.

Return Value:

    None

--*/

{
    ULONG CompressedStream = (ULONG)OpaqueScb & 1;
    PSCB Scb = (PSCB)((ULONG)OpaqueScb & ~1);
    PFCB Fcb = Scb->Fcb;

    ASSERT_SCB(Scb);

    PAGED_CODE();

    //
    //  Clear the toplevel at this point, if we set it above.
    //

    if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) {
        IoSetTopLevelIrp( NULL );
    }

    Scb->LazyWriteThread[CompressedStream] = NULL;

    if (NtfsSegmentNumber( &Fcb->FileReference ) <= MASTER_FILE_TABLE2_NUMBER) {

        NOTHING;

    } else if (Scb->Header.PagingIoResource != NULL) {
        ExReleaseResource( Scb->Header.PagingIoResource );
    } else {
        ExReleaseResource( Scb->Header.Resource );
    }

    return;
}
Beispiel #3
0
static
VOID
NTAPI
AcquireResourceThread(
    PVOID Context)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PTHREAD_DATA ThreadData = Context;
    BOOLEAN Ret;

    KeEnterCriticalRegion();
    Ret = ThreadData->AcquireResource(ThreadData->Res, ThreadData->Wait);
    if (ThreadData->RetExpected)
        ok_bool_true(Ret, "AcquireResource returned");
    else
        ok_bool_false(Ret, "AcquireResource returned");

    ok_bool_false(KeSetEvent(&ThreadData->OutEvent, 0, TRUE), "KeSetEvent returned");
    Status = KeWaitForSingleObject(&ThreadData->InEvent, Executive, KernelMode, FALSE, NULL);
    ok_eq_hex(Status, STATUS_SUCCESS);

    if (Ret)
        ExReleaseResource(ThreadData->Res);
    KeLeaveCriticalRegion();
}
Beispiel #4
0
VOID
NpReleaseVcb (
    )

/*++

Routine Description:

    This routine releases access to the Vcb

Arguments:

Return Value:

    None.

--*/

{
    PAGED_CODE();

    DebugTrace(0, Dbg, "NpReleaseVcb\n", 0);

    ExReleaseResource( &(NpVcb->Resource) );

    return;
}
Beispiel #5
0
VOID
FFSFloppyFlush(
	IN PVOID Parameter)
{
	PFFS_FLPFLUSH_CONTEXT Context;
	PFILE_OBJECT          FileObject;
	PFFS_FCB              Fcb;
	PFFS_VCB              Vcb;

	Context = (PFFS_FLPFLUSH_CONTEXT) Parameter;
	FileObject = Context->FileObject;
	Fcb = Context->Fcb;
	Vcb = Context->Vcb;

	FFSPrint((DBG_USER, "FFSFloppyFlushing ...\n"));

	IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);

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

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

	if (FileObject)
	{
		ASSERT(Fcb == (PFFS_FCB)FileObject->FsContext);

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

		CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);

		ObDereferenceObject(FileObject);
	}

	IoSetTopLevelIrp(NULL);

	ExFreePool(Parameter);
}
Beispiel #6
0
VOID
NtfsReleaseForCreateSection (
    IN PFILE_OBJECT FileObject
    )

{
    PSCB Scb = (PSCB)FileObject->FsContext;

    PAGED_CODE();

    if (Scb->Header.PagingIoResource != NULL) {

        ExReleaseResource( Scb->Header.PagingIoResource );
    }
}
Beispiel #7
0
NTSTATUS
NtfsReleaseFileForCcFlush (
    IN PFILE_OBJECT FileObject,
    IN PDEVICE_OBJECT DeviceObject
    )
{
    PFSRTL_COMMON_FCB_HEADER Header = FileObject->FsContext;

    PAGED_CODE();

    if (Header->PagingIoResource != NULL) {
        ExReleaseResource( Header->PagingIoResource );
    }

    return STATUS_SUCCESS;

    UNREFERENCED_PARAMETER( DeviceObject );
}
Beispiel #8
0
VOID
NtfsReleaseSharedResources (
    IN PIRP_CONTEXT IrpContext
    )

/*++

Routine Description:

    The routine releases all of the resources acquired shared for
    transaction.  The SharedScb structure is freed if necessary and
    the Irp Context field is cleared.

Arguments:


Return Value:

    None.

--*/
{

    PAGED_CODE();

    //
    //  If only one then free the Scb main resource.
    //

    if (IrpContext->SharedScbSize == 1) {

#ifdef _CAIRO_
        if (SafeNodeType(IrpContext->SharedScb) == NTFS_NTC_QUOTA_CONTROL) {
            NtfsReleaseQuotaControl( IrpContext,
                              (PQUOTA_CONTROL_BLOCK) IrpContext->SharedScb );
        } else {
            ExReleaseResource( ((PSCB) IrpContext->SharedScb)->Header.Resource );
        }

#else
        ExReleaseResource( ((PSCB) IrpContext->SharedScb)->Header.Resource );
#endif // _CAIRO_

    //
    //  Otherwise traverse the array and look for Scb's to release.
    //

    } else {

        PSCB *NextScb;
        ULONG Count;

        NextScb = IrpContext->SharedScb;
        Count = IrpContext->SharedScbSize;

        do {

            if (*NextScb != NULL) {

#ifdef _CAIRO_
                if (SafeNodeType(*NextScb) == NTFS_NTC_QUOTA_CONTROL) {

                    NtfsReleaseQuotaControl( IrpContext,
                                      (PQUOTA_CONTROL_BLOCK) *NextScb );
                } else {

                    ExReleaseResource( (*NextScb)->Header.Resource );
                }

#else
                ExReleaseResource( (*NextScb)->Header.Resource );
#endif // _CAIRO_

            }

            Count -= 1;
            NextScb += 1;

        } while (Count != 0);

        NtfsFreePool( IrpContext->SharedScb );
    }

    IrpContext->SharedScb = NULL;
    IrpContext->SharedScbSize = 0;

}
Beispiel #9
0
VOID
DfsDeleteDevices(
    PDFS_TIMER_CONTEXT DfsTimerContext)
{
    PLIST_ENTRY plink;
    PDFS_VCB Vcb;
    PLOGICAL_ROOT_DEVICE_OBJECT DeletedObject;

    if (DfsData.DeletedVcbQueue.Flink != &DfsData.DeletedVcbQueue) {

        DfsDbgTrace(0, Dbg, "Examining Deleted Vcbs...\n", 0);

        ExAcquireResourceExclusive(&DfsData.Resource, TRUE);

        for (plink = DfsData.DeletedVcbQueue.Flink;
                plink != &DfsData.DeletedVcbQueue;
                    NOTHING) {

             Vcb = CONTAINING_RECORD(
                        plink,
                        DFS_VCB,
                        VcbLinks);

             plink = plink->Flink;

             DeletedObject = CONTAINING_RECORD(
                                Vcb,
                                LOGICAL_ROOT_DEVICE_OBJECT,
                                Vcb);

             if (Vcb->OpenFileCount == 0 &&
                    Vcb->DirectAccessOpenCount == 0 &&
                        DeletedObject->DeviceObject.ReferenceCount == 0) {

                 DfsDbgTrace(0, Dbg, "Deleting Vcb@%08lx\n", Vcb);

                 if (Vcb->LogRootPrefix.Buffer != NULL)
                     ExFreePool(Vcb->LogRootPrefix.Buffer);

                 if (Vcb->LogicalRoot.Buffer != NULL)
                     ExFreePool(Vcb->LogicalRoot.Buffer);

                 RemoveEntryList(&Vcb->VcbLinks);

                 ObDereferenceObject((PVOID) DeletedObject);

                 IoDeleteDevice( &DeletedObject->DeviceObject );

             } else {

                 DfsDbgTrace(0, Dbg, "Not deleting Vcb@%08lx\n", Vcb);

                 DfsDbgTrace(0, Dbg,
                    "OpenFileCount = %d\n", Vcb->OpenFileCount);

                 DfsDbgTrace(0, Dbg,
                    "DirectAccessOpens = %d\n", Vcb->DirectAccessOpenCount);

                 DfsDbgTrace(0, Dbg,
                    "DeviceObject Reference count = %d\n",
                    DeletedObject->DeviceObject.ReferenceCount);

             }

        }

        ExReleaseResource(&DfsData.Resource);

    }

    DfsTimerContext->InUse = FALSE;

}
Beispiel #10
0
BOOLEAN
UdfFastQueryNetworkInfo (
    IN PFILE_OBJECT FileObject,
    IN BOOLEAN Wait,
    OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
    OUT PIO_STATUS_BLOCK IoStatus,
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This routine is for the fast query call for network file information.

Arguments:

    FileObject - Supplies the file object used in this operation

    Wait - Indicates if we are allowed to wait for the information

    Buffer - Supplies the output buffer to receive the basic information

    IoStatus - Receives the final status of the operation

Return Value:

    BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
        needs to take the long route.

--*/

{
    BOOLEAN Result = FALSE;
    TYPE_OF_OPEN TypeOfOpen;

    PFCB Fcb;
    PCCB Ccb;

    PAGED_CODE();

    ASSERT_FILE_OBJECT( FileObject );

    FsRtlEnterFileSystem();

    //
    //  Decode the file object to find the type of open and the data
    //  structures.
    //

    TypeOfOpen = UdfDecodeFileObject( FileObject, &Fcb, &Ccb );

    //
    //  We only support this request on user file or directory objects.
    //

    if (TypeOfOpen != UserFileOpen && TypeOfOpen != UserDirectoryOpen) {

        FsRtlExitFileSystem();
        return FALSE;
    }

    //
    //  Acquire the file shared to access the Fcb.
    //

    if (!ExAcquireResourceShared( Fcb->Resource, Wait )) {

        FsRtlExitFileSystem();
        return FALSE;
    }

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Only deal with 'good' Fcb's.
        //

        if (UdfVerifyFcbOperation( NULL, Fcb )) {

            //
            //  Fill in the input buffer from the Fcb fields.
            //

            Buffer->CreationTime = Fcb->Timestamps.CreationTime;
            Buffer->LastWriteTime =
            Buffer->ChangeTime =  Fcb->Timestamps.ModificationTime;
            Buffer->LastAccessTime = Fcb->Timestamps.AccessTime;

            Buffer->FileAttributes = Fcb->FileAttributes | UdfGetExtraFileAttributes( Ccb );

            //
            //  Check whether this is a directory.
            //

            if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {

                Buffer->AllocationSize.QuadPart =
                Buffer->EndOfFile.QuadPart = 0;

            } else {

                Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
                Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
            }

            //
            //  Update the IoStatus block with the size of this data.
            //

            IoStatus->Status = STATUS_SUCCESS;
            IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION );

            Result = TRUE;
        }

    } finally {

        ExReleaseResource( Fcb->Resource );

        FsRtlExitFileSystem();
    }

    return Result;
}
Beispiel #11
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 #12
0
BOOLEAN
NtfsFastUnlockAllByKey (
    IN PFILE_OBJECT FileObject,
    PVOID ProcessId,
    ULONG Key,
    OUT PIO_STATUS_BLOCK IoStatus,
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This is a call back routine for doing the fast unlock all by key call.

Arguments:

    FileObject - Supplies the file object used in this operation

    ProcessId - Supplies the process ID used in this operation

    Key - Supplies the key used in this operation

    Status - Receives the Status if this operation is successful

Return Value:

    BOOLEAN - TRUE if this operation completed and FALSE if caller
        needs to take the long route.

--*/

{
    BOOLEAN Results;
    IRP_CONTEXT IrpContext;
    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    UNREFERENCED_PARAMETER( DeviceObject );

    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsFastUnlockAllByKey\n") );

    IoStatus->Information = 0;

    //
    //  Decode the type of file object we're being asked to process and
    //  make sure that is is only a user file open.
    //

    TypeOfOpen = NtfsDecodeFileObject( &IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, FALSE );

    if (TypeOfOpen != UserFileOpen) {

        IoStatus->Status = STATUS_INVALID_PARAMETER;
        IoStatus->Information = 0;

        DebugTrace( -1, Dbg, ("NtfsFastUnlockAllByKey -> TRUE (STATUS_INVALID_PARAMETER)\n") );
        return TRUE;
    }

    //
    //  Acquire exclusive access to the Fcb this operation can always wait
    //

    FsRtlEnterFileSystem();

    if (Scb->ScbType.Data.FileLock == NULL) {

        (VOID) ExAcquireResourceExclusive( Fcb->Resource, TRUE );

    } else {

        (VOID) ExAcquireResourceShared( Fcb->Resource, TRUE );
    }

    try {

        //
        //  We check whether we can proceed based on the state of the file oplocks.
        //

        if (!FsRtlOplockIsFastIoPossible( &Scb->ScbType.Data.Oplock )) {

            try_return( Results = FALSE );
        }

        //
        //  If we don't have a file lock, then get one now.
        //

        if (Scb->ScbType.Data.FileLock == NULL
            && !NtfsCreateFileLock( Scb, FALSE )) {

            try_return( Results = FALSE );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request.  The call will always succeed.
        //

        Results = TRUE;
        IoStatus->Status = FsRtlFastUnlockAllByKey( Scb->ScbType.Data.FileLock,
                                                    FileObject,
                                                    ProcessId,
                                                    Key,
                                                    NULL );

        //
        //  Set the flag indicating if Fast I/O is possible
        //

        NtfsAcquireFsrtlHeader( Scb );
        Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
        NtfsReleaseFsrtlHeader( Scb );

    try_exit:  NOTHING;
    } finally {

        DebugUnwind( NtfsFastUnlockAllByKey );

        //
        //  Release the Fcb, and return to our caller
        //

        ExReleaseResource( Fcb->Resource );

        FsRtlExitFileSystem();

        DebugTrace( -1, Dbg, ("NtfsFastUnlockAllByKey -> %08lx\n", Results) );
    }

    return Results;
}
Beispiel #13
0
NTSTATUS
NtAllocateUuids (
    OUT PULARGE_INTEGER Time,
    OUT PULONG Range,
    OUT PULONG Sequence
    )

/*++

Routine Description:

    This function reserves a range of time for the caller(s) to use for 
    handing out Uuids.  As far a possible the same range of time and 
    sequence number will never be given out.  

    (It's possible to reboot 2^14-1 times and set the clock backwards and then 
    call this allocator and get a duplicate.  Since only the low 14bits of the 
    sequence number are used in a real uuid.) 

Arguments:

    Time - Supplies the address of a variable that will receive the
        start time (SYSTEMTIME format) of the range of time reserved.

    Range - Supplies the address of a variable that will receive the
        number of ticks (100ns) reserved after the value in Time.
        The range reserved is *Time to (*Time + *Range - 1).

    Sequence - Supplies the address of a variable that will receive
        the time sequence number.  This value is used with the associated
        range of time to prevent problems with clocks going backwards.

Return Value:

    STATUS_SUCCESS is returned if the service is successfully executed.

    STATUS_RETRY is returned if we're unable to reserve a range of
        UUIDs.  This may (?) occur if system clock hasn't advanced
        and the allocator is out of cached values.

    STATUS_ACCESS_VIOLATION is returned if the output parameter for the
        UUID cannot be written.

    STATUS_UNSUCCESSFUL is returned if some other service reports
        an error, most likly the registery.

--*/

{

    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;
    LARGE_INTEGER CurrentTime;
    LARGE_INTEGER AvailableTime;
    LARGE_INTEGER OutputTime;
    ULONG OutputRange;
    ULONG OutputSequence;

    PAGED_CODE();

    //
    // Establish an exception handler and attempt to write the output
    // arguments. If the write attempt fails, then return
    // the exception code as the service status. Otherwise return success
    // as the service status.
    //

    try {

        //
        // Get previous processor mode and probe arguments if necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWrite((PVOID)Time, sizeof(LARGE_INTEGER), sizeof(ULONG));
            ProbeForWrite((PVOID)Range, sizeof(ULONG), sizeof(ULONG));
            ProbeForWrite((PVOID)Sequence, sizeof(ULONG), sizeof(ULONG));
            }
        }
    except (ExSystemExceptionFilter())
        {
        return GetExceptionCode();
        }

    ExAcquireResourceExclusive(&ExpUuidLock, TRUE);

    //
    // Make sure we have a valid sequence number.  If not, make one up.
    //

    if (ExpUuidSequenceNumberValid == FALSE) {
        Status = ExpUuidLoadSequenceNumber(&ExpUuidSequenceNumber);

        if (!NT_SUCCESS(Status)) {
            // Unable read the sequence number, this means we should make one up.

            LARGE_INTEGER PerfCounter;
            LARGE_INTEGER PerfFrequency;

            // This should only happen when NtAllocateUuids() is called
            // for the first time on a given machine. (machine, not boot)

            KdPrint(("Uuid: Generating first sequence number.\n"));

            PerfCounter = KeQueryPerformanceCounter(&PerfFrequency);

            ExpUuidSequenceNumber ^= (ULONG)&Status ^ PerfCounter.LowPart ^
                PerfCounter.HighPart ^ (ULONG)Sequence;
            }
        else {
            // We increment the sequence number on every boot.
            ExpUuidSequenceNumber++;
            }

        ExpUuidSequenceNumberValid = TRUE;
        ExpUuidSequenceNumberNotSaved = TRUE;
        }

    //
    // Get the current time, usually we will have plenty of avaliable
    // to give the caller.  But we may need to deal with time going
    // backwards and really fast machines.
    //

    KeQuerySystemTime(&CurrentTime);

    AvailableTime.QuadPart = CurrentTime.QuadPart - ExpUuidLastTimeAllocated.QuadPart;

    if (AvailableTime.QuadPart < 0) {
            
        // Time has been set time backwards. This means that we must make sure
        // that somebody increments the sequence number and saves the new
        // sequence number in the registry.

        ExpUuidSequenceNumberNotSaved = TRUE;
        ExpUuidSequenceNumber++;

        // The sequence number has been changed, so it's now okay to set time
        // backwards.  Since time is going backwards anyway, it's okay to set
        // it back an extra millisecond or two.

        ExpUuidLastTimeAllocated.QuadPart = CurrentTime.QuadPart - 20000;
        AvailableTime.QuadPart = 20000;
        }

    if (AvailableTime.QuadPart == 0) {
        // System time hasn't moved.  The caller should yield the CPU and retry.
        ExReleaseResource(&ExpUuidLock);
        return(STATUS_RETRY);
        }

    //
    // Common case, time has moved forward.
    //

    if (AvailableTime.QuadPart > 10*1000*1000) {
        // We never want to give out really old (> 1 second) Uuids.
        AvailableTime.QuadPart = 10*1000*1000;
        }

    if (AvailableTime.QuadPart > 10000) {
        // We've got over a millisecond to give out.  We'll save some time for
        // another caller so that we can avoid returning STATUS_RETRY very offen.
        OutputRange = 10000;
        AvailableTime.QuadPart -= 10000;
        }
    else {
        // Not much time avaiable, give it all away.
        OutputRange = (ULONG)AvailableTime.QuadPart;
        AvailableTime.QuadPart = 0;
        }

    OutputTime.QuadPart = CurrentTime.QuadPart - (OutputRange + AvailableTime.QuadPart);

    ExpUuidLastTimeAllocated.QuadPart = OutputTime.QuadPart + OutputRange;

    // Last time allocated is just after the range we hand back to the caller
    // this may be almost a second behind the true system time.

    OutputSequence = ExpUuidSequenceNumber;

    ExReleaseResource(&ExpUuidLock);

    // Saving the sequence number will usually complete without any problems.
    // So we let any other threads go at this point. If the save fails,
    // we'll retry on some future call.

    if (ExpUuidSequenceNumberNotSaved == TRUE) {
        if (ExAcquireResourceExclusive(&ExpSequenceLock, FALSE) == TRUE) {
            if (ExpUuidSequenceNumberNotSaved == TRUE) {

                ExpUuidSequenceNumberNotSaved = FALSE;

                // Print this message just to make sure we aren't hitting the
                // registry too much under normal usage.

                KdPrint(("Uuid: Saving new sequence number.\n"));

                Status = ExpUuidSaveSequenceNumber(ExpUuidSequenceNumber);

                if (!NT_SUCCESS(Status)) {
                    ExpUuidSequenceNumberNotSaved = TRUE;
                    }
                }
            }
        ExReleaseResource(&ExpSequenceLock);
        }

    //
    // Attempt to store the result of this call into the output parameters.
    // This is done within an exception handler in case output parameters
    // are now invalid.
    //

    try {
        Time->QuadPart = OutputTime.QuadPart;
        *Range = OutputRange;
        *Sequence = OutputSequence;
    }
    except (ExSystemExceptionFilter()) {
        return GetExceptionCode();
        }

    return(STATUS_SUCCESS);
}
Beispiel #14
0
BOOLEAN
NtfsAcquireExclusiveFcb (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN PSCB Scb OPTIONAL,
    IN BOOLEAN NoDeleteCheck,
    IN BOOLEAN DontWait
    )

/*++

Routine Description:

    This routine acquires exclusive access to the Fcb.

    This routine will raise if it cannot acquire the resource and wait
    in the IrpContext is false.

Arguments:

    Fcb - Supplies the Fcb to acquire

    Scb - This is the Scb for which we are acquiring the Fcb

    NoDeleteCheck - If TRUE, we don't do any check for deleted files but
        always acquire the Fcb.

    DontWait - If TRUE this overrides the wait value in the IrpContext.
        We won't wait for the resource and return whether the resource
        was acquired.

Return Value:

    BOOLEAN - TRUE if acquired.  FALSE otherwise.

--*/

{
    NTSTATUS Status;
    BOOLEAN Wait;

    ASSERT_IRP_CONTEXT(IrpContext);
    ASSERT_FCB(Fcb);

    PAGED_CODE();

    Status = STATUS_CANT_WAIT;

    if (DontWait ||
        !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {

        Wait = FALSE;

    } else {

        Wait = TRUE;
    }

    if (ExAcquireResourceExclusive( Fcb->Resource, Wait )) {

        //
        //  The link count should be non-zero or the file has been
        //  deleted.  We allow deleted files to be acquired for close and
        //  also allow them to be acquired recursively in case we
        //  acquire them a second time after marking them deleted (i.e. rename)
        //

        if (NoDeleteCheck

            ||

            (IrpContext->MajorFunction == IRP_MJ_CLOSE)

            ||

            (IrpContext->MajorFunction == IRP_MJ_CREATE)

            ||

            (!FlagOn( Fcb->FcbState, FCB_STATE_FILE_DELETED )
             && (!ARGUMENT_PRESENT( Scb )
                 || !FlagOn( Scb->ScbState, SCB_STATE_ATTRIBUTE_DELETED )))) {

            //
            //  Put Fcb in the exclusive Fcb list for this IrpContext,
            //  excluding the bitmap for the volume, since we do not need
            //  to modify its file record and do not want unnecessary
            //  serialization/deadlock problems.
            //

            if ((Fcb->Vcb->BitmapScb == NULL) ||
                (Fcb->Vcb->BitmapScb->Fcb != Fcb)) {

                //
                //  We need to check if this Fcb is already in an
                //  exclusive list.  If it is then we want to attach
                //  the current IrpContext to the IrpContext holding
                //  this Fcb.
                //

                if (Fcb->ExclusiveFcbLinks.Flink == NULL) {

                    ASSERT( Fcb->BaseExclusiveCount == 0 );

                    InsertTailList( &IrpContext->ExclusiveFcbList,
                                    &Fcb->ExclusiveFcbLinks );
                }

                Fcb->BaseExclusiveCount += 1;
            }

            return TRUE;
        }

        //
        //  We need to release the Fcb and remember the status code.
        //

        ExReleaseResource( Fcb->Resource );
        Status = STATUS_FILE_DELETED;

    } else if (DontWait) {

        return FALSE;
    }

    NtfsRaiseStatus( IrpContext, Status, NULL, NULL );
}
Beispiel #15
0
VOID
NtfsReleaseVcbCheckDelete (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN UCHAR MajorCode,
    IN PFILE_OBJECT FileObject OPTIONAL
    )

/*++

Routine Description:

    This routine will release the Vcb.  We will also test here whether we should
    teardown the Vcb at this point.  If this is the last open queued to a dismounted
    volume or the last close from a failed mount or the failed mount then we will
    want to test the Vcb for a teardown.

Arguments:

    Vcb - Supplies the Vcb to acquire

    MajorCode - Indicates what type of operation we were called from.

    FileObject - Optionally supplies the file object whose VPB pointer we need to
        zero out

Return Value:

    None.

--*/

{
    ASSERT_IRP_CONTEXT(IrpContext);
    ASSERT_VCB(Vcb);

    if (FlagOn( Vcb->VcbState, VCB_STATE_PERFORMED_DISMOUNT ) &&
        (Vcb->CloseCount == 0)) {

        ULONG ReferenceCount;
        ULONG ResidualCount;

        KIRQL SavedIrql;
        BOOLEAN DeleteVcb = FALSE;

        ASSERT_EXCLUSIVE_RESOURCE( &Vcb->Resource );

        //
        //  The volume has gone through dismount.  Now we need to decide if this
        //  release of the Vcb is the last reference for this volume.  If so we
        //  can tear the volume down.
        //
        //  We compare the reference count in the Vpb with the state of the volume
        //  and the type of operation.  We also need to check if there is a
        //  referenced log file object.
        //

        IoAcquireVpbSpinLock( &SavedIrql );

        ReferenceCount = Vcb->Vpb->ReferenceCount;

        IoReleaseVpbSpinLock( SavedIrql );

        ResidualCount = 0;

        if (Vcb->LogFileObject != NULL) {

            ResidualCount = 1;
        }

        if (MajorCode == IRP_MJ_CREATE) {

            ResidualCount += 1;
        }

        //
        //  If the residual count is the same as the count in the Vpb then we
        //  can delete the Vpb.
        //

        if (ResidualCount == ReferenceCount) {

            SetFlag( Vcb->VcbState, VCB_STATE_DELETE_UNDERWAY );

            ExReleaseResource( &Vcb->Resource );

            //
            //  Never delete the Vcb unless this is the last release of
            //  this Vcb.
            //

            if (!ExIsResourceAcquiredExclusive( &Vcb->Resource ) &&
                (ExIsResourceAcquiredShared( &Vcb->Resource ) == 0)) {

                if (ARGUMENT_PRESENT(FileObject)) { FileObject->Vpb = NULL; }

                //
                //  If this is a create then the IO system will handle the
                //  Vpb.
                //

                if (MajorCode == IRP_MJ_CREATE) {

                    ClearFlag( Vcb->VcbState, VCB_STATE_TEMP_VPB );
                }

                //
                //  Use the global resource to synchronize the DeleteVcb process.
                //

                (VOID) ExAcquireResourceExclusive( &NtfsData.Resource, TRUE );

                RemoveEntryList( &Vcb->VcbLinks );

                ExReleaseResource( &NtfsData.Resource );

                NtfsDeleteVcb( IrpContext, &Vcb );

            } else {

                ClearFlag( Vcb->VcbState, VCB_STATE_DELETE_UNDERWAY );
            }

        } else {

            ExReleaseResource( &Vcb->Resource );
        }

    } else {

        ExReleaseResource( &Vcb->Resource );
    }
}
Beispiel #16
0
VOID
NtfsReleaseAllFiles (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN BOOLEAN ReleasePagingIo
    )

/*++

Routine Description:

    This routine non-recursively requires all files on a volume.

Arguments:

    Vcb - Supplies the volume

    ReleasePagingIo - Indicates whether we should release the paging io resources
        as well.

Return Value:

    None

--*/

{
    PFCB Fcb;
    PSCB *Scb;
    PVOID RestartKey;

    PAGED_CODE();

    //
    //  Loop to flush all of the prerestart streams, to do the loop
    //  we cycle through the Fcb Table and for each fcb we acquire it.
    //

    RestartKey = NULL;
    while (TRUE) {

        NtfsAcquireFcbTable( IrpContext, Vcb );
        Fcb = NtfsGetNextFcbTableEntry(Vcb, &RestartKey);
        NtfsReleaseFcbTable( IrpContext, Vcb );

        if (Fcb == NULL) {

            break;
        }

        ASSERT_FCB( Fcb );

        if (NtfsSegmentNumber( &Fcb->FileReference ) >= FIRST_USER_FILE_NUMBER) {

            //
            //  Release the file.
            //

            if (ReleasePagingIo && (Fcb->PagingIoResource != NULL)) {

                ExReleaseResource( Fcb->PagingIoResource );
            }

            NtfsReleaseFcb( IrpContext, Fcb );
        }
    }

    //
    //  Now release the Fcb's in the Vcb.
    //

    Scb = &Vcb->QuotaTableScb;

    while (TRUE) {

        if (*Scb != NULL) {

            if (ReleasePagingIo && ((*Scb)->Fcb->PagingIoResource != NULL)) {

                ExReleaseResource( (*Scb)->Fcb->PagingIoResource );
            }

            NtfsReleaseFcb( IrpContext, (*Scb)->Fcb );
        }

        if (Scb == &Vcb->MftScb) {

            break;
        }

        Scb -= 1;
    }

    NtfsReleaseVcb( IrpContext, Vcb );

    return;
}
Beispiel #17
0
VOID
NtfsReleaseScbFromReadAhead (
    IN PVOID OpaqueScb
    )

/*++

Routine Description:

    The address of this routine is specified when creating a CacheMap for
    a file.  It is subsequently called by the Lazy Writer after its
    read ahead.

Arguments:

    Scb - The Scb which was specified as a context parameter for this
          routine.

Return Value:

    None

--*/

{
    PREAD_AHEAD_THREAD ReadAheadThread;
    PVOID CurrentThread;
    KIRQL OldIrql;
    PSCB Scb = (PSCB)OpaqueScb;
    PFCB Fcb = Scb->Fcb;

    ASSERT_SCB(Scb);

    //
    //  Free our read ahead entry.
    //

    KeAcquireSpinLock( &NtfsData.StrucSupSpinLock, &OldIrql );

    CurrentThread = (PVOID)PsGetCurrentThread();
    ReadAheadThread = (PREAD_AHEAD_THREAD)NtfsData.ReadAheadThreads.Flink;

    while ((ReadAheadThread != (PREAD_AHEAD_THREAD)&NtfsData.ReadAheadThreads) &&
           (ReadAheadThread->Thread != CurrentThread)) {

        ReadAheadThread = (PREAD_AHEAD_THREAD)ReadAheadThread->Links.Flink;
    }

    ASSERT(ReadAheadThread != (PREAD_AHEAD_THREAD)&NtfsData.ReadAheadThreads);

    ReadAheadThread->Thread = NULL;

    //
    //  Move him to the end of the list so all the allocated entries are at
    //  the front, and we simplify our scans.
    //

    RemoveEntryList( &ReadAheadThread->Links );
    InsertTailList( &NtfsData.ReadAheadThreads, &ReadAheadThread->Links );

    KeReleaseSpinLock( &NtfsData.StrucSupSpinLock, OldIrql );

    if (Scb->Header.PagingIoResource != NULL) {
        ExReleaseResource( Scb->Header.PagingIoResource );
    }

    return;
}
Beispiel #18
0
BOOLEAN
NtfsAcquireScbForReadAhead (
    IN PVOID OpaqueScb,
    IN BOOLEAN Wait
    )

/*++

Routine Description:

    The address of this routine is specified when creating a CacheMap for
    a file.  It is subsequently called by the Lazy Writer prior to its
    performing read ahead to the file.

Arguments:

    Scb - The Scb which was specified as a context parameter for this
          routine.

    Wait - TRUE if the caller is willing to block.

Return Value:

    FALSE - if Wait was specified as FALSE and blocking would have
            been required.  The Fcb is not acquired.

    TRUE - if the Scb has been acquired

--*/

{
    PREAD_AHEAD_THREAD ReadAheadThread;
    PVOID CurrentThread;
    KIRQL OldIrql;
    PSCB Scb = (PSCB)OpaqueScb;
    PFCB Fcb = Scb->Fcb;
    BOOLEAN AcquiredFile = FALSE;

    ASSERT_SCB(Scb);

    //
    //  Acquire the Scb only for those files that the read wil
    //  acquire it for, i.e., not the first set of system files.
    //  Otherwise we can deadlock, for example with someone needing
    //  a new Mft record.
    //

    if ((Scb->Header.PagingIoResource == NULL) ||
        ExAcquireResourceShared( Scb->Header.PagingIoResource, Wait )) {

        AcquiredFile = TRUE;

        //
        //  Add our thread to the read ahead list.
        //

        KeAcquireSpinLock( &NtfsData.StrucSupSpinLock, &OldIrql );

        CurrentThread = (PVOID)PsGetCurrentThread();
        ReadAheadThread = (PREAD_AHEAD_THREAD)NtfsData.ReadAheadThreads.Flink;

        while ((ReadAheadThread != (PREAD_AHEAD_THREAD)&NtfsData.ReadAheadThreads) &&
               (ReadAheadThread->Thread != NULL)) {

            //
            //  We better not already see ourselves.
            //

            ASSERT( ReadAheadThread->Thread != CurrentThread );

            ReadAheadThread = (PREAD_AHEAD_THREAD)ReadAheadThread->Links.Flink;
        }

        //
        //  If we hit the end of the list, then allocate a new one.  Note we
        //  should have at most one entry per critical worker thread in the
        //  system.
        //

        if (ReadAheadThread == (PREAD_AHEAD_THREAD)&NtfsData.ReadAheadThreads) {

            ReadAheadThread = ExAllocatePoolWithTag( NonPagedPool, sizeof(READ_AHEAD_THREAD), 'RftN' );

            //
            //  If we failed to allocate an entry, clean up and raise.
            //

            if (ReadAheadThread == NULL) {

                KeReleaseSpinLock( &NtfsData.StrucSupSpinLock, OldIrql );

                if (NtfsSegmentNumber( &Fcb->FileReference ) > VOLUME_DASD_NUMBER) {

                    if (Scb->Header.PagingIoResource != NULL) {
                        ExReleaseResource( Scb->Header.PagingIoResource );
                    }
                }

                ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
            }
            InsertTailList( &NtfsData.ReadAheadThreads, &ReadAheadThread->Links );
        }

        ReadAheadThread->Thread = CurrentThread;

        KeReleaseSpinLock( &NtfsData.StrucSupSpinLock, OldIrql );
    }

    return AcquiredFile;
}
Beispiel #19
0
VOID
BowserTrace(
    PCHAR FormatString,
    ...
    )

#define LAST_NAMED_ARGUMENT FormatString

{
    CHAR OutputString[1024];
    IO_STATUS_BLOCK IoStatus;
    BOOLEAN ProcessAttached = FALSE;
    va_list ParmPtr;                    // Pointer to stack parms.
    NTSTATUS Status;

    PAGED_CODE();

    if (IoGetCurrentProcess() != BowserFspProcess) {
        KeAttachProcess(BowserFspProcess);

        ProcessAttached = TRUE;
    }


    if (BrowserTraceLogHandle == NULL) {

        if (!NT_SUCCESS(BowserOpenTraceLogFile(L"\\SystemRoot\\Bowser.Log"))) {

            BrowserTraceLogHandle = (HANDLE)0xffffffff;

            if (ProcessAttached) {
                KeDetachProcess();
            }

            return;
        }

    } else if (BrowserTraceLogHandle == (HANDLE)0xffffffff) {

        if (ProcessAttached) {
            KeDetachProcess();
        }

        return;
    }


    ExAcquireResourceExclusive(&BrowserTraceLock, TRUE);

    if (BrowserTraceLogHandle == NULL) {

        ExReleaseResource(&BrowserTraceLock);

        if (ProcessAttached) {
            KeDetachProcess();
        }

        return;
    }

    try {
        LARGE_INTEGER EndOfFile;

        EndOfFile.HighPart = 0xffffffff;
        EndOfFile.LowPart = FILE_WRITE_TO_END_OF_FILE;

        if (LastCharacter == '\n') {
            LARGE_INTEGER SystemTime;
            TIME_FIELDS TimeFields;

            KeQuerySystemTime(&SystemTime);

            ExSystemTimeToLocalTime(&SystemTime, &SystemTime);

            RtlTimeToTimeFields(&SystemTime, &TimeFields);

            //
            //  The last character written was a newline character.  We should
            //  timestamp this record in the file.
            //
/****
            sprintf(OutputString, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d: ", TimeFields.Month,
                                                            TimeFields.Day,
                                                            TimeFields.Year,
                                                            TimeFields.Hour,
                                                            TimeFields.Minute,
                                                            TimeFields.Second,
                                                            TimeFields.Milliseconds);
****/

            if (!NT_SUCCESS(Status = ZwWriteFile(BrowserTraceLogHandle, NULL, NULL, NULL, &IoStatus, OutputString, strlen(OutputString), &EndOfFile, NULL))) {
                KdPrint(("Error writing time to Browser log file: %lX\n", Status));
                return;
            }

            if (!NT_SUCCESS(IoStatus.Status)) {
                KdPrint(("Error writing time to Browser log file: %lX\n", IoStatus.Status));
                return;
            }

            if (IoStatus.Information != strlen(OutputString)) {
                KdPrint(("Error writing time to Browser log file: %lX\n", IoStatus.Status));
                return;
            }

        }

        va_start(ParmPtr, LAST_NAMED_ARGUMENT);

        //
        //  Format the parameters to the string.
        //

        vsprintf(OutputString, FormatString, ParmPtr);

        if (!NT_SUCCESS(Status = ZwWriteFile(BrowserTraceLogHandle, NULL, NULL, NULL, &IoStatus, OutputString, strlen(OutputString), &EndOfFile, NULL))) {
            KdPrint(("Error writing string to Browser log file: %ld\n", Status));
            return;
        }

        if (!NT_SUCCESS(IoStatus.Status)) {
            KdPrint(("Error writing string to Browser log file: %lX\n", IoStatus.Status));
            return;
        }

        if (IoStatus.Information != strlen(OutputString)) {
            KdPrint(("Error writing string to Browser log file: %ld\n", IoStatus.Status));
            return;
        }

        //
        //  Remember the last character output to the log.
        //

        LastCharacter = OutputString[strlen(OutputString)-1];

    } finally {
        ExReleaseResource(&BrowserTraceLock);

        if (ProcessAttached) {
            KeDetachProcess();
        }
    }
}
Beispiel #20
0
VOID
NtfsAcquireSharedFcb (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN PSCB Scb OPTIONAL,
    IN BOOLEAN NoDeleteCheck
    )

/*++

Routine Description:

    This routine acquires shared access to the Fcb.

    This routine will raise if it cannot acquire the resource and wait
    in the IrpContext is false.

Arguments:

    Fcb - Supplies the Fcb to acquire

    Scb - This is the Scb for which we are acquiring the Fcb

    NoDeleteCheck - If TRUE then acquire the file even if it has been deleted.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    ASSERT_IRP_CONTEXT(IrpContext);
    ASSERT_FCB(Fcb);

    Status = STATUS_CANT_WAIT;

    if (ExAcquireResourceShared( Fcb->Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) {

        //
        //  The link count should be non-zero or the file has been
        //  deleted.
        //

        if (NoDeleteCheck ||
            (!FlagOn( Fcb->FcbState, FCB_STATE_FILE_DELETED ) &&
             (!ARGUMENT_PRESENT( Scb ) ||
              !FlagOn( Scb->ScbState, SCB_STATE_ATTRIBUTE_DELETED )))) {

            //
            //  It's possible that this is a recursive shared aquisition of an
            //  Fcb we own exclusively at the top level.  In that case we
            //  need to bump the acquisition count.
            //

            if (Fcb->ExclusiveFcbLinks.Flink != NULL) {

                Fcb->BaseExclusiveCount += 1;
            }

            return;
        }

        //
        //  We need to release the Fcb and remember the status code.
        //

        ExReleaseResource( Fcb->Resource );
        Status = STATUS_FILE_DELETED;
    }

    NtfsRaiseStatus( IrpContext, Status, NULL, NULL );
}
Beispiel #21
0
NTSTATUS
DfsCommonClose (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
) {
    NTSTATUS Status;

    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    PFILE_OBJECT FileObject = IrpSp->FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PDFS_VCB Vcb;
    PDFS_FCB Fcb;

    BOOLEAN DontComplete = FALSE;
    BOOLEAN pktLocked;

    DfsDbgTrace(+1, Dbg, "DfsCommonClose: Entered\n", 0);

    DfsDbgTrace( 0, Dbg, "Irp          = %08lx\n", Irp);
    DfsDbgTrace( 0, Dbg, "->FileObject = %08lx\n", FileObject);


    //
    //  This action is a noop for unopened file objects.  Nothing needs
    //  to be done for FS device opens, either.
    //

    TypeOfOpen = DfsDecodeFileObject( FileObject, &Vcb, &Fcb);
    if (TypeOfOpen == UnopenedFileObject ||
        TypeOfOpen == FilesystemDeviceOpen ) {

        DfsDbgTrace(-1, Dbg, "DfsCommonClose:  Filesystem file object\n", 0);
        DfsCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
        return STATUS_SUCCESS;
    }

    try {

        //
        //  Case on the type of open that we are trying to close.
        //

        switch (TypeOfOpen) {

        case LogicalRootDeviceOpen:

            DfsDbgTrace(0, Dbg, "DfsCommonClose: Close LogicalRootDevice\n", 0);

            ExInterlockedDecrementLong(&Vcb->DirectAccessOpenCount, &DfsData.DfsLock);
            ExInterlockedDecrementLong(&Vcb->OpenFileCount, &DfsData.DfsLock);

            if (Vcb->VcbState & VCB_STATE_FLAG_LOCKED) {
                ASSERT (Vcb->FileObjectWithVcbLocked == FileObject);
                Vcb->VcbState &= ~VCB_STATE_FLAG_LOCKED;
                Vcb->FileObjectWithVcbLocked = NULL;
            }

            try_return( Status = STATUS_SUCCESS );

        case RedirectedFileOpen:

            DfsDbgTrace(0, Dbg, "DfsCommonClose:  File -> %wZ\n", &Fcb->FullFileName);

            //
            //  Decrement the OpenFileCount for the Vcb through which this
            //  file was opened.
            //

            ExInterlockedDecrementLong(&Vcb->OpenFileCount, &DfsData.DfsLock);

            //
            //  Decrement the RefCount on the DFS_MACHINE_ENTRY through which
            //  this file was opened
            //

            PktAcquireExclusive( TRUE, &pktLocked );

            ExAcquireResourceExclusive( &DfsData.Resource, TRUE );

            DfsDecrementMachEntryCount(Fcb->DfsMachineEntry, TRUE);

            ExReleaseResource( &DfsData.Resource );

            PktRelease();


            //
            //  Close the redirected file by simply passing through
            //  to the redirected device.  We detach the DFS_FCB from the
            //  file object before the close so it cannot be looked
            //  up in some other thread.
            //

            DfsDetachFcb( FileObject, Fcb);
            Status = DfsFilePassThrough(Fcb, Irp);

            DontComplete = TRUE;

            DfsDeleteFcb( IrpContext, Fcb );

            break;

        default:
            BugCheck("Dfs close, unexpected open type");
        }

        Status = STATUS_SUCCESS;

    try_exit: NOTHING;

    } finally {

        //
        //  If this is a normal termination, then complete the request.
        //  Even if we're not to complete the IRP, we still need to
        //  delete the IRP_CONTEXT.
        //

        if (!AbnormalTermination()) {
            if (DontComplete) {
                DfsCompleteRequest( IrpContext, NULL, 0 );
            } else {
                DfsCompleteRequest( IrpContext, Irp, Status );
            }
        }

        DfsDbgTrace(-1, Dbg, "DfsCommonClose:  Exit -> %08lx\n", Status);
    }
    return Status;
}
Beispiel #22
0
NTSTATUS
FFSv1WriteInode(
	IN PFFS_IRP_CONTEXT     IrpContext,
	IN PFFS_VCB             Vcb,
	IN PFFSv1_INODE         dinode1,
	IN ULONGLONG            offset,
	IN PVOID                Buffer,
	IN ULONG                size,
	IN BOOLEAN              bWriteToDisk,
	OUT PULONG              dwRet)
{
	PFFS_BDL    ffs_bdl = NULL;
	ULONG       blocks, i;
	NTSTATUS    Status = STATUS_UNSUCCESSFUL;
	ULONG       Totalblocks;
	LONGLONG    AllocSize;

	if (dwRet)
	{
		*dwRet = 0;
	}

	Totalblocks = (dinode1->di_blocks);
	AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);

	if ((LONGLONG)offset >= AllocSize)
	{
		FFSPrint((DBG_ERROR, "FFSv1WriteInode: beyond the file range.\n"));
		return STATUS_SUCCESS;
	}

	if ((LONGLONG)offset + size > AllocSize)
	{
		size = (ULONG)(AllocSize - offset);
	}

	blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl);

	if (blocks <= 0)
	{
		return STATUS_SUCCESS;
	}

#if DBG
	{
		ULONG   dwTotal = 0;
		FFSPrint((DBG_INFO, "FFSv1WriteInode: BDLCount = %xh Size=%xh Off=%xh\n",
					blocks, size, offset));
		for(i = 0; i < blocks; i++)
		{
			FFSPrint((DBG_INFO, "FFSv1WriteInode: Lba=%I64xh Len=%xh Off=%xh\n",
						ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
			dwTotal += ffs_bdl[i].Length;
		}

		if (dwTotal != size)
		{
			FFSBreakPoint();
		}

		FFSPrint((DBG_INFO, "FFSv1WriteInode: Total = %xh (WriteToDisk=%x)\n",
					dwTotal, bWriteToDisk));
	}
#endif

	if (bWriteToDisk)
	{

#if 0
		for(i = 0; i < blocks; i++)
		{
			{
				CcFlushCache(&(Vcb->SectionObject),
						(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
						ffs_bdl[i].Length,
						NULL);

				if (Vcb->SectionObject.DataSectionObject != NULL)
				{
					ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
					ExReleaseResource(&Vcb->PagingIoResource);

					CcPurgeCacheSection(&(Vcb->SectionObject),
							(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
							ffs_bdl[i].Length,
							FALSE);
				}
			}
		}
#endif

		// assume offset is aligned.
		Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
	}
	else
	{
		for(i = 0; i < blocks; i++)
		{
			if(!FFSSaveBuffer(IrpContext, Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset)))
				goto errorout;
		}

		if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
		{
			FFSPrint((DBG_USER, "FFSv1WriteInode is starting FlushingDpc...\n"));
			FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
		}

		Status = STATUS_SUCCESS;
	}

errorout:

	if (ffs_bdl)
		ExFreePool(ffs_bdl);

	if (NT_SUCCESS(Status))
	{
		if (dwRet) *dwRet = size;
	}

	return Status;
}
Beispiel #23
0
BOOLEAN
NtfsFastUnlockSingle (
    IN PFILE_OBJECT FileObject,
    IN PLARGE_INTEGER FileOffset,
    IN PLARGE_INTEGER Length,
    PEPROCESS ProcessId,
    ULONG Key,
    OUT PIO_STATUS_BLOCK IoStatus,
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This is a call back routine for doing the fast unlock single call.

Arguments:

    FileObject - Supplies the file object used in this operation

    FileOffset - Supplies the file offset used in this operation

    Length - Supplies the length used in this operation

    ProcessId - Supplies the process ID used in this operation

    Key - Supplies the key used in this operation

    Status - Receives the Status if this operation is successful

Return Value:

    BOOLEAN - TRUE if this operation completed and FALSE if caller
        needs to take the long route.

--*/

{
    BOOLEAN Results;
    PFCB Fcb;
    PSCB Scb;
    BOOLEAN ResourceAcquired = FALSE;

    UNREFERENCED_PARAMETER( DeviceObject );

    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsFastUnlockSingle\n") );

    IoStatus->Information = 0;

    //
    //  Decode the type of file object we're being asked to process and
    //  make sure that is is only a user file open.
    //

    if ((Scb = NtfsFastDecodeUserFileOpen( FileObject )) == NULL) {

        IoStatus->Status = STATUS_INVALID_PARAMETER;

        DebugTrace( -1, Dbg, ("NtfsFastUnlockSingle -> TRUE (STATUS_INVALID_PARAMETER)\n") );
        return TRUE;
    }

    Fcb = Scb->Fcb;

    //
    //  Acquire exclusive access to the Fcb this operation can always wait
    //

    FsRtlEnterFileSystem();

    if (Scb->ScbType.Data.FileLock == NULL) {

        (VOID) ExAcquireResourceExclusive( Fcb->Resource, TRUE );
        ResourceAcquired = TRUE;

    } else {

        //(VOID) ExAcquireResourceShared( Fcb->Resource, TRUE );
    }

    try {

        //
        //  We check whether we can proceed based on the state of the file oplocks.
        //

        if ((Scb->ScbType.Data.Oplock != NULL) &&
            !FsRtlOplockIsFastIoPossible( &Scb->ScbType.Data.Oplock )) {

            try_return( Results = FALSE );
        }

        //
        //  If we don't have a file lock, then get one now.
        //

        if (Scb->ScbType.Data.FileLock == NULL
            && !NtfsCreateFileLock( Scb, FALSE )) {

            try_return( Results = FALSE );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request.  The call will always succeed.
        //

        Results = TRUE;
        IoStatus->Status = FsRtlFastUnlockSingle( Scb->ScbType.Data.FileLock,
                                                  FileObject,
                                                  FileOffset,
                                                  Length,
                                                  ProcessId,
                                                  Key,
                                                  NULL,
                                                  FALSE );

        //
        //  Set the flag indicating if Fast I/O is possible.  We are
        //  only concerned if there are no longer any filelocks on this
        //  file.
        //

        if (!FsRtlAreThereCurrentFileLocks( Scb->ScbType.Data.FileLock ) &&
            (Scb->Header.IsFastIoPossible != FastIoIsPossible)) {

            NtfsAcquireFsrtlHeader( Scb );
            Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
            NtfsReleaseFsrtlHeader( Scb );
        }

    try_exit:  NOTHING;
    } finally {

        DebugUnwind( NtfsFastUnlockSingle );

        //
        //  Release the Fcb, and return to our caller
        //

        if (ResourceAcquired) {
            ExReleaseResource( Fcb->Resource );
        }

        FsRtlExitFileSystem();

        DebugTrace( -1, Dbg, ("NtfsFastUnlockSingle -> %08lx\n", Results) );
    }

    return Results;
}
Beispiel #24
0
BOOLEAN
NtfsAcquireScbForLazyWrite (
    IN PVOID OpaqueScb,
    IN BOOLEAN Wait
    )

/*++

Routine Description:

    The address of this routine is specified when creating a CacheMap for
    a file.  It is subsequently called by the Lazy Writer prior to its
    performing lazy writes to the file.  This callback is necessary to
    avoid deadlocks with the Lazy Writer.  (Note that normal writes
    acquire the Fcb, and then call the Cache Manager, who must acquire
    some of his internal structures.  If the Lazy Writer could not call
    this routine first, and were to issue a write after locking Caching
    data structures, then a deadlock could occur.)

Arguments:

    OpaqueScb - The Scb which was specified as a context parameter for this
                routine.

    Wait - TRUE if the caller is willing to block.

Return Value:

    FALSE - if Wait was specified as FALSE and blocking would have
            been required.  The Fcb is not acquired.

    TRUE - if the Scb has been acquired

--*/

{
    BOOLEAN AcquiredFile = TRUE;

    ULONG CompressedStream = (ULONG)OpaqueScb & 1;
    PSCB Scb = (PSCB)((ULONG)OpaqueScb & ~1);
    PFCB Fcb = Scb->Fcb;

    ASSERT_SCB(Scb);

    PAGED_CODE();

    //
    //  Acquire the Scb only for those files that the write will
    //  acquire it for, i.e., not the first set of system files.
    //  Otherwise we can deadlock, for example with someone needing
    //  a new Mft record.
    //

    if (NtfsSegmentNumber( &Fcb->FileReference ) <= MASTER_FILE_TABLE2_NUMBER) {

        //
        //  We need to synchronize the lazy writer with the clean volume
        //  checkpoint.  We do this by acquiring and immediately releasing this
        //  Scb.  This is to prevent the lazy writer from flushing the log file
        //  when the space may be at a premium.
        //

        if (ExAcquireResourceShared( Scb->Header.Resource, Wait )) {

            ExReleaseResource( Scb->Header.Resource );
            AcquiredFile = TRUE;
        }

    //
    //  Now acquire either the main or paging io resource depending on the
    //  state of the file.
    //

    } else if (Scb->Header.PagingIoResource != NULL) {
        AcquiredFile = ExAcquireResourceShared( Scb->Header.PagingIoResource, Wait );
    } else {
        AcquiredFile = ExAcquireResourceShared( Scb->Header.Resource, Wait );
    }

    if (AcquiredFile) {

        //
        // We assume the Lazy Writer only acquires this Scb once.  When he
        // has acquired it, then he has eliminated anyone who would extend
        // valid data, since they must take out the resource exclusive.
        // Therefore, it should be guaranteed that this flag is currently
        // clear (the ASSERT), and then we will set this flag, to insure
        // that the Lazy Writer will never try to advance Valid Data, and
        // also not deadlock by trying to get the Fcb exclusive.
        //

        ASSERT( Scb->LazyWriteThread[CompressedStream] == NULL );

        Scb->LazyWriteThread[CompressedStream] = PsGetCurrentThread();

        //
        //  Make Cc top level, so that we will not post or retry on errors.
        //  (If it is not NULL, it must be one of our internal calls to this
        //  routine, such as from Restart or Hot Fix.)
        //

        if (IoGetTopLevelIrp() == NULL) {
            IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
        }
    }

    return AcquiredFile;
}
Beispiel #25
0
BOOLEAN
PiInitPhase1(
    VOID
    )

/*++

Routine Description:

    This function performs Phase 1 initializaion of the Plug and Play Manager
    component of the NT system. It performs the following tasks:

    (1) performs initialization of value entries under all subkeys of
        HKLM\System\Enum (e.g., resetting 'FoundAtEnum' to FALSE).
    (2) initializes bus enumerator structures for all built-in bus extenders
        provided by the HAL.
    (3) builds up a list of all installed bus extenders.


Arguments:

    None.

Return Value:

    TRUE  - Initialization succeeded.

    FALSE - Initialization failed.

--*/

{
#if _PNP_POWER_
    NTSTATUS Status;
#endif

    PiScratchBuffer = ExAllocatePool(PagedPool, PNP_LARGE_SCRATCH_BUFFER_SIZE);
    if(!PiScratchBuffer) {
        return FALSE;
    }

    //
    // Since we'll be writing to PnP device sections in the registry, acquire
    // the PnP device registry resource for exclusive access. We'll also be
    // initializing the bus enumerator list, so we need exclusive access to
    // the PnP bus enumerator list as well.
    //
    KeEnterCriticalRegion();

#if _PNP_POWER_
    ExAcquireResourceExclusive(&PpBusResource, TRUE);
#endif // _PNP_POWER_

    ExAcquireResourceExclusive(&PpRegistryDeviceResource, TRUE);

    //
    // Initialize all 'FoundAtEnum' value entries in the HKLM\System\Enum tree
    // to FALSE.
    //
    PiInitializeSystemEnum();

#if _PNP_POWER_
    //
    // Initialize our bus enumerator list with all bus instances under the control
    // of the HAL's built-in bus extenders.
    //
    Status = PiRegisterBuiltInBuses();

    if(!NT_SUCCESS(Status)) {
#if DBG
        DbgPrint("PiInitPhase1: Couldn't register built-in buses\n");
#endif
        return FALSE;
    }

    //
    // Enumerate all services in the registry, building up a list of all
    // installed bus extenders.
    //
    Status = IopApplyFunctionToSubKeys(NULL,
                                       &CmRegistryMachineSystemCurrentControlSetServices,
                                       KEY_READ,
                                       TRUE,
                                       PiAddPlugPlayBusEnumeratorToList,
                                       NULL
                                      );
    if(!NT_SUCCESS(Status)) {
#if DBG
        DbgPrint("PiInitPhase1: Couldn't build bus enumerator list\n");
#endif
        return FALSE;
    }
#endif // _PNP_POWER_

    ExReleaseResource(&PpRegistryDeviceResource);

#if _PNP_POWER_
    ExReleaseResource(&PpBusResource);
#endif // _PNP_POWER_

    KeLeaveCriticalRegion();

    ExFreePool(PiScratchBuffer);

    return TRUE;
}
Beispiel #26
0
NTSTATUS
NtSystemDebugControl (
    IN SYSDBG_COMMAND Command,
    IN PVOID InputBuffer,
    IN ULONG InputBufferLength,
    OUT PVOID OutputBuffer,
    IN ULONG OutputBufferLength,
    OUT PULONG ReturnLength OPTIONAL
    )

/*++

Routine Description:

    This function controls the system debugger.

Arguments:

    Command - The command to be executed.  One of the following:

        SysDbgQueryTraceInformation
        SysDbgSetTracepoint
        SysDbgSetSpecialCall
        SysDbgClearSpecialCalls
        SysDbgQuerySpecialCalls

    InputBuffer - A pointer to a buffer describing the input data for
        the request, if any.  The structure of this buffer varies
        depending upon Command.

    InputBufferLength - The length in bytes of InputBuffer.

    OutputBuffer - A pointer to a buffer that is to receive the output
        data for the request, if any.  The structure of this buffer
        varies depending upon Command.

    OutputBufferLength - The length in bytes of OutputBuffer.

    ReturnLength - A optional pointer to a ULONG that is to receive the
        output data length for the request.

Return Value:

    Returns one of the following status codes:

        STATUS_SUCCESS - normal, successful completion.

        STATUS_INVALID_INFO_CLASS - The Command parameter did not
            specify a valid value.

        STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the
            Parameters buffer was not correct.

        STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer
            or a pointer within the Parameters buffer specified an
            invalid address.

        STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
            for this request to complete.

--*/

{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN releaseModuleResoure = FALSE;
    ULONG length = 0;
    KPROCESSOR_MODE PreviousMode;

    PreviousMode = KeGetPreviousMode();

    if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) {
        return STATUS_ACCESS_DENIED;
    }

    //
    // Operate within a try block in order to catch errors.
    //

    try {

        //
        // Probe input and output buffers, if previous mode is not
        // kernel.
        //

        if ( PreviousMode != KernelMode ) {

            if ( InputBufferLength != 0 ) {
                ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) );
            }

            if ( OutputBufferLength != 0 ) {
                ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) );
            }

            if ( ARGUMENT_PRESENT(ReturnLength) ) {
                ProbeForWriteUlong( ReturnLength );
            }
        }

        //
        // Switch on the command code.
        //

        switch ( Command ) {

#ifdef _X86_

        case SysDbgQueryTraceInformation:

            status = KdGetTraceInformation(
                        OutputBuffer,
                        OutputBufferLength,
                        &length
                        );

            break;

        case SysDbgSetTracepoint:

            if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) {
                return STATUS_INFO_LENGTH_MISMATCH;
            }

            KdSetInternalBreakpoint( InputBuffer );

            break;

        case SysDbgSetSpecialCall:

            if ( InputBufferLength != sizeof(PVOID) ) {
                return STATUS_INFO_LENGTH_MISMATCH;
            }

            KdSetSpecialCall( InputBuffer, NULL );

            break;

        case SysDbgClearSpecialCalls:

            KdClearSpecialCalls( );

            break;

        case SysDbgQuerySpecialCalls:

            status = KdQuerySpecialCalls(
                        OutputBuffer,
                        OutputBufferLength,
                        &length
                        );

            break;

#endif

        case SysDbgBreakPoint:
            if (KdDebuggerEnabled) {
                DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL);
            } else {
                status = STATUS_UNSUCCESSFUL;
            }
            break;

        default:

            //
            // Invalid Command.
            //

            status = STATUS_INVALID_INFO_CLASS;
        }

        if ( ARGUMENT_PRESENT(ReturnLength) ) {
            *ReturnLength = length;
        }
    }

    except ( EXCEPTION_EXECUTE_HANDLER ) {

        if ( releaseModuleResoure ) {
            ExReleaseResource( &PsLoadedModuleResource );
            KeLeaveCriticalRegion();
        }

        status = GetExceptionCode();

    }

    return status;

} // NtSystemDebugControl
Beispiel #27
0
NTSTATUS
IopSetDeviceSecurityDescriptors(
    IN PDEVICE_OBJECT           DeviceObject,
    IN PSECURITY_INFORMATION    SecurityInformation,
    IN PSECURITY_DESCRIPTOR     SecurityDescriptor,
    IN POOL_TYPE                PoolType,
    IN PGENERIC_MAPPING         GenericMapping,
    IN BOOLEAN                  DoAttachedDevices
    )
/*++

Routine Description:

    Call this routine to set device security descriptor

Arguments:

    DeviceObject - pointer to base device object (first one to set)
    SecurityInformation )_ passed directly from IopGetSetSecurityObject
    SecurityDescriptor  )
    PoolType            )
    GenericMapping      )
    DoAttachedDevices - if true, iterate the AttachedDevice list

ReturnValue:

    success, or error from first failure

--*/
{
    PDEVICE_OBJECT NewDeviceObject = NULL;
    PSECURITY_DESCRIPTOR OldSecurityDescriptor;
    KIRQL irql;
    NTSTATUS status;
    NTSTATUS firsterr = STATUS_SUCCESS;
    BOOLEAN first = TRUE;

    ASSERT(DeviceObject);

    IopAcquireEnumerationLock(NULL);        // ensure we have acquired P&P locks
    //
    // pre-reference this object to match the dereference later
    //
    ObReferenceObject( DeviceObject );

    do {
        KeEnterCriticalRegion();
        ExAcquireResourceExclusive( &IopSecurityResource, TRUE );

        OldSecurityDescriptor = DeviceObject->SecurityDescriptor;

        if (OldSecurityDescriptor || first) {
            //
            // always call this on the first object, only do it for others that have a security descriptor
            //
            status = SeSetSecurityDescriptorInfo( NULL,
                                                  SecurityInformation,
                                                  SecurityDescriptor,
                                                  &DeviceObject->SecurityDescriptor,
                                                  PoolType,
                                                  GenericMapping );

            if (NT_SUCCESS(firsterr)) {
                firsterr = status;
            }
            if (NT_SUCCESS( status )) {
                ASSERT(OldSecurityDescriptor);
                ExFreePool( OldSecurityDescriptor );
            }
            first = FALSE;
        }

        ExReleaseResource( &IopSecurityResource );
        KeLeaveCriticalRegion();

        //
        // get next device on attachment chain
        //
        ExAcquireSpinLock(&IopDatabaseLock,&irql);
        NewDeviceObject = DeviceObject->AttachedDevice;
        if ( NewDeviceObject != NULL ) {
            ObReferenceObject( NewDeviceObject );
        } else {
            DoAttachedDevices = FALSE;
        }
        ExReleaseSpinLock(&IopDatabaseLock,irql);

        ObDereferenceObject( DeviceObject );
        DeviceObject = NewDeviceObject;

    } while(DoAttachedDevices);

    IopReleaseEnumerationLock(NULL);

    return firsterr;    // of the PDO / single object
}
Beispiel #28
0
NTSTATUS
NtfsAcquireFileForModWrite (
    IN PFILE_OBJECT FileObject,
    IN PLARGE_INTEGER EndingOffset,
    OUT PERESOURCE *ResourceToRelease,
    IN PDEVICE_OBJECT DeviceObject
    )

{
    BOOLEAN AcquiredFile;

    PSCB Scb = (PSCB) (FileObject->FsContext);
    PFCB Fcb = Scb->Fcb;

    ASSERT_SCB(Scb);

    UNREFERENCED_PARAMETER( DeviceObject );

    PAGED_CODE();

    //
    //  Acquire the Scb only for those files that the write will
    //  acquire it for, i.e., not the first set of system files.
    //  Otherwise we can deadlock, for example with someone needing
    //  a new Mft record.
    //

    if (NtfsSegmentNumber( &Fcb->FileReference ) <= MASTER_FILE_TABLE2_NUMBER) {

        //
        //  We need to synchronize the lazy writer with the clean volume
        //  checkpoint.  We do this by acquiring and immediately releasing this
        //  Scb.  This is to prevent the lazy writer from flushing the log file
        //  when the space may be at a premium.
        //

        if (AcquiredFile = ExAcquireResourceShared( Scb->Header.Resource, FALSE )) {
            ExReleaseResource( Scb->Header.Resource );
        }
        *ResourceToRelease = NULL;

    //
    //  Now acquire either the main or paging io resource depending on the
    //  state of the file.
    //

    } else {

        //
        //  Figure out which resource to acquire.
        //

        if (Scb->Header.PagingIoResource != NULL) {
            *ResourceToRelease = Scb->Header.PagingIoResource;
        } else {
            *ResourceToRelease = Scb->Header.Resource;
        }

        //
        //  Try to acquire the resource with Wait FALSE
        //

        AcquiredFile = ExAcquireResourceShared( *ResourceToRelease, FALSE );

        //
        //  If we got the resource, check if he is possibly trying to extend
        //  ValidDataLength.  If so that will cause us to go into useless mode
        //  possibly doing actual I/O writing zeros out to the file past actual
        //  valid data in the cache.  This is so inefficient that it is better
        //  to tell MM not to do this write.
        //

        if (AcquiredFile) {
            if (Scb->CompressionUnit != 0) {
                ExAcquireFastMutex( Scb->Header.FastMutex );
                if ((EndingOffset->QuadPart > Scb->ValidDataToDisk) &&
                    (EndingOffset->QuadPart < (Scb->Header.FileSize.QuadPart + PAGE_SIZE - 1)) &&
                    !FlagOn(Scb->Header.Flags, FSRTL_FLAG_USER_MAPPED_FILE)) {

                    ExReleaseResource(*ResourceToRelease);
                    AcquiredFile = FALSE;
                    *ResourceToRelease = NULL;
                }
                ExReleaseFastMutex( Scb->Header.FastMutex );
            }
        } else {
            *ResourceToRelease = NULL;
        }
    }

    return (AcquiredFile ? STATUS_SUCCESS : STATUS_CANT_WAIT);
}
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
NTSTATUS
IopGetSetSecurityObject(
    IN PVOID Object,
    IN SECURITY_OPERATION_CODE OperationCode,
    IN PSECURITY_INFORMATION SecurityInformation,
    IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
    IN OUT PULONG CapturedLength,
    IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
    IN POOL_TYPE PoolType,
    IN PGENERIC_MAPPING GenericMapping
    )

/*++

Routine Description:

    This routine is invoked to either query or set the security descriptor
    for a file, directory, volume, or device.  It implements these functions
    by either performing an in-line check if the file is a device or a
    volume, or an I/O Request Packet (IRP) is generated and given to the
    driver to perform the operation.

Arguments:

    Object - Pointer to the file or device object representing the open object.

    SecurityInformation - Information about what is being done to or obtained
        from the object's security descriptor.

    SecurityDescriptor - Supplies the base security descriptor and returns
        the final security descriptor.  Note that if this buffer is coming
        from user space, it has already been probed by the object manager
        to length "CapturedLength", otherwise it points to kernel space and
        should not be probed.  It must, however, be referenced in a try
        clause.

    CapturedLength - For a query operation this specifies the size, in
        bytes, of the output security descriptor buffer and on return
        contains the number of bytes needed to store the complete security
        descriptor.  If the length needed is greater than the length
        supplied the operation will fail.  This parameter is ignored for
        the set and delete operations.  It is expected to point into
        system space, ie, it need not be probed and it will not change.

    ObjectsSecurityDescriptor - Supplies and returns the object's security
        descriptor.

    PoolType - Specifies from which type of pool memory is to be allocated.

    GenericMapping - Supplies the generic mapping for the object type.

Return Value:

    The final status of the operation is returned as the function value.

--*/

{
    NTSTATUS status;
    PFILE_OBJECT fileObject;
    PDEVICE_OBJECT deviceObject;
    PDEVICE_OBJECT devicePDO = NULL;
    BOOLEAN synchronousIo;

    UNREFERENCED_PARAMETER( ObjectsSecurityDescriptor );
    UNREFERENCED_PARAMETER( PoolType );

    PAGED_CODE();


    //
    // Begin by determining whether the security operation is to be performed
    // in this routine or by the driver.  This is based upon whether the
    // object represents a device object, or it represents a file object
    // to a device, or a file on the device. If the open is a direct device
    // open then use the device object.
    //

    if (((PDEVICE_OBJECT) (Object))->Type == IO_TYPE_DEVICE) {
        deviceObject = (PDEVICE_OBJECT) Object;
        fileObject = (PFILE_OBJECT) NULL;
    } else {
        fileObject = (PFILE_OBJECT) Object;
        if (fileObject->Flags & FO_DIRECT_DEVICE_OPEN) {
            deviceObject = IoGetAttachedDevice( fileObject->DeviceObject );
        }
        else {
                deviceObject = fileObject->DeviceObject;
        }
    }

    if (!fileObject ||
        (!fileObject->FileName.Length && !fileObject->RelatedFileObject) ||
        (fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {

        //
        // This security operation is for the device itself, either through
        // a file object, or directly to the device object.  For the latter
        // case, assignment operations are also possible.  Also note that
        // this may be a stream file object, which do not have security.
        // The security for a stream file is actually represented by the
        // security descriptor on the file itself, or the volume, or the
        // device.
        //

        if (OperationCode == AssignSecurityDescriptor) {

            //
            // Simply assign the security descriptor to the device object,
            // if this is a device object.
            //

            if (fileObject == NULL || !(fileObject->Flags & FO_STREAM_FILE)) {
                KeEnterCriticalRegion();
                ExAcquireResourceExclusive( &IopSecurityResource, TRUE );
                deviceObject->SecurityDescriptor = SecurityDescriptor;
                ExReleaseResource( &IopSecurityResource );
                KeLeaveCriticalRegion();
            }
            status = STATUS_SUCCESS;

        } else if (OperationCode == SetSecurityDescriptor) {

            //
            // This is a set operation.  The SecurityInformation parameter
            // determines what part of the SecurityDescriptor is going to
            // be applied to the ObjectsSecurityDescriptor.
            //

            //
            // if this deviceObject is attached to a PDO then we want
            // to modify the security on the PDO and apply it up the
            // device chain
            //
            if (fileObject == NULL || !(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
                //
                // see if there is a PDO for this object, and obtain it
                //
                devicePDO = IopGetDevicePDO(deviceObject);
            } else {
                devicePDO = NULL;
            }
            if (devicePDO) {
                //
                // set PDO and all attached device objects
                //
                status = IopSetDeviceSecurityDescriptors(devicePDO,SecurityInformation,SecurityDescriptor,PoolType,GenericMapping,TRUE);
                ObDereferenceObject( devicePDO );
            } else {
                //
                // set this device object only
                //
                status = IopSetDeviceSecurityDescriptors(deviceObject,SecurityInformation,SecurityDescriptor,PoolType,GenericMapping,FALSE);
            }

        } else if (OperationCode == QuerySecurityDescriptor) {

            //
            // This is a get operation.  The SecurityInformation parameter
            // determines what part of the SecurityDescriptor is going to
            // be returned from the ObjectsSecurityDescriptor.
            //

            KeEnterCriticalRegion();
            ExAcquireResourceShared( &IopSecurityResource, TRUE );
            status = SeQuerySecurityDescriptorInfo( SecurityInformation,
                                                    SecurityDescriptor,
                                                    CapturedLength,
                                                    &deviceObject->SecurityDescriptor );
            ExReleaseResource( &IopSecurityResource );
            KeLeaveCriticalRegion();

        } else {

            //
            // This is a delete operation.  Simply indicate that everything
            // worked just fine.
            //

            status = STATUS_SUCCESS;

        }

    } else if (OperationCode == DeleteSecurityDescriptor) {

        //
        // This is a delete operation for the security descriptor on a file
        // object.  This function will be performed by the file system once
        // the FCB itself is deleted.  Simply indicate that the operation
        // was successful.
        //

        status = STATUS_SUCCESS;

    } else {

        PIRP irp;
        IO_STATUS_BLOCK localIoStatus;
        KEVENT event;
        PIO_STACK_LOCATION irpSp;
        KPROCESSOR_MODE requestorMode;

        //
        // This file object does not refer to the device itself.  Rather, it
        // refers to either a file or a directory on the device.  This means
        // that the request must be passed to the file system for processing.
        // Note that the only requests that are passed through in this manner
        // are SET or QUERY security operations.  DELETE operations have
        // already been taken care of above since the file system which just
        // drop the storage on the floor when it really needs to, and ASSIGN
        // operations are irrelevant to file systems since they never
        // generate one because they never assign the security descriptor
        // to the object in the first place, they just assign it to the FCB.
        //

        requestorMode = KeGetPreviousMode();

        //
        // Begin by referencing the object by pointer.   Note that the object
        // handle has already been checked for the appropriate access by the
        // object system caller.  This reference must be performed because
        // standard I/O completion will dereference the object.
        //

        ObReferenceObject( fileObject );

        //
        // Make a special check here to determine whether this is a synchronous
        // I/O operation.  If it is, then wait here until the file is owned by
        // the current thread.  If this is not a (serialized) synchronous I/O
        // operation, then initialize the local event.
        //

        if (fileObject->Flags & FO_SYNCHRONOUS_IO) {

            BOOLEAN interrupted;

            if (!IopAcquireFastLock( fileObject )) {
                status = IopAcquireFileObjectLock( fileObject,
                                                   requestorMode,
                                                   (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
                                                   &interrupted );
                if (interrupted) {
                    ObDereferenceObject( fileObject );
                    return status;
                }
            }
            synchronousIo = TRUE;
        } else {
            KeInitializeEvent( &event, SynchronizationEvent, FALSE );
            synchronousIo = FALSE;
        }

        //
        // Set the file object to the Not-Signaled state.
        //

        KeClearEvent( &fileObject->Event );

        //
        // Get the address of the target device object.
        //

        deviceObject = IoGetRelatedDeviceObject( fileObject );

        //
        // Allocate and initialize the I/O Request Packet (IRP) for this
        // operation.  The allocation is performed with an exception handler
        // in case the caller does not have enough quota to allocate the packet.

        irp = IoAllocateIrp( deviceObject->StackSize, TRUE );
        if (!irp) {

            //
            // An IRP could not be allocated.  Cleanup and return an
            // appropriate error status code.
            //

            IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL );

            return STATUS_INSUFFICIENT_RESOURCES;
        }
        irp->Tail.Overlay.OriginalFileObject = fileObject;
        irp->Tail.Overlay.Thread = PsGetCurrentThread();
        irp->RequestorMode = requestorMode;

        //
        // Fill in the service independent parameters in the IRP.
        //

        if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
            irp->UserEvent = (PKEVENT) NULL;
        } else {
            irp->UserEvent = &event;
            irp->Flags = IRP_SYNCHRONOUS_API;
        }
        irp->UserIosb = &localIoStatus;
        irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;

        //
        // Get a pointer to the stack location for the first driver.  This will
        // be used to pass the original function codes and parameters.
        //

        irpSp = IoGetNextIrpStackLocation( irp );

        //
        // Now determine whether this is a set or a query operation.
        //

        if (OperationCode == QuerySecurityDescriptor) {

            //
            // This is a query operation.  Fill in the appropriate fields in
            // the stack location for the packet, as well as the fixed part
            // of the packet.  Note that each of these parameters has been
            // captured as well, so there is no need to perform any probing.
            // The only exception is the UserBuffer memory may change, but
            // that is the file system's responsibility to check.  Note that
            // it has already been probed, so the pointer is at least not
            // in an address space that the caller should not be accessing
            // because of mode.
            //

            irpSp->MajorFunction = IRP_MJ_QUERY_SECURITY;
            irpSp->Parameters.QuerySecurity.SecurityInformation = *SecurityInformation;
            irpSp->Parameters.QuerySecurity.Length = *CapturedLength;
            irp->UserBuffer = SecurityDescriptor;

        } else {

            //
            // This is a set operation.  Fill in the appropriate fields in
            // the stack location for the packet.  Note that access to the
            // SecurityInformation parameter is safe, as the parameter was
            // captured by the caller.  Likewise, the SecurityDescriptor
            // refers to a captured copy of the descriptor.
            //

            irpSp->MajorFunction = IRP_MJ_SET_SECURITY;
            irpSp->Parameters.SetSecurity.SecurityInformation = *SecurityInformation;
            irpSp->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;

        }

        irpSp->FileObject = fileObject;

        //
        // Insert the packet at the head of the IRP list for the thread.
        //

        IopQueueThreadIrp( irp );

        //
        // Update the operation count statistic for the current process for
        // operations other than read and write.
        //

        IopUpdateOtherOperationCount();

        //
        // Everything has been properly set up, so simply invoke the driver.
        //

        status = IoCallDriver( deviceObject, irp );

        //
        // If this operation was a synchronous I/O operation, check the return
        // status to determine whether or not to wait on the file object.  If
        // the file object is to be waited on, wait for the operation to be
        // completed and obtain the final status from the file object itself.
        //

        if (synchronousIo) {
            if (status == STATUS_PENDING) {
                (VOID) KeWaitForSingleObject( &fileObject->Event,
                                              Executive,
                                              KernelMode,
                                              FALSE,
                                              (PLARGE_INTEGER) NULL );
                status = fileObject->FinalStatus;
            }
            IopReleaseFileObjectLock( fileObject );

        } else {

            //
            // This is a normal synchronous I/O operation, as opposed to a
            // serialized synchronous I/O operation.  For this case, wait
            // for the local event and return the final status information
            // back to the caller.
            //

            if (status == STATUS_PENDING) {
                (VOID) KeWaitForSingleObject( &event,
                                              Executive,
                                              KernelMode,
                                              FALSE,
                                              (PLARGE_INTEGER) NULL );
                status = localIoStatus.Status;
            }
        }

        //
        // If this operation was just attempted on a file system or a device
        // driver of some kind that does not implement security, then return
        // a normal null security descriptor.
        //

        if (status == STATUS_INVALID_DEVICE_REQUEST) {

            //
            // The file system does not implement a security policy.  Determine
            // what type of operation this was and implement the correct
            // semantics for the file system.
            //

            if (OperationCode == QuerySecurityDescriptor) {

                //
                // The operation is a query.  If the caller's buffer is too
                // small, then indicate that this is the case and let him know
                // what size buffer is required.  Otherwise, attempt to return
                // a null security descriptor.
                //

               try {
                    status = SeAssignWorldSecurityDescriptor(
                                 SecurityDescriptor,
                                 CapturedLength,
                                 SecurityInformation
                                 );

                } except( EXCEPTION_EXECUTE_HANDLER ) {

                    //
                    // An exception was incurred while attempting to
                    // access the caller's buffer.  Clean everything
                    // up and return an appropriate status code.
                    //

                    status = GetExceptionCode();
                }

            } else {

                //
                // This was an operation other than a query.  Simply indicate
                // that the operation was successful.
                //

                status = STATUS_SUCCESS;
            }

        } else if (OperationCode == QuerySecurityDescriptor) {