Ejemplo n.º 1
0
NTSTATUS
NtfsCompleteMdl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the function of completing Mdl read and write
    requests.  It should be called only from NtfsFsdRead and NtfsFsdWrite.

Arguments:

    Irp - Supplies the originating Irp.

Return Value:

    NTSTATUS - Will always be STATUS_PENDING or STATUS_SUCCESS.

--*/

{
    PFILE_OBJECT FileObject;
    PIO_STACK_LOCATION IrpSp;
    PNTFS_ADVANCED_FCB_HEADER Header;

    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsCompleteMdl\n") );
    DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp        = %08lx\n", Irp) );

    //
    // Do completion processing.
    //

    FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;

    switch( IrpContext->MajorFunction ) {

    case IRP_MJ_READ:

        CcMdlReadComplete( FileObject, Irp->MdlAddress );
        break;

    case IRP_MJ_WRITE:

        try {

            PSCB Scb;
            VBO StartingVbo;
            LONGLONG ByteCount;
            LONGLONG ByteRange;
            BOOLEAN DoingIoAtEof = FALSE;

            ASSERT( FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ));

            IrpSp = IoGetCurrentIrpStackLocation( Irp );
            Scb = (PSCB)(IrpSp->FileObject->FsContext);
            Header = &(Scb->Header);

            //
            //  Now synchronize with the FsRtl Header and Scb.
            //

            if (Header->PagingIoResource != NULL) {

                StartingVbo = IrpSp->Parameters.Write.ByteOffset.QuadPart;
                ByteCount = (LONGLONG) IrpSp->Parameters.Write.Length;
                ByteRange = StartingVbo + ByteCount + PAGE_SIZE - 1;
                ClearFlag( ((ULONG) ByteRange), PAGE_SIZE - 1 );

                ExAcquireResourceSharedLite( Header->PagingIoResource, TRUE );
                NtfsAcquireFsrtlHeader( Scb );

                //
                //  Now see if this is at EOF.
                //  Recursive flush will generate IO which ends on page boundary
                //  which is why we rounded the range
                //

                if (ByteRange > Header->ValidDataLength.QuadPart) {

                    //
                    //  Mark that we are writing to EOF.  If someone else is currently
                    //  writing to EOF, wait for them.
                    //

                    ASSERT( ByteRange - StartingVbo < MAXULONG );

                    DoingIoAtEof = !FlagOn( Header->Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE ) ||
                                   NtfsWaitForIoAtEof( Header, (PLARGE_INTEGER)&StartingVbo, (ULONG)(ByteRange - StartingVbo) );

                    if (DoingIoAtEof) {

                        SetFlag( Header->Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE );

#if (DBG || defined( NTFS_FREE_ASSERTS ))
                        ((PSCB) Header)->IoAtEofThread = (PERESOURCE_THREAD) ExGetCurrentResourceThread();
#endif
                        //
                        //  Store this in the IrpContext until commit or post.
                        //

                        IrpContext->CleanupStructure = Scb;
                    }
                }

                NtfsReleaseFsrtlHeader( Scb );
            }

            CcMdlWriteComplete( FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress );

        } finally {

            if (Header->PagingIoResource != NULL) {

                ExReleaseResourceLite( Header->PagingIoResource );
            }
        }

        break;

    default:

        DebugTrace( DEBUG_TRACE_ERROR, 0, ("Illegal Mdl Complete.\n") );

        ASSERTMSG("Illegal Mdl Complete, About to bugcheck ", FALSE);
        NtfsBugCheck( IrpContext->MajorFunction, 0, 0 );
    }

    //
    // Mdl is now deallocated.
    //

    Irp->MdlAddress = NULL;

    //
    //  Ignore errors.  CC has already cleaned up his structures.
    //

    IrpContext->ExceptionStatus = STATUS_SUCCESS;
    NtfsMinimumExceptionProcessing( IrpContext );

    //
    // Complete the request and exit right away.
    //

    NtfsCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );

    DebugTrace( -1, Dbg, ("NtfsCompleteMdl -> STATUS_SUCCESS\n") );

    return STATUS_SUCCESS;
}
Ejemplo n.º 2
0
void JNetwork::ThreadProc(void* param)
{
  JNetwork* pThis = reinterpret_cast<JNetwork*>(param);
  JSocket* pSocket = NULL;
  if (pThis->serverIP.size()) {
    DebugTrace("Starting Client Thread");
    pThis->socket = new JSocket(pThis->serverIP);
    if(pThis->socket->isConnected())
      pSocket = pThis->socket;
  } else {
    DebugTrace("Starting Server Thread");
    pThis->socket = new JSocket();
    // Wait for some client
    pSocket = pThis->socket->Accept();
  }

  while(pSocket && pSocket->isConnected()) {
    char buff[1024];
    {
      boost::mutex::scoped_lock l(pThis->receiveMutex);
      int len =  pSocket->Read(buff, sizeof(buff));
      if(len) {
        DebugTrace("receiving " << len << " bytes : " << buff);
        pThis->received << buff;
      }
      // Checking for some command to execute
      size_t found = pThis->received.str().find("Command");
      if(found != string::npos)
      {
        map<string, processCmd>::iterator ite = sCommandMap.find((pThis->received.str()).substr(0, found) + "Command");
        if(ite != sCommandMap.end())
        {
          DebugTrace("begin of command received : "<< pThis->received.str() );
          DebugTrace("begin of command toSend : "<< pThis->toSend.str() );

          boost::mutex::scoped_lock l(pThis->sendMutex);
          pThis->toSend << pThis->received.str().substr(0, found) + "Response ";
          pThis->received.str("");
          processCmd theMethod = (ite)->second;
          theMethod(pThis->received, pThis->toSend);

          DebugTrace("end of command received : "<< pThis->received.str() );
          DebugTrace("end of command toSend : "<< pThis->toSend.str() );
        }
      }
      // Checking for some response to execute
      found = pThis->received.str().find("Response");
      if(found != string::npos)
      {
        map<string, processCmd>::iterator ite = sCommandMap.find((pThis->received.str()).substr(0, found) + "Response");
        if(ite != sCommandMap.end())
        {
          DebugTrace("begin of response received : "<< pThis->received.str() );
          DebugTrace("begin of response toSend : "<< pThis->toSend.str() );

          boost::mutex::scoped_lock l(pThis->sendMutex);
          string aString;
          pThis->received >> aString;
          processCmd theMethod = (ite)->second;
          theMethod(pThis->received, pThis->toSend);
          pThis->received.str("");

          DebugTrace("end of response received : "<< pThis->received.str() );
          DebugTrace("end of response toSend : "<< pThis->toSend.str() );
        }
      }
    }
Ejemplo n.º 3
0
NTSTATUS
NdFatSecondaryCommonRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP			Irp,
    IN ULONG		BytesToRead
)
{
    NTSTATUS					status;

    PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
    BOOLEAN						secondarySessionResourceAcquired = FALSE;

    PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation( Irp );
    PFILE_OBJECT				fileObject = irpSp->FileObject;

    struct Read					read;

    PSECONDARY_REQUEST			secondaryRequest = NULL;
    PNDFS_REQUEST_HEADER		ndfsRequestHeader;
    PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
    PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

    LARGE_INTEGER				timeOut;

    TYPE_OF_OPEN				typeOfOpen;
    PVCB						vcb;
    PFCB						fcb;
    PCCB						ccb;
    BOOLEAN						fcbAcquired = FALSE;

    PUCHAR						outputBuffer;
    ULONG						totalReadLength;

    _U64						primaryFileHandle = 0;


    ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );

    typeOfOpen = FatDecodeFileObject( fileObject, &vcb, &fcb, &ccb );

    ASSERT( typeOfOpen == UserFileOpen );

    if (FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

        /*if (FlagOn( fcb->FcbState, FCB_STATE_FILE_DELETED )) {

        	ASSERT( FALSE );
        	FatRaiseStatus( IrpContext, STATUS_FILE_DELETED, NULL, NULL );

        } else */{

            ASSERT( FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) );

            return STATUS_FILE_CORRUPT_ERROR;
        }
    }

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

        ASSERT( FALSE );
        DebugTrace2( 0, Dbg, ("Can't wait in create\n") );

        status = FatFsdPostRequest( IrpContext, Irp );

        DebugTrace2( -1, Dbg2, ("NdFatSecondaryCommonRead:  FatFsdPostRequest -> %08lx\n", status) );
        return status;
    }

    if (irpSp->Parameters.Read.ByteOffset.QuadPart == FILE_WRITE_TO_END_OF_FILE &&
            irpSp->Parameters.Read.ByteOffset.HighPart == -1) {

        read.ByteOffset = fcb->Header.FileSize;

    } else {

        read.ByteOffset = irpSp->Parameters.Read.ByteOffset;
    }

    read.Key	= 0;
    read.Length	= irpSp->Parameters.Read.Length;
    read.Length = BytesToRead;


    ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

    //FatAcquireSharedFcb( IrpContext, fcb );
    //fcbAcquired = TRUE;


    try {

        secondarySessionResourceAcquired
            = SecondaryAcquireResourceExclusiveLite( IrpContext,
                    &volDo->Secondary->SessionResource,
                    BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

        if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

            PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );
            FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
        }

        outputBuffer = FatMapUserBuffer( IrpContext, Irp );
        totalReadLength = 0;

        do {

            ULONG						outputBufferLength;

            if (fcb->UncleanCount == 0) {

                DebugTrace( 0, Dbg2, "NdFatSecondaryCommonRead: fileName = %wZ\n", &fileObject->FileName );

                status = STATUS_FILE_CLOSED;
                break;
            }

            if (!FlagOn(ccb->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {

                primaryFileHandle = ccb->PrimaryFileHandle;

            } else {

                PLIST_ENTRY	ccbListEntry;

                ExAcquireFastMutex( &fcb->CcbQMutex );

                for (primaryFileHandle = 0, ccbListEntry = fcb->CcbQueue.Flink;
                        ccbListEntry != &fcb->CcbQueue;
                        ccbListEntry = ccbListEntry->Flink) {

                    if (!FlagOn(CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {

                        primaryFileHandle = CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->PrimaryFileHandle;
                        break;
                    }
                }

                ExReleaseFastMutex( &fcb->CcbQMutex );
            }

            ASSERT( primaryFileHandle );

            outputBufferLength = ((read.Length-totalReadLength) <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize)
                                 ? (read.Length-totalReadLength) : volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize;

            secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary,
                               IRP_MJ_READ,
                               volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize );

            if (secondaryRequest == NULL) {

                FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
            }

            ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
            INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_READ, 0 );

            ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
            ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

            //ndfsWinxpRequestHeader->IrpTag   = (_U32)Irp;
            ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_READ;
            ndfsWinxpRequestHeader->IrpMinorFunction = 0;

            ndfsWinxpRequestHeader->FileHandle = ccb->PrimaryFileHandle;

            ndfsWinxpRequestHeader->IrpFlags   = 0;
            ndfsWinxpRequestHeader->IrpSpFlags = 0;

            ndfsWinxpRequestHeader->Read.Length		= outputBufferLength;
            ndfsWinxpRequestHeader->Read.Key		= read.Key;
            ndfsWinxpRequestHeader->Read.ByteOffset = read.ByteOffset.QuadPart + totalReadLength;

            secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
            QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

            timeOut.QuadPart = -NDFAT_TIME_OUT;
            status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );

            if (status != STATUS_SUCCESS) {

                secondaryRequest = NULL;
                status = STATUS_IO_DEVICE_ERROR;
                leave;
            }

            KeClearEvent( &secondaryRequest->CompleteEvent );

            if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

                if (IrpContext->OriginatingIrp)
                    PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );

                DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

                FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
            }

            ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

            if (ndfsWinxpReplytHeader->Status == STATUS_END_OF_FILE) {

                ASSERT( ndfsWinxpReplytHeader->Information == 0 );

                if (!(read.ByteOffset.QuadPart & (((ULONG)vcb->Bpb.BytesPerSector) - 1))) {


                    RtlZeroMemory( outputBuffer + totalReadLength,
                                   read.Length - totalReadLength );

                    totalReadLength = read.Length;

                } else {

                    ASSERT( FALSE );
                }

                DereferenceSecondaryRequest( secondaryRequest );
                secondaryRequest = NULL;

                break;
            }

            if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

                ASSERT( totalReadLength == 0 );
                ASSERT( ndfsWinxpReplytHeader->Status == STATUS_FILE_CLOSED );

                DebugTrace2( 0, Dbg, ("ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

                if (totalReadLength)
                    status = STATUS_SUCCESS;
                else
                    status = ndfsWinxpReplytHeader->Status;

                ASSERT( ndfsWinxpReplytHeader->Information == 0 );
                DereferenceSecondaryRequest( secondaryRequest );
                secondaryRequest = NULL;

                break;
            }

            ASSERT( ndfsWinxpReplytHeader->Information <= outputBufferLength );
            ASSERT( outputBufferLength == 0 || outputBuffer );

            //if (fcb->Header.FileSize.QuadPart < 100)
            //	DbgPrint( "data = %s\n", (_U8 *)(ndfsWinxpReplytHeader+1) );

            if (ndfsWinxpReplytHeader->Information && outputBuffer) {

                try {

                    RtlCopyMemory( outputBuffer + totalReadLength,
                                   (_U8 *)(ndfsWinxpReplytHeader+1),
                                   ndfsWinxpReplytHeader->Information );

                }
                finally {

                    if (AbnormalTermination()) {

                        DebugTrace2( 0, Dbg2, ("RedirectIrpMajorRead: Exception - output buffer is not valid\n") );
                        totalReadLength = read.Length; // Pretend that we read all the data.Buffer owner is already dead anyway..
                        status = STATUS_SUCCESS;

                    } else {

                        if (ndfsWinxpReplytHeader->Status == STATUS_SUCCESS)
                            totalReadLength += ndfsWinxpReplytHeader->Information;

                        if (totalReadLength)
                            status = STATUS_SUCCESS;
                        else
                            status = ndfsWinxpReplytHeader->Status;
                    }
                }
            }

            //if (fcb->Header.FileSize.QuadPart < 100)
            //	DbgPrint( "data = %s\n", outputBuffer );

            DereferenceSecondaryRequest( secondaryRequest );
            secondaryRequest = NULL;

        } while( totalReadLength < read.Length );


        if (status == STATUS_FILE_CLOSED) {

            _U64	fcbHandle;
            ULONG	dataSize;
            _U8		*ndfsWinxpRequestData;


            ASSERT( ccb );
            ASSERT( totalReadLength == 0 );
            ASSERT( secondaryRequest == NULL );

            if (ccb->CreateContext.RelatedFileHandle != 0) {

                ASSERT( FALSE );
                try_return( status = STATUS_FILE_CLOSED );
            }

            DebugTrace2( 0, Dbg, ("SessionRecovery: ccb->Lcb->ExactCaseLink.LinkName = %wZ \n", &ccb->Fcb->FullFileName) );

            dataSize = ccb->CreateContext.EaLength + ccb->CreateContext.FileNameLength;

            secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary,
                               IRP_MJ_CREATE,
                               (dataSize >= DEFAULT_MAX_DATA_SIZE) ? dataSize : DEFAULT_MAX_DATA_SIZE );

            if (secondaryRequest == NULL) {

                ASSERT( FALSE );
                try_return( status = STATUS_FILE_CLOSED );
            }

            ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;

            INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader,
                                            NDFS_COMMAND_EXECUTE,
                                            volDo->Secondary,
                                            IRP_MJ_CREATE,
                                            (ccb->BufferLength + ccb->Fcb->FullFileName.Length) );

            ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
            ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

            ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_CREATE;
            ndfsWinxpRequestHeader->IrpMinorFunction = 0;

            ndfsWinxpRequestHeader->FileHandle = 0;

            ndfsWinxpRequestHeader->IrpFlags   = 0;
            ndfsWinxpRequestHeader->IrpSpFlags = 0; //irpSp->Flags;

            ndfsWinxpRequestHeader->Create.AllocationSize = 0;
            ndfsWinxpRequestHeader->Create.EaLength = 0;
            ndfsWinxpRequestHeader->Create.FileAttributes = 0;

            ndfsWinxpRequestHeader->Create.Options = 0; //irpSp->Parameters.Create.Options & ~FILE_DELETE_ON_CLOSE;
            ndfsWinxpRequestHeader->Create.Options &= 0x00FFFFFF;
            ndfsWinxpRequestHeader->Create.Options |= (FILE_OPEN << 24);

            ndfsWinxpRequestHeader->Create.FileNameLength
                = (USHORT)(ccb->Fcb->FullFileName.Length + (ccb->BufferLength - ccb->CreateContext.EaLength));

            ndfsWinxpRequestHeader->Create.FileNameLength = ccb->CreateContext.FileNameLength;
            ndfsWinxpRequestHeader->Create.EaLength = 0; //ccb->CreateContext.EaLength;

            ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1);

            RtlCopyMemory( ndfsWinxpRequestData + ndfsWinxpRequestHeader->Create.EaLength,
                           ccb->Fcb->FullFileName.Buffer,
                           ccb->Fcb->FullFileName.Length );

            RtlCopyMemory( ndfsWinxpRequestData + ndfsWinxpRequestHeader->Create.EaLength + ccb->Fcb->FullFileName.Length,
                           ccb->Buffer + ccb->CreateContext.EaLength,
                           ccb->BufferLength - ccb->CreateContext.EaLength );

            secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
            QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

            timeOut.QuadPart = -NDFAT_TIME_OUT;
            status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );

            KeClearEvent(&secondaryRequest->CompleteEvent);

            if (status != STATUS_SUCCESS) {

                ASSERT( NDFAT_BUG );

                secondaryRequest = NULL;
                ASSERT( FALSE );
                try_return( status );
            }

            if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

                status = secondaryRequest->ExecuteStatus;
                DereferenceSecondaryRequest( secondaryRequest );
                secondaryRequest = NULL;
                ASSERT( FALSE );

                FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
            }

            ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

            DebugTrace2( 0, Dbg, ("SessionRecovery: ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

            if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

                ASSERT( FALSE );
                status = secondaryRequest->ExecuteStatus;
                DereferenceSecondaryRequest( secondaryRequest );
                secondaryRequest = NULL;
                try_return( status = STATUS_FILE_CLOSED );
            }

            primaryFileHandle = ndfsWinxpReplytHeader->Open.FileHandle;
            ASSERT( fcb->Handle == ndfsWinxpReplytHeader->Open.FcbHandle );

            DereferenceSecondaryRequest( secondaryRequest );
            secondaryRequest = NULL;

            do {

                ULONG						outputBufferLength;


                outputBufferLength = ((read.Length-totalReadLength) <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize)
                                     ? (read.Length-totalReadLength) : volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize;

                secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary,
                                   IRP_MJ_READ,
                                   volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize );

                if (secondaryRequest == NULL) {

                    FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
                }

                ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
                INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_READ, 0 );

                ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
                ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

                //ndfsWinxpRequestHeader->IrpTag   = (_U32)Irp;
                ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_READ;
                ndfsWinxpRequestHeader->IrpMinorFunction = 0;

                ndfsWinxpRequestHeader->FileHandle = primaryFileHandle;

                ndfsWinxpRequestHeader->IrpFlags   = 0;
                ndfsWinxpRequestHeader->IrpSpFlags = 0;

                ndfsWinxpRequestHeader->Read.Length		= outputBufferLength;
                ndfsWinxpRequestHeader->Read.Key		= read.Key;
                ndfsWinxpRequestHeader->Read.ByteOffset = read.ByteOffset.QuadPart + totalReadLength;

                secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
                QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

                timeOut.QuadPart = -NDFAT_TIME_OUT;
                status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );

                if (status != STATUS_SUCCESS) {

                    secondaryRequest = NULL;
                    status = STATUS_IO_DEVICE_ERROR;
                    leave;
                }

                KeClearEvent( &secondaryRequest->CompleteEvent );

                if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

                    if (IrpContext->OriginatingIrp)
                        PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );

                    DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

                    FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
                }

                ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

                if (ndfsWinxpReplytHeader->Status == STATUS_END_OF_FILE) {

                    ASSERT( ndfsWinxpReplytHeader->Information == 0 );

                    if (!(read.ByteOffset.QuadPart & (((ULONG)vcb->Bpb.BytesPerSector) - 1))) {


                        RtlZeroMemory( outputBuffer + totalReadLength,
                                       read.Length - totalReadLength );

                        totalReadLength = read.Length;

                    } else {

                        ASSERT( FALSE );
                    }

                    DereferenceSecondaryRequest( secondaryRequest );
                    secondaryRequest = NULL;

                    break;
                }

                if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

                    ASSERT( FALSE );

                    DebugTrace2( 0, Dbg2, ("ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

                    if (totalReadLength)
                        status = STATUS_SUCCESS;
                    else
                        status = ndfsWinxpReplytHeader->Status;

                    ASSERT( ndfsWinxpReplytHeader->Information == 0 );
                    DereferenceSecondaryRequest( secondaryRequest );
                    secondaryRequest = NULL;

                    break;
                }

                ASSERT( ndfsWinxpReplytHeader->Information <= outputBufferLength );
                ASSERT( outputBufferLength == 0 || outputBuffer );

                if (ndfsWinxpReplytHeader->Information && outputBuffer) {

                    try {

                        RtlCopyMemory( outputBuffer + totalReadLength,
                                       (_U8 *)(ndfsWinxpReplytHeader+1),
                                       ndfsWinxpReplytHeader->Information );

                    }
                    finally {

                        if (AbnormalTermination()) {

                            DebugTrace2( 0, Dbg2, ("RedirectIrpMajorRead: Exception - output buffer is not valid\n") );
                            totalReadLength = read.Length; // Pretend that we read all the data.Buffer owner is already dead anyway..
                            status = STATUS_SUCCESS;

                        } else {

                            if (ndfsWinxpReplytHeader->Status == STATUS_SUCCESS)
                                totalReadLength += ndfsWinxpReplytHeader->Information;

                            if (totalReadLength)
                                status = STATUS_SUCCESS;
                            else
                                status = ndfsWinxpReplytHeader->Status;
                        }
                    }
                }

                DereferenceSecondaryRequest( secondaryRequest );
                secondaryRequest = NULL;

            } while( totalReadLength < read.Length );

            ASSERT( totalReadLength == read.Length );

            ClosePrimaryFile( volDo->Secondary, primaryFileHandle );
        }

