Пример #1
0
PROOT_DCB_CCB
MsCreateRootDcbCcb (
    )

/*++

Routine Description:

    This routine creates a new root DCB CCB record.

Arguments:

Return Value:

    PROOT_DCB_CCB - returns a pointer to the newly allocate ROOT_DCB_CCB

--*/

{
    PROOT_DCB_CCB ccb;

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

    //
    // Allocate a new root DCB CCB record, and zero it out.
    //

    ccb = FsRtlAllocatePool( NonPagedPool, sizeof(ROOT_DCB_CCB) );
    RtlZeroMemory( ccb, sizeof(ROOT_DCB_CCB) );

    //
    // Set the proper node type code, node byte size, and reference count.
    //

    ccb->Header.NodeTypeCode = MSFS_NTC_ROOT_DCB_CCB;
    ccb->Header.NodeByteSize = sizeof(ROOT_DCB_CCB);
    ccb->Header.ReferenceCount = 1;
    ccb->Header.NodeState = NodeStateActive;

    //
    // Return to the caller.
    //

    DebugTrace(-1, Dbg, "MsCreateRootDcbCcb -> %08lx\n", (ULONG)ccb);

    return ccb;
}
Пример #2
0
VOID
LfsFindLogRecord (
    IN PLFCB Lfcb,
    IN OUT PLfsLCB Lcb,
    IN LSN Lsn,
    OUT PLFS_RECORD_TYPE RecordType,
    OUT TRANSACTION_ID *TransactionId,
    OUT PLSN UndoNextLsn,
    OUT PLSN PreviousLsn,
    OUT PULONG BufferLength,
    OUT PVOID *Buffer
    )

/*++

Routine Description:

    This routine is called recover a log record for a client.

Arguments:

    Lfcb - Log file control block for this file.

    Lcb - Pointer to the context block to update.

    Lsn - This is the Lsn for the log record.

    RecordType - Supplies the address to store the record type of this
                 log record.

    TransactionId - Supplies the address to store the transaction Id of
                    this log record.

    UndoNextLsn - Supplies the address to store the Undo Next Lsn for this
                  log record.

    PreviousLsn - Supplies the address to store the Previous Lsn for this
                  log record.

    BufferLength - Pointer to address to store the length in bytes of the
                   log record.

    Buffer - Pointer to store the address where the log record data begins.

Return Value:

    None

--*/

{
    PCHAR NewBuffer;
    BOOLEAN UsaError;
    LONGLONG LogRecordLength;
    ULONG PageOffset;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsFindLogRecord:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Lfcb          -> %08lx\n", Lfcb );
    LfsDebugTrace(  0, Dbg, "Context Block -> %08lx\n", Lcb );
    LfsDebugTrace(  0, Dbg, "Lsn (Low)     -> %08lx\n", Lsn.LowPart );

    NewBuffer = NULL;

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

    try {

        //
        //  Map the record header for this Lsn if we haven't already.
        //

        if (Lcb->RecordHeader == NULL) {

            LfsPinOrMapLogRecordHeader( Lfcb,
                                        Lsn,
                                        FALSE,
                                        FALSE,
                                        &UsaError,
                                        &Lcb->RecordHeader,
                                        &Lcb->RecordHeaderBcb );
        }

        //
        //  We now have the log record desired.  If the Lsn in the
        //  log record doesn't match the desired Lsn then the disk is
        //  corrupt.
        //

        if ( Lsn.QuadPart != Lcb->RecordHeader->ThisLsn.QuadPart ) {                                                   //**** xxNeq( Lsn, Lcb->RecordHeader->ThisLsn )

            ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
        }

        //
        //  Check that the length field isn't greater than the total available space
        //  in the log file.
        //

        LogRecordLength = Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength;                              //**** xxFromUlong( Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength );

        if ( LogRecordLength >= Lfcb->TotalAvailable ) {                                                               //**** xxGeq( LogRecordLength, Lfcb->TotalAvailable )

            ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
        }

        //
        //  If the entire log record is on this log page, put a pointer to
        //  the log record in the context block.
        //

        if (!FlagOn( Lcb->RecordHeader->Flags, LOG_RECORD_MULTI_PAGE )) {

            //
            //  If client size indicates that we have to go beyond the end of the current
            //  page, we raise an error.
            //

            PageOffset = LfsLsnToPageOffset( Lfcb, Lsn );

            if ((PageOffset + Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength)
                > (ULONG)Lfcb->LogPageSize) {

                ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
            }

            Lcb->CurrentLogRecord = LfsAdd2Ptr( Lcb->RecordHeader, LFS_RECORD_HEADER_SIZE, PVOID );
            Lcb->AuxilaryBuffer = FALSE;

        //
        //  Else we copy the data and remember that we allocated a buffer.
        //

        } else {

            NewBuffer = FsRtlAllocatePool( PagedPool, Lcb->RecordHeader->ClientDataLength );

            LfsCopyReadLogRecord( Lfcb,
                                  Lcb->RecordHeader,
                                  NewBuffer );

            Lcb->CurrentLogRecord = NewBuffer;

            Lcb->AuxilaryBuffer = TRUE;

            NewBuffer = NULL;
        }

        //
        //  We need to update the caller's parameters and the context block.
        //

        *RecordType = Lcb->RecordHeader->RecordType;
        *TransactionId = Lcb->RecordHeader->TransactionId;

        *UndoNextLsn = Lcb->RecordHeader->ClientUndoNextLsn;
        *PreviousLsn = Lcb->RecordHeader->ClientPreviousLsn;

        *Buffer = Lcb->CurrentLogRecord;
        *BufferLength = Lcb->RecordHeader->ClientDataLength;

    } finally {

        DebugUnwind( LfsFindLogRecord );

        //
        //  If an error occurred we unpin the record header and the log
        //  We also free the buffer if allocated by us.
        //

        if (NewBuffer != NULL) {

            ExFreePool( NewBuffer );
        }

        LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
        LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", *Buffer );
        LfsDebugTrace( -1, Dbg, "LfsFindLogRecord:  Exit\n", 0 );
    }

    return;
}
Пример #3
0
PFCB
MsCreateFcb (
    IN PVCB Vcb,
    IN PDCB ParentDcb,
    IN PUNICODE_STRING FileName,
    IN PEPROCESS CreatorProcess,
    IN ULONG MailslotQuota,
    IN ULONG MaximumMessageSize
    )

