Ejemplo n.º 1
0
NTSTATUS
XixFsClearFileContext(
	PXIFS_FILE_EMUL_CONTEXT FileContext
)
{

	NTSTATUS	RC = STATUS_SUCCESS;

	PAGED_CODE();
	
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Enter XixFsClearFileContext .\n"));

	try{
		if(FileContext->Buffer){
			ExFreePool(FileContext->Buffer);
			FileContext->Buffer = NULL;
		}
	}finally{
		if(AbnormalTermination()){
			RC = STATUS_INSUFFICIENT_RESOURCES;
		}
	}

	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Exit XixFsClearFileContext .\n"));
	return RC;
}
Ejemplo n.º 2
0
int main() {
  LONG Counter;

  Counter = 0;

  try {
    if (Echo(Counter) == Counter) {
      Counter += 3;
      leave;
    } else {
      Counter += 100;
    }
  }
  finally {
    if (AbnormalTermination() == 0) {
      Counter += 5;
    }
  }

  if (Counter != 8) {
    printf("test 51 failed.  Counter = %d\n", Counter);
    return -1;
  }

  return 0;
}
Ejemplo n.º 3
0
__drv_mustHoldCriticalRegion
FINISHED
FatAcquireExclusiveVcb_Real (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,    
    IN BOOLEAN NoOpCheck
    )

/*++

Routine Description:

    This routine acquires exclusive access to the Vcb.

    After we acquire the resource check to see if this operation is legal.
    If it isn't (ie. we get an exception), release the resource.

Arguments:

    Vcb - Supplies the Vcb to acquire

    NoOpCheck - if TRUE then don't do any verification of the request/volume state.

Return Value:

    FINISHED - TRUE if we have the resource and FALSE if we needed to block
        for the resource but Wait is FALSE.

--*/

{
    PAGED_CODE();

#pragma prefast( suppress: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
    if (ExAcquireResourceExclusiveLite( &Vcb->Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) {

        if (!NoOpCheck) {
            
            try {

                FatVerifyOperationIsLegal( IrpContext );

            } finally {

                if ( AbnormalTermination() ) {

                    FatReleaseVcb( IrpContext, Vcb );
                }
            }
        }

        return TRUE;
    }

    return FALSE;
}
Ejemplo n.º 4
0
//拷贝字符
bool CWHService::SetClipboardString(LPCTSTR pszString)
{
	//变量定义
	HANDLE hData=NULL;
	BOOL bOpenClopboard=FALSE;

	//执行逻辑
	__try
	{
		//打开拷贝
		bOpenClopboard=OpenClipboard(AfxGetMainWnd()->m_hWnd);
		if (bOpenClopboard==FALSE) __leave;

		//清空拷贝
		if (EmptyClipboard()==FALSE) __leave;

		//申请内存
		HANDLE hData=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,CountStringBuffer(pszString));
		if (hData==NULL) __leave;

		//复制数据
		lstrcpy((LPTSTR)GlobalLock(hData),pszString);
		GlobalUnlock(hData);

		//设置数据
		#ifndef _UNICODE
			::SetClipboardData(CF_TEXT,hData);
		#else
			::SetClipboardData(CF_UNICODETEXT,hData);
		#endif
	}

	//终止程序
	__finally
	{
		//释放内存
		if (hData!=NULL) GlobalUnlock(hData);

		//关闭拷贝
		if (bOpenClopboard==TRUE) CloseClipboard();

		//错误判断
		if (AbnormalTermination()==TRUE)
		{
			ASSERT(FALSE);
		}
	}

	return true;
}
Ejemplo n.º 5
0
FINISHED
FatAcquireSharedVcb (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb
    )

/*++

Routine Description:

    This routine acquires shared access to the Vcb.

    After we acquire the resource check to see if this operation is legal.
    If it isn't (ie. we get an exception), release the resource.

Arguments:

    Vcb - Supplies the Vcb to acquire

Return Value:

    FINISHED - TRUE if we have the resource and FALSE if we needed to block
        for the resource but Wait is FALSE.

--*/

{
    PAGED_CODE();

#pragma prefast( suppress: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
    if (ExAcquireResourceSharedLite( &Vcb->Resource, 
                                     BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) {

        try {

            FatVerifyOperationIsLegal( IrpContext );

        } finally {

            if ( AbnormalTermination() ) {

                FatReleaseVcb( IrpContext, Vcb );
            }
        }

        return TRUE;
    }

    return FALSE;
}
Ejemplo n.º 6
0
FINISHED
FatAcquireExclusiveVcb (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb
    )

/*++

Routine Description:

    This routine acquires exclusive access to the Vcb.

    After we acquire the resource check to see if this operation is legal.
    If it isn't (ie. we get an exception), release the resource.

Arguments:

    Vcb - Supplies the Vcb to acquire

Return Value:

    FINISHED - TRUE if we have the resource and FALSE if we needed to block
        for the resource but Wait is FALSE.

--*/

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

        try {

            FatVerifyOperationIsLegal( IrpContext );

        } finally {

            if ( AbnormalTermination() ) {

                FatReleaseVcb( IrpContext, Vcb );
            
            }
        }

        return TRUE;

    } else {

        return FALSE;
Ejemplo n.º 7
0
NTSTATUS
XixFsSetFileContext(
	PXIFS_VCB	pVCB,
	uint64	LotNumber,
	uint32	FileType,
	PXIFS_FILE_EMUL_CONTEXT FileContext
)
{
	NTSTATUS	RC = STATUS_SUCCESS;

	PAGED_CODE();
	
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Enter XixFsSetFileContext .\n"));


	FileContext->pVCB = pVCB;
	FileContext->LotNumber = LotNumber;
	FileContext->FileType = FileType;
	FileContext->pSearchedFCB = NULL;
	try{
		if(FileContext->Buffer == NULL){
			FileContext->Buffer = 
				ExAllocatePoolWithTag(NonPagedPool,XIDISK_FILE_HEADER_LOT_SIZE, TAG_BUFFER);
		}
	}finally{
		if(AbnormalTermination()){
			RC = STATUS_INSUFFICIENT_RESOURCES;
		}
	}

	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Exit XixFsSetFileContext .\n"));

	return RC;
}
Ejemplo n.º 8
0
NTSTATUS
XixFsReadFileInfoFromContext(
	BOOLEAN					Waitable,
	PXIFS_FILE_EMUL_CONTEXT FileContext
)
{
	NTSTATUS RC = STATUS_SUCCESS;
	PXIDISK_FILE_HEADER_LOT pFileHeader = NULL;
	PXIFS_VCB	pVCB = NULL;
	LARGE_INTEGER	Offset;
	uint32	BlockSize;
	uint32	LotType = LOT_INFO_TYPE_INVALID;
	uint32	Reason = 0;

	PAGED_CODE();
	
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Enter XixFsReadFileInfoFromContext.\n"));

	ASSERT(Waitable == TRUE);
	ASSERT(FileContext);
	pVCB = FileContext->pVCB;
	ASSERT_VCB(pVCB);


	DebugTrace( DEBUG_LEVEL_INFO, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
					 ("FileContext Searched LotNumber(%I64d) FileType(%ld)\n", 
					 FileContext->LotNumber,
					 FileContext->FileType
					 ));
	
	FileContext->pSearchedFCB = NULL;	


		
	try{
		if(FileContext->Buffer == NULL){
			FileContext->Buffer = 
				ExAllocatePoolWithTag(NonPagedPool,XIDISK_FILE_HEADER_LOT_SIZE, TAG_BUFFER);
		}
	}finally{
		if(AbnormalTermination()){
			RC = STATUS_INSUFFICIENT_RESOURCES;
		}

	}

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


	try{
		RC = XixFsRawReadLotAndFileHeader(
				pVCB->TargetDeviceObject,
				pVCB->LotSize,
				FileContext->LotNumber,
				FileContext->Buffer,
				XIDISK_FILE_HEADER_LOT_SIZE,
				pVCB->SectorSize
				);
				
		if(!NT_SUCCESS(RC)){
			DebugTrace(DEBUG_LEVEL_ALL, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
						("Fail Read File Data(%I64d).\n", FileContext->LotNumber));
			try_return (RC);
		}	
		
		pFileHeader = (PXIDISK_FILE_HEADER_LOT)FileContext->Buffer;

		// Check Header
		if(FileContext->FileType ==  FCB_TYPE_DIR){
			LotType = LOT_INFO_TYPE_DIRECTORY;
		}else{
			LotType = LOT_INFO_TYPE_FILE;
		}

		RC = XixFsCheckLotInfo(
				&pFileHeader->LotHeader.LotInfo,
				pVCB->VolumeLotSignature,
				FileContext->LotNumber,
				LotType,
				LOT_FLAG_BEGIN,
				&Reason
				);

		if(!NT_SUCCESS(RC)){
			RC = STATUS_FILE_CORRUPT_ERROR;
			try_return(RC);
		}
		
	}finally{

	}

	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Exit XixFsReadFileInfoFromContext Status (0x%x).\n", RC));

	return RC;
}
Ejemplo n.º 9
0
NTSTATUS
NdFatSecondaryCommonWrite3 (
	IN PIRP_CONTEXT IrpContext,
	IN PIRP			Irp
	)
{
	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 Write				write;
	
	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;

	BOOLEAN						writeToEof;
	PUCHAR						inputBuffer;
	ULONG						totalWriteLength;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
	ASSERT (!FlagOn(Irp->Flags, IRP_PAGING_IO));
	
	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) );

			status = STATUS_FILE_CORRUPT_ERROR;
	        FatCompleteRequest( IrpContext, Irp, status );
			return status;
		}
	}

	writeToEof = (irpSp->Parameters.Write.ByteOffset.QuadPart == FILE_WRITE_TO_END_OF_FILE && 
				  irpSp->Parameters.Write.ByteOffset.HighPart == -1);

	write.ByteOffset	= irpSp->Parameters.Write.ByteOffset;
	write.Key			= irpSp->Parameters.Write.Key;
	write.Length		= irpSp->Parameters.Write.Length;

	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( Dbg, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );

			if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
	
				try_return( status = STATUS_FILE_LOCK_CONFLICT );
				
			} else {

				FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
			}
		}

		inputBuffer = FatMapUserBuffer( IrpContext, Irp );
		totalWriteLength = 0;

		do {

			ULONG	inputBufferLength;
			_U8		*ndfsWinxpRequestData;
			_U64	primaryFileHandle;

			if (fcb->UncleanCount == 0) {

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

				totalWriteLength = write.Length;
				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 );

			inputBufferLength = ((write.Length-totalWriteLength) <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize) 
									? (write.Length-totalWriteLength) : volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize;

			secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, 
															  IRP_MJ_WRITE,
															  volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize );

			if (secondaryRequest == NULL) {

				FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
			}

			ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
			INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_WRITE, inputBufferLength );

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

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

			ndfsWinxpRequestHeader->FileHandle = primaryFileHandle;

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

			ndfsWinxpRequestHeader->Write.Length		= inputBufferLength;
			ndfsWinxpRequestHeader->Write.Key			= write.Key;
			if (writeToEof)
				ndfsWinxpRequestHeader->Write.ByteOffset = write.ByteOffset.QuadPart;
			else
				ndfsWinxpRequestHeader->Write.ByteOffset = write.ByteOffset.QuadPart + totalWriteLength;
			
			ndfsWinxpRequestHeader->Write.ForceWrite	= TRUE;


			DebugTrace2( 0, Dbg, ("ndfsWinxpRequestHeader->Write.ByteOffset = %I64d, ndfsWinxpRequestHeader->Write.Length = %d\n", 
								   ndfsWinxpRequestHeader->Write.ByteOffset, ndfsWinxpRequestHeader->Write.Length) );

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

			if (inputBufferLength) {

				try {

					RtlCopyMemory( ndfsWinxpRequestData,
								   inputBuffer + totalWriteLength,
								   inputBufferLength );

				} except (EXCEPTION_EXECUTE_HANDLER) {

					DebugTrace2( 0, Dbg2, ("RedirectIrp: Exception - Input buffer is not valid\n") );
					
					status = GetExceptionCode();
					break;
				}
			}

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

			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__) );

				if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
	
					try_return( status = STATUS_FILE_LOCK_CONFLICT );
				
				} else {

					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}
			}

			ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

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

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

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

			totalWriteLength += ndfsWinxpReplytHeader->Information;

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

		} while( totalWriteLength < write.Length );