try_exit:

        NOTHING;

    }
Ejemplo n.º 4
0
__drv_mustHoldCriticalRegion    
NTSTATUS
FatProcessException (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN NTSTATUS ExceptionCode
    )

/*++

Routine Description:

    This routine process an exception.  It either completes the request
    with the saved exception status or it sends it off to IoRaiseHardError()

Arguments:

    Irp - Supplies the Irp being processed

    ExceptionCode - Supplies the normalized exception status being handled

Return Value:

    NTSTATUS - Returns the results of either posting the Irp or the
        saved completion status.

--*/

{
    PVCB Vcb;
    PIO_STACK_LOCATION IrpSp;
    FAT_VOLUME_STATE TransitionState = VolumeDirty;
    ULONG SavedFlags = 0;

    PAGED_CODE();

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

    //
    //  If there is not an irp context, we must have had insufficient resources.
    //

    if ( !ARGUMENT_PRESENT( IrpContext ) ) {

        FatCompleteRequest( FatNull, Irp, ExceptionCode );

        return ExceptionCode;
    }

    //
    //  Get the real exception status from IrpContext->ExceptionStatus, and
    //  reset it.
    //

    ExceptionCode = IrpContext->ExceptionStatus;
    FatResetExceptionState( IrpContext );

    //
    //  If this is an Mdl write request, then take care of the Mdl
    //  here so that things get cleaned up properly.  Cc now leaves
    //  the MDL in place so a filesystem can retry after clearing an
    //  internal condition (FAT does not).
    //

    if ((IrpContext->MajorFunction == IRP_MJ_WRITE) &&
        (FlagOn( IrpContext->MinorFunction, IRP_MN_COMPLETE_MDL ) == IRP_MN_COMPLETE_MDL) &&
        (Irp->MdlAddress != NULL)) {

        PIO_STACK_LOCATION LocalIrpSp = IoGetCurrentIrpStackLocation(Irp);

        CcMdlWriteAbort( LocalIrpSp->FileObject, Irp->MdlAddress );
        Irp->MdlAddress = NULL;
    }

    //
    //  If we are going to post the request, we may have to lock down the
    //  user's buffer, so do it here in a try except so that we failed the
    //  request if the LockPages fails.
    //
    //  Also unpin any repinned Bcbs, protected by the try {} except {} filter.
    //

    try {

        SavedFlags = IrpContext->Flags;

        //
        //  Make sure we don't try to write through Bcbs
        //

        SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH);

        FatUnpinRepinnedBcbs( IrpContext );

        IrpContext->Flags = SavedFlags;

        //
        //  If we will have to post the request, do it here.  Note
        //  that the last thing FatPrePostIrp() does is mark the Irp pending,
        //  so it is critical that we actually return PENDING.  Nothing
        //  from this point to return can fail, so we are OK.
        //
        //  We cannot do a verify operations at APC level because we
        //  have to wait for Io operations to complete.
        //

        if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) &&
            (((ExceptionCode == STATUS_VERIFY_REQUIRED) && KeAreAllApcsDisabled()) ||
             (ExceptionCode == STATUS_CANT_WAIT))) {

            ExceptionCode = FatFsdPostRequest( IrpContext, Irp );
        }

    } except( FatExceptionFilter( IrpContext, GetExceptionInformation() ) ) {

        ExceptionCode = IrpContext->ExceptionStatus;
        IrpContext->ExceptionStatus = 0;

        IrpContext->Flags = SavedFlags;
    }

    //
    //  If we posted the request, just return here.
    //

    if (ExceptionCode == STATUS_PENDING) {

        return ExceptionCode;
    }

    Irp->IoStatus.Status = ExceptionCode;

    //
    //  If this request is not a "top-level" irp, just complete it.
    //

    if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL)) {

        //
        //  If there is a cache operation above us, commute verify
        //  to a lock conflict.  This will cause retries so that
        //  we have a chance of getting through without needing
        //  to return an unaesthetic error for the operation.
        //

        if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP &&
            ExceptionCode == STATUS_VERIFY_REQUIRED) {

            ExceptionCode = STATUS_FILE_LOCK_CONFLICT;
        }
        
        FatCompleteRequest( IrpContext, Irp, ExceptionCode );

        return ExceptionCode;
    }

    if (IoIsErrorUserInduced(ExceptionCode)) {

        //
        //  Check for the various error conditions that can be caused by,
        //  and possibly resolved by the user.
        //

        if (ExceptionCode == STATUS_VERIFY_REQUIRED) {

            PDEVICE_OBJECT Device;

            DebugTrace(0, Dbg, "Perform Verify Operation\n", 0);

            //
            //  Now we are at the top level file system entry point.
            //
            //  Grab the device to verify from the thread local storage
            //  and stick it in the information field for transportation
            //  to the fsp.  We also clear the field at this time.
            //

            Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread );
            IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL );

            if ( Device == NULL ) {

                Device = IoGetDeviceToVerify( PsGetCurrentThread() );
                IoSetDeviceToVerify( PsGetCurrentThread(), NULL );

                ASSERT( Device != NULL );
            }

            //
            //  Let's not BugCheck just because the driver messed up.
            //

            if (Device == NULL) {

                ExceptionCode = STATUS_DRIVER_INTERNAL_ERROR;

                FatCompleteRequest( IrpContext, Irp, ExceptionCode );

                return ExceptionCode;
            }

            //
            //  FatPerformVerify() will do the right thing with the Irp.

            return FatPerformVerify( IrpContext, Irp, Device );
        }

        //
        //  The other user induced conditions generate an error unless
        //  they have been disabled for this request.
        //

        if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS)) {

            FatCompleteRequest( IrpContext, Irp, ExceptionCode );

            return ExceptionCode;

        } else {

            //
            //  Generate a pop-up
            //

            PDEVICE_OBJECT RealDevice;
            PVPB Vpb;
            PETHREAD Thread;

            if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL) {

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

            } else {

                Vpb = NULL;
            }

            //
            //  The device to verify is either in my thread local storage
            //  or that of the thread that owns the Irp.
            //

            Thread = Irp->Tail.Overlay.Thread;
            RealDevice = IoGetDeviceToVerify( Thread );

            if ( RealDevice == NULL ) {

                Thread = PsGetCurrentThread();
                RealDevice = IoGetDeviceToVerify( Thread );

                ASSERT( RealDevice != NULL );
            }

            //
            //  Let's not BugCheck just because the driver messed up.
            //

            if (RealDevice == NULL) {

                FatCompleteRequest( IrpContext, Irp, ExceptionCode );

                return ExceptionCode;
            }

            //
            //  This routine actually causes the pop-up.  It usually
            //  does this by queuing an APC to the callers thread,
            //  but in some cases it will complete the request immediately,
            //  so it is very important to IoMarkIrpPending() first.
            //

            IoMarkIrpPending( Irp );
            IoRaiseHardError( Irp, Vpb, RealDevice );

            //
            //  We will be handing control back to the caller here, so
            //  reset the saved device object.
            //

            IoSetDeviceToVerify( Thread, NULL );

            //
            //  The Irp will be completed by Io or resubmitted.  In either
            //  case we must clean up the IrpContext here.
            //

            FatDeleteIrpContext( IrpContext );
            return STATUS_PENDING;
        }
    }

    //
    //  This is just a run of the mill error.  If is a STATUS that we
    //  raised ourselves, and the information would be use for the
    //  user, raise an informational pop-up.
    //

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

    //
    //  Now, if the Vcb is unknown to us this means that the error was raised
    //  in the process of a mount and before we even had a chance to build
    //  a full Vcb - and was really handled there.
    //

    if (Vcb != NULL) {

        if ( !FatDeviceIsFatFsdo( IrpSp->DeviceObject) &&
             !NT_SUCCESS(ExceptionCode) &&
             !FsRtlIsTotalDeviceFailure(ExceptionCode) ) {

            TransitionState = VolumeDirtyWithSurfaceTest;
        }

        //
        //  If this was a STATUS_FILE_CORRUPT or similar error indicating some
        //  nastiness out on the media, then mark the volume permanently dirty.
        //

        if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS) &&
            ( TransitionState == VolumeDirtyWithSurfaceTest ||
              (ExceptionCode == STATUS_FILE_CORRUPT_ERROR) ||
              (ExceptionCode == STATUS_DISK_CORRUPT_ERROR) ||
              (ExceptionCode == STATUS_EA_CORRUPT_ERROR) ||
              (ExceptionCode == STATUS_INVALID_EA_NAME) ||
              (ExceptionCode == STATUS_EA_LIST_INCONSISTENT) ||
              (ExceptionCode == STATUS_NO_EAS_ON_FILE) )) {

            ASSERT( NodeType(Vcb) == FAT_NTC_VCB );
            ASSERT( !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL));

            SetFlag( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY );
            SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

            //
            //  Do the "dirty" work, ignoring any error.  We need to take the Vcb here
            //  to synchronize against the verify path tearing things down, since
            //  we dropped all synchronization when backing up due to the exception.
            //

            FatAcquireExclusiveVcbNoOpCheck( IrpContext, Vcb);
            
            try {

                if (VcbGood == Vcb->VcbCondition) {

                    FatMarkVolume( IrpContext, Vcb, TransitionState );
                }
            } 
            except( FatExceptionFilter( IrpContext, GetExceptionInformation() ) ) {

                NOTHING;
            }

            FatReleaseVcb( IrpContext, Vcb);
        }
    }