/*++

Routine Description:

    This routine allocates, initializes, and inserts a new Fcb record into
    the in memory data structures.

Arguments:

    Vcb - Supplies the Vcb to associate the new FCB under.

    ParentDcb - Supplies the parent dcb that the new FCB is under.

    FileName - Supplies the file name of the file relative to the directory
        it's in (e.g., the file \config.sys is called "CONFIG.SYS" without
        the preceding backslash).

    CreatorProcess - Supplies a pointer to our creator process

    MailslotQuota - Supplies the initial quota

    MaximumMessageSize - Supplies the size of the largest message that
        can be written to the mailslot

Return Value:

    PFCB - Returns a pointer to the newly allocated FCB

--*/

{
    PFCB fcb;

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

    //
    // Allocate a new FCB record, and zero its fields.
    //

    fcb = FsRtlAllocatePool( NonPagedPool, sizeof(FCB) );
    RtlZeroMemory( fcb, sizeof(FCB) );

    //
    // Set the proper node type code, node byte size, and reference count.
    //

    fcb->Header.NodeTypeCode = MSFS_NTC_FCB;
    fcb->Header.NodeByteSize = sizeof(FCB);
    fcb->Header.ReferenceCount = 1;
    fcb->Header.NodeState = NodeStateActive;

    //
    // Insert this FCB into our parent DCB's queue.
    //

    InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
                    &fcb->ParentDcbLinks );

    //
    // Initialize other FCB fields.
    //

    fcb->ParentDcb = ParentDcb;
    fcb->Vcb = Vcb;

    MsAcquireGlobalLock();
    MsReferenceNode ( &Vcb->Header );
    if (Vcb->Header.ReferenceCount == 2) {
        //
        // Set the driver paging back to normal
        //
        MmResetDriverPaging(MsCreateFcb);
    }
    MsReleaseGlobalLock();

    fcb->CreatorProcess =  CreatorProcess;
    ExInitializeResource( &(fcb->Resource) );

    //
    // Initialize the CCB queue.
    //

    InitializeListHead( &fcb->Specific.Fcb.CcbQueue );

    //
    // Set the file name.
    //

    {
        PWCH Name;
        ULONG Length;

        Length = FileName->Length;

        Name = FsRtlAllocatePool( PagedPool, Length + 2 );

        RtlMoveMemory( Name, FileName->Buffer, Length );
        *(PWCH)( (PCH)Name + Length ) = L'\0';

        RtlInitUnicodeString( &fcb->FullFileName, Name );
        RtlInitUnicodeString( &fcb->LastFileName, &Name[1] );
    }

    //
    // Insert this FCB into the prefix table.
    //

    MsAcquirePrefixTableLock();
    if (!RtlInsertUnicodePrefix( &Vcb->PrefixTable,
                                 &fcb->FullFileName,
                                 &fcb->PrefixTableEntry )) {

        DebugDump("Error trying to name into prefix table\n", 0, fcb);
        KeBugCheck( MAILSLOT_FILE_SYSTEM );
    }
    MsReleasePrefixTableLock();

    //
    // Initialize the data queue.
    //

    MsInitializeDataQueue( &fcb->DataQueue,
                           CreatorProcess,
                           MailslotQuota,
                           MaximumMessageSize);

    //
    // Return to the caller.
    //

    DebugTrace(-1, Dbg, "MsCreateFcb -> %08lx\n", (ULONG)fcb);

    return fcb;
}
Пример #4
0
PCCB
MsCreateCcb (
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine creates a new CCB record.

Arguments:

    Fcb - Supplies a pointer to the FCB to which we are attached.

Return Value:

    PCCB - returns a pointer to the newly allocate CCB.

--*/

{
    PCCB ccb;

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

    ASSERT( Fcb->Header.NodeState == NodeStateActive );

    //
    //  Allocate a new CCB record and zero its fields.
    //

    ccb = FsRtlAllocatePool( NonPagedPool, sizeof(CCB) );
    RtlZeroMemory( ccb, sizeof(CCB) );

    //
    //  Set the proper node type code, node byte size, and reference count.
    //

    ccb->Header.NodeTypeCode = MSFS_NTC_CCB;
    ccb->Header.NodeByteSize = sizeof(CCB);
    ccb->Header.ReferenceCount = 1;
    ccb->Header.NodeState = NodeStateActive;

    //
    // Insert ourselves in the list of ccb for the fcb, and reference
    // the fcb.
    //

    MsAcquireCcbListLock();
    InsertTailList( &Fcb->Specific.Fcb.CcbQueue, &ccb->CcbLinks );
    MsReleaseCcbListLock();

    ccb->Fcb = Fcb;
    MsAcquireGlobalLock();
    MsReferenceNode( &Fcb->Header );
    MsReleaseGlobalLock();

    //
    // Initialize the CCB's resource.
    //

    ExInitializeResource( &ccb->Resource );

    //
    // Return to the caller.
    //

    DebugTrace(-1, Dbg, "MsCreateCcb -> %08lx\n", (ULONG)ccb);

    return ccb;
}
Пример #5
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;
}
Пример #6
0
PROOT_DCB
MsCreateRootDcb (
    IN PVCB Vcb
    )

/*++

Routine Description:

    This routine allocates, initializes, and inserts a new root DCB record
    into the in memory data structure.

Arguments:

    Vcb - Supplies the Vcb to associate the new DCB under

Return Value:

    PROOT_DCB - returns pointer to the newly allocated root DCB.

--*/