try_exit: NOTHING;

	} finally {

		if (!AbnormalTermination()) {
			
			if (totalWriteLength) {

				Irp->IoStatus.Information = totalWriteLength;
				Irp->IoStatus.Status = STATUS_SUCCESS;
		
			} else {
		
				Irp->IoStatus.Information = 0;
				Irp->IoStatus.Status = status;
			}
		}

		DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart = %I64x, write.Length = %x, totalWriteRequestLength = %x lastStatus = %x\n", 
								write.ByteOffset.QuadPart, write.Length, totalWriteLength, status) );

		if (!FlagOn(ccb->NdFatFlags, ND_FAT_CLEANUP_COMPLETE) && Irp->IoStatus.Status != STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart = %I64x, write.Length = %x, totalWriteRequestLength = %x lastStatus = %x\n", 
								 write.ByteOffset.QuadPart, write.Length, totalWriteLength, status) );

			PrintIrp( Dbg, "RedirectIrpMajorWrite", NULL, Irp );
		}

		if (secondarySessionResourceAcquired == TRUE)
			SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );

		if (fcbAcquired) {
             FatReleaseFcb( IrpContext, fcb );
        }

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}
			
	FatCompleteRequest( IrpContext, Irp, status );
	return status;
}
Ejemplo n.º 10
0
NTSTATUS
NtfsCommonLockControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for Lock Control called by both the fsd and fsp
    threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;
    BOOLEAN FcbAcquired = FALSE;

    BOOLEAN OplockPostIrp;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get a pointer to the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonLockControl\n") );
    DebugTrace( 0, Dbg, ("IrpContext    = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp           = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("MinorFunction = %08lx\n", IrpSp->MinorFunction) );

    //
    //  Extract and decode the type of file object we're being asked to process
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  If the file is not a user file open then we reject the request
    //  as an invalid parameter
    //

    if (TypeOfOpen != UserFileOpen) {

        NtfsCompleteRequest( &IrpContext, &Irp, STATUS_INVALID_PARAMETER );

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

    //
    //  Acquire exclusive access to the Fcb
    //

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

        NtfsAcquireExclusiveFcb( IrpContext, Fcb, Scb, FALSE, FALSE );
        FcbAcquired = TRUE;

    } else {

        //NtfsAcquireSharedFcb( IrpContext, Fcb, Scb );
    }

    OplockPostIrp = FALSE;

    try {

        //
        //  We check whether we can proceed based on the state of the file oplocks.
        //  This call might post the irp for us.
        //

        Status = FsRtlCheckOplock( &Scb->ScbType.Data.Oplock,
                                   Irp,
                                   IrpContext,
                                   NtfsOplockComplete,
                                   NULL );

        if (Status != STATUS_SUCCESS) {

            OplockPostIrp = TRUE;
            try_return( NOTHING );
        }

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

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

            NtfsCreateFileLock( Scb, TRUE );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request
        //

        Status = FsRtlProcessFileLock( Scb->ScbType.Data.FileLock, Irp, NULL );

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

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

    try_exit: NOTHING;
    } finally {

        DebugUnwind( NtfsCommonLockControl );

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

        if (FcbAcquired) {
            NtfsReleaseFcb( IrpContext, Fcb );
        }

        //
        //  Only if this is not an abnormal termination and we did not post the irp
        //  do we delete the irp context
        //

        if (!AbnormalTermination() && !OplockPostIrp) {

            NtfsCompleteRequest( &IrpContext, NULL, 0 );
        }

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

    return Status;
}
Ejemplo n.º 11
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 = -NDASFAT_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.LowPart < 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.LowPart < 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, ("SecondaryRecoverySessionStart: 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_NDAS_MAX_DATA_SIZE) ? dataSize : DEFAULT_NDAS_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 = -NDASFAT_TIME_OUT;
			status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );

			KeClearEvent(&secondaryRequest->CompleteEvent);

			if (status != STATUS_SUCCESS) {
		
				ASSERT( NDASFAT_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, ("SecondaryRecoverySessionStart: 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 = -NDASFAT_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;

	} finally {
Ejemplo n.º 12
0
NTSTATUS
NtfsCommonSetSecurityInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for Setting security information called by
    both the fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - the return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

#ifdef _CAIRO_
    PQUOTA_CONTROL_BLOCK OldQuotaControl;
    ULONG OldOwnerId;
    ULONG LargeStdInfo;
#endif // _CAIRO_

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

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

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

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

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  The only type of opens we accept are user file and directory opens
    //

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

        Status = STATUS_INVALID_PARAMETER;

    //
    //  If the this handle does not open the entire file then refuse access.
    //

    } else if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {

        Status = STATUS_INVALID_PARAMETER;

    } else {

        //
        //  Our operation is to acquire the fcb, do the operation and then
        //  release the fcb
        //

        NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, FALSE, FALSE );

        try {

#ifdef _CAIRO_

            //
            //  Capture the current OwnerId, Qutoa Control Block and
            //  size of standard information.
            //

            OldQuotaControl = Fcb->QuotaControl;
            OldOwnerId = Fcb->OwnerId;
            LargeStdInfo = Fcb->FcbState & FCB_STATE_LARGE_STD_INFO;

#endif // _CAIRO_

            Status = NtfsModifySecurity( IrpContext,
                                         Fcb,
                                         &IrpSp->Parameters.SetSecurity.SecurityInformation,
                                         IrpSp->Parameters.SetSecurity.SecurityDescriptor );

            if (NT_SUCCESS( Status )) {

#ifdef _CAIRO_
                //
                //  Make sure the new security descriptor Id is written out.
                //

                NtfsUpdateStandardInformation( IrpContext, Fcb );
#endif
            }

            //
            //  Abort transaction on error by raising.
            //

            NtfsCleanupTransaction( IrpContext, Status, FALSE );

            //
            //  Set the flag in the Ccb to indicate this change occurred.
            //

            SetFlag( Ccb->Flags,
                     CCB_FLAG_UPDATE_LAST_CHANGE | CCB_FLAG_SET_ARCHIVE );

        } finally {

            DebugUnwind( NtfsCommonSetSecurityInfo );

#ifdef _CAIRO_
            if (AbnormalTermination()) {

                //
                //  The request failed.  Restore the owner and
                //  QuotaControl are restored.
                //

                if (Fcb->QuotaControl != OldQuotaControl &&
                    Fcb->QuotaControl != NULL) {

                    //
                    //  A new quota control block was assigned.
                    //  Dereference it.
                    //

                    NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
                                                      &Fcb->QuotaControl );
                }

                Fcb->QuotaControl = OldQuotaControl;
                Fcb->OwnerId = OldOwnerId;

                if (LargeStdInfo == 0) {

                    //
                    //  The standard information has be returned to
                    //  its orginal size.
                    //

                    ClearFlag( Fcb->FcbState, FCB_STATE_LARGE_STD_INFO );
                }

            } else {

                //
                //  The request succeed.  If the quota control block was
                //  changed then derefence the old block.
                //

                if (Fcb->QuotaControl != OldQuotaControl &&
                    OldQuotaControl != NULL) {

                    NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
                                                      &OldQuotaControl);

                }
            }
#endif // _CAIRO_

            NtfsReleaseFcb( IrpContext, Fcb );
        }
    }

    //
    //  Now complete the request and return to our caller
    //

    NtfsCompleteRequest( &IrpContext, &Irp, Status );

    DebugTrace( -1, Dbg, ("NtfsCommonSetSecurityInfo -> %08lx", Status) );

    return Status;
}
Ejemplo n.º 13
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 );

    ASSERT( Vcb != NULL );

    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 );
                IrpContext = NULL;
                Irp = NULL;

            } else {

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

            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;

        case FileFsFullSizeInformation:

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

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
        }

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

        if (Irp != NULL) {
            
            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.º 14
0
LARGE_INTEGER
CcGetDirtyPages (
    __in PVOID LogHandle,
    __in PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
    __in PVOID Context1,
    __in PVOID Context2
    )

/*++

Routine Description:

    This routine may be called to return all of the dirty pages in all files
    for a given log handle.  Each page is returned by an individual call to
    the Dirty Page Routine.  The Dirty Page Routine is defined by a prototype
    in ntos\inc\cache.h.

Arguments:

    LogHandle - Log Handle which must match the log handle previously stored
                for all files which are to be returned.

    DirtyPageRoutine -- The routine to call as each dirty page for this log
                        handle is found.

    Context1 - First context parameter to be passed to the Dirty Page Routine.

    Context2 - First context parameter to be passed to the Dirty Page Routine.

Return Value:

    LARGE_INTEGER - Oldest Lsn found of all the dirty pages, or 0 if no dirty pages

--*/

{
    PSHARED_CACHE_MAP SharedCacheMap;
    PBCB Bcb, BcbToUnpin = NULL;
    KLOCK_QUEUE_HANDLE LockHandle;
    LARGE_INTEGER SavedFileOffset, SavedOldestLsn, SavedNewestLsn;
    ULONG SavedByteLength;
    LARGE_INTEGER OldestLsn = {0,0};

    //
    //  Synchronize with changes to the SharedCacheMap list.
    //

    CcAcquireMasterLock( &LockHandle.OldIrql );

    SharedCacheMap = CONTAINING_RECORD( CcDirtySharedCacheMapList.SharedCacheMapLinks.Flink,
                                        SHARED_CACHE_MAP,
                                        SharedCacheMapLinks );

    //
    //  Use try/finally for cleanup.  The only spot where we can raise is out of the
    //  filesystem callback, but we have the exception handler out here so we aren't
    //  constantly setting/unsetting it.
    //

    try {

        while (&SharedCacheMap->SharedCacheMapLinks != &CcDirtySharedCacheMapList.SharedCacheMapLinks) {

            //
            //  Skip over cursors, SharedCacheMaps for other LogHandles, and ones with
            //  no dirty pages
            //

            if (!FlagOn(SharedCacheMap->Flags, IS_CURSOR) && (SharedCacheMap->LogHandle == LogHandle) &&
                (SharedCacheMap->DirtyPages != 0)) {

                //
                //  This SharedCacheMap should stick around for a while in the dirty list.
                //

                CcIncrementOpenCount( SharedCacheMap, 'pdGS' );
                SharedCacheMap->DirtyPages += 1;
                CcReleaseMasterLock( LockHandle.OldIrql );

                //
                //  Set our initial resume point and point to first Bcb in List.
                //

                KeAcquireInStackQueuedSpinLock( &SharedCacheMap->BcbSpinLock, &LockHandle );
                Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Flink, BCB, BcbLinks );

                //
                //  Scan to the end of the Bcb list.
                //

                while (&Bcb->BcbLinks != &SharedCacheMap->BcbList) {

                    //
                    //  If the Bcb is dirty, then capture the inputs for the
                    //  callback routine so we can call without holding a spinlock.
                    //

                    if ((Bcb->NodeTypeCode == CACHE_NTC_BCB) && Bcb->Dirty) {

                        SavedFileOffset = Bcb->FileOffset;
                        SavedByteLength = Bcb->ByteLength;
                        SavedOldestLsn = Bcb->OldestLsn;
                        SavedNewestLsn = Bcb->NewestLsn;

                        //
                        //  Increment PinCount so the Bcb sticks around
                        //

                        Bcb->PinCount += 1;

                        KeReleaseInStackQueuedSpinLock( &LockHandle );

                        //
                        //  Any Bcb to unref from a previous loop?
                        //

                        if (BcbToUnpin != NULL) {
                            CcUnpinFileData( BcbToUnpin, TRUE, UNREF );
                            BcbToUnpin = NULL;
                        }

                        //
                        //  Call the file system.  This callback may raise status.
                        //

                        (*DirtyPageRoutine)( SharedCacheMap->FileObject,
                                             &SavedFileOffset,
                                             SavedByteLength,
                                             &SavedOldestLsn,
                                             &SavedNewestLsn,
                                             Context1,
                                             Context2 );

                        //
                        //  Possibly update OldestLsn
                        //

                        if ((SavedOldestLsn.QuadPart != 0) &&
                            ((OldestLsn.QuadPart == 0) || (SavedOldestLsn.QuadPart < OldestLsn.QuadPart ))) {
                            OldestLsn = SavedOldestLsn;
                        }

                        //
                        //  Now reacquire the spinlock and scan from the resume point
                        //  point to the next Bcb to return in the descending list.
                        //

                        KeAcquireInStackQueuedSpinLock( &SharedCacheMap->BcbSpinLock, &LockHandle );

                        //
                        //  Normally the Bcb can stay around a while, but if not,
                        //  we will just remember it for the next time we do not
                        //  have the spin lock.  We cannot unpin it now, because
                        //  we would lose our place in the list.
                        //
                        //  This is cheating, but it works and is sane since we're
                        //  already traversing the bcb list - dropping the bcb count
                        //  is OK, as long as we don't hit zero.  Zero requires a 
                        //  slight bit more attention that shouldn't be replicated.
                        //  (unmapping the view)
                        //

                        if (Bcb->PinCount > 1) {
                            Bcb->PinCount -= 1;
                        } else {
                            BcbToUnpin = Bcb;
                        }
                    }

                    Bcb = CONTAINING_RECORD( Bcb->BcbLinks.Flink, BCB, BcbLinks );
                }
                KeReleaseInStackQueuedSpinLock( &LockHandle );

                //
                //  We need to unref any Bcb we are holding before moving on to
                //  the next SharedCacheMap, or else CcDeleteSharedCacheMap will
                //  also delete this Bcb.
                //

                if (BcbToUnpin != NULL) {

                    CcUnpinFileData( BcbToUnpin, TRUE, UNREF );
                    BcbToUnpin = NULL;
                }

                CcAcquireMasterLock( &LockHandle.OldIrql );

                //
                //  Now release the SharedCacheMap, leaving it in the dirty list.
                //

                CcDecrementOpenCount( SharedCacheMap, 'pdGF' );
                SharedCacheMap->DirtyPages -= 1;
            }

            //
            //  Now loop back for the next cache map.
            //

            SharedCacheMap =
                CONTAINING_RECORD( SharedCacheMap->SharedCacheMapLinks.Flink,
                                   SHARED_CACHE_MAP,
                                   SharedCacheMapLinks );
        }

        CcReleaseMasterLock( LockHandle.OldIrql );

    } finally {

        //
        //  Drop the Bcb if we are being ejected.  We are guaranteed that the
        //  only raise is from the callback, at which point we have an incremented
        //  pincount.
        //

        if (AbnormalTermination()) {

            CcUnpinFileData( Bcb, TRUE, UNPIN );
        }
    }

    return OldestLsn;
}
Ejemplo n.º 15
0
IO_STATUS_BLOCK
MsCreateClientEnd (
    IN PFCB Fcb,
    IN PFILE_OBJECT FileObject,
    IN ACCESS_MASK DesiredAccess,
    IN USHORT ShareAccess,
    IN PACCESS_STATE AccessState,
    IN KPROCESSOR_MODE RequestorMode,
    IN PETHREAD UserThread
    )