Ejemplo n.º 5
0
VOID
FatFspDispatch (
    IN PVOID Context
    )

/*++

Routine Description:

    This is the main FSP thread routine that is executed to receive
    and dispatch IRP requests.  Each FSP thread begins its execution here.
    There is one thread created at system initialization time and subsequent
    threads created as needed.

Arguments:


    Context - Supplies the thread id.

Return Value:

    None - This routine never exits

--*/

{
    NTSTATUS Status;

    PIRP Irp;
    PIRP_CONTEXT IrpContext;
    PIO_STACK_LOCATION IrpSp;
    BOOLEAN VcbDeleted;

    PVOLUME_DEVICE_OBJECT VolDo;

    IrpContext = (PIRP_CONTEXT)Context;

    Irp = IrpContext->OriginatingIrp;

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Now because we are the Fsp we will force the IrpContext to
    //  indicate true on Wait.
    //

    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);

    //
    //  If this request has an associated volume device object, remember it.
    //

    if ( IrpSp->FileObject != NULL ) {

        VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
                                   VOLUME_DEVICE_OBJECT,
                                   DeviceObject );
    } else {

        VolDo = NULL;
    }

    //
    //  Now case on the function code.  For each major function code,
    //  either call the appropriate FSP routine or case on the minor
    //  function and then call the FSP routine.  The FSP routine that
    //  we call is responsible for completing the IRP, and not us.
    //  That way the routine can complete the IRP and then continue
    //  post processing as required.  For example, a read can be
    //  satisfied right away and then read can be done.
    //
    //  We'll do all of the work within an exception handler that
    //  will be invoked if ever some underlying operation gets into
    //  trouble (e.g., if FatReadSectorsSync has trouble).
    //

    while ( TRUE ) {

        DebugTrace(0, Dbg, "FatFspDispatch: Irp = 0x%08lx\n", Irp);

        //
        //  If this Irp was top level, note it in our thread local storage.
        //

        FsRtlEnterFileSystem();

        if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) ) {

            IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );

        } else {

            IoSetTopLevelIrp( Irp );
        }

#if __NDAS_FAT__

		do {

#if __NDAS_FAT_SECONDARY__

			BOOLEAN	volDoResourceAcquired = FALSE;

#endif

			try {

#if __NDAS_FAT_SECONDARY__

				Status = STATUS_SUCCESS;

				if (Irp && IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

					BOOLEAN volDoRecoveryResourceAcquired = FALSE;

					ASSERT( FatIsTopLevelRequest(IrpContext) );

					ASSERT( FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT) );

					while (TRUE) {
			
						ASSERT( volDoRecoveryResourceAcquired == FALSE );
						ASSERT( volDoResourceAcquired == FALSE );

						if (FlagOn(VolDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
		
							volDoRecoveryResourceAcquired 
								= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																		 &VolDo->Secondary->RecoveryResource, 
																		 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
							if (!FlagOn(VolDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

								SecondaryReleaseResourceLite( IrpContext, &VolDo->Secondary->RecoveryResource );
								volDoRecoveryResourceAcquired = FALSE;
								continue;
							}

							volDoResourceAcquired 
								= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																		 &VolDo->Secondary->Resource, 
																		 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
							try {
								
								SecondaryRecoverySessionStart( VolDo->Secondary, IrpContext );
								
							} finally {

								SecondaryReleaseResourceLite( IrpContext, &VolDo->Secondary->Resource );
								volDoResourceAcquired = FALSE;

								SecondaryReleaseResourceLite( IrpContext, &VolDo->Secondary->RecoveryResource );
								volDoRecoveryResourceAcquired = FALSE;
							}

							continue;
						}

						volDoResourceAcquired 
							= SecondaryAcquireResourceSharedLite( IrpContext, 
																  &VolDo->Secondary->Resource, 
																  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

						ASSERT( volDoResourceAcquired == TRUE );

						break;
					}
				}
#endif

	            switch ( IrpContext->MajorFunction ) {

		            //
			        //  For Create Operation,
				    //

					case IRP_MJ_CREATE:

						(VOID) FatCommonCreate( IrpContext, Irp );
	                    break;

		            //
			        //  For close operations.  We do a little kludge here in case
				    //  this close causes a volume to go away.  It will NULL the
					//  VolDo local variable so that we will not try to look at
	                //  the overflow queue.
		            //

	                case IRP_MJ_CLOSE:

		            {
			            PVCB Vcb;
				        PFCB Fcb;
					    PCCB Ccb;
						TYPE_OF_OPEN TypeOfOpen;

	                    //
		                //  Extract and decode the file object
			            //

				        TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );

					    //
						//  Do the close.  We have a slightly different format
	                    //  for this call because of the async closes.
		                //

			            Status = FatCommonClose( Vcb,
				                                 Fcb,
					                             Ccb,
						                         TypeOfOpen,
							                     TRUE,
								                 &VcbDeleted );

	                    //
		                //  If the VCB was deleted, do not try to access it later.
			            //

				        if (VcbDeleted) {

					        VolDo = NULL;
						}

	                    ASSERT(Status == STATUS_SUCCESS);

		                FatCompleteRequest( IrpContext, Irp, Status );

			            break;
				    }

	                //
		            //  For read operations
			        //

				    case IRP_MJ_READ:

					    (VOID) FatCommonRead( IrpContext, Irp );
						break;

	                //
		            //  For write operations,
			        //

				    case IRP_MJ_WRITE:

					    (VOID) FatCommonWrite( IrpContext, Irp );
						break;

	                //
		            //  For Query Information operations,
			        //

				    case IRP_MJ_QUERY_INFORMATION:

					    (VOID) FatCommonQueryInformation( IrpContext, Irp );
						break;

	                //
		            //  For Set Information operations,
			        //

				    case IRP_MJ_SET_INFORMATION:

					    (VOID) FatCommonSetInformation( IrpContext, Irp );
						break;

	                //
		            //  For Query EA operations,
			        //

				    case IRP_MJ_QUERY_EA:

					    (VOID) FatCommonQueryEa( IrpContext, Irp );
						break;

	                //
		            //  For Set EA operations,
			        //

				    case IRP_MJ_SET_EA:

					    (VOID) FatCommonSetEa( IrpContext, Irp );
						break;

	                //
		            //  For Flush buffers operations,
			        //

				    case IRP_MJ_FLUSH_BUFFERS:

					    (VOID) FatCommonFlushBuffers( IrpContext, Irp );
						break;

	                //
		            //  For Query Volume Information operations,
			        //

				    case IRP_MJ_QUERY_VOLUME_INFORMATION:

					    (VOID) FatCommonQueryVolumeInfo( IrpContext, Irp );
						break;

	                //
		            //  For Set Volume Information operations,
			        //

				    case IRP_MJ_SET_VOLUME_INFORMATION:

					    (VOID) FatCommonSetVolumeInfo( IrpContext, Irp );
						break;

	                //
		            //  For File Cleanup operations,
			        //

				    case IRP_MJ_CLEANUP:

					    (VOID) FatCommonCleanup( IrpContext, Irp );
						break;

	                //
		            //  For Directory Control operations,
			        //

				    case IRP_MJ_DIRECTORY_CONTROL:

					    (VOID) FatCommonDirectoryControl( IrpContext, Irp );
						break;

	                //
		            //  For File System Control operations,
			        //

				    case IRP_MJ_FILE_SYSTEM_CONTROL:

					    (VOID) FatCommonFileSystemControl( IrpContext, Irp );
						break;

	                //
		            //  For Lock Control operations,
			        //

				    case IRP_MJ_LOCK_CONTROL:

					    (VOID) FatCommonLockControl( IrpContext, Irp );
						break;

	                //
		            //  For Device Control operations,
			        //

				    case IRP_MJ_DEVICE_CONTROL:

					    (VOID) FatCommonDeviceControl( IrpContext, Irp );
						break;

	                //
		            //  For the Shutdown operation,
			        //

				    case IRP_MJ_SHUTDOWN:

					    (VOID) FatCommonShutdown( IrpContext, Irp );
						break;

	                //
		            //  For plug and play operations.
			        //

				    case IRP_MJ_PNP:

					    //
						//  I don't believe this should ever occur, but allow for the unexpected.
	                    //

		                (VOID) FatCommonPnp( IrpContext, Irp );
			            break;

				    //
					//  For any other major operations, return an invalid
	                //  request.
		            //

			        default:

				        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
					    break;

				}

#if __NDAS_FAT_SECONDARY__

				if (volDoResourceAcquired) {

					SecondaryReleaseResourceLite( NULL, &VolDo->Secondary->Resource );
					volDoResourceAcquired = FALSE;
				}
#endif


	        } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

#if __NDAS_FAT_SECONDARY__

				if (volDoResourceAcquired) {

					SecondaryReleaseResourceLite( NULL, &VolDo->Secondary->Resource );
					volDoResourceAcquired = FALSE;
				}
#endif
				
				//
			    //  We had some trouble trying to perform the requested
				//  operation, so we'll abort the I/O request with
	            //  the error status that we get back from the
		        //  execption code.
			    //

				Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
			}
		
		} while (Status == STATUS_CANT_WAIT);
//
//	compare addresses to see if the address is local.
//
BOOLEAN
xixfs_IsFromLocal(
		PLPX_ADDRESS	Addr
	) {
	NTSTATUS				ntStatus;

	SOCKETLPX_ADDRESS_LIST	socketLpxAddressList;
	LONG					idx_addr ;
	
	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Enter  xixfs_IsFromLocal \n"));


	DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM, 
		( "[LFS] xixfs_IsFromLocal: Entered with Addr:%02x:%02x:%02x:%02x:%02x:%02x\n",
				Addr->Node[0], Addr->Node[1], Addr->Node[2], 
				Addr->Node[3], Addr->Node[4], Addr->Node[5]
			));

	//
	//	get addresses from LPX
	//
	socketLpxAddressList.iAddressCount = 0 ;
	ntStatus = LpxTdiGetAddressList(
		&socketLpxAddressList
    	) ;
	
	if(!NT_SUCCESS(ntStatus)) {
		DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ( "[LFS] xixfs_IsFromLocal: LpxTdiGetAddressList() failed.\n")) ;
		return FALSE ;
	}
	if(0 == socketLpxAddressList.iAddressCount) {
		DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, ( "[LFS] xixfs_IsFromLocal: No NICs in the host.\n")) ;
		return FALSE ;
	}

	for(idx_addr = 0 ; idx_addr < socketLpxAddressList.iAddressCount ; idx_addr ++ ) {
		//
		//	BUG FIX for LPX: skip SocketLpxDevice
		//
		if( (0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[0]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[1]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[2]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[3]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[4]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[5]) ) {

			DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,  ( "[LFS] xixfs_IsFromLocal: We don't use SocketLpx device.\n") );
			continue ;

		}

		if( RtlCompareMemory(Addr->Node, socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node, ETHER_ADDR_LENGTH)
			== ETHER_ADDR_LENGTH ) {
				DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM, ( "[LFS] xixfs_IsFromLocal: found a address matching.\n")) ;
				return TRUE ;
		}
	}

	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Exit  xixfs_IsFromLocal \n"));

	return FALSE ;
}
Ejemplo n.º 7
0
BOOLEAN
FatCheckFileAccess (
    PIRP_CONTEXT IrpContext,
    IN UCHAR DirentAttributes,
    IN PACCESS_MASK DesiredAccess
    )