{
    PROOT_DCB rootDcb;

    PAGED_CODE();
    DebugTrace(+1, Dbg, "MsCreateRootDcb, Vcb = %08lx\n", (ULONG)Vcb);

    //
    // Make sure we don't already have a root dcb for this vcb
    //

    rootDcb = Vcb->RootDcb;

    if (rootDcb != NULL) {
        DebugDump("Error trying to create multiple root dcbs\n", 0, Vcb);
        KeBugCheck( MAILSLOT_FILE_SYSTEM );
    }

    //
    // Allocate a new DCB and zero its fields.
    //

    rootDcb = FsRtlAllocatePool( NonPagedPool, sizeof(DCB) );
    RtlZeroMemory( rootDcb, sizeof(DCB));

    //
    // Set the proper node type code, node byte size, and reference count.
    //

    rootDcb->Header.NodeTypeCode = MSFS_NTC_ROOT_DCB;
    rootDcb->Header.NodeByteSize = sizeof(ROOT_DCB);
    rootDcb->Header.ReferenceCount = 1;
    rootDcb->Header.NodeState = NodeStateActive;

    //
    // The root Dcb has an empty parent dcb links field
    //

    InitializeListHead( &rootDcb->ParentDcbLinks );

    //
    // Set the Vcb and give it a pointer to the new root DCB.
    //

    rootDcb->Vcb = Vcb;
    Vcb->RootDcb = rootDcb;

    //
    // Initialize the notify queues, and the parent dcb queue.
    //

    InitializeListHead( &rootDcb->Specific.Dcb.NotifyFullQueue );
    InitializeListHead( &rootDcb->Specific.Dcb.NotifyPartialQueue );
    InitializeListHead( &rootDcb->Specific.Dcb.ParentDcbQueue );

    //
    // Set the full file name
    //

    {
        PWCH Name;

        Name = FsRtlAllocatePool(PagedPool, 2 * sizeof(WCHAR));

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

        RtlInitUnicodeString( &rootDcb->FullFileName, Name );
        RtlInitUnicodeString( &rootDcb->LastFileName, Name );
    }

    //
    // Insert this DCB into the prefix table.
    //

    MsAcquirePrefixTableLock();
    if (!RtlInsertUnicodePrefix( &Vcb->PrefixTable,
                                 &rootDcb->FullFileName,
                                 &rootDcb->PrefixTableEntry )) {

        DebugDump("Error trying to insert root dcb into prefix table\n", 0, Vcb);
        KeBugCheck( MAILSLOT_FILE_SYSTEM );
    }

    MsReleasePrefixTableLock();


    //
    // Initialize the resource variable.
    //

    ExInitializeResource( &(rootDcb->Resource) );

    //
    // Return to the caller.
    //

    DebugTrace(-1, Dbg, "MsCreateRootDcb -> %8lx\n", (ULONG)rootDcb);

    return rootDcb;
}
Пример #7
0
NTSTATUS
FatCommonRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
)

/*++

Routine Description:

    This is the common read routine for NtReadFile, called from both
    the Fsd, or from the Fsp if a request could not be completed without
    blocking in the Fsd.  This routine has no code where it determines
    whether it is running in the Fsd or Fsp.  Instead, its actions are
    conditionalized by the Wait input parameter, which determines whether
    it is allowed to block or not.  If a blocking condition is encountered
    with Wait == FALSE, however, the request is posted to the Fsp, who
    always calls with WAIT == TRUE.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    PVCB Vcb;
    PFCB FcbOrDcb;
    PCCB Ccb;

    VBO StartingVbo;
    ULONG ByteCount;
    ULONG RequestedByteCount;

    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;
    TYPE_OF_OPEN TypeOfRead;

    BOOLEAN PostIrp = FALSE;
    BOOLEAN OplockPostIrp = FALSE;

    BOOLEAN FcbOrDcbAcquired = FALSE;

    BOOLEAN Wait;
    BOOLEAN PagingIo;
    BOOLEAN NonCachedIo;
    BOOLEAN SynchronousIo;

    NTSTATUS Status;

    FAT_IO_CONTEXT StackFatIoContext;

    //
    // A system buffer is only used if we have to access the
    // buffer directly from the Fsp to clear a portion or to
    // do a synchronous I/O, or a cached transfer.  It is
    // possible that our caller may have already mapped a
    // system buffer, in which case we must remember this so
    // we do not unmap it on the way out.
    //

    PVOID SystemBuffer = NULL;

    LARGE_INTEGER StartingByte;

    //
    // Get current Irp stack location.
    //

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

    //
    // Initialize the appropriate local variables.
    //

    Wait          = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    PagingIo      = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
    NonCachedIo   = BooleanFlagOn(Irp->Flags,IRP_NOCACHE);
    SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

    DebugTrace(+1, Dbg, "CommonRead\n", 0);
    DebugTrace( 0, Dbg, "  Irp                   = %8lx\n", Irp);
    DebugTrace( 0, Dbg, "  ->ByteCount           = %8lx\n", IrpSp->Parameters.Read.Length);
    DebugTrace( 0, Dbg, "  ->ByteOffset.LowPart  = %8lx\n", IrpSp->Parameters.Read.ByteOffset.LowPart);
    DebugTrace( 0, Dbg, "  ->ByteOffset.HighPart = %8lx\n", IrpSp->Parameters.Read.ByteOffset.HighPart);

    //
    //  Extract starting Vbo and offset.
    //

    StartingByte = IrpSp->Parameters.Read.ByteOffset;

    StartingVbo = StartingByte.LowPart;

    ByteCount = IrpSp->Parameters.Read.Length;
    RequestedByteCount = ByteCount;

    //
    //  Check for a null request, and return immediately
    //

    if (ByteCount == 0) {

        Irp->IoStatus.Information = 0;
        FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
        return STATUS_SUCCESS;
    }

    //
    //  Check for a non-zero high part offset
    //

    if ( StartingByte.HighPart != 0 ) {

        Irp->IoStatus.Information = 0;
        FatCompleteRequest( IrpContext, Irp, STATUS_END_OF_FILE );
        return STATUS_END_OF_FILE;
    }

    //
    // Extract the nature of the read from the file object, and case on it
    //

    TypeOfRead = FatDecodeFileObject(FileObject, &Vcb, &FcbOrDcb, &Ccb);

    //
    // Collect interesting statistics.  The FLAG_USER_IO bit will indicate
    // what type of io we're doing in the FatNonCachedIo function.
    //

    if (PagingIo) {
        CollectReadStats(Vcb, TypeOfRead, ByteCount);

        if (TypeOfRead == UserFileOpen) {
            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
        } else {
            ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
        }
    }

    //
    //  If there is a previous STACK FatIoContext pointer, NULL it.
    //

    if ((IrpContext->FatIoContext != NULL) &&
            FlagOn(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT)) {

        IrpContext->FatIoContext = NULL;
    }

    //
    //  Allocate if necessary and initialize a FAT_IO_CONTEXT block for
    //  all non cached Io, except Cvf file Io.  For synchronous Io
    //  we use stack storage, otherwise we allocate pool.
    //

    if (NonCachedIo &&
            !(FcbOrDcb && FlagOn(FcbOrDcb->FcbState,
                                 FCB_STATE_COMPRESSED_VOLUME_FILE))) {

        if (IrpContext->FatIoContext == NULL) {

            if (!Wait) {

                IrpContext->FatIoContext =
                    FsRtlAllocatePool( NonPagedPool, sizeof(FAT_IO_CONTEXT) );

            } else {

                IrpContext->FatIoContext = &StackFatIoContext;

                SetFlag( IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT );
            }
        }

        RtlZeroMemory( IrpContext->FatIoContext, sizeof(FAT_IO_CONTEXT) );

        if (Wait) {

            KeInitializeEvent( &IrpContext->FatIoContext->Wait.SyncEvent,
                               NotificationEvent,
                               FALSE );

        } else {

            IrpContext->FatIoContext->Wait.Async.ResourceThreadId =
                ExGetCurrentResourceThread();

            IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
                ByteCount;

            IrpContext->FatIoContext->Wait.Async.FileObject = FileObject;
        }
    }

    
    //
    // These two cases correspond to either a general opened volume, ie.
    // open ("a:"), or a read of the volume file (boot sector + fat(s))
    //

    if ((TypeOfRead == VirtualVolumeFile) ||
            (TypeOfRead == UserVolumeOpen)) {

        DebugTrace(0, Dbg, "Type of read is User Volume or virtual volume file\n", 0);

        if (TypeOfRead == UserVolumeOpen) {

            //
            //  Verify that the volume for this handle is still valid
            //

            FatQuickVerifyVcb( IrpContext, Vcb );

            if (!FlagOn( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE )) {

                (VOID)ExAcquireResourceExclusive( &Vcb->Resource, TRUE );

                try {

                    //
                    //  If the volume isn't locked, flush it.
                    //

                    if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED)) {

                        FatFlushVolume( IrpContext, Vcb );
                    }

                }
                finally {

                    ExReleaseResource( &Vcb->Resource );
                }

                SetFlag( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE );
            }
Пример #8
0
VOID
FsRtlpPostStackOverflow (
    IN PVOID Context,
    IN PKEVENT Event,
    IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine,
    IN BOOLEAN PagingFile
)

/*++

Routine Description:

    This routines posts a stack overflow item to the stack overflow
    thread and returns.

Arguments:

    Context - Supplies the context to pass to the stack overflow
        call back routine.  If the low order bit is set, then
        this overflow was a read to a paging file.

    Event - Supplies a pointer to an event to pass to the stack
        overflow call back routine.

    StackOverflowRoutine - Supplies the call back to use when
        processing the request in the overflow thread.

    PagingFile - Indicates if the read is destined to a paging file.

Return Value:

    None.

--*/