/*++

Routine Description:

    This routine performs the operation for opening the client end of a
    mailslot.  This routine does not complete the IRP, it performs the
    function and then returns a status.

Arguments:

    Fcb - Supplies the FCB for the mailslot being accessed.

    FileObject - Supplies the file object associated with the client end.

    DesiredAccess - Supplies the caller's desired access.

    ShareAccess - Supplies the caller's share access.

Return Value:

    IO_STATUS_BLOCK - Returns the appropriate status for the operation

--*/

{
    IO_STATUS_BLOCK iosb;
    PCCB ccb;

    BOOLEAN accessGranted;
    ACCESS_MASK grantedAccess;
    UNICODE_STRING name;
    PPRIVILEGE_SET Privileges = NULL;
    BOOLEAN shareAccessUpdated = FALSE;

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

    try {

        //
        //  First do an access check for the user against the Fcb
        //

        SeLockSubjectContext( &AccessState->SubjectSecurityContext );

        accessGranted = SeAccessCheck( Fcb->SecurityDescriptor,
                                       &AccessState->SubjectSecurityContext,
                                       TRUE,                        // Tokens are locked
                                       DesiredAccess,
                                       0,
                                       &Privileges,
                                       IoGetFileObjectGenericMapping(),
                                       RequestorMode,
                                       &grantedAccess,
                                       &iosb.Status );

        if (Privileges != NULL) {

              (VOID) SeAppendPrivileges(
                         AccessState,
                         Privileges
                         );

            SeFreePrivileges( Privileges );
        }

        if (accessGranted) {
            AccessState->PreviouslyGrantedAccess |= grantedAccess;
            AccessState->RemainingDesiredAccess &= ~grantedAccess;
        }

        RtlInitUnicodeString( &name, L"Mailslot" );

        SeOpenObjectAuditAlarm( &name,
                                NULL,
                                &FileObject->FileName,
                                Fcb->SecurityDescriptor,
                                AccessState,
                                FALSE,
                                accessGranted,
                                RequestorMode,
                                &AccessState->GenerateOnClose );


        SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );

        if (!accessGranted) {

            DebugTrace(0, Dbg, "Access Denied\n", 0 );

            try_return( iosb.Status );
        }

        //
        // Now make sure our share access is okay.
        //

        if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess,
                                                          ShareAccess,
                                                          FileObject,
                                                          &Fcb->ShareAccess,
                                                          TRUE ))) {

            DebugTrace(0, Dbg, "Sharing violation\n", 0);

            try_return( NOTHING );
        }

        shareAccessUpdated = TRUE;

        //
        // Create a CCB for this client.
        //

        ccb = MsCreateCcb( Fcb );

        //
        // Set the file object back pointers and our pointer to the
        // server file object.
        //

        MsSetFileObject( FileObject,
                         ccb,
                         NULL );

        ccb->FileObject = FileObject;

        //
        //  And set our return status
        //

        iosb.Status = STATUS_SUCCESS;
        iosb.Information = FILE_OPENED;


    try_exit: NOTHING;
    } finally {

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

        if (!NT_SUCCESS(iosb.Status) || AbnormalTermination()) {
            if (shareAccessUpdated) {
                IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
            }
        }

    }

    return iosb;
}
Ejemplo n.º 16
0
VOID
FatSetFullFileNameInFcb (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb
    )

/*++

Routine Description:

    If the FullFileName field in the Fcb has not yet been filled in, we
    proceed to do so.

Arguments:

    Fcb - Supplies the file.

Return Value:

    None

--*/

{
    if (Fcb->FullFileName.Buffer == NULL) {

        UNICODE_STRING Lfn;
        PFCB TmpFcb = Fcb;
        PFCB StopFcb;
        PWCHAR TmpBuffer;
        ULONG PathLength = 0;

        //
        //  We will assume we do this infrequently enough, that it's OK to
        //  to a pool allocation here.
        //

        Lfn.Length = 0;
        Lfn.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
        Lfn.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
                                               MAX_LFN_CHARACTERS * sizeof(WCHAR),
                                               TAG_FILENAME_BUFFER );

        try {

            //
            //  First determine how big the name will be.  If we find an
            //  ancestor with a FullFileName, our work is easier.
            //

            while (TmpFcb != Fcb->Vcb->RootDcb) {

                if ((TmpFcb != Fcb) && (TmpFcb->FullFileName.Buffer != NULL)) {

                    PathLength += TmpFcb->FullFileName.Length;

                    Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
                                                                         PathLength,
                                                                         TAG_FILENAME_BUFFER );

                    RtlCopyMemory( Fcb->FullFileName.Buffer,
                                   TmpFcb->FullFileName.Buffer,
                                   TmpFcb->FullFileName.Length );

                    break;
                }

                PathLength += TmpFcb->FinalNameLength + sizeof(WCHAR);

                TmpFcb = TmpFcb->ParentDcb;
            }

            //
            //  If FullFileName.Buffer is still NULL, allocate it.
            //

            if (Fcb->FullFileName.Buffer == NULL) {

                Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
                                                                     PathLength,
                                                                     TAG_FILENAME_BUFFER );
            }

            StopFcb = TmpFcb;

            TmpFcb = Fcb;
            TmpBuffer =  Fcb->FullFileName.Buffer + PathLength / sizeof(WCHAR);

            Fcb->FullFileName.Length =
            Fcb->FullFileName.MaximumLength = (USHORT)PathLength;

            while (TmpFcb != StopFcb) {

                FatGetUnicodeNameFromFcb( IrpContext,
                                          TmpFcb,
                                          &Lfn );

                TmpBuffer -= Lfn.Length / sizeof(WCHAR);

                RtlCopyMemory( TmpBuffer, Lfn.Buffer, Lfn.Length );

                TmpBuffer -= 1;

                *TmpBuffer = L'\\';

                TmpFcb = TmpFcb->ParentDcb;
            }

        } finally {

            if (AbnormalTermination()) {

                if (Fcb->FullFileName.Buffer) {

                    ExFreePool( Fcb->FullFileName.Buffer );
                    Fcb->FullFileName.Buffer = NULL;
                }
            }

            ExFreePool( Lfn.Buffer );
        }
    }
