Example #1
1
VOID
CmpLockRegistry(
    VOID
)
/*++

Routine Description:

    Lock the registry for shared (read-only) access

Arguments:

    None.

Return Value:

    None, the registry lock will be held for shared access upon return.

--*/
{
#if DBG
    PVOID       Caller;
    PVOID       CallerCaller;
#endif

    KeEnterCriticalRegion();
    ExAcquireResourceShared(&CmpRegistryLock, TRUE);

#if DBG
    RtlGetCallersAddress(&Caller, &CallerCaller);
    CMLOG(CML_FLOW, CMS_LOCKING) {
        KdPrint(("CmpLockRegistry: c, cc: %08lx  %08lx\n", Caller, CallerCaller));
    }
Example #2
0
VOID
NpAcquireSharedCcb (
    IN PNONPAGED_CCB NonpagedCcb
    )

/*++

Routine Description:

    This routine acquires shared access to the Ccb by first getting
    shared access to the Fcb.

Arguments:

    NonpagedCcb - Supplies the Ccb to acquire

Return Value:

    None.

--*/

{
    PAGED_CODE();

    DebugTrace(+1, Dbg, "NpAcquireSharedCcb, NonpagedCcb = %08lx\n", NonpagedCcb);

    (VOID)ExAcquireResourceShared( &(NpVcb->Resource), TRUE );

    (VOID)ExAcquireResourceShared( &(NonpagedCcb->Resource), TRUE );

    DebugTrace(-1, Dbg, "NpAcquireSharedCcb -> (VOID)\n", 0);

    return;
}
Example #3
0
VOID
NtfsAcquireSharedGlobal (
    IN PIRP_CONTEXT IrpContext
    )

/*++

Routine Description:

    This routine acquires shared access to the global resource.

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

Arguments:

Return Value:

    None.

--*/

{
    ASSERT_IRP_CONTEXT(IrpContext);

    PAGED_CODE();

    if (!ExAcquireResourceShared( &NtfsData.Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) {

        NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL );
    }

    return;
}
Example #4
0
VOID
NpAcquireSharedVcb (
    )

/*++

Routine Description:

    This routine acquires shared access to the Vcb

Arguments:

Return Value:

    None.

--*/

{
    PAGED_CODE();

    DebugTrace(+1, Dbg, "NpAcquireSharedVcb\n", 0);

    ExAcquireResourceShared( &(NpVcb->Resource), TRUE );

    DebugTrace(-1, Dbg, "NpAcquireSharedVcb -> (VOID)\n", 0);

    return;
}
Example #5
0
BOOLEAN
NtfsAcquireSharedVcb (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN BOOLEAN RaiseOnCantWait
    )

/*++

Routine Description:

    This routine acquires shared access to the Vcb.

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

Arguments:

    Vcb - Supplies the Vcb to acquire

    RaiseOnCantWait - Indicates if we should raise on an acquisition error
        or simply return a BOOLEAN indicating that we couldn't get the
        resource.

Return Value:

    None.

--*/

{
    ASSERT_IRP_CONTEXT(IrpContext);
    ASSERT_VCB(Vcb);

    PAGED_CODE();

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

        return TRUE;
    }

    if (RaiseOnCantWait) {

        NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL );

    } else {

        return FALSE;
    }
}
Example #6
0
NTSTATUS
NtfsAcquireFileForCcFlush (
    IN PFILE_OBJECT FileObject,
    IN PDEVICE_OBJECT DeviceObject
    )
{
    PFSRTL_COMMON_FCB_HEADER Header = FileObject->FsContext;

    PAGED_CODE();

    if (Header->PagingIoResource != NULL) {
        ExAcquireResourceShared( Header->PagingIoResource, TRUE );
    }

    return STATUS_SUCCESS;

    UNREFERENCED_PARAMETER( DeviceObject );
}
Example #7
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;
}
Example #8
0
BOOLEAN
FatFastUnlockAllByKey (
    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;
    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

    DebugTrace(+1, Dbg, "FatFastUnlockAllByKey\n", 0);

    IoStatus->Information = 0;

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

    if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) {

        IoStatus->Status = STATUS_INVALID_PARAMETER;

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

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

    FsRtlEnterFileSystem();

    (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE );

    try {

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

        if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {

            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( &Fcb->Specific.Fcb.FileLock,
                                                    FileObject,
                                                    ProcessId,
                                                    Key,
                                                    NULL );

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

        Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );

    try_exit:  NOTHING;
    } finally {

        DebugUnwind( FatFastUnlockAllByKey );

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

        ExReleaseResource( (Fcb)->Header.Resource );

        FsRtlExitFileSystem();

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

    return Results;
}
Example #9
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) {
Example #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;
}
Example #11
0
VOID
NtfsLoadAddOns (
    IN PDRIVER_OBJECT DriverObject,
    IN PVOID Context,
    IN ULONG Count
    )