/*++

Routine Description:

    This routine checks if a desired access is allowed to a file represented
    by the specified DirentAttriubutes.

Arguments:

    DirentAttributes - Supplies the Dirent attributes to check access for

    DesiredAccess - Supplies the desired access mask that we are checking for

Return Value:

    BOOLEAN - TRUE if access is allowed and FALSE otherwise

--*/

{
    BOOLEAN Result;

    DebugTrace(+1, Dbg, "FatCheckFileAccess\n", 0);
    DebugTrace( 0, Dbg, "DirentAttributes = %8lx\n", DirentAttributes);
    DebugTrace( 0, Dbg, "DesiredAccess    = %8lx\n", *DesiredAccess);

    PAGED_CODE();

    //
    //  This procedures is programmed like a string of filters each
    //  filter checks to see if some access is allowed,  if it is not allowed
    //  the filter return FALSE to the user without further checks otherwise
    //  it moves on to the next filter.  The filter check is to check for
    //  desired access flags that are not allowed for a particular dirent
    //

    Result = TRUE;

    try {

        //
        //  Check for Volume ID or Device Dirents, these are not allowed user
        //  access at all
        //

        if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_VOLUME_ID) ||
            FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DEVICE)) {

            DebugTrace(0, Dbg, "Cannot access volume id or device\n", 0);

            try_return( Result = FALSE );
        }

        //
        //  Check the desired access for the object - we only blackball that
        //  we do not understand.  The model of filesystems using ACLs is that
        //  they do not type the ACL to the object the ACL is on.  Permissions
        //  are not checked for consistency vs. the object type - dir/file.
        //

        if (FlagOn(*DesiredAccess, ~(DELETE |
                                     READ_CONTROL |
                                     WRITE_OWNER |
                                     WRITE_DAC |
                                     SYNCHRONIZE |
                                     ACCESS_SYSTEM_SECURITY |
                                     FILE_WRITE_DATA |
                                     FILE_READ_EA |
                                     FILE_WRITE_EA |
                                     FILE_READ_ATTRIBUTES |
                                     FILE_WRITE_ATTRIBUTES |
                                     FILE_LIST_DIRECTORY |
                                     FILE_TRAVERSE |
                                     FILE_DELETE_CHILD |
                                     FILE_APPEND_DATA))) {

            DebugTrace(0, Dbg, "Cannot open object\n", 0);

            try_return( Result = FALSE );
        }

        //
        //  Check for a read-only Dirent
        //

        if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {

            //
            //  Check the desired access for a read-only dirent.  AccessMask will contain
            //  the flags we're going to allow.
            //

            ACCESS_MASK AccessMask = DELETE | READ_CONTROL | WRITE_OWNER | WRITE_DAC |
                                    SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_READ_DATA |
                                    FILE_READ_EA | FILE_WRITE_EA | FILE_READ_ATTRIBUTES |
                                    FILE_WRITE_ATTRIBUTES | FILE_EXECUTE | FILE_LIST_DIRECTORY |
                                    FILE_TRAVERSE;

            //
            //  If this is a subdirectory also allow add file/directory and delete.
            //
            
            if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DIRECTORY)) {

                AccessMask |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_DELETE_CHILD;
            }
            
            if (FlagOn(*DesiredAccess, ~AccessMask)) {

                DebugTrace(0, Dbg, "Cannot open readonly\n", 0);

                try_return( Result = FALSE );
            }
        }

    try_exit: NOTHING;
    } finally {

        DebugUnwind( FatCheckFileAccess );

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

    UNREFERENCED_PARAMETER( IrpContext );

    return Result;
}
Ejemplo n.º 8
0
NTSTATUS
FatCommonSetVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for setting Volume Information called by both
    the fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;

    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;
    TYPE_OF_OPEN TypeOfOpen;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    //
    //  Get the current stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatCommonSetVolumeInfo...\n", 0);
    DebugTrace( 0, Dbg, "Irp                  = %08lx\n", Irp );
    DebugTrace( 0, Dbg, "->Length             = %08lx\n", IrpSp->Parameters.SetVolume.Length);
    DebugTrace( 0, Dbg, "->FsInformationClass = %08lx\n", IrpSp->Parameters.SetVolume.FsInformationClass);
    DebugTrace( 0, Dbg, "->Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer);

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.SetVolume.Length;
    FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Decode the file object to get the Vcb
    //

    TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );

    if (TypeOfOpen != UserVolumeOpen) {

        FatCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED );

        DebugTrace(-1, Dbg, "FatCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n", 0);

        return STATUS_ACCESS_DENIED;
    }

#ifndef DOUBLE_SPACE_WRITE
    ASSERT(Vcb->Dscb == NULL);
#endif // DOUBLE_SPACE_WRITE

    //
    //  Acquire exclusive access to the Vcb and enqueue the Irp if we didn't
    //  get access
    //

    if (!FatAcquireExclusiveVcb( IrpContext, Vcb )) {

        DebugTrace(0, Dbg, "Cannot acquire Vcb\n", 0);

        Status = FatFsdPostRequest( IrpContext, Irp );

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

    try {

        //
        //  Make sure the vcb is in a usable condition.  This will raise
        //  and error condition if the volume is unusable
        //
        //  Also verify the Root Dcb since we need info from there.
        //

        FatVerifyFcb( IrpContext, Vcb->RootDcb );

        //
        //  Based on the information class we'll do different actions.  Each
        //  of the procedures that we're calling performs the action if
        //  possible and returns true if it successful and false if it couldn't
        //  wait for any I/O to complete.
        //

        switch (FsInformationClass) {

        case FileFsLabelInformation:

            Status = FatSetFsLabelInfo( IrpContext, Vcb, Buffer );
            break;

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
        }

        FatUnpinRepinnedBcbs( IrpContext );

    } finally {

        DebugUnwind( FatCommonSetVolumeInfo );

        FatReleaseVcb( IrpContext, Vcb );

        if (!AbnormalTermination()) {

            FatCompleteRequest( IrpContext, Irp, Status );
        }

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

    return Status;
}
Ejemplo n.º 9
0
NTSTATUS
FatQueryFsVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_FS_VOLUME_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

Routine Description:

    This routine implements the query volume info call

Arguments:

    Vcb - Supplies the Vcb being queried

    Buffer - Supplies a pointer to the output buffer where the information
        is to be returned

    Length - Supplies the length of the buffer in byte.  This variable
        upon return recieves the remaining bytes free in the buffer

Return Value:

    NTSTATUS - Returns the status for the query

--*/

{
    ULONG BytesToCopy;

    NTSTATUS Status;

    DebugTrace(0, Dbg, "FatQueryFsVolumeInfo...\n", 0);

    //
    //  Zero out the buffer, then extract and fill up the non zero fields.
    //

    RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION) );

    Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;

    Buffer->SupportsObjects = FALSE;

    *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);

    //
    //  Check if the buffer we're given is long enough
    //

    if ( *Length >= (ULONG)Vcb->Vpb->VolumeLabelLength ) {

        BytesToCopy = Vcb->Vpb->VolumeLabelLength;

        Status = STATUS_SUCCESS;

    } else {

        BytesToCopy = *Length;

        Status = STATUS_BUFFER_OVERFLOW;
    }

    //
    //  Copy over what we can of the volume label, and adjust *Length
    //

    Buffer->VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;

    RtlCopyMemory( &Buffer->VolumeLabel[0],
                   &Vcb->Vpb->VolumeLabel[0],
                   BytesToCopy );

    *Length -= BytesToCopy;

    //
    //  Set our status and return to our caller
    //

    UNREFERENCED_PARAMETER( IrpContext );

    return Status;
}
Ejemplo n.º 10
0
    void DumpStatistics()
    {
#ifdef TRACK_OBJECT_USAGE

        DebugTrace("-----------------------------------------------------------");
        DebugTrace("Object Usage Stats" << std::endl);
        DebugTrace("CardPrimitive current count: " << InstanceCounter<CardPrimitive>::GetCurrentObjectCount());
        DebugTrace("CardPrimitive current byte usage: " << InstanceCounter<CardPrimitive>::GetCurrentByteCount());
        DebugTrace("CardPrimitive max count: " << InstanceCounter<CardPrimitive>::GetMaximumObjectCount());
        DebugTrace("CardPrimitive max byte usage: " << InstanceCounter<CardPrimitive>::GetMaximumByteCount() << std::endl);

        DebugTrace("MTGCard current count: " << InstanceCounter<MTGCard>::GetCurrentObjectCount());
        DebugTrace("MTGCard current byte usage: " << InstanceCounter<MTGCard>::GetCurrentByteCount());
        DebugTrace("MTGCard max count: " << InstanceCounter<MTGCard>::GetMaximumObjectCount());
        DebugTrace("MTGCard max byte usage: " << InstanceCounter<MTGCard>::GetMaximumByteCount() << std::endl);

        DebugTrace("MTGCardInstance current count: " << InstanceCounter<MTGCardInstance>::GetCurrentObjectCount());
        DebugTrace("MTGCardInstance current byte usage: " << InstanceCounter<MTGCardInstance>::GetCurrentByteCount());
        DebugTrace("MTGCardInstance max count: " << InstanceCounter<MTGCardInstance>::GetMaximumObjectCount());
        DebugTrace("MTGCardInstance max byte usage: " << InstanceCounter<MTGCardInstance>::GetMaximumByteCount() << std::endl);

        DebugTrace("ManaCost current count: " << InstanceCounter<ManaCost>::GetCurrentObjectCount());
        DebugTrace("ManaCost current byte usage: " << InstanceCounter<ManaCost>::GetCurrentByteCount());
        DebugTrace("ManaCost max count: " << InstanceCounter<ManaCost>::GetMaximumObjectCount());
        DebugTrace("ManaCost max byte usage: " << InstanceCounter<ManaCost>::GetMaximumByteCount() << std::endl);

        DebugTrace("ExtraCost current count: " << InstanceCounter<ExtraCost>::GetCurrentObjectCount());
        DebugTrace("ExtraCost current byte usage: " << InstanceCounter<ExtraCost>::GetCurrentByteCount());
        DebugTrace("ExtraCost max count: " << InstanceCounter<ExtraCost>::GetMaximumObjectCount());
        DebugTrace("ExtraCost max byte usage: " << InstanceCounter<ExtraCost>::GetMaximumByteCount() << std::endl);

        DebugTrace("-----------------------------------------------------------");

#endif
    }
Ejemplo n.º 11
0
NTSTATUS
FatCommonQueryVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for querying volume information called by both
    the fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;

    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    BOOLEAN WeAcquiredVcb = FALSE;

    //
    //  Get the current stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatCommonQueryVolumeInfo...\n", 0);
    DebugTrace( 0, Dbg, "Irp                  = %08lx\n", Irp );
    DebugTrace( 0, Dbg, "->Length             = %08lx\n", IrpSp->Parameters.QueryVolume.Length);
    DebugTrace( 0, Dbg, "->FsInformationClass = %08lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass);
    DebugTrace( 0, Dbg, "->Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer);

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.QueryVolume.Length;
    FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Decode the file object to get the Vcb
    //

    (VOID) FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );

    try {

        //
        //  Make sure the vcb is in a usable condition.  This will raise
        //  and error condition if the volume is unusable
        //
        //  Also verify the Root Dcb since we need info from there.
        //

        FatVerifyFcb( IrpContext, Vcb->RootDcb );

        //
        //  Based on the information class we'll do different actions.  Each
        //  of the procedures that we're calling fills up the output buffer
        //  if possible and returns true if it successfully filled the buffer
        //  and false if it couldn't wait for any I/O to complete.
        //

        switch (FsInformationClass) {

        case FileFsVolumeInformation:

            //
            //  This is the only routine we need the Vcb shared because of
            //  copying the volume label.  All other routines copy fields that
            //  cannot change or are just manifest constants.
            //

            if (!FatAcquireSharedVcb( IrpContext, Vcb )) {

                DebugTrace(0, Dbg, "Cannot acquire Vcb\n", 0);

                Status = FatFsdPostRequest( IrpContext, Irp );

            } else {

                Status = FatQueryFsVolumeInfo( IrpContext, Vcb, Buffer, &Length );

                WeAcquiredVcb = TRUE;
            }

            break;

        case FileFsSizeInformation:

            Status = FatQueryFsSizeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsDeviceInformation:

            Status = FatQueryFsDeviceInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsAttributeInformation:

            Status = FatQueryFsAttributeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
        }

        //
        //  Set the information field to the number of bytes actually filled in
        //

        Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;

    } finally {

        DebugUnwind( FatCommonQueryVolumeInfo );

        if ( WeAcquiredVcb ) { FatReleaseVcb( IrpContext, Vcb ); }

        if (!AbnormalTermination()) {

            FatCompleteRequest( IrpContext, Irp, Status );
        }

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

    return Status;
}
Ejemplo n.º 12
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 );
            }
Ejemplo n.º 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;
}
Ejemplo n.º 14
0
NTSTATUS
FatFsdRead (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
)