Ejemplo n.º 17
0
int main(int argc, char **argv)
{
	DWORD dwRet = RET_OK;
	HWND hWnd = NULL;
	HANDLE hThread = NULL;
	MSG msg;
	char *chUserName = NULL;
	char *chPasswd = NULL;
	char *chAlias = NULL;

	//Флаги выполнения
	BOOL bIsPlugin = FALSE;
	BOOL bIsOraLib = FALSE;
	BOOL bIsInitDDE = FALSE;

	//Установка местного фильтра необрабатываемых исключений
	SetUnhandledExceptionFilter(__UnhandledExceptionFilter);

	__try {

	Init_CrSec();

	//Баннер
	printf("%s\n", chBanner);
	WriteLog(LOG_FILE_NAME, chBanner, (DWORD) strlen(chBanner));

	dwRet = CreateStealthWin(&hWnd);
	if (dwRet != RET_OK) {
		printf("[ERR] main(..) -> CreateStealthWin(..) : %d\n", dwRet);
		WriteLog_DDE("[ERR] main(..) -> CreateStealthWin(..)", dwRet);
		dwRet = 1;
		__leave;
	}

	dwRet = InitIniValues();
	if (dwRet != RET_OK) {
		printf("[ERR] main(..) -> InitIniValues(..) : %d\n", dwRet);
		WriteLog_DDE("[ERR] main(..) -> InitIniValues(..)", dwRet);		
		dwRet = 1;
		__leave;
	}

	dwRet = Init_Plugins();
	if (dwRet != RET_OK) {
		printf("[ERR] main(..) -> Init_Plugins(..) : %d\n", dwRet);
		WriteLog_DDE("[ERR] main(..) -> Init_Plugins(..)", dwRet);
		dwRet = 1;
		__leave;
	}
	bIsPlugin = TRUE;

	if (g_chOraEnable == 'Y') {
		if (argc != 4){//Проверка ORA - аргументов
			printf("%s\n", "Usage: ex4g_dde <username> <passwd> <alias>");
			WriteLog_DDE("Usage: ex4g_dde <username> <passwd> <alias>", 0);
			WriteLog_DDE("[ERR] main(..) -> argc", argc);			
			dwRet = 1;
			__leave;
		}
		chUserName = argv[1];
		chPasswd = argv[2];
		chAlias = argv[3];

		printf("[INF] InitOraConnect(..) : Try ORA Connect - Wait...\n");

		dwRet = Init_Ora_Lib();
		if (dwRet != RET_OK) {
			WriteLog_DDE("[ERR] main(..) -> Init_Ora_Lib(..)", dwRet);
			dwRet = 1;
			__leave;
		}
		bIsOraLib = TRUE;		

		dwRet = InitOraConnect(chUserName, chPasswd, chAlias, g_dwOraSessMax);
		if (dwRet != RET_OK) {
			WriteLog_DDE("[ERR] main(..) -> InitOraConnect(..)", dwRet);
			dwRet = 1;
			__leave;
		}

		printf("[OK] InitOraConnect(..) : %d\n", dwRet);
		WriteLog_DDE("[OK] main(..) -> InitOraConnect(..)", dwRet);
	}

	dwRet = Init_Dde();
	if (dwRet != RET_OK){
		printf("[ERR] Init_Dde(..) : %u\n", dwRet);
		WriteLog_DDE("[ERR] main(..) -> Init_Dde(..)", dwRet);
		dwRet = 1;
		__leave;
	}
	bIsInitDDE = TRUE;

	hThread = (HANDLE) _beginthreadex(NULL, 0, MakeCmd, hWnd, 0, NULL);			
	if (hThread == NULL) {
		WriteLog_DDE("[ERR] main(..) -> MakeCmd", GetLastError());
		dwRet = 1;		
		__leave;
	}

	while (GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
    }
	
	}
	__finally {

		if (AbnormalTermination()) {
			PrintCallStackAtomic();
		}

		if (bIsInitDDE) {
			printf("[OK] UnInit_Dde(..) : %d\n", 0);
			WriteLog_DDE("[OK] main(..) -> UnInit_Dde(..)", 0);
			UnInit_Dde();
		}
		if (bIsOraLib) {
			printf("[OK] CloseOraConnect(..) : %d\n", 0);
			WriteLog_DDE("[OK] main(..) -> CloseOraConnect(..)", 0);
			CloseOraConnect();
			Free_Ora_Lib();			
		}
		if (bIsPlugin) {
			printf("[OK] Free_Plugins(..) : %d\n", 0);
			WriteLog_DDE("[OK] main(..) -> Free_Plugins(..)", 0);
			Free_Plugins();
		}
		CloseHandle(hThread);
		UnInit_CrSec();

	}

	return dwRet;
}
Ejemplo n.º 18
0
PLBCB
LfsGetLbcb (
    IN PLFCB Lfcb
    )

/*++

Routine Description:

    This routine is called to add a Lbcb to the active queue.

Arguments:

    Lfcb - This is the file control block for the log file.

Return Value:

    PLBCB - Pointer to the Lbcb allocated.

--*/

{
    PLBCB Lbcb = NULL;
    PVOID PageHeader;
    PBCB PageHeaderBcb = NULL;

    BOOLEAN WrappedOrUsaError;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsGetLbcb:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Lfcb      -> %08lx\n", Lfcb );

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

    try {

        //
        //  Pin the desired record page.
        //

        LfsPreparePinWriteData( Lfcb,
                                Lfcb->NextLogPage,
                                (ULONG)Lfcb->LogPageSize,
                                &PageHeader,
                                &PageHeaderBcb );

        //
        //  Put our signature into the page so we won't fail if we
        //  see a previous 'BAAD' signature.
        //

        *((PULONG) PageHeader) = LFS_SIGNATURE_RECORD_PAGE_ULONG;

        //
        //  Now allocate an Lbcb.
        //

        LfsAllocateLbcb( Lfcb, &Lbcb );

        //
        //  If we are at the beginning of the file we test that the
        //  sequence number won't wrap to 0.
        //

        if (!FlagOn( Lfcb->Flags, LFCB_NO_LAST_LSN | LFCB_REUSE_TAIL )
            && ( Lfcb->NextLogPage == Lfcb->FirstLogPage )) {

            Lfcb->SeqNumber = Lfcb->SeqNumber + 1;

            //
            //  If the sequence number is going from 0 to 1, then
            //  this is the first time the log file has wrapped.  We want
            //  to remember this because it means that we can now do
            //  large spiral writes.
            //

            if (Int64ShllMod32( Lfcb->SeqNumber, Lfcb->FileDataBits ) == 0) {

                LfsDebugTrace( 0, Dbg, "Log sequence number about to wrap:  Lfcb -> %08lx\n", Lfcb );
                KeBugCheck( FILE_SYSTEM );
            }

            //
            //  If this number is greater or equal to  the wrap sequence number in
            //  the Lfcb, set the wrap flag in the Lbcb.
            //

            if (!FlagOn( Lfcb->Flags, LFCB_LOG_WRAPPED )
                && ( Lfcb->SeqNumber >= Lfcb->SeqNumberForWrap )) {

                SetFlag( Lbcb->LbcbFlags, LBCB_LOG_WRAPPED );
                SetFlag( Lfcb->Flags, LFCB_LOG_WRAPPED );
            }
        }

        //
        //  Now initialize the rest of the Lbcb fields.
        //

        Lbcb->FileOffset = Lfcb->NextLogPage;
        Lbcb->SeqNumber = Lfcb->SeqNumber;
        Lbcb->BufferOffset = Lfcb->LogPageDataOffset;

        //
        //  Store the next page in the Lfcb.
        //

        LfsNextLogPageOffset( Lfcb,
                              Lfcb->NextLogPage,
                              &Lfcb->NextLogPage,
                              &WrappedOrUsaError );

        Lbcb->Length = Lfcb->LogPageSize;
        Lbcb->PageHeader = PageHeader;
        Lbcb->LogPageBcb = PageHeaderBcb;

        Lbcb->ResourceThread = ExGetCurrentResourceThread();

        //
        //  If we are reusing a previous page then set a flag in
        //  the Lbcb to indicate that we should flush a copy
        //  first.
        //

        if (FlagOn( Lfcb->Flags, LFCB_REUSE_TAIL )) {

            SetFlag( Lbcb->LbcbFlags, LBCB_FLUSH_COPY );
            ClearFlag( Lfcb->Flags, LFCB_REUSE_TAIL );

            (ULONG)Lbcb->BufferOffset = Lfcb->ReusePageOffset;

            Lbcb->Flags = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Flags;
            Lbcb->LastLsn = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Copy.LastLsn;
            Lbcb->LastEndLsn = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Header.Packed.LastEndLsn;
        }

        //
        //  Put the Lbcb on the active queue
        //

        InsertTailList( &Lfcb->LbcbActive, &Lbcb->ActiveLinks );

        SetFlag( Lbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE );

    } finally {

        DebugUnwind( LfsGetLbcb );

        //
        //  If an error occurred, we need to clean up any blocks which
        //  have not been added to the active queue.
        //

        if (AbnormalTermination()) {

            if (Lbcb != NULL) {

                LfsDeallocateLbcb( Lfcb, Lbcb );
                Lbcb = NULL;
            }

            //
            //  Unpin the system page if pinned.
            //

            if (PageHeaderBcb != NULL) {

                CcUnpinData( PageHeaderBcb );
            }
        }

        LfsDebugTrace( -1, Dbg, "LfsGetLbcb:  Exit\n", 0 );
    }

    return Lbcb;
}
Ejemplo n.º 19
0
PPRIMARY_SESSION
PrimarySession_Create (
	IN  PIRP_CONTEXT			IrpContext,  
	IN	PVOLUME_DEVICE_OBJECT	VolDo,		 
	IN  PSESSION_INFORMATION	SessionInformation,
	IN  PIRP					Irp
	)
{
	PPRIMARY_SESSION	primarySession;
 	OBJECT_ATTRIBUTES	objectAttributes;
	NTSTATUS			status;
	LARGE_INTEGER		timeOut;

		
	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	VolDo_Reference( VolDo );

	primarySession = FsRtlAllocatePoolWithTag( NonPagedPool, sizeof(PRIMARY_SESSION), NDFAT_ALLOC_TAG );
	
	if (primarySession == NULL) {

		ASSERT( NDASFAT_INSUFFICIENT_RESOURCES );
		VolDo_Dereference( VolDo );
		return NULL;
	}

	try {
	
		RtlZeroMemory( primarySession, sizeof(PRIMARY_SESSION) );

		primarySession->Flags = PRIMARY_SESSION_FLAG_INITIALIZING;

		primarySession->ReferenceCount = 1;
		primarySession->VolDo = VolDo;
		
		ExInitializeFastMutex( &primarySession->FastMutex )
		
		InitializeListHead( &primarySession->ListEntry );

		primarySession->NetdiskPartitionInformation = SessionInformation->NetdiskPartitionInformation;
	
		RtlInitEmptyUnicodeString( &primarySession->NetdiskPartitionInformation.VolumeName,
								   primarySession->NetdiskPartitionInformation.VolumeNameBuffer,
								   sizeof(primarySession->NetdiskPartitionInformation.VolumeNameBuffer) );

		if (RtlAppendUnicodeStringToString( &primarySession->NetdiskPartitionInformation.VolumeName,
											&SessionInformation->NetdiskPartitionInformation.VolumeName) != STATUS_SUCCESS) {

			ASSERT( NDASFAT_UNEXPECTED );
		}

		ASSERT( primarySession->NetdiskPartitionInformation.VolumeName.Buffer == primarySession->NetdiskPartitionInformation.VolumeNameBuffer );

		primarySession->ConnectionFileHandle		= SessionInformation->ConnectionFileHandle;
		primarySession->ConnectionFileObject		= SessionInformation->ConnectionFileObject;

		primarySession->RemoteAddress				= SessionInformation->RemoteAddress;
		primarySession->IsLocalAddress				= SessionInformation->IsLocalAddress;

		primarySession->Irp									= Irp;

		primarySession->SessionContext = SessionInformation->SessionContext;

		primarySession->SessionContext.PrimaryMaxDataSize	= DEFAULT_NDAS_MAX_DATA_SIZE; //SessionInformation->PrimaryMaxDataSize;
		primarySession->SessionContext.SecondaryMaxDataSize	= DEFAULT_NDAS_MAX_DATA_SIZE; // SessionInformation->SecondaryMaxDataSize;

		DebugTrace2( 0, Dbg2, ("primarySession->ConnectionFileHandle = %x " 
							   "primarySession->SessionContext.PrimaryMaxDataSize = %x primarySession->SessionContext.SecondaryMaxDataSize = %x\n", 
							    primarySession->ConnectionFileHandle, primarySession->SessionContext.PrimaryMaxDataSize, primarySession->SessionContext.SecondaryMaxDataSize) );

		KeInitializeEvent( &primarySession->ReadyEvent, NotificationEvent, FALSE );
	
		InitializeListHead( &primarySession->RequestQueue );
		KeInitializeSpinLock( &primarySession->RequestQSpinLock );
		KeInitializeEvent( &primarySession->RequestEvent, NotificationEvent, FALSE );

		primarySession->ThreadHandle = 0;
		primarySession->ThreadObject = NULL;

		primarySession->Thread.TdiReceiveContext.Irp = NULL;
		KeInitializeEvent( &primarySession->Thread.TdiReceiveContext.CompletionEvent, NotificationEvent, FALSE );

		InitializeObjectAttributes( &objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );

		primarySession->Thread.SessionState = SESSION_TREE_CONNECT;
	
		ExInterlockedInsertTailList( &VolDo->PrimarySessionQueue,
									 &primarySession->ListEntry,
									 &VolDo->PrimarySessionQSpinLock );

		status = PsCreateSystemThread( &primarySession->ThreadHandle,
									   THREAD_ALL_ACCESS,
									   &objectAttributes,
									   NULL,
									   NULL,
									   PrimarySessionThreadProc,
									   primarySession );
	
		if (!NT_SUCCESS(status)) {

			leave;
		}

		status = ObReferenceObjectByHandle( primarySession->ThreadHandle,
											FILE_READ_DATA,
											NULL,
											KernelMode,
											&primarySession->ThreadObject,
											NULL );

		if (!NT_SUCCESS(status)) {

			leave;
		}

		timeOut.QuadPart = -NDASFAT_TIME_OUT;
		status = KeWaitForSingleObject( &primarySession->ReadyEvent,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );


		if (!NT_SUCCESS(status)) {

			leave;
		}

		KeClearEvent( &primarySession->ReadyEvent );

		DebugTrace2( 0, Dbg, ("PrimarySession_Create: The primary thread are ready\n") );
	
		DebugTrace2( 0, Dbg2, ("Fat PrimarySession_Create: primarySession = %p\n", primarySession) );
	
	} finally {

		if (AbnormalTermination()) {

			status = IrpContext->ExceptionStatus;
		}

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASFAT_UNEXPECTED );
			PrimarySession_Close( primarySession );
			primarySession = NULL;
		}
	}

	return primarySession;
}
Ejemplo n.º 20
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;
    }

    //
    //  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.º 21