/*++

Routine Description:

    This routine attempts to load any NTFS add-ons and notify them about
    any previously mounted volumes.

Arguments:

    DriverObject - Driver object for NTFS

    Context - Unused, required by I/O system.

    Count - Unused, required by I/O system.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    UNICODE_STRING UnicodeString;
    ULONG i;
    WCHAR Buffer[80];

    TOP_LEVEL_CONTEXT TopLevelContext;
    PTOP_LEVEL_CONTEXT ThreadTopLevelContext;

    IRP_CONTEXT LocalIrpContext;
    IRP LocalIrp;

    PIRP_CONTEXT IrpContext;

    PLIST_ENTRY Links;
    PVCB Vcb;

    PVCB VcbForTearDown = NULL;
    BOOLEAN AcquiredGlobal = FALSE;

    PAGED_CODE();

    UNREFERENCED_PARAMETER(Context);
    UNREFERENCED_PARAMETER(Count);
    UNREFERENCED_PARAMETER(DriverObject);

    //
    // For each add-on try to load it.
    //

    for (i = 0; NtfsAddonNames[i] != NULL; i++) {

        wcscpy(Buffer, NTFS_SERVICE_KEY);
        wcscat(Buffer, NtfsAddonNames[i]);

        RtlInitUnicodeString( &UnicodeString, Buffer);

        Status = ZwLoadDriver( &UnicodeString );

#if DBG
        DbgPrint("NtfsLoadAddOns: Loaded module %ws. Status = 0x%lx\n", Buffer, Status);
#endif

    }

    RtlZeroMemory( &LocalIrpContext, sizeof(LocalIrpContext) );
    RtlZeroMemory( &LocalIrp, sizeof(LocalIrp) );

    IrpContext = &LocalIrpContext;
    IrpContext->NodeTypeCode = NTFS_NTC_IRP_CONTEXT;
    IrpContext->NodeByteSize = sizeof(IRP_CONTEXT);
    IrpContext->OriginatingIrp = &LocalIrp;
    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    InitializeListHead( &IrpContext->ExclusiveFcbList );

    //
    //  Make sure we don't get any pop-ups
    //

    ThreadTopLevelContext = NtfsSetTopLevelIrp( &TopLevelContext, TRUE, FALSE );
    ASSERT( ThreadTopLevelContext == &TopLevelContext );

    (VOID) ExAcquireResourceShared( &NtfsData.Resource, TRUE );
    AcquiredGlobal = TRUE;

    __try {

        NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );

        __try {

            for (Links = NtfsData.VcbQueue.Flink;
                 Links != &NtfsData.VcbQueue;
                 Links = Links->Flink) {

                Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks);

                IrpContext->Vcb = Vcb;

                if (FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) {

                    Status = CiMountVolume( Vcb, IrpContext);

                    // Bugbug: What should we do if this fails?
                    // BugBug: add call out for views.

                    NtfsCommitCurrentTransaction( IrpContext );

                }
            }

        } __except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {

            NOTHING;
        }

    } __finally {

        if (AcquiredGlobal) {
            ExReleaseResource( &NtfsData.Resource );
        }

        NtfsRestoreTopLevelIrp( ThreadTopLevelContext );
    }

    //
    //  And return to our caller
    //

    return;

}
Example #12
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 );
}
Example #13
0
NTSTATUS
FatPostStackOverflowRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN PFCB Fcb
)

/*++

Routine Description:

    This routine posts a read request that could not be processed by
    the fsp thread because of stack overflow potential.

Arguments:

    Irp - Supplies the request to process.

    Fcb - Supplies the file.

Return Value:

    STATUS_PENDING.

--*/