/*++

Routine Description:

    This is the driver entry to the common read routine for NtReadFile calls.
    For synchronous requests, the CommonRead is called with Wait == TRUE,
    which means the request will always be completed in the current thread,
    and never passed to the Fsp.  If it is not a synchronous request,
    CommonRead is called with Wait == FALSE, which means the request
    will be passed to the Fsp only if there is a need to block.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Read exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    PFCB Fcb;
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

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

    //
    //  Call the common Read routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    //
    //  We are first going to do a quick check for paging file IO.
    //

    Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext);

    if ((NodeType(Fcb) == FAT_NTC_FCB) &&
            FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) {

        //
        //  Do the usual STATUS_PENDING things.
        //

        IoMarkIrpPending( Irp );

        //
        //  If there is not enough stack to do this read, then post this
        //  read to the overflow queue.
        //

        if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

            KEVENT Event;
            PAGING_FILE_OVERFLOW_PACKET Packet;

            Packet.Irp = Irp;
            Packet.Fcb = Fcb;

            KeInitializeEvent( &Event, NotificationEvent, FALSE );

            FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead );

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

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

        } else {

            //
            //  Perform the actual IO, it will be completed when the io finishes.
            //

            FatPagingFileIo( Irp, Fcb );
        }

        FsRtlExitFileSystem();

        return STATUS_PENDING;
    }

    try {

        TopLevel = FatIsIrpTopLevel( Irp );

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        //
        //  If this is an Mdl complete request, don't go through
        //  common read.
        //

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

            DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 );
            try_return( Status = FatCompleteMdl( IrpContext, Irp ));
        }

        //
        //  We can't handle DPC calls yet, post it.
        //

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

            DebugTrace(0, Dbg, "Passing DPC call to Fsp\n", 0 );
            try_return( Status = FatFsdPostRequest( IrpContext, Irp ));
        }

        //
        //  Check if we have enough stack space to process this request.  If there
        //  isn't enough then we will pass the request off to the stack overflow thread.
        //

        if ((IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) &&
                ((NodeType(Fcb) == FAT_NTC_FCB) ||
                 (NodeType(Fcb) == FAT_NTC_DCB) ||
                 (NodeType(Fcb) == FAT_NTC_ROOT_DCB))) {

            DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 );
            try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) );
        }

        Status = FatCommonRead( IrpContext, Irp );

try_exit:
        NOTHING;
    }
    except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) {
        IoSetTopLevelIrp( NULL );
    }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
static VOID
xixfs_FindOutChanges(
		PSOCKETLPX_ADDRESS_LIST	Original,
		PSOCKETLPX_ADDRESS_LIST	Updated,
		PSOCKETLPX_ADDRESS_LIST	Disabled,
		PSOCKETLPX_ADDRESS_LIST	Enabled
	) {
	LONG	idx_ori, idx_updated, idx_disabled, idx_enabled ;
	BOOLEAN	found ;
	UINT32	matchmask ;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Enter xixfs_FindOutChanges \n"));


	ASSERT(sizeof(matchmask) * 8 >= MAX_SOCKETLPX_INTERFACE) ;

	idx_disabled  = 0 ;
	Disabled->iAddressCount = 0 ;
	matchmask = 0 ;
	for(idx_ori = 0 ; idx_ori < Original->iAddressCount ; idx_ori ++ ) {

		found = FALSE ;

		//
		//	find disabled ones.
		//
		for(idx_updated = 0 ; idx_updated < Updated->iAddressCount ; idx_updated ++) {
			
			if( RtlCompareMemory(
						Original->SocketLpx[idx_ori].LpxAddress.Node,
						Updated->SocketLpx[idx_updated].LpxAddress.Node,
						ETHER_ADDR_LENGTH
						) == ETHER_ADDR_LENGTH ) {

				//
				//	check this match in the bit mask.
				//	help find enabled ones.
				//
				matchmask |= 1 << idx_updated ;

				found = TRUE ;
				break ;
			}
			
		}

		//
		//	add disabled one to the list
		//
		if(!found) {
			RtlCopyMemory(Disabled->SocketLpx[idx_disabled].LpxAddress.Node,
							Original->SocketLpx[idx_ori].LpxAddress.Node,
							ETHER_ADDR_LENGTH
						) ;

			Disabled->iAddressCount ++ ;
			idx_disabled ++ ;
		}
	}

	//
	//	find enabled ones.
	//
	idx_enabled = 0 ;
	Enabled->iAddressCount = 0 ;
	for(idx_updated = 0 ; idx_updated < Updated->iAddressCount ; idx_updated ++) {
		//
		//	add enabled one to the list.
		//
		if(!(matchmask & (1 << idx_updated))) {
			RtlCopyMemory( 
					Enabled->SocketLpx[idx_enabled].LpxAddress.Node,
					Updated->SocketLpx[idx_updated].LpxAddress.Node,
					ETHER_ADDR_LENGTH
				) ;

			Enabled->iAddressCount ++ ;
			idx_enabled ++ ;
		}
	}
	
	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Exit xixfs_FindOutChanges \n"));
}
Ejemplo n.º 16
0
NTSTATUS
FatQueryFsSizeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_FS_SIZE_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

Routine Description:

    This routine implements the query volume size call

Arguments:

    Vcb - Supplies the Vcb being queried

    Buffer - Supplies a pointer to the output buffer where the information
        is to be returned

    Length - Supplies the length of the buffer in byte.  This variable
        upon return recieves the remaining bytes free in the buffer

Return Value:

    Status - Returns the status for the query

--*/

{
    PDSCB Dscb = Vcb->Dscb;

    DebugTrace(0, Dbg, "FatQueryFsSizeInfo...\n", 0);

    RtlZeroMemory( Buffer, sizeof(FILE_FS_SIZE_INFORMATION) );

    //
    //  Set the output buffer.  If this is a double space volume, we have
    //  some additional work to do.
    //

    Dscb = Vcb->Dscb;

    if (Dscb && (Dscb->SectorsAllocated != 0)) {

        ULONG EstimatedClustersFree;

        //
        //  Compute how many clusters we think we can represent on this
        //  disk.  This is:
        //
        //      (Total - Allocated) * (Represented / Allocated)
        //
        //  which for computational reasons, we reduce to:
        //
        //      (Total * Represented / Allocated) - Represented
        //

        EstimatedClustersFree =
            (ULONG)
            ((((LONGLONG)(Dscb->CvfLayout.CvfHeap.Size / 512) *
              (LONGLONG)(Dscb->SectorsRepresented)) /

             Dscb->SectorsAllocated)

             -

             Dscb->SectorsRepresented)

            /

            Vcb->Bpb.SectorsPerCluster;

        //
        //  Now, if this number is smaller than the remaining clusters in
        //  the FAT table, then use it.
        //

        Buffer->AvailableAllocationUnits.LowPart =
            EstimatedClustersFree < Vcb->AllocationSupport.NumberOfFreeClusters ?
            EstimatedClustersFree : Vcb->AllocationSupport.NumberOfFreeClusters;

        //
        //  To get the total number of clusters, take how many FAT clusters
        //  we have used, and add the number returned above.
        //

        Buffer->TotalAllocationUnits.LowPart =
            Vcb->AllocationSupport.NumberOfClusters -
            Vcb->AllocationSupport.NumberOfFreeClusters +
            Buffer->AvailableAllocationUnits.LowPart;

    } else {

        Buffer->TotalAllocationUnits.LowPart =
                                    Vcb->AllocationSupport.NumberOfClusters;
        Buffer->AvailableAllocationUnits.LowPart =
                                    Vcb->AllocationSupport.NumberOfFreeClusters;
    }

    Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
    Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;

    //
    //  Adjust the length variable
    //

    *Length -= sizeof(FILE_FS_SIZE_INFORMATION);

    //
    //  And return success to our caller
    //

    UNREFERENCED_PARAMETER( IrpContext );

    return STATUS_SUCCESS;
}
//
//	send a packet.
//
NTSTATUS
xixfs_SendDatagram(
	IN PLFSDG_Socket		socket,
	IN PXIXFSDG_PKT			pkt,
	PLPX_ADDRESS		LpxRemoteAddress

) {
	NTSTATUS	ntStatus ;
	ULONG		result ;
	ULONG		idx_addr ;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Enter  xixfs_SendDatagram \n"));

	//
	//	send a packet
	//
	for(idx_addr = 0 ; idx_addr < socket->SocketCnt ; idx_addr ++ ) {

		RtlCopyMemory(&pkt->SourceAddr, &socket->Sockets[idx_addr].NICAddr, sizeof(LPX_ADDRESS)) ;
		

		DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM, 
			( "[LFS] xixfs_SendDatagram: Souce address: [0x%02X:%02X:%02X:%02X:%02X:%02X] : Port (%ld)\n",
					pkt->SourceAddr.Node[0],pkt->SourceAddr.Node[1],pkt->SourceAddr.Node[2],
					pkt->SourceAddr.Node[3],pkt->SourceAddr.Node[4],pkt->SourceAddr.Node[5], NTOHS(pkt->SourceAddr.Port)) );


		DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM, 
			( "[LFS] xixfs_SendDatagram: Dest address: [0x%02X:%02X:%02X:%02X:%02X:%02X] : Port (%ld)\n",
					LpxRemoteAddress->Node[0],LpxRemoteAddress->Node[1],LpxRemoteAddress->Node[2],
					LpxRemoteAddress->Node[3],LpxRemoteAddress->Node[4],LpxRemoteAddress->Node[5], NTOHS(LpxRemoteAddress->Port) ));



		ntStatus = LpxTdiSendDataGram(
				socket->Sockets[idx_addr].AddressFile,
				LpxRemoteAddress,
				(PUCHAR)&pkt->RawHeadDG,
				pkt->PacketSize,
				0,
				&result
			) ;
		if(STATUS_PENDING == ntStatus) {
			DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
				( "[COM] xixfs_SendDatagram: outgoing packet is pending.\n")) ;
		} else if(!NT_SUCCESS(ntStatus)) {
			DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
				( "[COM] xixfs_SendDatagram: sending failed.\n")) ;
		} else if(result != pkt->PacketSize) {
			DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
				( "[COM] xixfs_SendDatagram: unexpected data length sent. len:%lu\n", result)) ;
		}
		//
		//	patch02172004
		//	Some NICs don't support loop-back for broadcast packet.
		//	set Source address here.
		//if(NT_SUCCESS(ntStatus)) {
			
			DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
				( "[COM] xixfs_SendDatagram: Sending OK. \n")) ;

		//	RtlCopyMemory(&pkt->SourceAddr, &socket->Sockets[idx_addr].NICAddr, sizeof(LPX_ADDRESS)) ;
		//}


	}

	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Exit  xixfs_SendDatagram \n"));
	return STATUS_SUCCESS ;
}
Ejemplo n.º 18
0
NTSTATUS
FatQueryFsDeviceInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_FS_DEVICE_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

Routine Description:

    This routine implements the query volume device call

Arguments:

    Vcb - Supplies the Vcb being queried

    Buffer - Supplies a pointer to the output buffer where the information
        is to be returned

    Length - Supplies the length of the buffer in byte.  This variable
        upon return recieves the remaining bytes free in the buffer

Return Value:

    Status - Returns the status for the query

--*/

{
    DebugTrace(0, Dbg, "FatQueryFsDeviceInfo...\n", 0);

    RtlZeroMemory( Buffer, sizeof(FILE_FS_DEVICE_INFORMATION) );

    //
    //  Set the output buffer
    //

    Buffer->DeviceType = FILE_DEVICE_DISK;

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

    if (Vcb->Dscb != NULL) {

        SetFlag( Buffer->Characteristics, FILE_VIRTUAL_VOLUME );
    }

    //
    //  Adjust the length variable
    //

    *Length -= sizeof(FILE_FS_DEVICE_INFORMATION);

    //
    //  And return success to our caller
    //

    UNREFERENCED_PARAMETER( IrpContext );

    return STATUS_SUCCESS;
}
Ejemplo n.º 19
0
NTSTATUS
FatFsdCleanup (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of closing down a handle to a
    file object.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Cleanup exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

#if __NDAS_FAT__

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

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

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    //
    //  If we were called with our file system device object instead of a
    //  volume device object, just complete this request with STATUS_SUCCESS
    //

    if ( FatDeviceIsFatFsdo( VolumeDeviceObject))  {

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

        IoCompleteRequest( Irp, IO_DISK_INCREMENT );

        return STATUS_SUCCESS;
    }

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

    //
    //  Call the common Cleanup routine, with blocking allowed.
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#if __NDAS_FAT__

	do {
	
		try {

			if (IrpContext == NULL) { 

				IrpContext = FatCreateIrpContext( Irp, TRUE );
				IrpContext->TopLevel = TopLevel;

#if __NDAS_FAT_PRIMARY__
			{
				ULONG_PTR				stackBottom;
				ULONG_PTR				stackTop;
			    BOOLEAN					ValidPrimaryRequest = FALSE;
				PPRIMARY_REQUEST_INFO	primaryRequestInfo;
				PIO_STACK_LOCATION		irpSp = IoGetCurrentIrpStackLocation( Irp );
    

				//primaryRequestInfo = (PPRIMARY_REQUEST_INFO)FatGetTopLevelContext()->SavedTopLevelIrp;
				primaryRequestInfo = (PPRIMARY_REQUEST_INFO)IoGetTopLevelIrp();
			    IoGetStackLimits( &stackTop, &stackBottom );

			    if ( (ULONG_PTR)primaryRequestInfo <= stackBottom - sizeof(PRIMARY_REQUEST_INFO)	&&
					 (ULONG_PTR) primaryRequestInfo >= stackTop										&&
					 (!FlagOn( (ULONG_PTR) primaryRequestInfo, 0x3 ))								&&
					 primaryRequestInfo->PrimaryTag == 0xe2027482) {										

					ValidPrimaryRequest = TRUE;
				}
					
				if (ValidPrimaryRequest) {
						
					//ASSERT( FatIsTopLevelRequest(IrpContext) );

					IoSetTopLevelIrp( NULL );
					TopLevel = FatIsIrpTopLevel( Irp );
					ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL );

					if (IsListEmpty(&VolumeDeviceObject->PrimarySessionQueue))
						ASSERT( FALSE );

					IrpContext->PrimaryRequestInfo = *primaryRequestInfo;

					DebugTrace2( 0, Dbg, ("primaryRequestInfo = %p\n", primaryRequestInfo) );
				}
			} 
#endif
			}

#if __NDAS_FAT_SECONDARY__

			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
				SetFlag( IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_FILE );

				Status = STATUS_SUCCESS;

				while (TRUE) {
										
					ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					ASSERT( secondaryResourceAcquired == FALSE );

					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) || 
						FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {
		
						if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
						
						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Secondary->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Secondary->Resource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
						try {
								
							SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Secondary->Resource, 
															  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

					if (secondaryResourceAcquired == FALSE) {

						ASSERT( FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ||
								FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING) );
						continue;
					}

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = FatCommonCleanup( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Secondary->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Secondary->Resource );
					}
				}

			} else
				Status = FatCommonCleanup( IrpContext, Irp );