0
PPRIMARY_SESSION
PrimarySession_Create (
	IN  PPRIMARY					Primary,
	IN	HANDLE						ListenFileHandle,
	IN  PFILE_OBJECT				ListenFileObject,
	IN  PLPXTDI_OVERLAPPED_CONTEXT	ListenOverlapped,
	IN  ULONG						ListenSocketIndex,
	IN  PLPX_ADDRESS				RemoteAddress
	)
{
	PPRIMARY_SESSION	primarySession;
 	OBJECT_ATTRIBUTES	objectAttributes;
	NTSTATUS			status;
	LARGE_INTEGER		timeOut;

		
	NDAS_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	Primary_Reference( Primary );

	primarySession = FsRtlAllocatePoolWithTag( NonPagedPool, sizeof(PRIMARY_SESSION), LFS_ALLOC_TAG );
	
	if (primarySession == NULL) {

		NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES );

		Primary_Dereference( Primary );
		return NULL;
	}

	try {
	
		RtlZeroMemory( primarySession, sizeof(PRIMARY_SESSION) );

		primarySession->Flags = PRIMARY_SESSION_FLAG_INITIALIZING;

		primarySession->ReferenceCount = 1;
		primarySession->Primary = Primary;
		
		ExInitializeFastMutex( &primarySession->FastMutex );
		
		InitializeListHead( &primarySession->ListEntry );

		KeInitializeEvent( &primarySession->ReadyEvent, NotificationEvent, FALSE );
	
		InitializeListHead( &primarySession->RequestQueue );
		KeInitializeSpinLock( &primarySession->RequestQSpinLock );
		KeInitializeEvent( &primarySession->RequestEvent, NotificationEvent, FALSE );

		InitializeListHead( &primarySession->NetdiskPartitionListEntry );

		primarySession->ThreadHandle = 0;
		primarySession->ThreadObject = NULL;

		NdasFcInitialize( &primarySession->SendNdasFcStatistics );
		NdasFcInitialize( &primarySession->RecvNdasFcStatistics );

		primarySession->ConnectionFileHandle	= ListenFileHandle;
		primarySession->ConnectionFileObject	= ListenFileObject;
		
		LpxTdiV2MoveOverlappedContext( &primarySession->ReceiveOverlapped, ListenOverlapped );

		RtlCopyMemory( &primarySession->RemoteAddress, RemoteAddress, sizeof(LPX_ADDRESS) );
		primarySession->IsLocalAddress			= Lfs_IsLocalAddress(RemoteAddress);

		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("primarySession->ConnectionFileHandle = %p\n", primarySession->ConnectionFileHandle) );

		primarySession->Thread.SessionState = SESSION_CLOSE;
		primarySession->SessionContext.SessionKey = (UINT32)PtrToUlong(primarySession);

		primarySession->SessionContext.PrimaryMaxDataSize = (LfsRegistry.MaxDataTransferPri < DEFAULT_MAX_DATA_SIZE)
													? LfsRegistry.MaxDataTransferPri:DEFAULT_MAX_DATA_SIZE;

		primarySession->SessionContext.SecondaryMaxDataSize = (LfsRegistry.MaxDataTransferSec < DEFAULT_MAX_DATA_SIZE)
													? LfsRegistry.MaxDataTransferSec:DEFAULT_MAX_DATA_SIZE;

		//
		//	Initialize transport context for traffic control
		//

		InitTransCtx( &primarySession->Thread.TransportCtx, primarySession->SessionContext.SecondaryMaxDataSize );

		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimarySession_Create: PriMaxData:%08u SecMaxData:%08u\n",
												  primarySession->SessionContext.PrimaryMaxDataSize,
												  primarySession->SessionContext.SecondaryMaxDataSize) );

		ExAcquireFastMutex( &GlobalLfs.FastMutex );
		primarySession->SessionContext.Uid = GlobalLfs.Uid++;
		ExReleaseFastMutex( &GlobalLfs.FastMutex );

		InitializeObjectAttributes( &objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );

		status = PsCreateSystemThread( &primarySession->ThreadHandle,
									   THREAD_ALL_ACCESS,
									   &objectAttributes,
									   NULL,
									   NULL,
									   PrimarySessionThreadProc,
									   primarySession );
	
		if (!NT_SUCCESS(status)) {

			leave;
		}

		status = ObReferenceObjectByHandle( primarySession->ThreadHandle,
											FILE_READ_DATA,
											NULL,
											KernelMode,
											&primarySession->ThreadObject,
											NULL );

		if (!NT_SUCCESS(status)) {

			leave;
		}

		timeOut.QuadPart = -LFS_TIME_OUT;
		status = KeWaitForSingleObject( &primarySession->ReadyEvent,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );


		if (!NT_SUCCESS(status)) {

			leave;
		}

		KeClearEvent( &primarySession->ReadyEvent );

		ExInterlockedInsertTailList( &Primary->PrimarySessionQueue[ListenSocketIndex],
									 &primarySession->ListEntry,
									 &Primary->PrimarySessionQSpinLock[ListenSocketIndex] );

		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimarySession_Create: The primary thread are ready\n") );
		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("Fat PrimarySession_Create: primarySession = %p\n", primarySession) );
	
	} finally {

		if (AbnormalTermination()) {

			status = STATUS_UNSUCCESSFUL;
		}

		if (!NT_SUCCESS(status)) {

			ASSERT( LFS_UNEXPECTED );
			PrimarySession_Close( primarySession );
			primarySession = NULL;
		}
	}

	return primarySession;
}
Ejemplo n.º 22
0
NTSTATUS
FatCommonLockControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
)

/*++

Routine Description:

    This is the common routine for doing Lock control operations called
    by both the fsd and fsp threads

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;

    TYPE_OF_OPEN TypeOfOpen;

    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

    BOOLEAN OplockPostIrp = FALSE;

    //
    //  Get a pointer to the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatCommonLockControl\n", 0);
    DebugTrace( 0, Dbg, "Irp           = %08lx\n", Irp);
    DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);

    //
    //  Decode the type of file object we're being asked to process
    //

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

    //
    //  If the file is not a user file open then we reject the request
    //  as an invalid parameter
    //

    if (TypeOfOpen != UserFileOpen) {

        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );

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

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

    if (!FatAcquireSharedFcb( IrpContext, Fcb )) {

        Status = FatFsdPostRequest( IrpContext, Irp );

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

    try {

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

        Status = FsRtlCheckOplock( &Fcb->Specific.Fcb.Oplock,
                                   Irp,
                                   IrpContext,
                                   FatOplockComplete,
                                   NULL );

        if (Status != STATUS_SUCCESS) {

            OplockPostIrp = TRUE;
            try_return( NOTHING );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request
        //

        Status = FsRtlProcessFileLock( &Fcb->Specific.Fcb.FileLock, Irp, NULL );

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

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

try_exit:
        NOTHING;
    }
    finally {

        DebugUnwind( FatCommonLockControl );

        //
        //  Only if this is not an abnormal termination do we delete the
        //  irp context
        //

        if (!AbnormalTermination() && !OplockPostIrp) {

            FatCompleteRequest( IrpContext, FatNull, 0 );
        }

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

        FatReleaseFcb( IrpContext, Fcb );

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

    return Status;
}
Ejemplo n.º 23
0
NTSTATUS
FatCommonLockControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for doing Lock control operations called
    by both the fsd and fsp threads

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_STACK_LOCATION IrpSp;

    TYPE_OF_OPEN TypeOfOpen;

    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

    BOOLEAN OplockPostIrp = FALSE;

    PAGED_CODE();

    //
    //  Get a pointer to the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatCommonLockControl\n", 0);
    DebugTrace( 0, Dbg, "Irp           = %08lx\n", Irp);
    DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);

    //
    //  Decode the type of file object we're being asked to process
    //

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

    //
    //  If the file is not a user file open then we reject the request
    //  as an invalid parameter
    //

    if (TypeOfOpen != UserFileOpen) {

        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );

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

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

    if (!FatAcquireSharedFcb( IrpContext, Fcb )) {

        Status = FatFsdPostRequest( IrpContext, Irp );

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

    try {

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

#if (NTDDI_VERSION >= NTDDI_WIN8)

        if (((IRP_MN_LOCK == IrpSp->MinorFunction) &&
             ((ULONGLONG)IrpSp->Parameters.LockControl.ByteOffset.QuadPart <
              (ULONGLONG)Fcb->Header.AllocationSize.QuadPart)) ||
            ((IRP_MN_LOCK != IrpSp->MinorFunction) &&
             FsRtlAreThereWaitingFileLocks( &Fcb->Specific.Fcb.FileLock ))) {

            //
            //  Check whether we can proceed based on the state of file oplocks if doing
            //  an operation that interferes with oplocks. Those operations are:
            //
            //      1. Lock a range within the file's AllocationSize.
            //      2. Unlock a range when there are waiting locks on the file. This one
            //         is not guaranteed to interfere with oplocks, but it could, as
            //         unlocking this range might cause a waiting lock to be granted
            //         within AllocationSize!
            //

#endif
            Status = FsRtlCheckOplock( FatGetFcbOplock(Fcb),
                                       Irp,
                                       IrpContext,
                                       FatOplockComplete,
                                       NULL );

#if (NTDDI_VERSION >= NTDDI_WIN8)
        }
#endif

        if (Status != STATUS_SUCCESS) {

            OplockPostIrp = TRUE;
            try_return( NOTHING );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request
        //

        Status = FsRtlProcessFileLock( &Fcb->Specific.Fcb.FileLock, Irp, NULL );

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

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

    try_exit:  NOTHING;
    } finally {

        DebugUnwind( FatCommonLockControl );

        //
        //  Only if this is not an abnormal termination do we delete the
        //  irp context
        //

        if (!AbnormalTermination() && !OplockPostIrp) {

            FatCompleteRequest( IrpContext, FatNull, 0 );
        }

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

        FatReleaseFcb( IrpContext, Fcb );

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

    return Status;
}
Ejemplo n.º 24
0
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    This is the initialization routine for the mailslot file system
    device driver.  This routine creates the device object for the mailslot
    device and performs all other driver initialization.

Arguments:

    DriverObject - Pointer to driver object created by the system.

Return Value:

    NTSTATUS - The function value is the final status from the initialization
        operation.

--*/