{
    PSTACK_OVERFLOW_ITEM StackOverflowItem;

    //
    //  Allocate a stack overflow work item it will later be deallocated by
    //  the stack overflow thread
    //

    StackOverflowItem = FsRtlAllocatePool( PagingFile ?
                                           NonPagedPoolMustSucceed :
                                           NonPagedPool,
                                           sizeof(STACK_OVERFLOW_ITEM) );

    //
    //  Fill in the fields in the new item
    //

    StackOverflowItem->Context              = Context;
    StackOverflowItem->Event                = Event;
    StackOverflowItem->StackOverflowRoutine = StackOverflowRoutine;

    ExInitializeWorkItem( &StackOverflowItem->Item,
                          &FsRtlStackOverflowRead,
                          StackOverflowItem );

    //
    //  Safely add it to the overflow queue
    //

    KeInsertQueue( &FsRtlWorkerQueues[PagingFile],
                   &StackOverflowItem->Item.List );

    //
    //  And return to our caller
    //

    return;
}
Пример #9
0
BOOLEAN
FsRtlInitSystem (
    )
{
    ULONG i;

    ULONG Value;
    UNICODE_STRING ValueName;

    extern KSEMAPHORE FsRtlpUncSemaphore;

    PAGED_CODE();

    //
    //  Allocate and initialize all the paging Io resources
    //

    FsRtlPagingIoResources = FsRtlAllocatePool( NonPagedPool,
                                                FSRTL_NUMBER_OF_RESOURCES *
                                                sizeof(ERESOURCE) );

    for (i=0; i < FSRTL_NUMBER_OF_RESOURCES; i++) {

        ExInitializeResource( &FsRtlPagingIoResources[i] );
    }

    //
    //  Initialize the global tunneling structures.
    //

    FsRtlInitializeTunnels();

    //
    //  Initialize the global filelock structures.
    //

    FsRtlInitializeFileLocks();

    //
    //  Initialize the global largemcb structures.
    //

    FsRtlInitializeLargeMcbs();

    //
    // Initialize the semaphore used to guard loading of the MUP
    //

    KeInitializeSemaphore( &FsRtlpUncSemaphore, 1, MAXLONG );

    //
    // Pull the bit from the registry telling us whether to do a safe
    // or dangerous extension truncation.
    //

    ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
    ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
    ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);

    if (NT_SUCCESS(FsRtlGetCompatibilityModeValue( &ValueName, &Value )) &&
        (Value != 0)) {

        FsRtlSafeExtensions = FALSE;
    }

    //
    // Initialize the FsRtl stack overflow work QueueObject and thread.
    //

    if (!NT_SUCCESS(FsRtlInitializeWorkerThread())) {

        return FALSE;
    }

    return TRUE;
}
Пример #10
0
VOID
NTAPI
FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
               IN PFCB Fcb)
{
    FF_DIRENT DirEnt;
    FF_ERROR Err;
    POEM_STRING ShortName;
    CHAR ShortNameRaw[13];
    UCHAR EntryBuffer[32];
    UCHAR NumLFNs;
    PUNICODE_STRING UnicodeName;
    OEM_STRING LongNameOem;
    NTSTATUS Status;

    /* Get the dir entry */
    Err = FF_GetEntry(Fcb->Vcb->Ioman,
                      Fcb->FatHandle->DirEntry,
                      Fcb->FatHandle->DirCluster,
                      &DirEnt);

    if (Err != FF_ERR_NONE)
    {
        DPRINT1("Error %d getting dirent of a file\n", Err);
        return;
    }

    /* Read the dirent to fetch the raw short name */
    FF_FetchEntry(Fcb->Vcb->Ioman,
                  Fcb->FatHandle->DirCluster,
                  Fcb->FatHandle->DirEntry,
                  EntryBuffer);
    NumLFNs = (UCHAR)(EntryBuffer[0] & ~0x40);
    RtlCopyMemory(ShortNameRaw, EntryBuffer, 11);

    /* Initialize short name string */
    ShortName = &Fcb->ShortName.Name.Ansi;
    ShortName->Buffer = Fcb->ShortNameBuffer;
    ShortName->Length = 0;
    ShortName->MaximumLength = sizeof(Fcb->ShortNameBuffer);

    /* Convert raw short name to a proper string */
    Fati8dot3ToString(ShortNameRaw, FALSE, ShortName);

    /* Add the short name link */
    FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksAnsi, &Fcb->ShortName);
    Fcb->ShortName.Fcb = Fcb;

    /* Get the long file name (if any) */
    if (NumLFNs > 0)
    {
        /* Prepare the oem string */
        LongNameOem.Buffer = DirEnt.FileName;
        LongNameOem.MaximumLength = FF_MAX_FILENAME;
        LongNameOem.Length = strlen(DirEnt.FileName);

        /* Prepare the unicode string */
        UnicodeName = &Fcb->LongName.Name.String;
        UnicodeName->Length = (LongNameOem.Length + 1) * sizeof(WCHAR);
        UnicodeName->MaximumLength = UnicodeName->Length;
        UnicodeName->Buffer = FsRtlAllocatePool(PagedPool, UnicodeName->Length);

        /* Convert it to unicode */
        Status = RtlOemStringToUnicodeString(UnicodeName, &LongNameOem, FALSE);
        if (!NT_SUCCESS(Status))
        {
            ASSERT(FALSE);
        }

        /* Set its length */
        Fcb->FileNameLength = UnicodeName->Length;

        /* Save case-preserved copy */
        Fcb->ExactCaseLongName.Length = UnicodeName->Length;
        Fcb->ExactCaseLongName.MaximumLength = UnicodeName->Length;
        Fcb->ExactCaseLongName.Buffer =
            FsRtlAllocatePoolWithTag(PagedPool, UnicodeName->Length, TAG_FILENAME);

        RtlCopyMemory(Fcb->ExactCaseLongName.Buffer,
                      UnicodeName->Buffer,
                      UnicodeName->Length);

        /* Perform a trick which is done by MS's FASTFAT driver to monocase
           the filename */
        RtlDowncaseUnicodeString(UnicodeName, UnicodeName, FALSE);
        RtlUpcaseUnicodeString(UnicodeName, UnicodeName, FALSE);

        DPRINT("Converted long name: %wZ\n", UnicodeName);

        /* Add the long unicode name link */
        FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksUnicode, &Fcb->LongName);
        Fcb->LongName.Fcb = Fcb;

        /* Indicate that this FCB has a unicode long name */
        SetFlag(Fcb->State, FCB_STATE_HAS_UNICODE_NAME);
    }
    else
    {
        /* No LFN, set exact case name to 0 length */
        Fcb->ExactCaseLongName.Length = 0;
        Fcb->ExactCaseLongName.MaximumLength = 0;

        /* Set the length based on the short name */
        Fcb->FileNameLength = RtlOemStringToCountedUnicodeSize(ShortName);
    }

    /* Mark the fact that names were added to splay trees*/
    SetFlag(Fcb->State, FCB_STATE_HAS_NAMES);
}
Пример #11
0
PLFCB
LfsAllocateLfcb (
    )