#else
	        Status = FatCommonCleanup( IrpContext, Irp );
#endif

		} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

			//
	        //  We had some trouble trying to perform the requested
		    //  operation, so we'll abort the I/O request with
			//  the error status that we get back from the
	        //  execption code
		    //

			Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
		}

	} while (Status == STATUS_CANT_WAIT);
Ejemplo n.º 20
0
NTSTATUS
FatFsdQueryVolumeInformation (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the Fsd part of the NtQueryVolumeInformation API
    call.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the file
        being queried exists.

    Irp - Supplies the Irp being processed.

Return Value:

    NTSTATUS - The FSD status for the Irp.

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

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

    //
    //  Call the common query routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        Status = FatCommonQueryVolumeInfo( IrpContext, Irp );

    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Ejemplo n.º 21
0
ULONG
FatExceptionFilter (
    IN PIRP_CONTEXT IrpContext,
    IN PEXCEPTION_POINTERS ExceptionPointer
    )

/*++

Routine Description:

    This routine is used to decide if we should or should not handle
    an exception status that is being raised.  It inserts the status
    into the IrpContext and either indicates that we should handle
    the exception or bug check the system.

Arguments:

    ExceptionPointers - The result of GetExceptionInformation() in the context
        of the exception.

Return Value:

    ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks

--*/

{
    NTSTATUS ExceptionCode;

    ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode;
    DebugTrace(0, DEBUG_TRACE_UNWIND, "FatExceptionFilter %X\n", ExceptionCode);
    DebugDump("FatExceptionFilter\n", Dbg, NULL );

    //
    // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code
    // from the exception record.
    //

    if (ExceptionCode == STATUS_IN_PAGE_ERROR) {
        if (ExceptionPointer->ExceptionRecord->NumberParameters >= 3) {
            ExceptionCode = (NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2];
        }
    }

    //
    //  If there is not an irp context, we must have had insufficient resources.
    //

    if ( !ARGUMENT_PRESENT( IrpContext ) ) {

        if (!FsRtlIsNtstatusExpected( ExceptionCode )) {

#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
            FatBugCheck( (ULONG_PTR)ExceptionPointer->ExceptionRecord,
                         (ULONG_PTR)ExceptionPointer->ContextRecord,
                         (ULONG_PTR)ExceptionPointer->ExceptionRecord->ExceptionAddress );
        }

        return EXCEPTION_EXECUTE_HANDLER;
    }

    //
    //  For the purposes of processing this exception, let's mark this
    //  request as being able to wait and disable  write through if we
    //  aren't posting it.
    //

    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

    if ( (ExceptionCode != STATUS_CANT_WAIT) &&
         (ExceptionCode != STATUS_VERIFY_REQUIRED) ) {

        SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH);
    }

    if ( IrpContext->ExceptionStatus == 0 ) {

        if (FsRtlIsNtstatusExpected( ExceptionCode )) {

            IrpContext->ExceptionStatus = ExceptionCode;

            return EXCEPTION_EXECUTE_HANDLER;

        } else {

#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
            FatBugCheck( (ULONG_PTR)ExceptionPointer->ExceptionRecord,
                         (ULONG_PTR)ExceptionPointer->ContextRecord,
                         (ULONG_PTR)ExceptionPointer->ExceptionRecord->ExceptionAddress );
        }

    } else {

        //
        //  We raised this code explicitly ourselves, so it had better be
        //  expected.
        //

        ASSERT( IrpContext->ExceptionStatus == ExceptionCode );
        ASSERT( FsRtlIsNtstatusExpected( ExceptionCode ) );
    }

    return EXCEPTION_EXECUTE_HANDLER;
}
Ejemplo n.º 22
0
NTSTATUS
FatQueryFsAttributeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

Routine Description:

    This routine implements the query volume attribute call

Arguments:

    Vcb - Supplies the Vcb being queried

    Buffer - Supplies a pointer to the output buffer where the information
        is to be returned

    Length - Supplies the length of the buffer in byte.  This variable
        upon return recieves the remaining bytes free in the buffer

Return Value:

    Status - Returns the status for the query

--*/

{
    ULONG BytesToCopy;

    NTSTATUS Status;

    DebugTrace(0, Dbg, "FatQueryFsAttributeInfo...\n", 0);

    //
    //  Determine how much of the file system name will fit.
    //

    if ( (*Length - FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
                                  FileSystemName[0] )) >= 6 ) {

        BytesToCopy = 6;
        *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
                                 FileSystemName[0] ) + 6;
        Status = STATUS_SUCCESS;

    } else {

        BytesToCopy = *Length - FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
                                              FileSystemName[0]);
        *Length = 0;

        Status = STATUS_BUFFER_OVERFLOW;
    }

    //
    //  Set the output buffer
    //

    Buffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES |
                                   FILE_UNICODE_ON_DISK;

#ifdef WE_WON_ON_APPEAL

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

        SetFlag( Buffer->FileSystemAttributes, FILE_VOLUME_IS_COMPRESSED );
    }

#endif // WE_WON_ON_APPEAL

    Buffer->MaximumComponentNameLength = FatData.ChicagoMode ? 255 : 12;
    Buffer->FileSystemNameLength       = BytesToCopy;

    RtlCopyMemory( &Buffer->FileSystemName[0], L"FAT", BytesToCopy );

    //
    //  And return success to our caller
    //

    UNREFERENCED_PARAMETER( IrpContext );
    UNREFERENCED_PARAMETER( Vcb );

    return Status;
}
Ejemplo n.º 23
0
VOID
W2KNtfsCleanupAttributeContext (
    IN OUT PIRP_CONTEXT IrpContext,
    IN OUT PATTRIBUTE_ENUMERATION_CONTEXT AttributeContext
    )

/*++

Routine Description:

    This routine is called to free any resources claimed within an enumeration
    context and to unpin mapped or pinned data.

Arguments:

    IrpContext - context of the call

    AttributeContext - Pointer to the enumeration context to perform cleanup
                       on.

Return Value:

    None.

--*/

{

    UNREFERENCED_PARAMETER( IrpContext );

    PAGED_CODE();

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

    //
    //  TEMPCODE   We need a call to cleanup any Scb's created.
    //

    //
    //  Unpin any Bcb's pinned here.
    //

    NtfsUnpinBcb( IrpContext, &AttributeContext->FoundAttribute.Bcb );
    NtfsUnpinBcb( IrpContext, &AttributeContext->AttributeList.Bcb );
    NtfsUnpinBcb( IrpContext, &AttributeContext->AttributeList.NonresidentListBcb );

    //
    //  Originally, we zeroed the entire context at this point.  This is
    //  wildly inefficient since the context is either deallocated soon thereafter
    //  or is initialized again.
    //
    //  RtlZeroMemory( AttributeContext, sizeof(ATTRIBUTE_ENUMERATION_CONTEXT) );
    //

    //  BUGBUG - set entire contents to -1 (and reset Bcb's to NULL) to verify
    //  that no one reuses this data structure

#if DBG
    RtlFillMemory( AttributeContext, sizeof( *AttributeContext ), -1 );
    AttributeContext->FoundAttribute.Bcb = NULL;
    AttributeContext->AttributeList.Bcb = NULL;
    AttributeContext->AttributeList.NonresidentListBcb = NULL;
#endif

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

    return;
}
Ejemplo n.º 24
0
NTSTATUS
FatSetFsLabelInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_FS_LABEL_INFORMATION Buffer
    )

/*++

Routine Description:

    This routine implements the set volume label call

Arguments:

    Vcb - Supplies the Vcb being queried

    Buffer - Supplies the input where the information is stored.

Return Value:

    NTSTATUS - Returns the status for the operation

--*/

{
    NTSTATUS Status;

    PDIRENT Dirent;
    PBCB DirentBcb = NULL;
    ULONG ByteOffset;

    WCHAR TmpBuffer[11];
    UCHAR OemBuffer[11];
    OEM_STRING OemLabel;
    UNICODE_STRING UnicodeString;
    UNICODE_STRING UpcasedLabel;

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

    //
    //  Setup our local variable
    //

    UnicodeString.Length = (USHORT)Buffer->VolumeLabelLength;
    UnicodeString.MaximumLength = UnicodeString.Length;
    UnicodeString.Buffer = (PWSTR) &Buffer->VolumeLabel[0];

    //
    //  Make sure the name can fit into the stack buffer
    //

    if ( UnicodeString.Length > 11*sizeof(WCHAR) ) {

        return STATUS_INVALID_VOLUME_LABEL;
    }

    //
    //  Upcase the name and convert it to the Oem code page.
    //

    OemLabel.Buffer = &OemBuffer[0];
    OemLabel.Length = 0;
    OemLabel.MaximumLength = 11;

    Status = FatUpcaseUnicodeStringToCountedOemString( &OemLabel,
                                                       &UnicodeString,
                                                       FALSE );

    //
    //  Volume label that fits in 11 unicode character length limit
    //  is not necessary within 11 characters in OEM character set.
    //

    if (!NT_SUCCESS( Status )) {

        DebugTrace(-1, Dbg, "FatSetFsLabelInfo:  Label must be too long. %08lx\n", Status );

        return STATUS_INVALID_VOLUME_LABEL;
    }

    //
    //  Get the Unicode upcased string to store in the VPB.
    //

    UpcasedLabel.Length = UnicodeString.Length;
    UpcasedLabel.MaximumLength = 11*sizeof(WCHAR);
    UpcasedLabel.Buffer = &TmpBuffer[0];

    Status = RtlOemStringToCountedUnicodeString( &UpcasedLabel,
                                                 &OemLabel,
                                                 FALSE );

    if (!NT_SUCCESS( Status )) {

        DebugTrace(-1, Dbg, "FatSetFsLabelInfo:  Label must be too long. %08lx\n", Status );

        return STATUS_INVALID_VOLUME_LABEL;
    }

    DirentBcb = NULL;

    //
    //  Make this look like a write through to disk.  This is important to
    //  avoid a unpleasant window where it looks like we have the wrong volume.
    //

    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH );

    try {

        //
        //  Check for a label length other than zero.
        //

        if (OemLabel.Length > 0) {

            ULONG i;

            //
            //  Check the label for illegal characters
            //

            for (i=0; i < (ULONG)OemLabel.Length; i += 1) {

                if ( FsRtlIsLeadDbcsCharacter( OemLabel.Buffer[i] ) ) {

                    i += 1;
                    continue;
                }

                if (!FsRtlIsAnsiCharacterLegalFat(OemLabel.Buffer[i], FALSE) ||
                    (OemLabel.Buffer[i] == '.')) {

                    DebugTrace( 0, Dbg, "INVALID VOLUME LABEL\n", 0);

                    try_return( Status = STATUS_INVALID_VOLUME_LABEL );
                }
            }

            //
            //  Locate the volume label if there already is one
            //

            FatLocateVolumeLabel( IrpContext,
                                  Vcb,
                                  &Dirent,
                                  &DirentBcb,
                                  &ByteOffset );

            //
            //  Check that we really got one, if not then we need to create
            //  a new one.  The procedure we call will raise an appropriate
            //  status if we are not able to allocate a new dirent
            //

            if (Dirent == NULL) {

                ByteOffset = FatCreateNewDirent( IrpContext,
                                                 Vcb->RootDcb,
                                                 1 );

                FatPrepareWriteDirectoryFile( IrpContext,
                                              Vcb->RootDcb,
                                              ByteOffset,
                                              sizeof(DIRENT),
                                              &DirentBcb,
                                              &Dirent,
                                              FALSE,
                                              &Status );

                ASSERT( NT_SUCCESS( Status ));
            }

            //
            //  Now reconstruct the volume label dirent and mark it dirty
            //

            FatConstructLabelDirent( IrpContext,
                                     Dirent,
                                     &OemLabel );

            FatSetDirtyBcb( IrpContext, DirentBcb, Vcb );

            //
            //  Unpin the Bcb here so that we will get any IO errors
            //  here before changing the VPB label.
            //

            FatUnpinBcb( IrpContext, DirentBcb );
            FatUnpinRepinnedBcbs( IrpContext );

            //
            //  Now set the upcased label in the VPB
            //

            RtlCopyMemory( &Vcb->Vpb->VolumeLabel[0],
                           &UpcasedLabel.Buffer[0],
                           Buffer->VolumeLabelLength );

            Vcb->Vpb->VolumeLabelLength = (USHORT)Buffer->VolumeLabelLength;

        } else {

            //
            //  Otherwise we're trying to delete the label
            //  Locate the current volume label if there already is one
            //

            FatLocateVolumeLabel( IrpContext,
                                  Vcb,
                                  &Dirent,
                                  &DirentBcb,
                                  &ByteOffset );

            //
            //  Check that we really got one
            //

            if (Dirent == NULL) {

                try_return( Status = STATUS_SUCCESS );
            }

            //
            //  Now delete the current label.
            //

            Dirent->FileName[0] = FAT_DIRENT_DELETED;

            ASSERT( (Vcb->RootDcb->Specific.Dcb.UnusedDirentVbo == 0xffffffff) ||
                    RtlAreBitsSet( &Vcb->RootDcb->Specific.Dcb.FreeDirentBitmap,
                                   ByteOffset / sizeof(DIRENT),
                                   1 ) );

            RtlClearBits( &Vcb->RootDcb->Specific.Dcb.FreeDirentBitmap,
                          ByteOffset / sizeof(DIRENT),
                          1 );

            FatSetDirtyBcb( IrpContext, DirentBcb, Vcb );

            //
            //  Unpin the Bcb here so that we will get any IO errors
            //  here before changing the VPB label.
            //

            FatUnpinBcb( IrpContext, DirentBcb );
            FatUnpinRepinnedBcbs( IrpContext );

            //
            //  Now set the label in the VPB
            //

            Vcb->Vpb->VolumeLabelLength = 0;
        }

        Status = STATUS_SUCCESS;

    try_exit: NOTHING;
    } finally {

        DebugUnwind( FatSetFsALabelInfo );

        FatUnpinBcb( IrpContext, DirentBcb );

        DebugTrace(-1, Dbg, "FatSetFsALabelInfo -> STATUS_SUCCESS\n", 0);
    }

    return Status;
}
Ejemplo n.º 25
0
bool ActionStack::CheckUserInput(JButton inputKey)
{
    JButton key = inputKey;
    JButton trigger = (options[Options::REVERSETRIGGERS].number ? JGE_BTN_NEXT : JGE_BTN_PREV);
    if (mode == ACTIONSTACK_STANDARD)
    {        
        if (askIfWishesToInterrupt)
        {
            int x,y;
            if(observer->getInput()->GetLeftClickCoordinates(x, y))
            {
                key = handleInterruptRequest(inputKey, x, y);
            }
            
            if (JGE_BTN_SEC == key && gModRules.game.canInterrupt())
            {
                setIsInterrupting(askIfWishesToInterrupt);
                return true;
            }
            else if ((JGE_BTN_OK == key) || (trigger == key))
            {
                cancelInterruptOffer();
                return true;
            }
            else if ((JGE_BTN_PRI == key))
            {
                cancelInterruptOffer(DONT_INTERRUPT_ALL);
                return true;
            }
            return true;
        }
        else if (observer->isInterrupting)
        {
            if (JGE_BTN_SEC == key)
            {
                endOfInterruption();
                return true;
            }
        }
    }
    else if (mode == ACTIONSTACK_TARGET)
    {
        if (modal)
        {
            if (JGE_BTN_UP == key)
            {
                if (mObjects[mCurr])
                {
                    int n = getPreviousIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1);
                    if (n != -1 && n != mCurr && mObjects[mCurr]->Leaving(JGE_BTN_UP))
                    {
                        mCurr = n;
                        mObjects[mCurr]->Entering();
                        DebugTrace("ACTIONSTACK UP TO mCurr = " << mCurr);
                    }
                }
                return true;
            }
            else if (JGE_BTN_DOWN == key)
            {
                if( mObjects[mCurr])
                {
                    int n = getNextIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1);
                    if (n!= -1 && n != mCurr && mObjects[mCurr]->Leaving(JGE_BTN_DOWN))
                    {
                        mCurr = n;
                        mObjects[mCurr]->Entering();
                        DebugTrace("ACTIONSTACK DOWN TO mCurr " << mCurr);
                    }
                }
                return true;
            }
            else if (JGE_BTN_OK == key)
            {
                DebugTrace("ACTIONSTACK CLICKED mCurr = " << mCurr);

                observer->stackObjectClicked(((Interruptible *) mObjects[mCurr]));
                return true;
            }
            return true; //Steal the input to other layers if we're visible
        }
        if (JGE_BTN_CANCEL == key)
        {
            if (modal) modal = 0;
            else modal = 1;
            return true;
        }
    }
    return false;
}
static VOID
xixfs_NetEventDetectorProc(
		PVOID lpParameter   // thread data
	) {
	PNETEVTCTX	NetEvtCtx  = (PNETEVTCTX)lpParameter;
	NTSTATUS	ntStatus ;
	SOCKETLPX_ADDRESS_LIST	addressList ;
	LARGE_INTEGER	TimeOut ;
	LONG			idx_callbacks ;
	
	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Enter xixfs_NetEventDetectorProc \n"));


	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("[LFS] xixfs_NetEventDetectorProc: Initializing Networking event detector...\n")) ;
	//
	//	get the address list
	//
	ntStatus = LpxTdiGetAddressList(
			&NetEvtCtx->AddressList
		);
	if(!NT_SUCCESS(ntStatus)) {
		DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, 
			( "[LFS] xixfs_NetEventDetectorProc: LpxTdiGetAddressList() failed. NTSTATUS:%lu\n", ntStatus));