{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING nameString;
    PDEVICE_OBJECT deviceObject;
    PMSFS_DEVICE_OBJECT msfsDeviceObject;

    BOOLEAN vcbInitialized;

    PAGED_CODE();

    //
    // Initialize MSFS global data.
    //

    MsInitializeData();

    //
    // Set driver to be completely paged out.
    //
    MmPageEntireDriver(DriverEntry);

    //
    // Create the MSFS device object.
    //

    RtlInitUnicodeString( &nameString, L"\\Device\\Mailslot" );
    status = IoCreateDevice( DriverObject,
                             sizeof(MSFS_DEVICE_OBJECT)-sizeof(DEVICE_OBJECT),
                             &nameString,
                             FILE_DEVICE_MAILSLOT,
                             0,
                             FALSE,
                             &deviceObject );

    if (!NT_SUCCESS( status )) {
        return status;

    }

    //
    //  Now because we use the irp stack for storing a data entry we need
    //  to bump up the stack size in the device object we just created.
    //

    deviceObject->StackSize += 1;

    //
    // Note that because of the way data copying is done, we set neither
    // the Direct I/O or Buffered I/O bit in DeviceObject->Flags.  If
    // data is not buffered we may set up for Direct I/O by hand.
    //

    //
    // Initialize the driver object with this driver's entry points.
    //

    DriverObject->MajorFunction[IRP_MJ_CREATE] =
        (PDRIVER_DISPATCH)MsFsdCreate;
    DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] =
        (PDRIVER_DISPATCH)MsFsdCreateMailslot;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] =
        (PDRIVER_DISPATCH)MsFsdClose;
    DriverObject->MajorFunction[IRP_MJ_READ] =
        (PDRIVER_DISPATCH)MsFsdRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE] =
        (PDRIVER_DISPATCH)MsFsdWrite;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
        (PDRIVER_DISPATCH)MsFsdQueryInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
        (PDRIVER_DISPATCH)MsFsdSetInformation;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
        (PDRIVER_DISPATCH)MsFsdQueryVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] =
        (PDRIVER_DISPATCH)MsFsdCleanup;
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
        (PDRIVER_DISPATCH)MsFsdDirectoryControl;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
        (PDRIVER_DISPATCH)MsFsdFsControl;
    DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] =
        (PDRIVER_DISPATCH)MsFsdQuerySecurityInfo;
    DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] =
        (PDRIVER_DISPATCH)MsFsdSetSecurityInfo;

#ifdef _PNP_POWER_
    //
    // Mailslots should probably have a SetPower handler to ensure
    // that the driver is not powered down while a guarateed
    // mailslot delivery is in progress.   For now, we'll just
    // ignore this and let the machine set power.
    //

    deviceObject->DeviceObjectExtension->PowerControlNeeded = FALSE;
#endif

    vcbInitialized = FALSE;

    try {

        //
        // Initialize stuff
        //

        msfsDeviceObject = (PMSFS_DEVICE_OBJECT)deviceObject;

        //
        // Now initialize the Vcb, and create the root dcb
        //

        MsInitializeVcb( &msfsDeviceObject->Vcb );
        (VOID)MsCreateRootDcb( &msfsDeviceObject->Vcb );
        vcbInitialized = TRUE;

    } finally {

        if (AbnormalTermination() ) {

            //
            // We encountered some unrecoverable error while initializing.
            // Cleanup as necessary.
            //

            if (vcbInitialized) {
                MsDeleteVcb( &msfsDeviceObject->Vcb );
            }
        }
    }

    //
    // Return to the caller.
    //

    return( status );
}
Ejemplo n.º 25
0
PXIXFS_LCB
xixfs_FCBTLBFindPrefix (
    IN PXIXFS_IRPCONTEXT IrpContext,
    IN OUT PXIXFS_FCB *CurrentFcb,
    IN OUT PUNICODE_STRING RemainingName,
	IN BOOLEAN	bIgnoreCase
    )
{
	UNICODE_STRING LocalRemainingName;
	UNICODE_STRING FinalName;
	
	PXIXFS_LCB	NameLink;
	PXIXFS_LCB	CurrentLcb = NULL;
	BOOLEAN		Waitable = FALSE;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CREATE|DEBUG_TARGET_CLOSE| DEBUG_TARGET_FCB),
		("Enter xixfs_FCBTLBFindPrefix \n" ));   
	//
	//  Check inputs.
	//

	ASSERT_IRPCONTEXT( IrpContext );
	ASSERT_FCB( *CurrentFcb );
	ASSERT_EXCLUSIVE_FCB( *CurrentFcb );


	

	Waitable =  XIXCORE_TEST_FLAGS(IrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT);

	try{
		//
		//  Make a local copy of the input strings.
		//

		LocalRemainingName = *RemainingName;

		//
		//  Loop until we find the longest matching prefix.
		//

		while (TRUE) {

			//
			//  If there are no characters left or we are not at an IndexFcb then
			//  return immediately.
			//

			if ((LocalRemainingName.Length == 0) ||
				(XifsSafeNodeType( *CurrentFcb ) != XIFS_NODE_FCB)) {

				try_return(TRUE); 
				// return CurrentLcb;
			}

			if((*CurrentFcb)->XixcoreFcb.FCBType != FCB_TYPE_DIR){
				try_return(TRUE); 
				//return CurrentLcb;

			}

			//
			//  Split off the next component from the name.
			//

			FsRtlDissectName( LocalRemainingName,
								&FinalName,
								&LocalRemainingName);

			//
			//  Check if this name is in the splay tree for this Fcb.
			//


			if(bIgnoreCase){
				NameLink = xixfs_NLFindNameLinkIgnoreCase( IrpContext,
											&(*CurrentFcb)->IgnoreCaseRoot,
											&FinalName );
			}else{
				NameLink = xixfs_NLFindNameLink( IrpContext,
											&(*CurrentFcb)->Root,
											&FinalName );
			}



			//
			//  If we didn't find a match then exit.
			//

			if (NameLink == NULL) { 

				break;
			}



			//
			//
			//
			//if ( XIXCORE_TEST_FLAGS(NameLink->LCBFlags, 
			//	(XIFSD_LCB_STATE_LINK_IS_GONE)) )
			//{
			//	break;
			//}


			CurrentLcb = NameLink;

			//
			//  Update the caller's remaining name string to reflect the fact that we found
			//  a match.
			//

			*RemainingName = LocalRemainingName;

			//
			//  Move down to the next component in the tree.  Acquire without waiting.
			//  If this fails then lock the Fcb to reference this Fcb and then drop
			//  the parent and acquire the child.
			//

			ASSERT( NameLink->ParentFcb == *CurrentFcb );

			if (!XifsdAcquireFcbExclusive( Waitable, NameLink->ChildFcb, FALSE ))  
			{

				//
				//  If we can't wait then raise CANT_WAIT.
				//

				if ( Waitable) {

					XifsdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}

				XifsdLockVcb( IrpContext, IrpContext->VCB );
				NameLink->ChildFcb->FCBReference += 1;
				NameLink->Reference += 1;
				XifsdUnlockVcb( IrpContext, IrpContext->VCB );

				XifsdReleaseFcb( IrpContext, *CurrentFcb );
				XifsdAcquireFcbExclusive(  Waitable, NameLink->ChildFcb, FALSE );

				XifsdLockVcb( IrpContext, IrpContext->VCB );
				NameLink->ChildFcb->FCBReference -= 1;
				NameLink->Reference -= 1;
				XifsdUnlockVcb( IrpContext, IrpContext->VCB );

			} else {

				XifsdReleaseFcb( IrpContext, *CurrentFcb );
			}

			*CurrentFcb = NameLink->ChildFcb;
		}
	}finally{
		if(AbnormalTermination()){
			ExRaiseStatus(STATUS_CANT_WAIT);
		}
	}

	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CREATE|DEBUG_TARGET_CLOSE| DEBUG_TARGET_FCB),
		("Exit xixfs_FCBTLBFindPrefix \n" ));   
	return CurrentLcb;
}
Ejemplo n.º 26
0
VOID
FatPrepareWriteVolumeFile (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN VBO StartingVbo,
    IN ULONG ByteCount,
    OUT PBCB *Bcb,
    OUT PVOID *Buffer,
    IN BOOLEAN Reversible,
    IN BOOLEAN Zero
    )

/*++

Routine Description:

    This routine first looks to see if the specified range of sectors,
    is already in the cache.  If so, it increments the BCB PinCount,
    sets the BCB dirty, and returns with the location of the sectors.

    If the sectors are not in the cache and Wait is TRUE, it finds a
    free BCB (potentially causing a flush), and clears out the entire
    buffer.  Once this is done, it increments the BCB PinCount, sets the
    BCB dirty, and returns with the location of the sectors.

    If the sectors are not in the cache and Wait is FALSE, this routine
    raises STATUS_CANT_WAIT.

Arguments:

    Vcb - Pointer to the VCB for the volume

    StartingVbo - The virtual offset of the first byte to be written

    ByteCount - Number of bytes to be written

    Bcb - Returns a pointer to the BCB which is valid until unpinned

    Buffer - Returns a pointer to the sectors, which is valid until unpinned

    Reversible - Supplies TRUE if the specified range of modification should
        be repinned so that the operation can be reversed in a controlled
        fashion if errors are encountered.
    
    Zero - Supplies TRUE if the specified range of bytes should be zeroed

--*/