{
    PKEVENT Event;
    PERESOURCE Resource;

    DebugTrace(0, Dbg, "Getting too close to stack limit pass request to Fsp\n", 0 );

    //
    //  Allocate an event and get shared on the resource we will
    //  be later using the common read.
    //

    Event = FsRtlAllocatePool( NonPagedPool, sizeof(KEVENT) );
    KeInitializeEvent( Event, NotificationEvent, FALSE );

    if (FlagOn(Irp->Flags, IRP_PAGING_IO) && (Fcb->Header.PagingIoResource != NULL)) {

        Resource = Fcb->Header.PagingIoResource;

    } else {

        Resource = Fcb->Header.Resource;
    }

    ExAcquireResourceShared( Resource, TRUE );

    try {

        //
        //  Make the Irp just like a regular post request and
        //  then send the Irp to the special overflow thread.
        //  After the post we will wait for the stack overflow
        //  read routine to set the event that indicates we can
        //  now release the scb resource and return.
        //

        FatPrePostIrp( IrpContext, Irp );

        //
        //  If this read is the result of a verify, we have to
        //  tell the overflow read routne to temporarily
        //  hijack the Vcb->VerifyThread field so that reads
        //  can go through.
        //

        if (Fcb->Vcb->VerifyThread == KeGetCurrentThread()) {

            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ);
        }

        FsRtlPostStackOverflow( IrpContext, Event, FatStackOverflowRead );

        //
        //  And wait for the worker thread to complete the item
        //

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

    }
    finally {

        ExReleaseResource( Resource );

        ExFreePool( Event );
    }

    return STATUS_PENDING;
}
Example #14
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;
}
Example #15
0
VOID
NtfsAcquireSharedScbForTransaction (
    IN PIRP_CONTEXT IrpContext,
    IN PSCB Scb
    )

/*++

Routine Description:

    This routine is called to acquire an Scb shared in order to perform updates to
    the an Scb stream.  This is used if the transaction writes to a range of the
    stream without changing the size or position of the data.  The caller must
    already provide synchronization to the data itself.

    There is no corresponding Scb release.  It will be released when the transaction commits.
    We will acquire the Scb exclusive if it is not yet in the open attribute table.

Arguments:

    Scb - Scb to acquire

Return Value:

    None.

--*/

{
    PSCB *Position;
    PSCB *ScbArray;
    ULONG Count;

    PAGED_CODE();

    //
    //  Make sure we have a free spot in the Scb array in the IrpContext.
    //

    if (IrpContext->SharedScb == NULL) {

        Position = (PSCB *) &IrpContext->SharedScb;
        IrpContext->SharedScbSize = 1;

    //
    //  Too bad the first one is not available.  If the current size is one then allocate a
    //  new block and copy the existing value to it.
    //

    } else if (IrpContext->SharedScbSize == 1) {

        ScbArray = NtfsAllocatePool( PagedPool, sizeof( PSCB ) * 4 );
        RtlZeroMemory( ScbArray, sizeof( PSCB ) * 4 );
        *ScbArray = IrpContext->SharedScb;
        IrpContext->SharedScb = ScbArray;
        IrpContext->SharedScbSize = 4;
        Position = ScbArray + 1;

    //
    //  Otherwise look through the existing array and look for a free spot.  Allocate a larger
    //  array if we need to grow it.
    //

    } else {

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

        do {

            if (*Position == NULL) {

                break;
            }

            Count -= 1;
            Position += 1;

        } while (Count != 0);

        //
        //  If we didn't find one then allocate a new structure.
        //

        if (Count == 0) {

            ScbArray = NtfsAllocatePool( PagedPool, sizeof( PSCB ) * IrpContext->SharedScbSize * 2 );
            RtlZeroMemory( ScbArray, sizeof( PSCB ) * IrpContext->SharedScbSize * 2 );
            RtlCopyMemory( ScbArray,
                           IrpContext->SharedScb,
                           sizeof( PSCB ) * IrpContext->SharedScbSize );

            NtfsFreePool( IrpContext->SharedScb );
            IrpContext->SharedScb = ScbArray;
            Position = ScbArray + IrpContext->SharedScbSize;
            IrpContext->SharedScbSize *= 2;
        }
    }

    ExAcquireResourceShared( Scb->Header.Resource, TRUE );

    if (Scb->NonpagedScb->OpenAttributeTableIndex == 0) {

        ExReleaseResource( Scb->Header.Resource );
        ExAcquireResourceExclusive( Scb->Header.Resource, TRUE );
    }

    *Position = Scb;

    return;
}
Example #16
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);
}
Example #17
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;
}