//		goto termination ;
	}

	DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
		("[LFS] xixfs_NetEventDetectorProc: Networking event detector started...\n")) ;

	// Main loop...
	while(1) {
		TimeOut.QuadPart = - NETEVT_FREQ ;
		ntStatus = KeWaitForSingleObject(
				&NetEvtCtx->ShutdownEvent,
				Executive,
				KernelMode,
				FALSE,
				&TimeOut
			);
		
		DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
			( "[LFS] xixfs_NetEventDetectorProc: NTSTATUS:%lu\n", ntStatus));

		if(0 == ntStatus) {
			DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
				( "[COM] xixfs_NetEventDetectorProc: ShutDown event received. NTSTATUS:%lu\n", ntStatus));
			break ;
		} else if(STATUS_TIMEOUT == ntStatus) {
			//
			//	Time Out.
			//
			DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
				( "[COM] xixfs_NetEventDetectorProc: Time out. Go ahead and check changes. NTSTATUS:%lu\n", ntStatus));
		} else {
			DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
				( "[COM] xixfs_NetEventDetectorProc: KeWaitForSingleObject() failed. NTSTATUS:%lu\n", ntStatus));
			break ;
		}

		//
		//	check changes
		//
		ntStatus = LpxTdiGetAddressList(
				&addressList
			);
		if(!NT_SUCCESS(ntStatus)) {
			DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, 
				( "[LFS] xixfs_NetEventDetectorProc: LpxTdiGetAddressList() failed. NTSTATUS:%lu\n", ntStatus));

			continue ;
		}

		xixfs_FindOutChanges(
				&NetEvtCtx->AddressList,
				&addressList,
				&NetEvtCtx->DisabledAddressList,
				&NetEvtCtx->EnabledAddressList
			);

		//
		//	call back
		//
		if(
			NetEvtCtx->DisabledAddressList.iAddressCount == 0 &&
			NetEvtCtx->EnabledAddressList.iAddressCount == 0
			) {

			continue ;
		}

		DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
			( "[LFS] xixfs_NetEventDetectorProc: Networking event detected.\n"));

		//
		//	call callbacks and update address list.
		//
		for(idx_callbacks = 0 ; idx_callbacks < NetEvtCtx->CallbackCnt ; idx_callbacks ++ ) {

			if(NetEvtCtx->Callbacks[idx_callbacks]) {
				NetEvtCtx->Callbacks[idx_callbacks](
						&NetEvtCtx->AddressList,
						&addressList,
						&NetEvtCtx->DisabledAddressList,
						&NetEvtCtx->EnabledAddressList,
						NetEvtCtx->CallbackContext[idx_callbacks]
					) ;
			} else {
				DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
					("[LFS] xixfs_NetEventDetectorProc: Callback #%d is NULL.\n", idx_callbacks)) ;
			}
		}

		RtlCopyMemory(&NetEvtCtx->AddressList, &addressList, sizeof(SOCKETLPX_ADDRESS_LIST)) ;
	}