{
    LARGE_INTEGER Vbo;

    PAGED_CODE();
    
    //
    //  Check to see that all references are within the Bios Parameter Block
    //  or the fat(s).
    //

    ASSERT( ((StartingVbo + ByteCount) <= (ULONG)
            (FatRootDirectoryLbo( &Vcb->Bpb ))));

    DebugTrace(+1, Dbg, "FatPrepareWriteVolumeFile\n", 0);
    DebugTrace( 0, Dbg, "Vcb         = %08lx\n", Vcb);
    DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", (ULONG)StartingVbo);
    DebugTrace( 0, Dbg, "ByteCount   = %08lx\n", ByteCount);
    DebugTrace( 0, Dbg, "Zero        = %08lx\n", Zero);

    //
    //  Call the Cache manager to attempt the transfer.
    //

    Vbo.QuadPart = StartingVbo;

    if (!CcPinRead( Vcb->VirtualVolumeFile,
                    &Vbo,
                    ByteCount,
                    BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
                    Bcb,
                    Buffer )) {

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

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

        FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    }

    //
    //  This keeps the data pinned until we complete the request
    //  and writes the dirty bit through to the disk.
    //

    DbgDoit( IrpContext->PinCount += 1 )

    try {

        if (Zero) {
            
            RtlZeroMemory( *Buffer, ByteCount );
        }

        FatSetDirtyBcb( IrpContext, *Bcb, Vcb, Reversible );

    } finally {

        if (AbnormalTermination()) {

            FatUnpinBcb(IrpContext, *Bcb);
        }
    }

    DebugTrace(-1, Dbg, "FatPrepareWriteVolumeFile -> VOID, *Bcb = %08lx\n", *Bcb);

    return;
}
Ejemplo n.º 27
0
NTSTATUS
NdFatCommonFlushBuffers (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for flushing a buffer.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;

    PIO_STACK_LOCATION IrpSp;

    PFILE_OBJECT FileObject;

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

    BOOLEAN VcbAcquired = FALSE;
    BOOLEAN FcbAcquired = FALSE;

    PDIRENT Dirent;
    PBCB DirentBcb = NULL;

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

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;



    PAGED_CODE();

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatCommonFlushBuffers\n", 0);
    DebugTrace( 0, Dbg, "Irp           = %08lx\n", Irp);
    DebugTrace( 0, Dbg, "->FileObject  = %08lx\n", IrpSp->FileObject);

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

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

    //
    //  CcFlushCache is always synchronous, so if we can't wait enqueue
    //  the irp to the Fsp.
    //

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

        Status = FatFsdPostRequest( IrpContext, Irp );

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

    Status = STATUS_SUCCESS;

    try {

		if (!FlagOn(Ccb->NdFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

			do {
			
				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 );	
				}

				secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, IRP_MJ_FLUSH_BUFFERS, 0 );

				if (secondaryRequest == NULL) {
	
					Status = STATUS_INSUFFICIENT_RESOURCES;
					break;
				}

				ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;

				INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_FLUSH_BUFFERS, 0 );

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

				INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, 
													  IrpContext->OriginatingIrp, 
													  IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp), 
													  Ccb->PrimaryFileHandle );
				
				ASSERT( !ExIsResourceAcquiredSharedLite(&IrpContext->Vcb->Resource) );	

				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) {

					ASSERT( NDFAT_BUG );
					break;
				}

				KeClearEvent (&secondaryRequest->CompleteEvent);

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

					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}

				if (secondaryRequest->ExecuteStatus == STATUS_SUCCESS) {

					ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
					ASSERT(ndfsWinxpReplytHeader->Status == STATUS_SUCCESS);
				}

				if (secondaryRequest) {

					DereferenceSecondaryRequest( secondaryRequest );
					secondaryRequest = NULL;
				}

				if ( secondarySessionResourceAcquired == TRUE ) {
					
					SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );		
					secondarySessionResourceAcquired = FALSE;
				}

				break;

			} while(0);
		} 

		Status = STATUS_SUCCESS;

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

        switch (TypeOfOpen) {

        case VirtualVolumeFile:
        case EaFile:
        case DirectoryFile:

            DebugTrace(0, Dbg, "Flush that does nothing\n", 0);
            break;

        case UserFileOpen:

            DebugTrace(0, Dbg, "Flush User File Open\n", 0);

            (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );

            FcbAcquired = TRUE;

            FatVerifyFcb( IrpContext, Fcb );

            //
            //  If the file is cached then flush its cache
            //

            Status = FatFlushFile( IrpContext, Fcb, Flush );

            //
            //  Also update and flush the file's dirent in the parent directory if the
            //  file flush worked.
            //

            if (NT_SUCCESS( Status )) {

                //
                //  Insure that we get the filesize to disk correctly.  This is
                //  benign if it was already good.
                //
                //  (why do we need to do this?)
                //

                SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED);
#if 0
                FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
#endif                
                //
                //  Flush the volume file to get any allocation information
                //  updates to disk.
                //

                if (FlagOn(Fcb->FcbState, FCB_STATE_FLUSH_FAT)) {

                    Status = FatFlushFat( IrpContext, Vcb );

                    ClearFlag(Fcb->FcbState, FCB_STATE_FLUSH_FAT);
                }

                //
                //  Set the write through bit so that these modifications
                //  will be completed with the request.
                //

                SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
            }

            break;

        case UserDirectoryOpen:

            //
            //  If the user had opened the root directory then we'll
            //  oblige by flushing the volume.
            //

            if (NodeType(Fcb) != FAT_NTC_ROOT_DCB) {

                DebugTrace(0, Dbg, "Flush a directory does nothing\n", 0);
                break;
            }

        case UserVolumeOpen:

            DebugTrace(0, Dbg, "Flush User Volume Open, or root dcb\n", 0);

            //
            //  Acquire exclusive access to the Vcb.
            //

            {
                BOOLEAN Finished;
                Finished = FatAcquireExclusiveSecondaryVcb( IrpContext, Vcb );
                ASSERT( Finished );
            }

            VcbAcquired = TRUE;

            //
            //  Mark the volume clean and then flush the volume file,
            //  and then all directories
            //

            Status = FatFlushVolume( IrpContext, Vcb, Flush );

            //
            //  If the volume was dirty, do the processing that the delayed
            //  callback would have done.
            //

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

                //
                //  Cancel any pending clean volumes.
                //

                (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
                (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );

                //
                //  The volume is now clean, note it.
                //

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

                    FatMarkVolume( IrpContext, Vcb, VolumeClean );
                    ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY );
                }

                //
                //  Unlock the volume if it is removable.
                //

                if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
                    !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE)) {

                    FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
                }
            }

            break;

        default:

            FatBugCheck( TypeOfOpen, 0, 0 );
        }

        FatUnpinBcb( IrpContext, DirentBcb );

        FatUnpinRepinnedBcbs( IrpContext );

    } finally {

        DebugUnwind( FatCommonFlushBuffers );

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );

		if (secondarySessionResourceAcquired) {

			SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );		
		}

        FatUnpinBcb( IrpContext, DirentBcb );

        if (VcbAcquired) { FatReleaseSecondaryVcb( IrpContext, Vcb ); }

        if (FcbAcquired) { FatReleaseFcb( IrpContext, Fcb ); }

        //
        //  If this is a normal termination then pass the request on
        //  to the target device object.
        //

        if (!AbnormalTermination()) {

            NTSTATUS DriverStatus;
            PIO_STACK_LOCATION NextIrpSp;

            //
            //  Get the next stack location, and copy over the stack location
            //

            NextIrpSp = IoGetNextIrpStackLocation( Irp );

            *NextIrpSp = *IrpSp;

            //
            //  Set up the completion routine
            //

            IoSetCompletionRoutine( Irp,
                                    FatFlushCompletionRoutine,
                                    ULongToPtr( Status ),
                                    TRUE,
                                    TRUE,
                                    TRUE );

            //
            //  Send the request.
            //

            DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);

            Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
                     Status : DriverStatus;

            //
            //  Free the IrpContext and return to the caller.
            //

            FatCompleteRequest( IrpContext, FatNull, STATUS_SUCCESS );
        }

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

    return Status;
}
Ejemplo n.º 28
0
VOID
FatPrepareWriteDirectoryFile (
    IN PIRP_CONTEXT IrpContext,
    IN PDCB Dcb,
    IN VBO StartingVbo,
    IN ULONG ByteCount,
    OUT PBCB *Bcb,
    OUT PVOID *Buffer,
    IN BOOLEAN Zero,
    IN BOOLEAN Reversible,
    OUT PNTSTATUS Status
    )

/*++

Routine Description:

    This routine first looks to see if the specified range of sectors
    is already in the cache.  If so, it increments the BCB PinCount,
    sets the BCB dirty, and returns TRUE with the location of the sectors.

    The IrpContext->Flags .. Wait == TRUE/FALSE actions of this routine are identical to
    FatPrepareWriteVolumeFile() above.

Arguments:

    Dcb - Pointer to the DCB for the directory

    StartingVbo - The virtual offset of the first byte to be written

    ByteCount - Number of bytes to be written

    Bcb - Returns a pointer to the BCB which is valid until unpinned

    Buffer - Returns a pointer to the sectors, which is valid until unpinned

    Zero - Supplies TRUE if the specified range of bytes should be zeroed
    
    Reversible - Supplies TRUE if the specified range of modification should
        be repinned so that the operation can be reversed in a controlled
        fashion if errors are encountered.
    
    Status - Returns the status of the operation.

--*/