/*++

Routine Description:

    This routine allocates and initializes a log file control block.

Arguments:

Return Value:

    PLFCB - A pointer to the log file control block just
                              allocated and initialized.

--*/

{
    PLFCB Lfcb = NULL;
    ULONG Count;
    PLBCB NextLbcb;

    PAGED_CODE();

    DebugTrace( +1, Dbg, "LfsAllocateLfcb:  Entered\n", 0 );

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

    try {

        //
        //  Allocate and zero the structure for the Lfcb.
        //

        Lfcb = FsRtlAllocatePool( PagedPool, sizeof( LFCB ));

        //
        //  Zero out the structure initially.
        //

        RtlZeroMemory( Lfcb, sizeof( LFCB ));

        //
        //  Initialize the log file control block.
        //

        Lfcb->NodeTypeCode = LFS_NTC_LFCB;
        Lfcb->NodeByteSize = sizeof( LFCB );

        //
        //  Initialize the client links.
        //

        InitializeListHead( &Lfcb->LchLinks );

        //
        //  Initialize the Lbcb links.
        //

        InitializeListHead( &Lfcb->LbcbWorkque );
        InitializeListHead( &Lfcb->LbcbActive );

        //
        //  Initialize and allocate the spare Lbcb queue.
        //

        InitializeListHead( &Lfcb->SpareLbcbList );

        for (Count = 0; Count < LFCB_RESERVE_LBCB_COUNT; Count++ ) {

            NextLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' );

            if (NextLbcb != NULL) {

                InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) NextLbcb );
                Lfcb->SpareLbcbCount += 1;
            }
        }

        //
        //  Allocate the Lfcb synchronization event.
        //

        Lfcb->Sync = FsRtlAllocatePool( NonPagedPool, sizeof( LFCB_SYNC ));

        ExInitializeResource( &Lfcb->Sync->Resource );

        //
        //  Initialize the pseudo Lsn for the restart Lbcb's
        //

        Lfcb->NextRestartLsn = LfsLi1;

        //
        //  Initialize the event to the signalled state.
        //

        KeInitializeEvent( &Lfcb->Sync->Event, NotificationEvent, TRUE );

        Lfcb->Sync->UserCount = 0;

    } finally {

        DebugUnwind( LfsAllocateFileControlBlock );

        if (AbnormalTermination()
            && Lfcb != NULL) {

            LfsDeallocateLfcb( Lfcb, TRUE );
            Lfcb = NULL;
        }

        DebugTrace( -1, Dbg, "LfsAllocateLfcb:  Exit -> %08lx\n", Lfcb );
    }

    return Lfcb;
}
Пример #12
0
NTSTATUS
NpQueryDirectory (
    IN PROOT_DCB RootDcb,
    IN PROOT_DCB_CCB Ccb,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the work routine for querying a directory.

Arugments:

    RootDcb - Supplies the dcb being queried

    Ccb - Supplies the context of the caller

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The return status for the operation.

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;

    PUCHAR Buffer;
    CLONG SystemBufferLength;

    UNICODE_STRING FileName;
    ULONG FileIndex;
    FILE_INFORMATION_CLASS FileInformationClass;
    BOOLEAN RestartScan;
    BOOLEAN ReturnSingleEntry;
    BOOLEAN IndexSpecified;

    static WCHAR Star = L'*';

    BOOLEAN CaseInsensitive = TRUE; //*** Make searches case insensitive

    ULONG CurrentIndex;

    ULONG LastEntry;
    ULONG NextEntry;

    PLIST_ENTRY Links;
    PFCB Fcb;

    PFILE_DIRECTORY_INFORMATION DirInfo;
    PFILE_NAMES_INFORMATION NamesInfo;

    PAGED_CODE();

    //
    //  Get the current stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "NpQueryDirectory\n", 0 );
    DebugTrace( 0, Dbg, "RootDcb              = %08lx\n", RootDcb);
    DebugTrace( 0, Dbg, "Ccb                  = %08lx\n", Ccb);
    DebugTrace( 0, Dbg, "SystemBuffer         = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
    DebugTrace( 0, Dbg, "Length               = %08lx\n", IrpSp->Parameters.QueryDirectory.Length);
    DebugTrace( 0, Dbg, "FileName             = %Z\n",    IrpSp->Parameters.QueryDirectory.FileName);
    DebugTrace( 0, Dbg, "FileIndex            = %08lx\n", IrpSp->Parameters.QueryDirectory.FileIndex);
    DebugTrace( 0, Dbg, "FileInformationClass = %08lx\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
    DebugTrace( 0, Dbg, "RestartScan          = %08lx\n", FlagOn(IrpSp->Flags, SL_RESTART_SCAN));
    DebugTrace( 0, Dbg, "ReturnSingleEntry    = %08lx\n", FlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY));
    DebugTrace( 0, Dbg, "IndexSpecified       = %08lx\n", FlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED));

    //
    //  Save references to the input parameters within the Irp
    //

    SystemBufferLength   = IrpSp->Parameters.QueryDirectory.Length;

    FileIndex            = IrpSp->Parameters.QueryDirectory.FileIndex;

    FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;

    RestartScan          = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN);
    ReturnSingleEntry    = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
    IndexSpecified       = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);

    if (IrpSp->Parameters.QueryDirectory.FileName != NULL) {

        FileName = *(PUNICODE_STRING)IrpSp->Parameters.QueryDirectory.FileName;

    } else {

        FileName.Length = 0;
        FileName.Buffer = NULL;
    }

    //
    //  Check if the ccb already has a query template attached.  If it
    //  does not already have one then we either use the string we are
    //  given or we attach our own containing "*"
    //

    if (Ccb->QueryTemplate == NULL) {

        //
        //  This is our first time calling query directory so we need
        //  to either set the query template to the user specified string
        //  or to "*"
        //

        if (FileName.Buffer == NULL) {

            DebugTrace(0, Dbg, "Set template to *\n", 0);

            FileName.Length = 2;
            FileName.Buffer = &Star;
        }

        DebugTrace(0, Dbg, "Set query template -> %Z\n", &FileName);

        //
        //  Allocate space for the query template
        //

        Ccb->QueryTemplate = FsRtlAllocatePool( PagedPool,
                                                sizeof(UNICODE_STRING) + FileName.Length );

        //
        //  Initialize the query template and copy over the string
        //

        Ccb->QueryTemplate->Length = FileName.Length;
        Ccb->QueryTemplate->Buffer = (PWCH)Ccb->QueryTemplate +
                                     sizeof(UNICODE_STRING) / sizeof(WCHAR);

        RtlCopyMemory( Ccb->QueryTemplate->Buffer,
                       FileName.Buffer,
                       FileName.Length );

        //
        //  Now zero out the FileName so we won't think we're to use it
        //  as a subsearch string.
        //

        FileName.Length = 0;
        FileName.Buffer = NULL;
    }

    //
    //  Check if we were given an index to start with or if we need to
    //  restart the scan or if we should use the index that was saved in
    //  the ccb
    //

    if (RestartScan) {

        FileIndex = 0;

    } else if (!IndexSpecified) {

        FileIndex = Ccb->IndexOfLastCcbReturned + 1;
    }

    //
    //  Now we are committed to completing the Irp, we do that in
    //  the finally clause of the following try.
    //

    try {

        ULONG BaseLength;
        ULONG LengthAdded;

        //
        // Map the user buffer.
        //

        Buffer = NpMapUserBuffer( Irp );

        //
        //  At this point we are about to enter our query loop.  We have
        //  already decided which Fcb index we need to return.  The variables
        //  LastEntry and NextEntry are used to index into the user buffer.
        //  LastEntry is the last entry we added to the user buffer, and
        //  NextEntry is the current one we're working on.  CurrentIndex
        //  is the Fcb index that we are looking at next.  Logically the
        //  way the loop works is as follows.
        //
        //  Scan all of the Fcb in the directory
        //
        //      if the Fcb matches the query template then
        //
        //          if the CurrentIndex is >= the FileIndex then
        //
        //              process this fcb, and decide if we should
        //              continue the main loop
        //
        //          end if
        //
        //          Increment the current index
        //
        //      end if
        //
        //  end scan
        //

        CurrentIndex = 0;

        LastEntry = 0;
        NextEntry =0;

        switch (FileInformationClass) {

        case FileDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
                                       FileName[0] );
            break;

        case FileFullDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
                                       FileName[0] );
            break;

        case FileNamesInformation:

            BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
                                       FileName[0] );
            break;

        case FileBothDirectoryInformation:

            BaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
                                       FileName[0] );
            break;

        default:

            try_return( Status = STATUS_INVALID_INFO_CLASS );
        }

        for (Links = RootDcb->Specific.Dcb.ParentDcbQueue.Flink;
             Links != &RootDcb->Specific.Dcb.ParentDcbQueue;
             Links = Links->Flink) {

            Fcb = CONTAINING_RECORD(Links, FCB, ParentDcbLinks);

            ASSERT(Fcb->NodeTypeCode == NPFS_NTC_FCB);

            DebugTrace(0, Dbg, "Top of Loop\n", 0);
            DebugTrace(0, Dbg, "Fcb          = %08lx\n", Fcb);
            DebugTrace(0, Dbg, "CurrentIndex = %08lx\n", CurrentIndex);
            DebugTrace(0, Dbg, "FileIndex    = %08lx\n", FileIndex);
            DebugTrace(0, Dbg, "LastEntry    = %08lx\n", LastEntry);
            DebugTrace(0, Dbg, "NextEntry    = %08lx\n", NextEntry);

            //
            //  Check if the Fcb represents a named pipe that is part of
            //  our query template
            //

            if (FsRtlIsNameInExpression( Ccb->QueryTemplate,
                                         &Fcb->LastFileName,
                                         CaseInsensitive,
                                         NULL )) {

                //
                //  The fcb is in the query template so now check if
                //  this is the index we should start returning
                //

                if (CurrentIndex >= FileIndex) {

                    ULONG BytesToCopy;
                    ULONG BytesRemainingInBuffer;

                    //
                    //  Here are the rules concerning filling up the buffer:
                    //
                    //  1.  The Io system garentees that there will always be
                    //      enough room for at least one base record.
                    //
                    //  2.  If the full first record (including file name) cannot
                    //      fit, as much of the name as possible is copied and
                    //      STATUS_BUFFER_OVERFLOW is returned.
                    //
                    //  3.  If a subsequent record cannot completely fit into the
                    //      buffer, none of it (as in 0 bytes) is copied, and
                    //      STATUS_SUCCESS is returned.  A subsequent query will
                    //      pick up with this record.
                    //

                    BytesRemainingInBuffer = SystemBufferLength - NextEntry;

                    if ( (NextEntry != 0) &&
                         ( (BaseLength + Fcb->LastFileName.Length > BytesRemainingInBuffer) ||
                           (SystemBufferLength < NextEntry) ) ) {

                        DebugTrace(0, Dbg, "Next entry won't fit\n", 0);

                        try_return( Status = STATUS_SUCCESS );
                    }

                    ASSERT( BytesRemainingInBuffer >= BaseLength );

                    //
                    //  See how much of the name we will be able to copy into
                    //  the system buffer.  This also dictates out return
                    //  value.
                    //

                    if ( BaseLength + Fcb->LastFileName.Length <=
                         BytesRemainingInBuffer ) {

                        BytesToCopy = Fcb->LastFileName.Length;
                        Status = STATUS_SUCCESS;

                    } else {

                        BytesToCopy = BytesRemainingInBuffer - BaseLength;
                        Status = STATUS_BUFFER_OVERFLOW;
                    }

                    //
                    //  Note how much of buffer we are consuming and zero
                    //  the base part of the structure.
                    //

                    LengthAdded = BaseLength + BytesToCopy;

                    RtlZeroMemory( &Buffer[NextEntry], BaseLength );

                    //
                    //  Now fill the base parts of the strucure that are
                    //  applicable.
                    //

                    switch (FileInformationClass) {

                    case FileBothDirectoryInformation:

                        //
                        //  We don't need short name
                        //

                        DebugTrace(0, Dbg, "Getting directory full information\n", 0);

                    case FileFullDirectoryInformation:

                        //
                        //  We don't use EaLength, so fill in nothing here.
                        //

                        DebugTrace(0, Dbg, "Getting directory full information\n", 0);

                    case FileDirectoryInformation:

                        DebugTrace(0, Dbg, "Getting directory information\n", 0);

                        //
                        //  The eof indicates the number of instances and
                        //  allocation size is the maximum allowed
                        //

                        DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];

                        DirInfo->EndOfFile.QuadPart = Fcb->OpenCount;
                        DirInfo->AllocationSize.QuadPart = Fcb->Specific.Fcb.MaximumInstances;

                        DirInfo->FileAttributes = FILE_ATTRIBUTE_NORMAL;

                        DirInfo->FileNameLength = Fcb->LastFileName.Length;

                        break;

                    case FileNamesInformation:

                        DebugTrace(0, Dbg, "Getting names information\n", 0);


                        NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];

                        NamesInfo->FileNameLength = Fcb->LastFileName.Length;

                        break;

                    default:

                        NpBugCheck( FileInformationClass, 0, 0 );
                    }

                    RtlCopyMemory( &Buffer[NextEntry + BaseLength],
                                   Fcb->LastFileName.Buffer,
                                   BytesToCopy );

                    //
                    //  Update the ccb to the index we've just used
                    //

                    Ccb->IndexOfLastCcbReturned = CurrentIndex;

                    //
                    //  And indicate how much of the system buffer we have
                    //  currently used up.  We must compute this value before
                    //  we long align outselves for the next entry
                    //

                    Irp->IoStatus.Information = NextEntry + LengthAdded;

                    //
                    //  Setup the previous next entry offset
                    //

                    *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;

                    //
                    //  Check if the last entry didn't completely fit
                    //

                    if ( Status == STATUS_BUFFER_OVERFLOW ) {

                        try_return( NOTHING );
                    }

                    //
                    //  Check if we are only to return a single entry
                    //

                    if (ReturnSingleEntry) {

                        try_return( Status = STATUS_SUCCESS );
                    }

                    //
                    //  Set ourselves up for the next iteration
                    //

                    LastEntry = NextEntry;
                    NextEntry += (ULONG)QuadAlign( LengthAdded );
                }

                //
                //  Increment the current index by one
                //

                CurrentIndex += 1;
            }
        }

        //
        //  At this point we've scanned the entire list of Fcb so if
        //  the NextEntry is zero then we haven't found anything so we
        //  will return no more files, otherwise we return success.
        //

        if (NextEntry == 0) {

            Status = STATUS_NO_MORE_FILES;

        } else {

            Status = STATUS_SUCCESS;
        }

    try_exit: NOTHING;
    } finally {

        if (!AbnormalTermination()) {

            NpCompleteRequest( Irp, Status );
        }

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

    return Status;
}
Пример #13
-1
NTSTATUS
DfsDriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
) {
    NTSTATUS Status;
    UNICODE_STRING UnicodeString;
    PDEVICE_OBJECT DeviceObject;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PWSTR p;
    int i;
    HANDLE hTemp;
    HANDLE DirHandle;
    IO_STATUS_BLOCK iosb;

    //
    // See if someone else has already created a File System Device object
    // with the name we intend to use. If so, we bail.
    //

    RtlInitUnicodeString( &UnicodeString, DFS_DRIVER_NAME );

    InitializeObjectAttributes(
        &ObjectAttributes,
        &UnicodeString,
        OBJ_CASE_INSENSITIVE,
        0,
        NULL);

    Status = ZwCreateFile(
                 &hTemp,
                 SYNCHRONIZE,
                 &ObjectAttributes,
                 &iosb,
                 NULL,
                 FILE_ATTRIBUTE_NORMAL,
                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                 FILE_OPEN,
                 0,
                 NULL,
                 0);

    if (NT_SUCCESS(Status)) {
        ZwClose( hTemp );
        DfsDbgTrace(0, Dbg, "Dfs driver already loaded!\n", 0);
        return( STATUS_UNSUCCESSFUL );
    }

    //
    // Create the filesystem device object.
    //

    Status = IoCreateDevice( DriverObject,
             0,
             &UnicodeString,
             FILE_DEVICE_DFS_FILE_SYSTEM,
             FILE_REMOTE_DEVICE,
             FALSE,
             &DeviceObject );
    if ( !NT_SUCCESS( Status ) ) {
        return Status;
    }

    //
    // Create a permanent object directory in which the logical root
    // device objects will reside.  Make the directory temporary, so
    // we can just close the handle to make it go away.
    //

    UnicodeString.Buffer = p = LogicalRootDevPath;
    UnicodeString.Length = 0;
    UnicodeString.MaximumLength = MAX_LOGICAL_ROOT_LEN;
    while (*p++ != UNICODE_NULL)
        UnicodeString.Length += sizeof (WCHAR);

    InitializeObjectAttributes(
        &ObjectAttributes,
        &UnicodeString,
        OBJ_PERMANENT,
        NULL,
        NULL );

    Status = ZwCreateDirectoryObject(
                &DirHandle,
                DIRECTORY_ALL_ACCESS,
                &ObjectAttributes);

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

    ZwMakeTemporaryObject(DirHandle);

    p[-1] = UNICODE_PATH_SEP;
    UnicodeString.Length += sizeof (WCHAR);

    //
    // Initialize the driver object with this driver's entry points.
    // Most are simply passed through to some other device driver.
    //

    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
        DriverObject->MajorFunction[i] = DfsVolumePassThrough;
    }

    DriverObject->MajorFunction[IRP_MJ_CREATE]      = (PDRIVER_DISPATCH)DfsFsdCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]       = (PDRIVER_DISPATCH)DfsFsdClose;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]     = (PDRIVER_DISPATCH)DfsFsdCleanup;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdQueryInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdSetInformation;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)DfsFsdFileSystemControl;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdQueryVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdSetVolumeInformation;

    DriverObject->FastIoDispatch = &FastIoDispatch;

    //
    //  Initialize the global data structures
    //

    RtlZeroMemory(&DfsData, sizeof (DFS_DATA));

    DfsData.NodeTypeCode = DSFS_NTC_DATA_HEADER;
    DfsData.NodeByteSize = sizeof( DFS_DATA );

    InitializeListHead( &DfsData.VcbQueue );
    InitializeListHead( &DfsData.DeletedVcbQueue );

    InitializeListHead( &DfsData.Credentials );
    InitializeListHead( &DfsData.DeletedCredentials );

    DfsData.DriverObject = DriverObject;
    DfsData.FileSysDeviceObject = DeviceObject;

    DfsData.LogRootDevName = UnicodeString;

    ExInitializeResource( &DfsData.Resource );
    KeInitializeEvent( &DfsData.PktWritePending, NotificationEvent, TRUE );
    KeInitializeSemaphore( &DfsData.PktReferralRequests, 1, 1 );

    DfsData.MachineState = DFS_CLIENT;

    //
    //  Allocate Provider structures.
    //

    DfsData.pProvider = ExAllocatePool( PagedPool,
                       sizeof ( PROVIDER_DEF ) * MAX_PROVIDERS);

    for (i = 0; i < MAX_PROVIDERS; i++) {
        DfsData.pProvider[i].NodeTypeCode = DSFS_NTC_PROVIDER;
        DfsData.pProvider[i].NodeByteSize = sizeof ( PROVIDER_DEF );
    }

    DfsData.cProvider = 0;
    DfsData.maxProvider = MAX_PROVIDERS;

    //
    //  Initialize the system wide PKT
    //

    PktInitialize(&DfsData.Pkt);

    {
    ULONG SystemSizeMultiplier;
    ULONG ZoneSegmentSize;

    switch (MmQuerySystemSize()) {
    default:
    case MmSmallSystem:
        SystemSizeMultiplier = 4;
        break;
    case MmMediumSystem:
        SystemSizeMultiplier = 8;
        break;

    case MmLargeSystem:
        SystemSizeMultiplier = 16;
        break;
    }

    //
    //  Allocate the DFS_FCB hash table structure.  The number of hash buckets
    //  will depend upon the memory size of the system.
    //

    Status = DfsInitFcbs(SystemSizeMultiplier * 2);

    //
    //  Now initialize the zone structures for allocating IRP context
    //  records.  The size of the zone will depend upon the memory
    //  available in the system.
    //

    KeInitializeSpinLock( &DfsData.IrpContextSpinLock );

    ZoneSegmentSize = (SystemSizeMultiplier *
               QuadAlign(sizeof(IRP_CONTEXT))) +
              sizeof(ZONE_SEGMENT_HEADER);

    (VOID) ExInitializeZone( &DfsData.IrpContextZone,
                 QuadAlign(sizeof(IRP_CONTEXT)),
                 FsRtlAllocatePool( NonPagedPool,
                            ZoneSegmentSize ),
                 ZoneSegmentSize );

    }

    //
    //  Set up global pointer to the system process.
    //

    DfsData.OurProcess = PsGetCurrentProcess();

    //
    //  Register the file system with the I/O system
    //

    IoRegisterFileSystem( DeviceObject );

    //
    //  Initialize the provider definitions from the registry.
    //

    if (!NT_SUCCESS( ProviderInit() )) {

        DfsDbgTrace(0,DEBUG_TRACE_ERROR,
               "Could not initialize some or all providers!\n", 0);

    }

    //
    // Initialize the logical roots device objects. These are what form the
    // link between the outside world and the Dfs driver.
    //

    Status = DfsInitializeLogicalRoot( DD_DFS_DEVICE_NAME, NULL, NULL, 0);

    if (!NT_SUCCESS(Status)) {
      DfsDbgTrace(-1, DEBUG_TRACE_ERROR, "Failed creation of root logical root %08lx\n", Status);
      return(Status);
    }

    //
    // Let us start off the Timer Routine.
    //

    RtlZeroMemory(&DfsTimerContext, sizeof(DFS_TIMER_CONTEXT));
    DfsTimerContext.InUse = FALSE;
    DfsTimerContext.TickCount = 0;
    IoInitializeTimer(DeviceObject, DfsIoTimerRoutine, &DfsTimerContext);
    DfsDbgTrace(0, Dbg, "Initialized the Timer routine\n", 0);

    //
    //  Let us start the timer now.
    //

    IoStartTimer(DeviceObject);

    return STATUS_SUCCESS;
}