//termination:
	DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM,
		("[LFS] Networking event detector terminated.\n")) ;

	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Exit xixfs_NetEventDetectorProc \n"));
	PsTerminateSystemThread(0) ;
}
Ejemplo n.º 27
0
// static
NamedType* NamedType::CreateFromArchive(TypeArchive& ar, uint32 id, TypeLib* typelib, StringIn qname)
{
	//ASSERT(typelib->m_loaded);
	/*
	if (!typelib->m_loaded)
	{
		typelib->m_loaded = true;

		char fullname[260];

		_makepath(fullname, "C:", "\\mmstudio\\Win32\\bin\\debug", typelib->m_typeinfo_filename->c_str(), "typeinfo");

		IO::FileByteStream file(new StringA(fullname), IO::FileMode_Read);
		TypeArchive ar2(TypeArchive::Mode_Load, &file);
		ar2.m_pGlobalNamespace = ar.m_pGlobalNamespace;
		ar2.m_bSortedDecls = ar.m_bSortedDecls;
		ar2.m_typestuff = ar.m_typestuff;

		ar2 >> ar2.m_typelib;

		uint ntypelibs;
		ar2 >> ntypelibs;
		for (uint i = 0; i < ntypelibs; i++)
		{
			TypeLib* typelib;
			ar2 >> typelib;
		}

		Namespace* pNamespace;
		ar2 >> pNamespace;

		uint ntypes;
		ar2 >> ntypes;

		for (i = 0; i < ntypes; i++)
		{
			NamedType* type;
			ar2 >> type;

			typelib->m_alltypes.insert(map<StringA*, NamedType*, Ref_Less<StringA> >::value_type(type->m_qname, type));
		}
	}
	*/

//	map<StringA*, NamedType*, Ref_Less<StringA> >::iterator it = typelib->m_typesByName.find(qname);

	NamedType* pobj = typelib->FindNamedType(qname);
	if (pobj == NULL)
	{
		/*
		char buffer[1024];
		sprintf_s(buffer, "'%S' imports '%S', but couldn't find type '%s'\n", ar.m_typelib->m_typeinfo_filename->c_str(), typelib->m_typeinfo_filename->c_str(), qname->c_str());
	//	throw std::exception(buffer);
		printf(buffer);
		*/

		DebugTrace(__FILE__ <<  paren(__LINE__) << " : TODO; FIX BUG HERE\n");

	//	ASSERT(0);
		ar.m_typeLoad.push_back(NULL);

		return NULL;
	}
	else
	{

	//	ar.m_objectmapLoad.insert(map<uint32, TypeSerializable*>::value_type(id, pobj));
		if (ar.m_typeLoad.size() < id+1) ar.m_typeLoad.resize(id+1);
		ar.m_typeLoad[id] = pobj;
	//	ASSERT(ar.m_typeLoad.size() == id);

		return pobj;
	}
}
//
//	open a datagram socket
//
NTSTATUS
xixfs_OpenDGSocket(
	OUT PLFSDG_Socket		Socket,
	IN USHORT				PortNo
) {
	HANDLE						addressFileHandle = NULL;
	HANDLE						connectionFileHandle = NULL;
	PFILE_OBJECT					addressFileObject = NULL;
	PFILE_OBJECT					connectionFileObject = NULL;
	NTSTATUS					ntStatus ;
	SOCKETLPX_ADDRESS_LIST		socketLpxAddressList;
	LONG						idx_addr ;
	ULONG						open_addr ;

	LPX_ADDRESS				NICAddr ;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Enter  xixfs_OpenDGSocket \n"));
	

	Socket->SocketCnt = 0 ;

	//
	//	get addresses from LPX
	//
	ntStatus = LpxTdiGetAddressList(
				&socketLpxAddressList
   				 ) ;
	
	if(!NT_SUCCESS(ntStatus)) {
		return ntStatus;
	}
	if(0 == socketLpxAddressList.iAddressCount) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}


	//
	//	open a port for each NIC.
	//
	open_addr = 0 ;

	for(idx_addr = 0 ; idx_addr < socketLpxAddressList.iAddressCount; idx_addr ++) {

		if( (0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[0]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[1]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[2]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[3]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[4]) &&
			(0 == socketLpxAddressList.SocketLpx[idx_addr].LpxAddress.Node[5]) ) {
			continue ;
		}

		RtlCopyMemory(&NICAddr, &socketLpxAddressList.SocketLpx[idx_addr].LpxAddress, sizeof(LPX_ADDRESS)) ;
		NICAddr.Port = HTONS(PortNo) ;

		//
		//	open a connection and address.
		//	if this calling for a datagram server, don't create a connection.
		//
		ntStatus = LpxTdiOpenAddress(
				&addressFileHandle,
				&addressFileObject,
				&NICAddr
			);
		if(!NT_SUCCESS(ntStatus)) {
			DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL, 
				( "[LFS] xixfs_OpenDGSocket: couldn't open a address %d:'%02X:%02X:%02X:%02X:%02X:%02X/%d'\n",
						idx_addr,
						NICAddr.Node[0],NICAddr.Node[1],NICAddr.Node[2],
						NICAddr.Node[3],NICAddr.Node[4],NICAddr.Node[5],
						(int)NTOHS(NICAddr.Port) ) );
			continue ;
		}


		DebugTrace(DEBUG_LEVEL_INFO, DEBUG_TARGET_HOSTCOM, 
			( "[LFS] xixfs_OpenDGSocket: opened a address:'%02X:%02X:%02X:%02X:%02X:%02X/%d'\n",
					NICAddr.Node[0],NICAddr.Node[1],NICAddr.Node[2],
					NICAddr.Node[3],NICAddr.Node[4],NICAddr.Node[5],
					(int)NTOHS(NICAddr.Port)
			) );
		//
		//	return values
		//	close handles, but leave objects
		//
		Socket->Sockets[open_addr].AddressFile = addressFileObject ;
		Socket->Sockets[open_addr].AddressFileHandle = addressFileHandle ;
		RtlCopyMemory(&Socket->Sockets[open_addr].NICAddr, &NICAddr, sizeof(LPX_ADDRESS)) ;

		open_addr ++ ;


	}

	Socket->SocketCnt = (USHORT)open_addr ;
	
	DebugTrace(DEBUG_LEVEL_TRACE, DEBUG_TARGET_HOSTCOM,
		("Exit  xixfs_OpenDGSocket \n"));
	return ntStatus ;
}
Ejemplo n.º 29
0
/*************************************************************************
*
* Function: Ext2CommonClose()
*
* Description:
*	The actual work is performed here. This routine may be invoked in one'
*	of the two possible contexts:
*	(a) in the context of a system worker thread
*	(b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS NTAPI Ext2CommonClose(
PtrExt2IrpContext			PtrIrpContext,
PIRP						PtrIrp,
BOOLEAN						FirstAttempt )
{
	NTSTATUS					RC = STATUS_SUCCESS;
	PIO_STACK_LOCATION	PtrIoStackLocation = NULL;
	PFILE_OBJECT			PtrFileObject = NULL;
	PtrExt2FCB				PtrFCB = NULL;
	PtrExt2CCB				PtrCCB = NULL;
	PtrExt2VCB				PtrVCB = NULL;
	PtrExt2NTRequiredFCB	PtrReqdFCB = NULL;
	PERESOURCE				PtrResourceAcquired = NULL;
	PERESOURCE				PtrPagingIoResourceAcquired = NULL;

	BOOLEAN					CompleteIrp = TRUE;
	BOOLEAN					PostRequest = FALSE;
	BOOLEAN					AcquiredVCB = FALSE;
	BOOLEAN					BlockForResource;
	int						i = 1;

	try 
	{
		// First, get a pointer to the current I/O stack location
		PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
		ASSERT(PtrIoStackLocation);

		PtrFileObject = PtrIoStackLocation->FileObject;
		ASSERT(PtrFileObject);

		if( !PtrFileObject->FsContext2 )
		{
			//	This must be a Cleanup request received 
			//	as a result of IoCreateStreamFileObject
			//	Only such a File object would have a NULL CCB

			DebugTrace( DEBUG_TRACE_SPECIAL, " === Close with NULL CCB", 0);
			if( PtrFileObject )
			{
				DebugTrace( DEBUG_TRACE_SPECIAL, "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}
			try_return();
		}

		// Get the FCB and CCB pointers

		Ext2GetFCB_CCB_VCB_FromFileObject ( 
			PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );

		PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
		ASSERT( PtrVCB );

		if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
		//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
		{
			DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
		}
		else
		{
			DebugTrace(DEBUG_TRACE_FILE_NAME,   " === Close File Name : -null-", 0);
		}

		//	(a) Acquiring the VCBResource Exclusively...
		//	This is done to synchronise with the close and cleanup routines...
//		if( ExTryToAcquireResourceExclusiveLite(&(PtrVCB->VCBResource) ) )

		BlockForResource = !FirstAttempt;
		if( !FirstAttempt )
		{
			DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Close]", 0);
		}
		else
		{
			DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [Close]", 0);
		}
		if( PtrFileObject )
		{
			DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
		}

		i = 1;
		while( !AcquiredVCB )
		{
			DebugTraceState( "VCB       AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
			if(! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
			{
				DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Acquisition FAILED [Close]", 0);
				if( BlockForResource && i != 1000 )
				{
					LARGE_INTEGER Delay;
					
					//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY	);

					Delay.QuadPart = -500 * i;
					KeDelayExecutionThread( KernelMode, FALSE, &Delay );
					DebugTrace(DEBUG_TRACE_MISC,  "*** Retrying... after 50 * %ld ms [Close]", i);
				}
				else
				{
					if( i == 1000 )
						DebugTrace(DEBUG_TRACE_MISC,  "*** Reposting... [Close]", 0 );
					PostRequest = TRUE;
					try_return( RC = STATUS_PENDING );
				}
			}
			else
			{
				DebugTrace(DEBUG_TRACE_MISC,  "*** VCB Acquired in [Close]", 0);
				AcquiredVCB = TRUE;
			}
			i *= 10;
		}

		//	(b) Acquire the file (FCB) exclusively
		if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
		{
			//	This FCB is an FCB indeed. ;)
			//	So acquiring it exclusively...
			//	This is done to synchronise with read/write routines...
			if( !FirstAttempt )
			{
				DebugTrace(DEBUG_TRACE_MISC,   "*** Going into a block to acquire FCB Exclusively [Close]", 0);
			}
			else
			{
				DebugTrace(DEBUG_TRACE_MISC,  "*** Attempting to acquire FCB Exclusively [Close]", 0);
			}
			if( PtrFileObject )
			{
				DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}

			PtrReqdFCB = &PtrFCB->NTRequiredFCB;

			i = 1;
			while( !PtrResourceAcquired )
			{
				DebugTraceState( "FCBMain   AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
				if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->MainResource), FALSE ) )
				{
					DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquisition FAILED [Close]", 0);
					if( BlockForResource && i != 1000 )
					{
						LARGE_INTEGER Delay;
						
						//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY	);

						Delay.QuadPart = -500 * i;
						KeDelayExecutionThread( KernelMode, FALSE, &Delay );
						DebugTrace(DEBUG_TRACE_MISC,  "*** Retrying... after 50 * %ld ms [Close]", i);
					}
					else
					{
						if( i == 1000 )
							DebugTrace(DEBUG_TRACE_MISC,  "*** Reposting... [Close]", 0 );
						PostRequest = TRUE;
						try_return( RC = STATUS_PENDING );
					}
				}
				else
				{
					DebugTrace(DEBUG_TRACE_MISC,  "*** FCB acquired [Close]", 0);
					PtrResourceAcquired = & ( PtrReqdFCB->MainResource );
				}
				i *= 10;
			}

			i = 1;
			while( !PtrPagingIoResourceAcquired )
			{
				DebugTraceState( "FCBPaging   AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
				if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->PagingIoResource), FALSE ) )
				{
					DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquisition FAILED [Close]", 0);
					if( BlockForResource && i != 1000 )
					{
						LARGE_INTEGER Delay;
						
						// KeSetPriorityThread( PsGetCurrentThread(), LOW_REALTIME_PRIORITY );

						Delay.QuadPart = -500 * i;
						KeDelayExecutionThread( KernelMode, FALSE, &Delay );
						DebugTrace(DEBUG_TRACE_MISC,  "*** Retrying... after 50 * %ld ms [Close]", i);
					}
					else
					{
						if( i == 1000 )
							DebugTrace(DEBUG_TRACE_MISC,  "*** Reposting... [Close]", 0 );
						PostRequest = TRUE;
						try_return( RC = STATUS_PENDING );
					}
				}
				else
				{
					DebugTrace(DEBUG_TRACE_MISC,  "*** FCB acquired [Close]", 0);
					PtrPagingIoResourceAcquired = & ( PtrReqdFCB->PagingIoResource );
				}
				i *= 10;
			}

			// (c) Delete the CCB structure (free memory)
			RemoveEntryList( &PtrCCB->NextCCB );
			Ext2ReleaseCCB( PtrCCB );
			PtrFileObject->FsContext2 = NULL;

			// (d) Decrementing the Reference Count...
			if( PtrFCB->ReferenceCount )
			{
				InterlockedDecrement( &PtrFCB->ReferenceCount );
			}
			else
			{
				Ext2BreakPoint();
			}	
			DebugTrace(DEBUG_TRACE_REFERENCE,  "^^^^^ReferenceCount = 0x%lX [Close]", PtrFCB->ReferenceCount );
			DebugTrace(DEBUG_TRACE_REFERENCE,  "^^^^^OpenHandleCount = 0x%lX [Close]", PtrFCB->OpenHandleCount );
			if( PtrFCB->ReferenceCount == 0 )
			{

				//	Attempting to update time stamp values
				//	Errors are ignored...
				//	Not considered as critical errors...
				
				{
					ULONG			CreationTime, AccessTime, ModificationTime;
					EXT2_INODE		Inode;

					CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart 
									- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
					AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart 
									- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
					ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
									- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
					if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
					{
						//	Update time stamps in the inode...
						Inode.i_ctime = CreationTime;
						Inode.i_atime = AccessTime;
						Inode.i_mtime = ModificationTime;

						//	Updating the inode...
						Ext2WriteInode( NULL, PtrVCB, PtrFCB->INodeNo, &Inode );
					}
				}


				if( PtrFCB->INodeNo == EXT2_ROOT_INO )
				{
					//
					//	Root Directory FCB
					//	Preserve this
					//	FSD has a File Object for this FCB...
					//
					DebugTrace(DEBUG_TRACE_MISC,  "^^^^^Root Directory FCB ; leaveing it alone[Close]", 0);
					//	Do nothing...
					
				}
				else if( PtrFCB->DcbFcb.Dcb.PtrDirFileObject )
				{
					//
					//	If this is a FCB created on the FSD's initiative
					//	Leave it alone
					//
					DebugTrace(DEBUG_TRACE_MISC,  "^^^^^FCB Created  on the FSD's initiative; leaveing it alone[Close]", 0);
					if( !PtrFCB->ClosableFCBs.OnClosableFCBList )
					{
						InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
							&PtrFCB->ClosableFCBs.ClosableFCBList );
						PtrVCB->ClosableFCBs.Count++;

						PtrFCB->ClosableFCBs.OnClosableFCBList = TRUE;
					}
					
					if( PtrVCB->ClosableFCBs.Count > EXT2_MAXCLOSABLE_FCBS_UL )
					{
						PtrExt2FCB		PtrTempFCB = NULL;
						//	Checking if Closable FCBs are too many in number...
						//	Shouldn't block the 
						//	Should do this asynchronously...
						//	Maybe later...
						PLIST_ENTRY		PtrEntry = NULL;

						PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead );
						
						PtrTempFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList );
						if( Ext2CloseClosableFCB( PtrTempFCB ) )
						{
							DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Close]", PtrTempFCB );
							ExFreePool( PtrTempFCB );
							PtrVCB->ClosableFCBs.Count--;
						}
						else
						{
							//	Put the FCB back in the list...
							InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
								&PtrTempFCB->ClosableFCBs.ClosableFCBList );
						}
						DebugTrace( DEBUG_TRACE_SPECIAL, "ClosableFCBs Count = %ld [Close]", PtrVCB->ClosableFCBs.Count );
					}
				}
				else
				{
					//	Remove this FCB as well...
					DebugTrace(DEBUG_TRACE_MISC,  "^^^^^Deleting FCB  [Close]", 0);
					RemoveEntryList( &PtrFCB->NextFCB );

					if ( PtrPagingIoResourceAcquired )
					{
						Ext2ReleaseResource(PtrPagingIoResourceAcquired);
						DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
							PtrPagingIoResourceAcquired->ActiveCount, 
							PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters, 
							PtrPagingIoResourceAcquired->NumberOfSharedWaiters );

						PtrPagingIoResourceAcquired = NULL;
					}

					if ( PtrResourceAcquired ) 
					{
						Ext2ReleaseResource(PtrResourceAcquired);
						DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released [Close]", 0);
						DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
							PtrResourceAcquired->ActiveCount, 
							PtrResourceAcquired->NumberOfExclusiveWaiters, 
							PtrResourceAcquired->NumberOfSharedWaiters );

						if( PtrFileObject )
						{
							DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
						}
						PtrResourceAcquired = NULL;
					}

					Ext2ReleaseFCB( PtrFCB );
				}

			}
			CompleteIrp = TRUE;
		}
		else
		{
			//	This must be a volume close...
			//	What do I do now? ;)
			DebugTrace(DEBUG_TRACE_MISC,   "VCB Close Requested !!!", 0);
			CompleteIrp = TRUE;
		}
		try_return();
		
		try_exit:	NOTHING;

	} 
	finally 
	{
		if ( PtrPagingIoResourceAcquired )
		{
			Ext2ReleaseResource(PtrPagingIoResourceAcquired);
			DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
				PtrPagingIoResourceAcquired->ActiveCount,
				PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters,
				PtrPagingIoResourceAcquired->NumberOfSharedWaiters );

			PtrPagingIoResourceAcquired = NULL;
		}

		if ( PtrResourceAcquired ) 
		{
			Ext2ReleaseResource(PtrResourceAcquired);
			DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released [Close]", 0);
			DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
				PtrResourceAcquired->ActiveCount, 
				PtrResourceAcquired->NumberOfExclusiveWaiters, 
				PtrResourceAcquired->NumberOfSharedWaiters );

			if( PtrFileObject )
			{
				DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}
			PtrResourceAcquired = NULL;
		}

		if (AcquiredVCB) 
		{
			ASSERT(PtrVCB);
			Ext2ReleaseResource(&(PtrVCB->VCBResource));
			DebugTraceState( "VCB       AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
			DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Released [Close]", 0);

			AcquiredVCB = FALSE;
			if( PtrFileObject )
			{
				DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}
			
		}

		if( PostRequest )
		{
			RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
		}
		else if( CompleteIrp && RC != STATUS_PENDING )
		{
			// complete the IRP
			IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );

			Ext2ReleaseIrpContext( PtrIrpContext );
		}

	} // end of "finally" processing

	return(RC);
}
Ejemplo n.º 30
0
VOID
NtfsPreparePinWriteStream (
    IN PIRP_CONTEXT IrpContext,
    IN PSCB Scb,
    IN LONGLONG FileOffset,
    IN ULONG Length,
    IN BOOLEAN Zero,
    OUT PVOID *Bcb,
    OUT PVOID *Buffer
    )

/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_SCB( Scb );

    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsPreparePinWriteStream\n") );
    DebugTrace( 0, Dbg, ("Scb        = %08lx\n", Scb) );
    DebugTrace( 0, Dbg, ("FileOffset = %016I64x\n", FileOffset) );
    DebugTrace( 0, Dbg, ("Length     = %08lx\n", Length) );

    //
    //  The file object should already exist in the Scb.
    //

    ASSERT( Scb->FileObject != NULL );

    //
    //  If we are trying to go beyond the end of the allocation, assume
    //  we have some corruption.
    //

    if ((FileOffset + Length) > Scb->Header.AllocationSize.QuadPart) {

        NtfsRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Scb->Fcb );
    }

    //
    //  Call the cache manager to do it.  This call may raise, or
    //  will return FALSE if waiting is required.
    //

    if (!CcPreparePinWrite( Scb->FileObject,
                            (PLARGE_INTEGER)&FileOffset,
                            Length,
                            Zero,
                            FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ),
                            Bcb,
                            Buffer )) {

        ASSERT( !FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ));

        //
        // Could not pin the data without waiting (cache miss).
        //

        NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL );
    }
#ifdef MAPCOUNT_DBG
    IrpContext->MapCount++;
#endif

    DebugTrace( 0, Dbg, ("Bcb -> %08lx\n", *Bcb) );
    DebugTrace( 0, Dbg, ("Buffer -> %08lx\n", *Buffer) );
    DebugTrace( -1, Dbg, ("NtfsPreparePinWriteStream -> VOID\n") );

    return;
}