{
    LARGE_INTEGER Vbo;
    ULONG InitialAllocation;
    BOOLEAN UnwindWeAllocatedDiskSpace = FALSE;
    ULONG ClusterSize;

    PVOID LocalBuffer;

    PAGED_CODE();
    
    DebugTrace(+1, Dbg, "FatPrepareWriteDirectoryFile\n", 0);
    DebugTrace( 0, Dbg, "Dcb         = %08lx\n", Dcb);
    DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", (ULONG)StartingVbo);
    DebugTrace( 0, Dbg, "ByteCount   = %08lx\n", ByteCount);
    DebugTrace( 0, Dbg, "Zero        = %08lx\n", Zero);

    *Bcb = NULL;
    *Buffer = NULL;

    //
    //  If we need to create a directory file and initialize the
    //  cachemap, do so.
    //

    FatOpenDirectoryFile( IrpContext, Dcb );

    //
    //  If the transfer is beyond the allocation size we need to
    //  extend the directory's allocation.  The call to
    //  AddFileAllocation will raise a condition if
    //  it runs out of disk space.  Note that the root directory
    //  cannot be extended.
    //

    Vbo.QuadPart = StartingVbo;

    try {

        if (StartingVbo + ByteCount > Dcb->Header.AllocationSize.LowPart) {

            if (NodeType(Dcb) == FAT_NTC_ROOT_DCB &&
                !FatIsFat32(Dcb->Vcb)) {

                FatRaiseStatus( IrpContext, STATUS_DISK_FULL );
            }

            DebugTrace(0, Dbg, "Try extending normal directory\n", 0);

            InitialAllocation = Dcb->Header.AllocationSize.LowPart;

            FatAddFileAllocation( IrpContext,
                                  Dcb,
                                  Dcb->Specific.Dcb.DirectoryFile,
                                  StartingVbo + ByteCount );

            UnwindWeAllocatedDiskSpace = TRUE;

            //
            //  Inform the cache manager of the new allocation
            //

            Dcb->Header.FileSize.LowPart =
                Dcb->Header.AllocationSize.LowPart;

            CcSetFileSizes( Dcb->Specific.Dcb.DirectoryFile,
                            (PCC_FILE_SIZES)&Dcb->Header.AllocationSize );

            //
            //  Set up the Bitmap buffer if it is not big enough already
            //

            FatCheckFreeDirentBitmap( IrpContext, Dcb );

            //
            //  The newly allocated clusters should be zeroed starting at
            //  the previous allocation size
            //

            Zero = TRUE;
            Vbo.QuadPart = InitialAllocation;
            ByteCount = Dcb->Header.AllocationSize.LowPart - InitialAllocation;
        }

        //
        // Call the Cache Manager to attempt the transfer, going one cluster
        // at a time to avoid pinning across a page boundary.
        //

        ClusterSize =
            1 << Dcb->Vcb->AllocationSupport.LogOfBytesPerCluster;

        while (ByteCount > 0) {

            ULONG BytesToPin;

            *Bcb = NULL;

            if (ByteCount > ClusterSize) {
                BytesToPin = ClusterSize;
            } else {
                BytesToPin = ByteCount;
            }

            ASSERT( (Vbo.QuadPart / ClusterSize) ==
                    (Vbo.QuadPart + BytesToPin - 1)/ClusterSize );

            if (!CcPinRead( Dcb->Specific.Dcb.DirectoryFile,
                            &Vbo,
                            BytesToPin,
                            BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
                            Bcb,
                            &LocalBuffer )) {
    
                //
                // Could not read the data without waiting (cache miss).
                //

                FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
            }

            //
            //  Update our caller with the beginning of their request.
            //
            
            if (*Buffer == NULL) {

                *Buffer = LocalBuffer;
            }

            DbgDoit( IrpContext->PinCount += 1 )

            if (Zero) {
                
                //
                //  We set this guy dirty right now so that we can raise CANT_WAIT when
                //  it needs to be done.  It'd be beautiful if we could noop the read IO
                //  since we know we don't care about it.
                //
                
                RtlZeroMemory( LocalBuffer, BytesToPin );
                CcSetDirtyPinnedData( *Bcb, NULL );
            }

            ByteCount -= BytesToPin;
            Vbo.QuadPart += BytesToPin;


            if (ByteCount > 0) {

                FatUnpinBcb( IrpContext, *Bcb );
            }
        }

        //
        //  This lets us get the data pinned until we complete the request
        //  and writes the dirty bit through to the disk.
        //

        FatSetDirtyBcb( IrpContext, *Bcb, Dcb->Vcb, Reversible );

        *Status = STATUS_SUCCESS;

    } finally {

        DebugUnwind( FatPrepareWriteDirectoryFile );

        if (AbnormalTermination()) {

            //
            //  These steps are carefully arranged - FatTruncateFileAllocation can raise.
            //  Make sure we unpin the buffer.  If FTFA raises, the effect should be benign.
            //
            
            FatUnpinBcb(IrpContext, *Bcb);
            
            if (UnwindWeAllocatedDiskSpace == TRUE) {

                //
                //  Inform the cache manager of the change.
                //

                FatTruncateFileAllocation( IrpContext, Dcb, InitialAllocation );

                Dcb->Header.FileSize.LowPart =
                    Dcb->Header.AllocationSize.LowPart;

                CcSetFileSizes( Dcb->Specific.Dcb.DirectoryFile,
                                (PCC_FILE_SIZES)&Dcb->Header.AllocationSize );
            }
        }

        DebugTrace(-1, Dbg, "FatPrepareWriteDirectoryFile -> (VOID), *Bcb = %08lx\n", *Bcb);
    }

    return;
}
Ejemplo n.º 29
0
BOOLEAN
LfsReadNextLogRecord (
    IN LFS_LOG_HANDLE LogHandle,
    IN OUT LFS_LOG_CONTEXT Context,
    OUT PLFS_RECORD_TYPE RecordType,
    OUT TRANSACTION_ID *TransactionId,
    OUT PLSN UndoNextLsn,
    OUT PLSN PreviousLsn,
    OUT PLSN Lsn,
    OUT PULONG BufferLength,
    OUT PVOID *Buffer
    )

/*++

Routine Description:

    This routine is called to continue a query operation.  The Lfs uses
    private information stored in the context structure to determine the
    next log record to return to the caller.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    Context - Supplies the address to store a pointer to the Lfs created
              context structure.

    Lsn - Lsn for this log record.

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

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

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

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

    BufferLength - This is the length of the log data.

    Buffer - This is a pointer to the start of the log data.

Return Value:

    None

--*/

{
    volatile NTSTATUS Status = STATUS_SUCCESS;

    PLCH Lch;

    PLFCB Lfcb;

    PLfsLCB Lcb;

    BOOLEAN FoundNextLsn;

    BOOLEAN UnwindRememberLcbFields;
    PBCB UnwindRecordHeaderBcb;
    PLFS_RECORD_HEADER UnwindRecordHeader;
    PVOID UnwindCurrentLogRecord;
    BOOLEAN UnwindAuxilaryBuffer;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsReadNextLogRecord:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle    -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "Context       -> %08lx\n", Context );

    FoundNextLsn = FALSE;

    UnwindRememberLcbFields = FALSE;

    Lch = (PLCH) LogHandle;
    Lcb = (PLfsLCB) Context;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-except to catch errors.
    //

    try {

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

        try {

            //
            //  Acquire the log file control block for this log file.
            //

            LfsAcquireLch( Lch );
            Lfcb = Lch->Lfcb;

            //
            //  If the Log file has been closed then refuse access.
            //

            if (Lfcb == NULL) {

                ExRaiseStatus( STATUS_ACCESS_DENIED );
            }

            //
            //  Check that the client Id is valid.
            //

            LfsValidateClientId( Lfcb, Lch );

            //
            //  Check that the context structure is valid.
            //

            LfsValidateLcb( Lcb, Lch );

            //
            //  Remember any context fields to be overwritten.
            //

            UnwindRememberLcbFields = TRUE;

            UnwindRecordHeaderBcb = Lcb->RecordHeaderBcb;
            Lcb->RecordHeaderBcb = NULL;

            UnwindRecordHeader = Lcb->RecordHeader;
            UnwindCurrentLogRecord = Lcb->CurrentLogRecord;

            UnwindAuxilaryBuffer = Lcb->AuxilaryBuffer;
            Lcb->AuxilaryBuffer = FALSE;

            //
            //  Find the next Lsn number based on the current Lsn number in
            //  the context block.
            //

            if (LfsFindClientNextLsn( Lfcb, Lcb, Lsn )) {

                //
                //  We can give up the Lfcb as we know the Lsn is within the file.
                //

                LfsReleaseLfcb( Lfcb );

                //
                //  Cleanup the context block so we can do the next search.
                //

                Lcb->CurrentLogRecord = NULL;
                Lcb->AuxilaryBuffer = FALSE;

                //
                //  Perform the work of getting the log record.
                //

                LfsFindLogRecord( Lfcb,
                                  Lcb,
                                  *Lsn,
                                  RecordType,
                                  TransactionId,
                                  UndoNextLsn,
                                  PreviousLsn,
                                  BufferLength,
                                  Buffer );

                FoundNextLsn = TRUE;
            }

        } finally {

            DebugUnwind( LfsReadNextLogRecord );

            //
            //  If we exited due to an error, we have to restore the context
            //  block.
            //

            if (UnwindRememberLcbFields) {

                if (AbnormalTermination()) {

                    //
                    //  If the record header in the context block is not
                    //  the same as we started with.  Then we unpin that
                    //  data.
                    //

                    if (Lcb->RecordHeaderBcb != NULL) {

                        CcUnpinData( Lcb->RecordHeaderBcb );

                    }

                    if (Lcb->CurrentLogRecord != NULL
                        && Lcb->AuxilaryBuffer == TRUE) {

                        ExFreePool( Lcb->CurrentLogRecord );
                    }

                    Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb;
                    Lcb->RecordHeader = UnwindRecordHeader;
                    Lcb->CurrentLogRecord = UnwindCurrentLogRecord;
                    Lcb->AuxilaryBuffer = UnwindAuxilaryBuffer;

                //
                //  Otherwise, if we have successfully found the next Lsn,
                //  we free up any resources being held from the previous search.
                //

                } else if (FoundNextLsn ) {

                    if (UnwindRecordHeaderBcb != NULL) {

                        CcUnpinData( UnwindRecordHeaderBcb );
                    }

                    if (UnwindCurrentLogRecord != NULL
                        && UnwindAuxilaryBuffer == TRUE) {

                        ExFreePool( UnwindCurrentLogRecord );
                    }

                //
                //  Restore the Bcb and auxilary buffer field for the final
                //  cleanup.
                //

                } else {

                    if (UnwindRecordHeaderBcb != NULL) {

                        if (Lcb->RecordHeaderBcb != NULL) {

                            CcUnpinData( UnwindRecordHeaderBcb );

                        } else {

                            Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb;
                        }
                    }

                    if (UnwindAuxilaryBuffer) {

                        if (Lcb->CurrentLogRecord == UnwindCurrentLogRecord) {

                            Lcb->AuxilaryBuffer = TRUE;

                        } else {

                            ExFreePool( UnwindCurrentLogRecord );
                        }
                    }
                }
            }

            //
            //  Release the log file control block if held.
            //

            LfsReleaseLch( Lch );

            LfsDebugTrace(  0, Dbg, "Lsn (Low)     -> %08lx\n", Lsn->LowPart );
            LfsDebugTrace(  0, Dbg, "Lsn (High)    -> %08lx\n", Lsn->HighPart );
            LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
            LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", *Buffer );
            LfsDebugTrace( -1, Dbg, "LfsReadNextLogRecord:  Exit\n", 0 );
        }

    } except (LfsExceptionFilter( GetExceptionInformation() )) {

        Status = GetExceptionCode();
    }

    if (Status != STATUS_SUCCESS) {

        ExRaiseStatus( Status );
    }

    return FoundNextLsn;
}
Ejemplo n.º 30
0
NTSTATUS
DfsCommonClose (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
) {
    NTSTATUS Status;

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

    TYPE_OF_OPEN TypeOfOpen;
    PDFS_VCB Vcb;
    PDFS_FCB Fcb;

    BOOLEAN DontComplete = FALSE;
    BOOLEAN pktLocked;

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

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


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

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

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

    try {

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

        switch (TypeOfOpen) {

        case LogicalRootDeviceOpen:

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

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

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

            try_return( Status = STATUS_SUCCESS );

        case RedirectedFileOpen:

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

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

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

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

            PktAcquireExclusive( TRUE, &pktLocked );

            ExAcquireResourceExclusive( &DfsData.Resource, TRUE );

            DfsDecrementMachEntryCount(Fcb->DfsMachineEntry, TRUE);

            ExReleaseResource( &DfsData.Resource );

            PktRelease();


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

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

            DontComplete = TRUE;

            DfsDeleteFcb( IrpContext, Fcb );

            break;

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

        Status = STATUS_SUCCESS;

    try_exit: NOTHING;

    } finally {

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

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

        DfsDbgTrace(-1, Dbg, "DfsCommonClose:  Exit -> %08lx\n", Status);
    }
    return Status;
}