예제 #1
0
VOID
PrimarySession_Close (
	IN 	PPRIMARY_SESSION	PrimarySession
	)
{
	DebugTrace2( 0, Dbg2, ("PrimarySession_Close: PrimarySession = %p\n", PrimarySession) );

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	if (FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOP)) {

		ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );
		return;
	}

	SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOP );

	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );
	
	if (PrimarySession->ThreadHandle == NULL) {

		ASSERT( NDASFAT_BUG );
		PrimarySession_Dereference( PrimarySession );

		return;
	}

	ASSERT( PrimarySession->ThreadObject != NULL );

	if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED)) {

		ObDereferenceObject( PrimarySession->ThreadObject );

		PrimarySession->ThreadHandle = NULL;
		PrimarySession->ThreadObject = NULL;

	
	} else {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
		NTSTATUS					ntStatus;
		LARGE_INTEGER				timeOut;
	
		
		primarySessionRequest = AllocPrimarySessionRequest( FALSE );
		primarySessionRequest->RequestType = PRIMARY_SESSION_REQ_DISCONNECT;

		QueueingPrimarySessionRequest( PrimarySession,
									   primarySessionRequest,
									   FALSE );

		primarySessionRequest = AllocPrimarySessionRequest( FALSE );
		primarySessionRequest->RequestType = PRIMARY_SESSION_REQ_DOWN;

		QueueingPrimarySessionRequest( PrimarySession,
									   primarySessionRequest,
									   FALSE );

		timeOut.QuadPart = -NDASFAT_TIME_OUT;
		ntStatus = KeWaitForSingleObject( PrimarySession->ThreadObject,
										  Executive,
										  KernelMode,
										  FALSE,
										  &timeOut );

		if (ntStatus == STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg, ("PrimarySession_Close: thread stoped\n") );

			ObDereferenceObject( PrimarySession->ThreadObject );

			PrimarySession->ThreadHandle = NULL;
			PrimarySession->ThreadObject = NULL;
				
		} else {

			ASSERT( NDASFAT_BUG );
			return;
		}
	}

#if 0
    interval.QuadPart = (5 * DELAY_ONE_SECOND);      //delay 5 seconds
    KeDelayExecutionThread( KernelMode, FALSE, &interval );
#endif

	if (PrimarySession->ConnectionFileHandle) {

		LpxTdiDisassociateAddress( PrimarySession->ConnectionFileObject );
		LpxTdiCloseConnection( PrimarySession->ConnectionFileHandle, PrimarySession->ConnectionFileObject );
	}

	PrimarySession->ConnectionFileHandle = NULL;
	PrimarySession->ConnectionFileObject = NULL;

	PrimarySession_Dereference( PrimarySession );

	return;
}
예제 #2
0
VOID
Secondary_Dereference (
	IN  PSECONDARY	Secondary
	)
{
    LONG result;
	
    result = InterlockedDecrement (&Secondary->ReferenceCount);
    ASSERT (result >= 0);

    if (result == 0) {

		PVOLUME_DEVICE_OBJECT volDo = Secondary->VolDo;

#if __NDAS_FAT_DBG__
		
		BOOLEAN acquired;

		acquired = SecondaryAcquireResourceExclusiveLite( NULL, &Secondary->RecoveryResource, TRUE );
		if (acquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->RecoveryResource );
		else
			ASSERT( FALSE );

		acquired = SecondaryAcquireResourceExclusiveLite( NULL, &Secondary->Resource, TRUE );
		if (acquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->Resource );
		else
			ASSERT( FALSE );

		acquired = SecondaryAcquireResourceExclusiveLite( NULL, &Secondary->CreateResource, TRUE );
		if (acquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->CreateResource );
		else
			ASSERT( FALSE );

		acquired = SecondaryAcquireResourceExclusiveLite( NULL, &Secondary->SessionResource, TRUE );
		if (acquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->SessionResource );
		else
			ASSERT( FALSE );

#endif
		ASSERT( Secondary->TryCloseActive == FALSE );

		if (Secondary->TryCloseWorkItem)
			IoFreeWorkItem( Secondary->TryCloseWorkItem );

		ExDeleteResourceLite( &Secondary->RecoveryResource );
		ExDeleteResourceLite( &Secondary->Resource );
		ExDeleteResourceLite( &Secondary->CreateResource );
		ExDeleteResourceLite( &Secondary->SessionResource );

		ExFreePoolWithTag( Secondary, NDFAT_ALLOC_TAG );

		DebugTrace2( 0, Dbg2, ("Secondary_Dereference: Secondary is Freed Secondary  = %p\n", Secondary) );
		DebugTrace2( 0, Dbg2, ("Secondary_Dereference: voldo->Reference = %d\n", volDo->ReferenceCount) );

		VolDo_Dereference( volDo );
	}
}
예제 #3
0
VOID
Secondary_TryCloseFilExts(
	PSECONDARY Secondary
	)
{
	PLIST_ENTRY		listEntry;


	Secondary_Reference( Secondary );

	if (ExTryToAcquireFastMutex(&Secondary->RecoveryCcbQMutex) == FALSE) {

		Secondary_Dereference(Secondary);
		return;
	}
	
	if (BooleanFlagOn(Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {

		ExReleaseFastMutex(&Secondary->RecoveryCcbQMutex);
		Secondary_Dereference(Secondary);
		return;
	}

	listEntry = Secondary->RecoveryCcbQueue.Flink;

	while (listEntry != &Secondary->RecoveryCcbQueue) {

		PCCB						ccb;
		PFCB						fcb;

		PSECTION_OBJECT_POINTERS	section;
		BOOLEAN						dataSectionExists;
		BOOLEAN						imageSectionExists;
		IRP_CONTEXT					IrpContext;

		ccb = CONTAINING_RECORD( listEntry, CCB, ListEntry );
		listEntry = listEntry->Flink;

		if (ccb->Fcb == NULL) {

			ASSERT(NDFAT_BUG);
			continue;
		}	

		if (NodeType(ccb->Fcb) != FAT_NTC_FCB) 
			continue;

		fcb = ccb->Fcb;

		if (fcb->UncleanCount != 0 || fcb->NonCachedUncleanCount != 0) {

			DebugTrace2( 0, Dbg, ("Secondary_TryCloseFilExts: fcb->FullFileName = %wZ\n", &ccb->Fcb->FullFileName) );
			break;
		}

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFilExts: fcb->FullFileName = %wZ\n", &ccb->Fcb->FullFileName) );

		RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );
		SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
		
		section = &fcb->NonPaged->SectionObjectPointers;			
		if (section == NULL)
			break;

		dataSectionExists = (BOOLEAN)(section->DataSectionObject != NULL);
		imageSectionExists = (BOOLEAN)(section->ImageSectionObject != NULL);

		if (imageSectionExists) {

			(VOID)MmFlushImageSection( section, MmFlushForWrite );
		}

		if (dataSectionExists) {

            CcPurgeCacheSection( section, NULL, 0, FALSE );
	    }
	}

	ExReleaseFastMutex( &Secondary->RecoveryCcbQMutex );
	Secondary_Dereference( Secondary );

	return;
}
VOID
SecondaryRecoveryThreadProc (
	IN	PSECONDARY	Secondary
	)
{
	NTSTATUS	status;

	BOOLEAN		secondaryResourceAcquired = FALSE;
	BOOLEAN		secondaryRecoveryResourceAcquired = FALSE;


	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	DebugTrace2( 0, Dbg2, ("SecondaryRecoveryThreadProc: Start Secondary = %p\n", Secondary) );
	
	Secondary_Reference( Secondary );
	FsRtlEnterFileSystem();

	KeSetEvent( &Secondary->RecoveryReadyEvent, IO_DISK_INCREMENT, FALSE );

	try {

		secondaryRecoveryResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( NULL, 
													 &Secondary->VolDo->RecoveryResource, 
													 TRUE );
								
		if (!FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

			NDAS_ASSERT( FALSE );

			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->RecoveryResource );
			secondaryRecoveryResourceAcquired = FALSE;

			leave;
		}

		secondaryResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( NULL, 
													 &Secondary->VolDo->Resource, 
													 TRUE );
		
		try {
								
			status = SecondaryRecoverySession( Secondary );
								
		} finally {

			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->Resource );
			secondaryResourceAcquired = FALSE;

			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->RecoveryResource );
			secondaryRecoveryResourceAcquired = FALSE;
		}
	
	} finally {

		if (secondaryResourceAcquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->Resource );

		if (secondaryRecoveryResourceAcquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->RecoveryResource );

		Secondary->RecoveryThreadHandle = NULL;

		FsRtlExitFileSystem();
		Secondary_Dereference( Secondary );

		DebugTrace2( 0, Dbg2, ("SecondaryRecoveryThreadProc: Terminated Secondary = %p\n", Secondary) );
	}

	PsTerminateSystemThread( STATUS_SUCCESS );
}
예제 #5
0
PSECONDARY
Secondary_Create(
	IN  PIRP_CONTEXT			IrpContext,
	IN	PVOLUME_DEVICE_OBJECT	VolDo		 
	)
{
	NTSTATUS			status;
	PSECONDARY			secondary;

	OBJECT_ATTRIBUTES	objectAttributes;
	LARGE_INTEGER		timeOut;
	ULONG				tryQuery;
	BOOLEAN				isLocalAddress;
	

	UNREFERENCED_PARAMETER( IrpContext );

	secondary = ExAllocatePoolWithTag( NonPagedPool, sizeof(SECONDARY), NDFAT_ALLOC_TAG );
	
	if (secondary == NULL) {

		ASSERT( NDFAT_INSUFFICIENT_RESOURCES );
		return NULL;
	}
	
	RtlZeroMemory( secondary, sizeof(SECONDARY) );

#define MAX_TRY_QUERY 2

	for (tryQuery = 0; tryQuery < MAX_TRY_QUERY; tryQuery++) {

		status = ((PVOLUME_DEVICE_OBJECT) FatData.DiskFileSystemDeviceObject)->
			NdfsCallback.QueryPrimaryAddress( &VolDo->NetdiskPartitionInformation, &secondary->PrimaryAddress, &isLocalAddress );

		DebugTrace2( 0, Dbg2, ("Secondary_Create: QueryPrimaryAddress %08x\n", status) );

		if (NT_SUCCESS(status)) {

			DebugTrace2( 0, Dbg2, ("Secondary_Create: QueryPrimaryAddress: Found PrimaryAddress :%02x:%02x:%02x:%02x:%02x:%02x/%d\n",
				secondary->PrimaryAddress.Node[0], secondary->PrimaryAddress.Node[1],
				secondary->PrimaryAddress.Node[2], secondary->PrimaryAddress.Node[3],
				secondary->PrimaryAddress.Node[4], secondary->PrimaryAddress.Node[5],
				NTOHS(secondary->PrimaryAddress.Port)) );
			break;
		}
	}

	if (status != STATUS_SUCCESS || isLocalAddress) {

		ExFreePoolWithTag( secondary, NDFAT_ALLOC_TAG );
		return NULL;
	}

	secondary->Flags = SECONDARY_FLAG_INITIALIZING;

	ExInitializeResourceLite( &secondary->RecoveryResource );
	ExInitializeResourceLite( &secondary->Resource );
	ExInitializeResourceLite( &secondary->SessionResource );
	ExInitializeResourceLite( &secondary->CreateResource );

	ExInitializeFastMutex( &secondary->FastMutex );

	secondary->ReferenceCount = 1;

	VolDo_Reference( VolDo );
	secondary->VolDo = VolDo;

	secondary->ThreadHandle = NULL;

	InitializeListHead( &secondary->RecoveryCcbQueue );
    ExInitializeFastMutex( &secondary->RecoveryCcbQMutex );

	InitializeListHead( &secondary->DeletedFcbQueue );

	KeQuerySystemTime( &secondary->TryCloseTime );

	secondary->TryCloseWorkItem = IoAllocateWorkItem( (PDEVICE_OBJECT)VolDo );

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

	////////////////////////////////////////
	InitializeListHead( &secondary->FcbQueue );
	ExInitializeFastMutex( &secondary->FcbQMutex );
	/////////////////////////////////////////


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

	secondary->SessionId = 0;
	
	status = PsCreateSystemThread( &secondary->ThreadHandle,
								   THREAD_ALL_ACCESS,
								   &objectAttributes,
								   NULL,
								   NULL,
								   SecondaryThreadProc,
								   secondary );

	if (!NT_SUCCESS(status)) {

		ASSERT( NDFAT_UNEXPECTED );
		Secondary_Close( secondary );
		
		return NULL;
	}

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

	if (!NT_SUCCESS(status)) {

		ASSERT( NDFAT_INSUFFICIENT_RESOURCES );
		Secondary_Close( secondary );
		
		return NULL;
	}

	secondary->SessionId ++;

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

	if (status != STATUS_SUCCESS) {
	
		ASSERT( NDFAT_BUG );
		Secondary_Close( secondary );
		
		return NULL;
	}

	KeClearEvent( &secondary->ReadyEvent );

	ExAcquireFastMutex( &secondary->FastMutex );

	if (!FlagOn(secondary->Thread.Flags, SECONDARY_THREAD_FLAG_START) ||
		FlagOn(secondary->Thread.Flags, SECONDARY_THREAD_FLAG_STOPED)) {

		if (secondary->Thread.SessionStatus != STATUS_DISK_CORRUPT_ERROR) {
	
			ExReleaseFastMutex( &secondary->FastMutex );

			Secondary_Close( secondary );
			return NULL;
		}
	} 

	ASSERT( secondary->Thread.SessionContext.SessionSlotCount != 0 );

	ClearFlag( secondary->Flags, SECONDARY_FLAG_INITIALIZING );
	SetFlag( secondary->Flags, SECONDARY_FLAG_START );

	ExReleaseFastMutex( &secondary->FastMutex );

	DebugTrace2( 0, Dbg2,
				("Secondary_Create: The client thread are ready secondary = %p\n", secondary) );

	return secondary;
}
예제 #6
0
NTSTATUS
RecvMessage (
	IN PFILE_OBJECT			ConnectionFileObject,
	IN PNDAS_FC_STATISTICS	RecvNdasFcStatistics,
	IN PLARGE_INTEGER		TimeOut,
	IN UINT8				*Buffer, 
	IN UINT32				BufferLength
	)
{
	NTSTATUS		status;
	UINT32			remainDataLength;
	UINT32			chooseDataLength;
	LARGE_INTEGER	startTime;
	LARGE_INTEGER	endTime;


	return RecvIt( ConnectionFileObject,
				   Buffer,
				   BufferLength,
				   NULL,
				   NULL,
				   0,
				   TimeOut );

	chooseDataLength = NdasFcChooseTransferSize( RecvNdasFcStatistics, BufferLength );

	startTime = NdasCurrentTime();

	remainDataLength = BufferLength;

	do {

		status = RecvIt( ConnectionFileObject,
						 Buffer + BufferLength - remainDataLength,
						 (remainDataLength < chooseDataLength) ? remainDataLength : chooseDataLength,
						 NULL,
						 NULL,
						 0,
						 TimeOut );

		if (status != STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg2, ("Error when Recv data\n") );

			return status;
		}

		if (remainDataLength > chooseDataLength) {

			remainDataLength -= chooseDataLength;
			
		} else {

			remainDataLength = 0;
		}

	} while (remainDataLength);

	endTime = NdasCurrentTime();

	NdasFcUpdateTrasnferSize( RecvNdasFcStatistics, 
						  chooseDataLength, 
						  BufferLength,
						  startTime, 
						  endTime );

	return STATUS_SUCCESS;
}
예제 #7
0
NTSTATUS
NdasFatSecondaryUserFsCtrl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for implementing the user's requests made
    through NtFsControlFile.

Arguments:

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    ULONG FsControlCode;

    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

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

	TYPE_OF_OPEN				typeOfOpen;
	PVCB						vcb;
	PFCB						fcb;
	PCCB						ccb;

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;
	UINT8						*ndfsWinxpRequestData;

	LARGE_INTEGER				timeOut;

	struct FileSystemControl	fileSystemControl;

	PVOID						inputBuffer = NULL;
	ULONG						inputBufferLength;
	PVOID						outputBuffer = NULL;
	ULONG						outputBufferLength;
	ULONG						bufferLength;


    //
    //  Save some references to make our life a little easier
    //

    FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;

    DebugTrace(+1, Dbg,"FatUserFsCtrl...\n", 0);
    DebugTrace( 0, Dbg,"FsControlCode = %08lx\n", FsControlCode);

    //
    //  Some of these Fs Controls use METHOD_NEITHER buffering.  If the previous mode
    //  of the caller was userspace and this is a METHOD_NEITHER, we have the choice
    //  of realy buffering the request through so we can possibly post, or making the
    //  request synchronous.  Since the former was not done by design, do the latter.
    //

    if (Irp->RequestorMode != KernelMode && (FsControlCode & 3) == METHOD_NEITHER) {

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    }

    //
    //  Case on the control code.
    //

    switch ( FsControlCode ) {

    case FSCTL_REQUEST_OPLOCK_LEVEL_1:
    case FSCTL_REQUEST_OPLOCK_LEVEL_2:
    case FSCTL_REQUEST_BATCH_OPLOCK:
    case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
    case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
    case FSCTL_OPLOCK_BREAK_NOTIFY:
    case FSCTL_OPLOCK_BREAK_ACK_NO_2:
    case FSCTL_REQUEST_FILTER_OPLOCK :

		//ASSERT( FALSE );

		//Status = STATUS_SUCCESS;
		//break;

        Status = FatOplockRequest( IrpContext, Irp );
		return Status;

    case FSCTL_LOCK_VOLUME:

		FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) );
		return Status;

		//Status = FatLockVolume( IrpContext, Irp );
        break;

    case FSCTL_UNLOCK_VOLUME:

		FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) );
		return Status;

		//Status = FatUnlockVolume( IrpContext, Irp );
        break;

    case FSCTL_DISMOUNT_VOLUME:

		FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) );
		return Status;

        //Status = FatDismountVolume( IrpContext, Irp );
        break;

    case FSCTL_MARK_VOLUME_DIRTY:

		FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace2( -1, Dbg, ("NdasFatSecondaryUserFsCtrl -> %08lx\n", Status) );
		return Status;

		//Status = FatDirtyVolume( IrpContext, Irp );
        break;

    case FSCTL_IS_VOLUME_DIRTY:

        Status = FatIsVolumeDirty( IrpContext, Irp );
        break;

    case FSCTL_IS_VOLUME_MOUNTED:

        Status = FatIsVolumeMounted( IrpContext, Irp );

		DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		break;

    case FSCTL_IS_PATHNAME_VALID:

		Status = FatIsPathnameValid( IrpContext, Irp );
		
		DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		break;

    case FSCTL_QUERY_RETRIEVAL_POINTERS:
        Status = FatQueryRetrievalPointers( IrpContext, Irp );
        break;

    case FSCTL_QUERY_FAT_BPB:

		Status = FatQueryBpb( IrpContext, Irp );

		DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		break;

    case FSCTL_FILESYSTEM_GET_STATISTICS:
        Status = FatGetStatistics( IrpContext, Irp );
        break;

    case FSCTL_GET_VOLUME_BITMAP:
        Status = FatGetVolumeBitmap( IrpContext, Irp );
        break;

    case FSCTL_GET_RETRIEVAL_POINTERS:
        Status = FatGetRetrievalPointers( IrpContext, Irp );
        break;

    case FSCTL_MOVE_FILE:

		FatCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace2( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;
		
		//Status = FatMoveFile( IrpContext, Irp );
        break;

    case FSCTL_ALLOW_EXTENDED_DASD_IO:
        Status = FatAllowExtendedDasdIo( IrpContext, Irp );
        break;

    default :

        DebugTrace(0, Dbg, "Invalid control code -> %08lx\n", FsControlCode );

        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
        Status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

	ASSERT( !ExIsResourceAcquiredSharedLite(&volDo->Vcb.Resource) );	

	if (Status != STATUS_SUCCESS) {

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

	inputBuffer = IrpContext->InputBuffer;
	outputBuffer = IrpContext->outputBuffer;

	ASSERT( IrpSp->Parameters.FileSystemControl.InputBufferLength ? (inputBuffer != NULL) : (inputBuffer == NULL) );
	ASSERT( IrpSp->Parameters.FileSystemControl.OutputBufferLength ? (outputBuffer != NULL) : (outputBuffer == NULL) );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

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

		return FatFsdPostRequest( IrpContext, Irp );
	}

	try {

		secondarySessionResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( IrpContext, 
													 &volDo->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 );
			NDAS_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
			SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );	
		}

		ASSERT( IS_SECONDARY_FILEOBJECT(IrpSp->FileObject) );
		
		typeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &vcb, &fcb, &ccb );

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

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

			try_return( Status = STATUS_FILE_CORRUPT_ERROR );
		}
		
		fileSystemControl.FsControlCode			= IrpSp->Parameters.FileSystemControl.FsControlCode;
		fileSystemControl.InputBufferLength		= IrpSp->Parameters.FileSystemControl.InputBufferLength;
		fileSystemControl.OutputBufferLength	= IrpSp->Parameters.FileSystemControl.OutputBufferLength;

		if (inputBuffer == NULL)
			fileSystemControl.InputBufferLength = 0;
		if (outputBuffer == NULL)
			fileSystemControl.OutputBufferLength = 0;

		outputBufferLength	= fileSystemControl.OutputBufferLength;
		
		if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) {			// 29
		
			inputBufferLength = 0;			
		
		} else if (fileSystemControl.FsControlCode == FSCTL_MARK_HANDLE) {		// 63
		
			inputBufferLength = 0;			
		
		} else {
		
			inputBufferLength  = fileSystemControl.InputBufferLength;
		}
		
		bufferLength = (inputBufferLength >= outputBufferLength) ? inputBufferLength : outputBufferLength;

		secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, 
														  IRP_MJ_FILE_SYSTEM_CONTROL,
														  bufferLength );

		if (secondaryRequest == NULL) {

			NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES );
			Status = Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
			Irp->IoStatus.Information = 0;
			try_return( Status );
		}

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

		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
		ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );
		INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, Irp, IrpSp, ccb->PrimaryFileHandle );

		ndfsWinxpRequestHeader->FileSystemControl.OutputBufferLength	= fileSystemControl.OutputBufferLength;
		ndfsWinxpRequestHeader->FileSystemControl.InputBufferLength		= fileSystemControl.InputBufferLength;
		ndfsWinxpRequestHeader->FileSystemControl.FsControlCode			= fileSystemControl.FsControlCode;

#if 0
		if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) {		// 29
				
			PMOVE_FILE_DATA	moveFileData = inputBuffer;	
			PFILE_OBJECT	moveFileObject;
			PCCB			moveCcb;

			Status = ObReferenceObjectByHandle( moveFileData->FileHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&moveFileObject,
												NULL );

			if (Status != STATUS_SUCCESS) {

				ASSERT( FALSE );
				try_return( Status );
			}
	
			ObDereferenceObject( moveFileObject );

			moveCcb = moveFileObject->FsContext2;

			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.FileHandle	= moveCcb->PrimaryFileHandle;
			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.StartingVcn	= moveFileData->StartingVcn.QuadPart;
			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.StartingLcn	= moveFileData->StartingLcn.QuadPart;
			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.ClusterCount	= moveFileData->ClusterCount;
		
		} else
#endif
		if (fileSystemControl.FsControlCode == FSCTL_MARK_HANDLE) {	// 63
		
			PMARK_HANDLE_INFO	markHandleInfo = inputBuffer;	
			PFILE_OBJECT		volumeFileObject;
			PCCB				volumeCcb;

			Status = ObReferenceObjectByHandle( markHandleInfo->VolumeHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&volumeFileObject,
												NULL );

			if (Status != STATUS_SUCCESS) {

				try_return( Status );
			}
	
			ObDereferenceObject( volumeFileObject );

			volumeCcb = volumeFileObject->FsContext2;

			ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.UsnSourceInfo	= markHandleInfo->UsnSourceInfo;
			ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.VolumeHandle	= volumeCcb->PrimaryFileHandle;
			ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.HandleInfo		= markHandleInfo->HandleInfo;
		
		} else {

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

			if (inputBufferLength)
				RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength );
		}

		ASSERT( !ExIsResourceAcquiredSharedLite(&IrpContext->Vcb->Resource) );	

		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;
			try_return( Status = STATUS_IO_DEVICE_ERROR );
		}

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

			NDAS_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
			SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
		}

		ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
		Status = Irp->IoStatus.Status = NTOHL(ndfsWinxpReplytHeader->Status4);
		Irp->IoStatus.Information = NTOHL(ndfsWinxpReplytHeader->Information32);

		if (FsControlCode == FSCTL_GET_NTFS_VOLUME_DATA && Status != STATUS_SUCCESS)
			DebugTrace2( 0, Dbg2, ("FSCTL_GET_NTFS_VOLUME_DATA: Status = %x, Irp->IoStatus.Information = %d\n", Status, Irp->IoStatus.Information) );

		if (NTOHL(secondaryRequest->NdfsReplyHeader.MessageSize4) - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REPLY_HEADER)) {

			ASSERT( Irp->IoStatus.Status == STATUS_SUCCESS || Irp->IoStatus.Status == STATUS_BUFFER_OVERFLOW );
			ASSERT( Irp->IoStatus.Information );
			ASSERT( Irp->IoStatus.Information <= outputBufferLength );
			ASSERT( outputBuffer );

			RtlCopyMemory( outputBuffer,
						   (UINT8 *)(ndfsWinxpReplytHeader+1),
						   Irp->IoStatus.Information );
		}

		if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE && Status != STATUS_SUCCESS)
			DebugTrace2( 0, Dbg2, ("NtfsDefragFile: status = %x\n", Status) );

#if 0
		if (Status == STATUS_SUCCESS && fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) {		// 29
				
			PMOVE_FILE_DATA	moveFileData = inputBuffer;	
			PFILE_OBJECT	moveFileObject;

			TYPE_OF_OPEN	typeOfOpen;
			PVCB			vcb;
			PFCB			moveFcb;
			PSCB			moveScb;
			PCCB			moveCcb;


			Status = ObReferenceObjectByHandle( moveFileData->FileHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&moveFileObject,
												NULL );

			if (Status != STATUS_SUCCESS) {

				try_return( Status );
			}
	
			ObDereferenceObject( moveFileObject );
				
			typeOfOpen = NtfsDecodeFileObject( IrpContext, moveFileObject, &vcb, &moveFcb, &moveScb, &moveCcb, TRUE );
		
			if (typeOfOpen == UserFileOpen && FlagOn(volDo->NdasFatFlags, ND_FAT_DEVICE_FLAG_DIRECT_RW) && ndfsWinxpReplytHeader->FileInformationSet && NTOHLL(ndfsWinxpReplytHeader->AllocationSize8)) {

				PNDFS_FAT_MCB_ENTRY	mcbEntry;
				ULONG			index;
				VCN				testVcn;

			
				SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ACQUIRE_PAGING );
				NtfsAcquireFcbWithPaging( IrpContext, moveFcb, 0 );
				NtfsAcquireNtfsMcbMutex( &moveScb->Mcb );

				mcbEntry = (PNDFS_FAT_MCB_ENTRY)( ndfsWinxpReplytHeader+1 );

				if (moveScb->Header.AllocationSize.QuadPart) {

					NtfsRemoveNtfsMcbEntry( &moveScb->Mcb, 0, 0xFFFFFFFF );
				}

				for (index=0, testVcn=0; index < NTOHL(ndfsWinxpReplytHeader->NumberOfMcbEntry4); index++) {

					ASSERT( mcbEntry[index].Vcn == testVcn );
					testVcn += (LONGLONG)mcbEntry[index].ClusterCount;

					NtfsAddNtfsMcbEntry( &moveScb->Mcb, 
										 mcbEntry[index].Vcn, 
										 (mcbEntry[index].Lcn << vcb->AllocationSupport.LogOfBytesPerSector), 
										 (LONGLONG)mcbEntry[index].ClusterCount, 
										 TRUE );
				}
					
				ASSERT( LlBytesFromClusters(vcb, testVcn) == NTOHLL(ndfsWinxpReplytHeader->AllocationSize8) );

				if (moveScb->Header.AllocationSize.QuadPart != NTOHLL(ndfsWinxpReplytHeader->AllocationSize8))
					SetFlag( moveScb->ScbState, SCB_STATE_TRUNCATE_ON_CLOSE );		

				moveScb->Header.FileSize.LowPart = NTOHLL(ndfsWinxpReplytHeader->FileSize8);
				moveScb->Header.AllocationSize.QuadPart = NTOHLL(ndfsWinxpReplytHeader->AllocationSize8);
				ASSERT( moveScb->Header.AllocationSize.QuadPart >= moveScb->Header.FileSize.LowPart );

				if (moveFileObject->SectionObjectPointer->DataSectionObject != NULL && moveFileObject->PrivateCacheMap == NULL) {

					CcInitializeCacheMap( moveFileObject,
										  (PCC_FILE_SIZES)&moveScb->Header.AllocationSize,
										  FALSE,
										  &NtfsData.CacheManagerCallbacks,
										  moveScb );

					//CcSetAdditionalCacheAttributes( fileObject, TRUE, TRUE );
				}

				if (CcIsFileCached(moveFileObject)) {

					NtfsSetBothCacheSizes( moveFileObject,
										   (PCC_FILE_SIZES)&scb->Header.AllocationSize,
										   moveScb );
				}

				NtfsReleaseNtfsMcbMutex( &moveScb->Mcb );
				NtfsReleaseFcb( IrpContext, moveFcb );
			}
		}

#endif
try_exit:  NOTHING;

	} finally {

		if (secondarySessionResourceAcquired == TRUE) {

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

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}

	FatCompleteRequest( IrpContext, Irp, Status );

    DebugTrace(-1, Dbg, "FatUserFsCtrl -> %08lx\n", Status );
    return Status;
}
예제 #8
0
VOID
FatUnload(
    IN PDRIVER_OBJECT DriverObject
    )

/*++

Routine Description:

    This is the unload routine for the filesystem

Arguments:

    DriverObject - Pointer to driver object created by the system.

Return Value:

    None

--*/

{
#if __NDAS_FAT__
	UNICODE_STRING linkString;
#endif

#if DBG
	DbgPrint( "\n************NdasFat %s %s %s\n", __FUNCTION__, __DATE__, __TIME__ );
#endif

    ExDeleteNPagedLookasideList (&FatEResourceLookasideList);
    ExDeleteNPagedLookasideList (&FatNonPagedFcbLookasideList);
    ExDeleteNPagedLookasideList (&FatIrpContextLookasideList);
    ExDeleteResourceLite( &FatData.Resource );
    IoFreeWorkItem (FatData.FatCloseItem);
    ObDereferenceObject( FatDiskFileSystemDeviceObject);
#if __NDAS_FAT__
	if (FatCdromFileSystemDeviceObject)
#endif
    ObDereferenceObject( FatCdromFileSystemDeviceObject);

#if __NDAS_FAT__

    RtlInitUnicodeString( &linkString, NDAS_FAT_CONTROL_LINK_NAME );
    IoDeleteSymbolicLink( &linkString );

	DebugTrace2( 0, Dbg2, ("NdasFatUnload occured NdasFatControlDeviceObject->ReferenceCount = %x\n", 
						   FatControlDeviceObject->ReferenceCount) );

	IoDeleteDevice( FatControlDeviceObject );

	DebugTrace2( 0, Dbg2, ("NdasFatUnload occured NdasFatFileSystemDeviceObject->ReferenceCount = %x\n", 
						   FatDiskFileSystemDeviceObject->ReferenceCount) );

	IoDeleteDevice( FatDiskFileSystemDeviceObject );

	if (FatCdromFileSystemDeviceObject) {

		IoDeleteDevice( FatCdromFileSystemDeviceObject );
	}

#endif

#if DBG
	DbgPrint( "\n************NdasFat %s %s %s return\n", __FUNCTION__, __DATE__, __TIME__ );
#endif

}
예제 #9
0
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    This is the initialization routine for the Fat file system
    device driver.  This routine creates the device object for the FileSystem
    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.

--*/

{
    USHORT MaxDepth;
    NTSTATUS Status;
    UNICODE_STRING UnicodeString;
    FS_FILTER_CALLBACKS FilterCallbacks;
    UNICODE_STRING ValueName;
    ULONG Value;

#if __NDAS_FAT__
	UNICODE_STRING	linkString;
	UNICODE_STRING	functionName;
	UNICODE_STRING	tempUnicode;
#endif

#if DBG
	DbgPrint( "\n************NdasFat %s %s %s\n", __FUNCTION__, __DATE__, __TIME__ );
#endif

#if __NDAS_FAT_DBG__

	FatDebugTraceLevel |= DEBUG_TRACE_ERROR;
	FatDebugTraceLevel |= DEBUG_TRACE_CLEANUP;
	FatDebugTraceLevel |= DEBUG_TRACE_CLOSE;
	FatDebugTraceLevel |= DEBUG_TRACE_CREATE;
	FatDebugTraceLevel |= DEBUG_TRACE_DIRCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_EA;
	FatDebugTraceLevel |= DEBUG_TRACE_FILEINFO;
	FatDebugTraceLevel |= DEBUG_TRACE_FSCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_LOCKCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_READ;
	FatDebugTraceLevel |= DEBUG_TRACE_VOLINFO;
	FatDebugTraceLevel |= DEBUG_TRACE_WRITE;
	FatDebugTraceLevel |= DEBUG_TRACE_DEVCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_FLUSH;
	FatDebugTraceLevel |= DEBUG_TRACE_PNP;
	FatDebugTraceLevel |= DEBUG_TRACE_SHUTDOWN;
	

	//FatDebugTraceLevel |= DEBUG_TRACE_FSCTRL;
	//FatDebugTraceLevel |= DEBUG_INFO_DEVCTRL;
	//FatDebugTraceLevel |= DEBUG_TRACE_WRITE;
	//FatDebugTraceLevel = 0xFFFFFFFFFFFFFFFF;
	//FatDebugTraceLevel |= DEBUG_TRACE_STRUCSUP;
	//FatDebugTraceLevel |= DEBUG_TRACE_FILEINFO;

	FatDebugTraceLevel = 0x00000009;

	FatDebugTraceLevel |= DEBUG_INFO_FSCTRL;
	FatDebugTraceLevel |= DEBUG_INFO_READ;
	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_FILOBSUP;
	FatDebugTraceLevel |= DEBUG_TRACE_PNP;
	FatDebugTraceLevel |= DEBUG_TRACE_SHUTDOWN;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;
	FatDebugTraceLevel |= DEBUG_INFO_CREATE;
	FatDebugTraceLevel |= DEBUG_INFO_STRUCSUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLEANUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;
	FatDebugTraceLevel |= DEBUG_INFO_ALL;
	FatDebugTraceLevel |= DEBUG_INFO_WRITE;
	FatDebugTraceLevel &= ~DEBUG_TRACE_UNWIND;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;

	FatDebugTraceLevel = 0x00000009;

	FatDebugTraceLevel |= DEBUG_INFO_FSCTRL;
	FatDebugTraceLevel |= DEBUG_INFO_READ;
	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_FILOBSUP;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;
	FatDebugTraceLevel |= DEBUG_INFO_CREATE;
	FatDebugTraceLevel |= DEBUG_INFO_STRUCSUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLEANUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;
	FatDebugTraceLevel |= DEBUG_INFO_ALL;
	FatDebugTraceLevel |= DEBUG_INFO_WRITE;

	FatDebugTraceLevel  = 0x00000000;

	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_PRIMARY;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;

	DebugTrace2( 0, DEBUG_INFO_ALL, ("sizeof(NDFS_WINXP_REPLY_HEADER) = %d\n", sizeof(NDFS_WINXP_REPLY_HEADER)) );

#endif

#if __NDAS_FAT_WIN2K_SUPPORT__

	PsGetVersion( &gOsMajorVersion, &gOsMinorVersion, NULL, NULL );

	RtlInitUnicodeString( &functionName, L"SeFilterToken" );
	NdasFatSeFilterToken = MmGetSystemRoutineAddress( &functionName );

	if (IS_WINDOWSXP_OR_LATER()) {

		// to prevent incomprehensible error

		RtlInitUnicodeString( &functionName, L"CcMdlWriteAbort" ); 
		NdasFatCcMdlWriteAbort = MmGetSystemRoutineAddress( &functionName );
	}

	RtlInitUnicodeString( &functionName, L"KeAreApcsDisabled" );
	NdasFatKeAreApcsDisabled = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"KeAreAllApcsDisabled" );
	NdasFatKeAreAllApcsDisabled = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"FsRtlRegisterFileSystemFilterCallbacks" );
	NdasFatFsRtlRegisterFileSystemFilterCallbacks = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"FsRtlAreVolumeStartupApplicationsComplete" );
	NdasFatFsRtlAreVolumeStartupApplicationsComplete = MmGetSystemRoutineAddress( &functionName );
	
	RtlInitUnicodeString( &functionName, L"MmDoesFileHaveUserWritableReferences" );
	NdasFatMmDoesFileHaveUserWritableReferences = MmGetSystemRoutineAddress( &functionName );

#endif

#if __NDAS_FAT__
	
    RtlInitUnicodeString( &UnicodeString, NDAS_FAT_CONTROL_DEVICE_NAME );

    Status = IoCreateDevice( DriverObject,
                             0,                 //  has no device extension
                             &UnicodeString,
                             FILE_DEVICE_NULL,
                             0,
                             FALSE,
                             &FatControlDeviceObject );

	if (!NT_SUCCESS(Status)) {

		return Status;
	}

    RtlInitUnicodeString( &linkString, NDAS_FAT_CONTROL_LINK_NAME );
    Status = IoCreateSymbolicLink( &linkString, &UnicodeString );

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

#endif

#if __NDAS_FAT__

    RtlInitUnicodeString( &UnicodeString, NDAS_FAT_DEVICE_NAME );

    Status = IoCreateDevice( DriverObject,
                             sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
                             &UnicodeString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatDiskFileSystemDeviceObject );

	if (!NT_SUCCESS(Status)) {
		
        IoDeleteSymbolicLink( &linkString );
        IoDeleteDevice( FatControlDeviceObject );
	    return Status;
    }

	RtlZeroMemory( (PUCHAR)FatDiskFileSystemDeviceObject+sizeof(DEVICE_OBJECT), 
				   sizeof(VOLUME_DEVICE_OBJECT)-sizeof(DEVICE_OBJECT) );

#else

    //
    // Create the device object for disks.  To avoid problems with filters who
    // know this name, we must keep it.
    //

    RtlInitUnicodeString( &UnicodeString, L"\\Fat" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatDiskFileSystemDeviceObject );

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

#endif

#if !__NDAS_FAT__

    //
    // Create the device object for "cdroms".
    //

    RtlInitUnicodeString( &UnicodeString, L"\\FatCdrom" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_CD_ROM_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatCdromFileSystemDeviceObject );

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

#endif

    DriverObject->DriverUnload = FatUnload;

    //
    //  Note that because of the way data caching is done, we set neither
    //  the Direct I/O or Buffered I/O bit in DeviceObject->Flags.  If
    //  data is not in the cache, or the request 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)FatFsdCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]                    = (PDRIVER_DISPATCH)FatFsdClose;
    DriverObject->MajorFunction[IRP_MJ_READ]                     = (PDRIVER_DISPATCH)FatFsdRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE]                    = (PDRIVER_DISPATCH)FatFsdWrite;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION]        = (PDRIVER_DISPATCH)FatFsdQueryInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION]          = (PDRIVER_DISPATCH)FatFsdSetInformation;
    DriverObject->MajorFunction[IRP_MJ_QUERY_EA]                 = (PDRIVER_DISPATCH)FatFsdQueryEa;
    DriverObject->MajorFunction[IRP_MJ_SET_EA]                   = (PDRIVER_DISPATCH)FatFsdSetEa;
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]            = (PDRIVER_DISPATCH)FatFsdFlushBuffers;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]   = (PDRIVER_DISPATCH)FatFsdSetVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]                  = (PDRIVER_DISPATCH)FatFsdCleanup;
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL]        = (PDRIVER_DISPATCH)FatFsdDirectoryControl;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL]      = (PDRIVER_DISPATCH)FatFsdFileSystemControl;
    DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL]             = (PDRIVER_DISPATCH)FatFsdLockControl;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = (PDRIVER_DISPATCH)FatFsdDeviceControl;
    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]                 = (PDRIVER_DISPATCH)FatFsdShutdown;
    DriverObject->MajorFunction[IRP_MJ_PNP]                      = (PDRIVER_DISPATCH)FatFsdPnp;

    DriverObject->FastIoDispatch = &FatFastIoDispatch;

    RtlZeroMemory(&FatFastIoDispatch, sizeof(FatFastIoDispatch));

    FatFastIoDispatch.SizeOfFastIoDispatch =    sizeof(FAST_IO_DISPATCH);
    FatFastIoDispatch.FastIoCheckIfPossible =   FatFastIoCheckIfPossible;  //  CheckForFastIo
    FatFastIoDispatch.FastIoRead =              FsRtlCopyRead;             //  Read
    FatFastIoDispatch.FastIoWrite =             FsRtlCopyWrite;            //  Write
    FatFastIoDispatch.FastIoQueryBasicInfo =    FatFastQueryBasicInfo;     //  QueryBasicInfo
    FatFastIoDispatch.FastIoQueryStandardInfo = FatFastQueryStdInfo;       //  QueryStandardInfo
    FatFastIoDispatch.FastIoLock =              FatFastLock;               //  Lock
    FatFastIoDispatch.FastIoUnlockSingle =      FatFastUnlockSingle;       //  UnlockSingle
    FatFastIoDispatch.FastIoUnlockAll =         FatFastUnlockAll;          //  UnlockAll
    FatFastIoDispatch.FastIoUnlockAllByKey =    FatFastUnlockAllByKey;     //  UnlockAllByKey
    FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FatFastQueryNetworkOpenInfo;
    FatFastIoDispatch.AcquireForCcFlush =       FatAcquireForCcFlush;
    FatFastIoDispatch.ReleaseForCcFlush =       FatReleaseForCcFlush;
    FatFastIoDispatch.MdlRead =                 FsRtlMdlReadDev;
    FatFastIoDispatch.MdlReadComplete =         FsRtlMdlReadCompleteDev;
    FatFastIoDispatch.PrepareMdlWrite =         FsRtlPrepareMdlWriteDev;
    FatFastIoDispatch.MdlWriteComplete =        FsRtlMdlWriteCompleteDev;
    
#if __NDAS_FAT_SECONDARY__

	RtlZeroMemory(&FatFastIoDispatch, sizeof(FAST_IO_DISPATCH));
	FatFastIoDispatch.SizeOfFastIoDispatch			 =	sizeof(FAST_IO_DISPATCH);

	//FatFastIoDispatch.FastIoCheckIfPossible			=  FatFastIoCheckIfPossible;  //  CheckForFastIo
	//FatFastIoDispatch.AcquireForModWrite				=  FatAcquireFileForModWrite;
	//FatFastIoDispatch.AcquireFileForNtCreateSection	=  FatAcquireForCreateSection;
	//FatFastIoDispatch.ReleaseFileForNtCreateSection	=  FatReleaseForCreateSection;

	FatFastIoDispatch.AcquireForCcFlush				=  FatAcquireForCcFlush;
	FatFastIoDispatch.ReleaseForCcFlush				=  FatReleaseForCcFlush;

#endif

    //
    //  Initialize the filter callbacks we use.
    //

#if __NDAS_FAT_WIN2K_SUPPORT__

	if (IS_WINDOWSVISTA_OR_LATER()) {

		if (NdasFatFsRtlRegisterFileSystemFilterCallbacks) {

			RtlZeroMemory( &FilterCallbacks, sizeof(FS_FILTER_CALLBACKS) );

			FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);

			FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;

			Status = NdasFatFsRtlRegisterFileSystemFilterCallbacks( DriverObject, &FilterCallbacks );

		    if (!NT_SUCCESS( Status )) {

			    IoDeleteDevice( FatDiskFileSystemDeviceObject );
				IoDeleteDevice( FatCdromFileSystemDeviceObject );
				return Status;
			}
		}
	}

#else

    RtlZeroMemory( &FilterCallbacks,
                   sizeof(FS_FILTER_CALLBACKS) );

    FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
    FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;

    Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
                                                     &FilterCallbacks );

    if (!NT_SUCCESS( Status )) {

        IoDeleteDevice( FatDiskFileSystemDeviceObject );
        IoDeleteDevice( FatCdromFileSystemDeviceObject );
        return Status;
    }

#endif

    //
    //  Initialize the global data structures
    //

    //
    //  The FatData record
    //

    RtlZeroMemory( &FatData, sizeof(FAT_DATA));

    FatData.NodeTypeCode = FAT_NTC_DATA_HEADER;
    FatData.NodeByteSize = sizeof(FAT_DATA);

    InitializeListHead(&FatData.VcbQueue);

    FatData.DriverObject = DriverObject;
    FatData.DiskFileSystemDeviceObject = FatDiskFileSystemDeviceObject;
    FatData.CdromFileSystemDeviceObject = FatCdromFileSystemDeviceObject;

    //
    //  This list head keeps track of closes yet to be done.
    //

    InitializeListHead( &FatData.AsyncCloseList );
    InitializeListHead( &FatData.DelayedCloseList );
    
    FatData.FatCloseItem = IoAllocateWorkItem( FatDiskFileSystemDeviceObject);

    if (FatData.FatCloseItem == NULL) {
        IoDeleteDevice (FatDiskFileSystemDeviceObject);

#if __NDAS_FAT__
		if (FatCdromFileSystemDeviceObject)
#endif
        IoDeleteDevice (FatCdromFileSystemDeviceObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    //  Now initialize our general purpose spinlock (gag) and figure out how
    //  deep and wide we want our delayed lists (along with fooling ourselves
    //  about the lookaside depths).
    //

    KeInitializeSpinLock( &FatData.GeneralSpinLock );

    switch ( MmQuerySystemSize() ) {

    case MmSmallSystem:

        MaxDepth = 4;
        FatMaxDelayedCloseCount = FAT_MAX_DELAYED_CLOSES;
        break;

    case MmMediumSystem:

        MaxDepth = 8;
        FatMaxDelayedCloseCount = 4 * FAT_MAX_DELAYED_CLOSES;
        break;

    case MmLargeSystem:

        MaxDepth = 16;
        FatMaxDelayedCloseCount = 16 * FAT_MAX_DELAYED_CLOSES;
        break;
    }


    //
    //  Initialize the cache manager callback routines
    //

    FatData.CacheManagerCallbacks.AcquireForLazyWrite  = &FatAcquireFcbForLazyWrite;
    FatData.CacheManagerCallbacks.ReleaseFromLazyWrite = &FatReleaseFcbFromLazyWrite;
    FatData.CacheManagerCallbacks.AcquireForReadAhead  = &FatAcquireFcbForReadAhead;
    FatData.CacheManagerCallbacks.ReleaseFromReadAhead = &FatReleaseFcbFromReadAhead;

    FatData.CacheManagerNoOpCallbacks.AcquireForLazyWrite  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &FatNoOpRelease;
    FatData.CacheManagerNoOpCallbacks.AcquireForReadAhead  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &FatNoOpRelease;

    //
    //  Set up global pointer to our process.
    //

    FatData.OurProcess = PsGetCurrentProcess();

    //
    //  Read the registry to determine if we are in ChicagoMode.
    //

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

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.ChicagoMode = FALSE;

    } else {

        FatData.ChicagoMode = TRUE;
    }

    //
    //  Read the registry to determine if we are going to generate LFNs
    //  for valid 8.3 names with extended characters.
    //

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

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.CodePageInvariant = FALSE;

    } else {

        FatData.CodePageInvariant = TRUE;
    }

    //
    //  Initialize our global resource and fire up the lookaside lists.
    //

    ExInitializeResourceLite( &FatData.Resource );

    ExInitializeNPagedLookasideList( &FatIrpContextLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(IRP_CONTEXT),
                                     TAG_IRP_CONTEXT,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(NON_PAGED_FCB),
                                     TAG_FCB_NONPAGED,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatEResourceLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(ERESOURCE),
                                     TAG_ERESOURCE,
                                     MaxDepth );

    ExInitializeSListHead( &FatCloseContextSList );
    ExInitializeFastMutex( &FatCloseQueueMutex );
    KeInitializeEvent( &FatReserveEvent, SynchronizationEvent, TRUE );

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

    IoRegisterFileSystem(FatDiskFileSystemDeviceObject);
    ObReferenceObject (FatDiskFileSystemDeviceObject);
#if __NDAS_FAT__
	if (FatCdromFileSystemDeviceObject) {

		IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
		ObReferenceObject (FatCdromFileSystemDeviceObject);
	}
#else
    IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
    ObReferenceObject (FatCdromFileSystemDeviceObject);
#endif

#if __NDAS_FAT__

	FatData.FileSystemRegistered = TRUE;

	RtlInitEmptyUnicodeString( &FatData.Root, 
							   FatData.RootBuffer,
							   sizeof(FatData.RootBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\" );
	RtlCopyUnicodeString( &FatData.Root, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.MountMgrRemoteDatabase, 
							   FatData.MountMgrRemoteDatabaseBuffer,
							   sizeof(FatData.MountMgrRemoteDatabaseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\:$MountMgrRemoteDatabase" );
	RtlCopyUnicodeString( &FatData.MountMgrRemoteDatabase, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.ExtendReparse, 
							   FatData.ExtendReparseBuffer,
							   sizeof(FatData.ExtendReparseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION" );
	RtlCopyUnicodeString( &FatData.ExtendReparse, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.MountPointManagerRemoteDatabase, 
							   FatData.MountPointManagerRemoteDatabaseBuffer,
							   sizeof(FatData.MountPointManagerRemoteDatabaseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\System Volume Information\\MountPointManagerRemoteDatabase" );
	RtlCopyUnicodeString( &FatData.MountPointManagerRemoteDatabase, &tempUnicode );

#endif

    //
    //  Find out if we are running an a FujitsuFMR machine.
    //

    FatData.FujitsuFMR = FatIsFujitsuFMR();

#if __NDAS_FAT__

    //
    //  Check to see if new kernel is present to decide if we want
    //  to support advance fcb headers
    //

    RtlInitUnicodeString( &UnicodeString, L"FsRtlTeardownPerStreamContexts" );
    FatFsRtlTeardownPerStreamContexts = MmGetSystemRoutineAddress( &UnicodeString );

#endif

    //
    //  And return to our caller
    //

    return( STATUS_SUCCESS );
}
예제 #10
0
NTSTATUS
SecondaryRecoverySession (
	IN  PSECONDARY		Secondary
	)
{
	NTSTATUS			status;
	LONG				slotIndex;

	LARGE_INTEGER		timeOut;
	OBJECT_ATTRIBUTES	objectAttributes;

	ULONG				reconnectionTry;
    PLIST_ENTRY			ccblistEntry;
	BOOLEAN				isLocalAddress;


	DebugTrace2( 0, Dbg2, ("SecondaryRecoverySession: Called Secondary = %p\n", Secondary) );

	SetFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

	ASSERT( FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); 
	ASSERT( Secondary->ThreadHandle );

	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	for (slotIndex=0; slotIndex < Secondary->Thread.SessionContext.SessionSlotCount; slotIndex++) {

		ASSERT( Secondary->Thread.SessionSlot[slotIndex] == NULL );
	}

	if (Secondary->ThreadHandle) {

		ASSERT( Secondary->ThreadObject );
		
		timeOut.QuadPart = -NDASFAT_TIME_OUT;
		status = KeWaitForSingleObject( Secondary->ThreadObject,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );

		if (status != STATUS_SUCCESS) {

			NDASFAT_ASSERT( FALSE );

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return status;
		}

		DebugTrace2( 0, Dbg2, ("Secondary_Stop: thread stoped\n") );

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = 0;
		Secondary->ThreadObject = 0;

		RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );
	}

	for (status = STATUS_UNSUCCESSFUL, reconnectionTry = 0; reconnectionTry < MAX_RECONNECTION_TRY; reconnectionTry++) {

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_LOCKED)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->NdasFatFlags, ND_FAT_DEVICE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY) {
			
			status = STATUS_SUCCESS;
		
		} else {

			status = ((PVOLUME_DEVICE_OBJECT) FatData.DiskFileSystemDeviceObject)->
						NdfsCallback.SecondaryToPrimary( Secondary->VolDo->Vcb.Vpb->RealDevice, TRUE );

			if (status == STATUS_NO_SUCH_DEVICE) {

				NDASFAT_ASSERT( FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_LOCKED) );
				ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

				return STATUS_UNSUCCESSFUL;
			}
		}

		//FatDebugTraceLevel = 0;

		DebugTrace2( 0, Dbg2, ("SecondaryToPrimary status = %x\n", status) ); 

#if 0
		if (queryResult == TRUE) {
			
			BOOLEAN	result0, result1;
		    IRP_CONTEXT IrpContext;
		
			ASSERT( Secondary->VolDo->Vcb.VirtualVolumeFile );
			result0 = CcPurgeCacheSection( &Secondary->VolDo->Vcb.SectionObjectPointers,
										   NULL,
										   0,
										   FALSE );
			ASSERT( Secondary->VolDo->Vcb.RootDcb->Specific.Dcb.DirectoryFile );
			result1 = CcPurgeCacheSection( &Secondary->VolDo->Vcb.RootDcb->NonPaged->SectionObjectPointers,
										   NULL,
										   0,
										   FALSE );
		
			ASSERT( result0 == TRUE );
			ASSERT( result1 == TRUE );

			ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
		    RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );
            SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);
			FatTearDownAllocationSupport ( &IrpContext, &Secondary->VolDo->Vcb );
   			FatSetupAllocationSupport( &IrpContext, &Secondary->VolDo->Vcb );
			FatCheckDirtyBit( &IrpContext, &Secondary->VolDo->Vcb );

	        ASSERT( IrpContext.Repinned.Bcb[0] == NULL );
	        FatUnpinRepinnedBcbs( &IrpContext );
    
			Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; 
			Secondary->VolDo->SecondaryState = CONNECT_TO_LOCAL_STATE;
		}
#endif

		if (status == STATUS_SUCCESS) {

			PVCB				vcb = &Secondary->VolDo->Vcb;
#if 0
			TOP_LEVEL_CONTEXT	topLevelContext;
			PTOP_LEVEL_CONTEXT	threadTopLevelContext;
#endif
			IRP_CONTEXT			tempIrpContext2;
			PIRP_CONTEXT		tempIrpContext = NULL;

			SetFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&FatData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&FatData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->SecondaryResource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->SecondaryResource) );	


			//FatReleaseAllResources( IrpContext );

			//ObReferenceObject( vcb->TargetDeviceObject );

			DebugTrace2( 0, Dbg2, ("Vcb->State = %X\n", vcb->VcbState) );
			DebugTrace2( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );

			tempIrpContext = NULL;

#if 0
			threadTopLevelContext = FatInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			FatInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            FatUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );
			
			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
#endif
			tempIrpContext = &tempIrpContext2;

			RtlZeroMemory( tempIrpContext, sizeof(IRP_CONTEXT) );
			SetFlag( tempIrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
			SetFlag( tempIrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

			try {
			
				status = STATUS_UNSUCCESSFUL;
				status = CleanUpVcb( tempIrpContext, vcb );
			
			} finally {
                
				//FatCompleteRequest( tempIrpContext, NULL, 0 );
				//ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

			ASSERT( status == STATUS_SUCCESS );
			//ASSERT( FlagOn(vcb->VcbState, VCB_STATE_MOUNT_COMPLETED) );
			ASSERT( FlagOn(Secondary->VolDo->NdasFatFlags, ND_FAT_DEVICE_FLAG_MOUNTED) );
			ASSERT( !ExIsResourceAcquiredExclusiveLite(&FatData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&FatData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->SecondaryResource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->SecondaryResource) );	

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );


			DebugTrace2( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->OpenFileCount) );

#if 0
			tempIrpContext = NULL;

			threadTopLevelContext = FatInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			FatInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            FatUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
#endif

			Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; 

			tempIrpContext = &tempIrpContext2;

			RtlZeroMemory( tempIrpContext, sizeof(IRP_CONTEXT) );
			SetFlag( tempIrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
			SetFlag( tempIrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
			
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;
			
			SetFlag( Secondary->Flags, SECONDARY_FLAG_REMOUNT_VOLUME );

			try {
			
				status = STATUS_UNSUCCESSFUL;

				status = NdasFatMountVolume( tempIrpContext, vcb->TargetDeviceObject, vcb->Vpb, NULL );
			
			} finally {
                
				//FatCompleteRequest( tempIrpContext, NULL, 0 );
				//ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			//ObDereferenceObject( vcb->TargetDeviceObject );

			//FatDebugTraceLevel = 0xFFFFFFFFFFFFFFFF;
			//FatDebugTraceLevel |= DEBUG_TRACE_CREATE;

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_REMOUNT_VOLUME );

			ASSERT( status == STATUS_SUCCESS );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&FatData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&FatData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			DebugTrace2( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace2( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->OpenFileCount) );

#if 0

			if (vcb->MftScb) {
			
				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftScb->Header.Resource) );	
			}

			if (vcb->Mft2Scb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->Mft2Scb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->Mft2Scb->Header.Resource) );	
			}

			if (vcb->LogFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->LogFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->LogFileScb->Header.Resource) );			
			}

			if (vcb->VolumeDasdScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->VolumeDasdScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->VolumeDasdScb->Header.Resource) );			
			}

			if (vcb->AttributeDefTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->AttributeDefTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->AttributeDefTableScb->Header.Resource) );			
			}

			if (vcb->UpcaseTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UpcaseTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UpcaseTableScb->Header.Resource) );			
			}

			if (vcb->RootIndexScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->RootIndexScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->RootIndexScb->Header.Resource) );			
			}

			if (vcb->BitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BitmapScb->Header.Resource) );			
			}

			if (vcb->BadClusterFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BadClusterFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BadClusterFileScb->Header.Resource) );		
			}

			if (vcb->MftBitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftBitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftBitmapScb->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorStream) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorStream->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorStream->Header.Resource) );			
			}

			if (vcb->UsnJournal) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UsnJournal->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UsnJournal->Header.Resource) );			
			}

			if (vcb->ExtendDirectory) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->ExtendDirectory->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->ExtendDirectory->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorHashIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
			}

			if (vcb->SecurityIdIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityIdIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityIdIndex->Header.Resource) );			
			}
#endif
		}


		status = ((PVOLUME_DEVICE_OBJECT) FatData.DiskFileSystemDeviceObject)->
						NdfsCallback.QueryPrimaryAddress( &Secondary->VolDo->NetdiskPartitionInformation, &Secondary->PrimaryAddress, &isLocalAddress );

		DebugTrace2( 0, Dbg2, ("RecoverSession: LfsTable_QueryPrimaryAddress status = %X\n", status) );
	
		if (status == STATUS_SUCCESS && !(Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY && isLocalAddress)) {

			DebugTrace2( 0, Dbg, ("SecondaryRecoverySessionStart: Found PrimaryAddress :%02x:%02x:%02x:%02x:%02x:%02x/%d\n",
								  Secondary->PrimaryAddress.Node[0],
								  Secondary->PrimaryAddress.Node[1],
								  Secondary->PrimaryAddress.Node[2],
								  Secondary->PrimaryAddress.Node[3],
								  Secondary->PrimaryAddress.Node[4],
								  Secondary->PrimaryAddress.Node[5],
								  NTOHS(Secondary->PrimaryAddress.Port)) );
		
		} else {

			//ASSERT( FALSE );
			continue;
		}	

		KeInitializeEvent( &Secondary->ReadyEvent, NotificationEvent, FALSE );
		KeInitializeEvent( &Secondary->RequestEvent, NotificationEvent, FALSE );

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

		status = PsCreateSystemThread( &Secondary->ThreadHandle,
									   THREAD_ALL_ACCESS,
									   &objectAttributes,
									   NULL,
									   NULL,
									   SecondaryThreadProc,
									   Secondary );

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASFAT_UNEXPECTED );
			break;
		}

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

		if (!NT_SUCCESS(status)) {

			ASSERT (NDASFAT_INSUFFICIENT_RESOURCES );
			break;
		}

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

		if (status != STATUS_SUCCESS) {

			ASSERT( NDASFAT_BUG );
			break;
		}

		KeClearEvent( &Secondary->ReadyEvent );

		InterlockedIncrement( &Secondary->SessionId );	

		ExAcquireFastMutex( &Secondary->FastMutex );

		if (!FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_START) || FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_STOPED)) {

			ExReleaseFastMutex( &Secondary->FastMutex );

			if (Secondary->Thread.SessionStatus == STATUS_DISK_CORRUPT_ERROR) {

				status = STATUS_SUCCESS;
				break;
			}

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

			if (status != STATUS_SUCCESS) {

				ASSERT( NDASFAT_BUG );
				return status;
			}

			DebugTrace2( 0, Dbg, ("Secondary_Stop: thread stoped\n") );

			ObDereferenceObject( Secondary->ThreadObject );

			Secondary->ThreadHandle = 0;
			Secondary->ThreadObject = 0;

			RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );

			continue;
		} 

		ExReleaseFastMutex( &Secondary->FastMutex );

		status = STATUS_SUCCESS;

		DebugTrace2( 0, Dbg2, ("SecondaryRecoverySession Success Secondary = %p\n", Secondary) );

		break;
	}
예제 #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 {
예제 #12
0
NTSTATUS
ReceiveNdfsWinxpMessage (
	IN  PPRIMARY_SESSION	PrimarySession,
	IN  _U16				Mid
	)
{
	PNDFS_REQUEST_HEADER		ndfsRequestHeader = (PNDFS_REQUEST_HEADER)PrimarySession->Thread.SessionSlot[Mid].RequestMessageBuffer;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	_U8							*cryptWinxpRequestMessage;

	NTSTATUS					tdiStatus;
#if __NDAS_FAT_DES__
	int							desResult;
#endif

	cryptWinxpRequestMessage = PrimarySession->Thread.SessionSlot[Mid].CryptWinxpMessageBuffer;	
	//ASSERT(ndfsRequestHeader->Splitted == 0 && ndfsRequestHeader->MessageSecurity == 0);
		
	if (ndfsRequestHeader->Splitted == 0) {

		ASSERT( ndfsRequestHeader->MessageSize <= PrimarySession->Thread.SessionSlot[Mid].RequestMessageBufferLength );

		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
	
		if (ndfsRequestHeader->MessageSecurity == 0) {

			tdiStatus = RecvMessage( PrimarySession->ConnectionFileObject,
									 (_U8 *)ndfsWinxpRequestHeader,
									 ndfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER),
									 NULL );
	
			PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpRequestHeader = ndfsWinxpRequestHeader;
	
			return tdiStatus;
		}

		ASSERT(ndfsRequestHeader->MessageSecurity == 1);
		
		tdiStatus = RecvMessage( PrimarySession->ConnectionFileObject,
								 cryptWinxpRequestMessage,
								 sizeof(NDFS_WINXP_REQUEST_HEADER),
								 NULL );

			if (tdiStatus != STATUS_SUCCESS) {

				return tdiStatus;
			}

#if __NDAS_FAT_DES__

		RtlZeroMemory(&PrimarySession->DesCbcContext, sizeof(PrimarySession->DesCbcContext));
		RtlZeroMemory(PrimarySession->Iv, sizeof(PrimarySession->Iv));
		//DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartition->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_DECRYPT);
		DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_DECRYPT);
		desResult = DES_CBCUpdate(&PrimarySession->DesCbcContext, (_U8 *)ndfsWinxpRequestHeader, cryptWinxpRequestMessage, sizeof(NDFS_WINXP_REQUEST_HEADER));
		ASSERT(desResult == IDOK);
#endif
		if (ndfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER) - sizeof(NDFS_WINXP_REQUEST_HEADER)) {

			if (ndfsWinxpRequestHeader->IrpMajorFunction == IRP_MJ_WRITE && ndfsRequestHeader->RwDataSecurity == 0) {

				tdiStatus = RecvMessage( PrimarySession->ConnectionFileObject,
										 (_U8 *)(ndfsWinxpRequestHeader+1),
										 ndfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER) - sizeof(NDFS_WINXP_REQUEST_HEADER),
										 NULL );

				if (tdiStatus != STATUS_SUCCESS) {

					return tdiStatus;
				}
			
			} else {

				tdiStatus = RecvMessage( PrimarySession->ConnectionFileObject,
										 cryptWinxpRequestMessage,
										 ndfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER) - sizeof(NDFS_WINXP_REQUEST_HEADER),
										 NULL );

				if (tdiStatus != STATUS_SUCCESS) {

					return tdiStatus;
				}

#if __NDAS_FAT_DES__
				desResult = DES_CBCUpdate(&PrimarySession->DesCbcContext, (_U8 *)(ndfsWinxpRequestHeader+1), cryptWinxpRequestMessage, ndfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER) - sizeof(NDFS_WINXP_REQUEST_HEADER));
				ASSERT(desResult == IDOK);
#endif
			}
		}

		PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpRequestHeader = ndfsWinxpRequestHeader;

		return STATUS_SUCCESS;
	}

	ASSERT( ndfsRequestHeader->Splitted == 1 );

//	if (ndfsRequestHeader->MessageSize > (PrimarySession->RequestMessageBufferLength - sizeof(NDFS_REQUEST_HEADER) - sizeof(NDFS_WINXP_REQUEST_HEADER)))
	{
		PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpRequestMessagePoolLength = ndfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER);
		PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpRequestMessagePool 
			= ExAllocatePoolWithTag(
				NonPagedPool,
				PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpRequestMessagePoolLength,
				PRIMARY_SESSION_BUFFERE_TAG
				);
		ASSERT(PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpRequestMessagePool);
		if (PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpRequestMessagePool == NULL) {
			DebugTrace2( 0, Dbg,	("ReceiveNdfsWinxpMessage: failed to allocate ExtendWinxpRequestMessagePool\n"));
			return STATUS_INSUFFICIENT_RESOURCES;
		}
		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpRequestMessagePool);
	}
//	else
//		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);

	if (ndfsRequestHeader->MessageSecurity == 0)
	{
		tdiStatus = RecvMessage(
						PrimarySession->ConnectionFileObject,
						(_U8 *)ndfsWinxpRequestHeader,
						sizeof(NDFS_WINXP_REQUEST_HEADER),
						NULL
						);
		if (tdiStatus != STATUS_SUCCESS)
		{
			return tdiStatus;
		}
	}
	else
	{
		tdiStatus = RecvMessage(
						PrimarySession->ConnectionFileObject,
						cryptWinxpRequestMessage,
						sizeof(NDFS_WINXP_REQUEST_HEADER),
						NULL
						);

		if (tdiStatus != STATUS_SUCCESS)
		{
			return tdiStatus;
		}
#if __NDAS_FAT_DES__
		RtlZeroMemory(&PrimarySession->DesCbcContext, sizeof(PrimarySession->DesCbcContext));
		RtlZeroMemory(PrimarySession->Iv, sizeof(PrimarySession->Iv));
		//DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartition->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_DECRYPT);
		DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_DECRYPT);
		desResult = DES_CBCUpdate(&PrimarySession->DesCbcContext, (_U8 *)ndfsWinxpRequestHeader, cryptWinxpRequestMessage, sizeof(NDFS_WINXP_REQUEST_HEADER));
		ASSERT(desResult == IDOK);
#endif
	}

	while(1)
	{
		PNDFS_REQUEST_HEADER	splitNdfsRequestHeader = &PrimarySession->Thread.SessionSlot[Mid].SplitNdfsRequestHeader;


		tdiStatus = RecvMessage(
						PrimarySession->ConnectionFileObject,
						(_U8 *)splitNdfsRequestHeader,
						sizeof(NDFS_REQUEST_HEADER),
						NULL
						);
		if (tdiStatus != STATUS_SUCCESS)
			return tdiStatus;

		if (!(
			PrimarySession->Thread.SessionState == SESSION_SETUP
			&& ndfsRequestHeader->Uid == PrimarySession->SessionContext.Uid
			&& ndfsRequestHeader->Tid == PrimarySession->SessionContext.Tid
			))
		{
			ASSERT(NDASFAT_BUG);
			return STATUS_UNSUCCESSFUL;
		}

		if (ndfsRequestHeader->MessageSecurity == 0)
		{
			tdiStatus = RecvMessage(
							PrimarySession->ConnectionFileObject,
							(_U8 *)ndfsWinxpRequestHeader + ndfsRequestHeader->MessageSize - splitNdfsRequestHeader->MessageSize,
							splitNdfsRequestHeader->Splitted 
								? PrimarySession->SessionContext.PrimaryMaxDataSize
								: (splitNdfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER)),
							NULL
								);
			if (tdiStatus != STATUS_SUCCESS)
				return tdiStatus;
		}
		else
		{
			tdiStatus = RecvMessage(
							PrimarySession->ConnectionFileObject,
							cryptWinxpRequestMessage,
							splitNdfsRequestHeader->Splitted 
								? PrimarySession->SessionContext.PrimaryMaxDataSize
								: (splitNdfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER)),
							NULL
							);
			if (tdiStatus != STATUS_SUCCESS)
				return tdiStatus;
#if __NDAS_FAT_DES__

			desResult = DES_CBCUpdate(
							&PrimarySession->DesCbcContext, 
							(_U8 *)ndfsWinxpRequestHeader + ndfsRequestHeader->MessageSize - splitNdfsRequestHeader->MessageSize, 
							cryptWinxpRequestMessage, 
							splitNdfsRequestHeader->Splitted 
								? PrimarySession->SessionContex.PrimaryMaxDataSize
								: (splitNdfsRequestHeader->MessageSize - sizeof(NDFS_REQUEST_HEADER))
								);
			ASSERT(desResult == IDOK);
#endif
		}

		if (splitNdfsRequestHeader->Splitted)
			continue;

		PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpRequestHeader = ndfsWinxpRequestHeader;

		return STATUS_SUCCESS;
	}
}
예제 #13
0
NTSTATUS
SendNdfsWinxpMessage (
	IN PPRIMARY_SESSION			PrimarySession,
	IN PNDFS_REPLY_HEADER		NdfsReplyHeader, 
	IN PNDFS_WINXP_REPLY_HEADER	NdfsWinxpReplyHeader,
	IN _U32						ReplyDataSize,
	IN _U16						Mid
	)
{
	NTSTATUS	tdiStatus;
	_U32		remaninigDataSize;		


	//ASSERT(ReplyDataSize <= PrimarySession->SessionContext.SecondaryMaxDataSize && PrimarySession->MessageSecurity == 0);

	if (ReplyDataSize <= PrimarySession->SessionContext.SecondaryMaxDataSize) {

#if __NDAS_FAT_DES__
		int desResult;
		_U8 *cryptWinxpRequestMessage = PrimarySession->Thread.SessionSlot[Mid].CryptWinxpMessageBuffer;
#endif

		RtlCopyMemory( NdfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(NdfsReplyHeader->Protocol) );
		NdfsReplyHeader->Status		= NDFS_SUCCESS;
		NdfsReplyHeader->Flags	    = PrimarySession->SessionContext.Flags;
		NdfsReplyHeader->Uid		= PrimarySession->SessionContext.Uid;
		NdfsReplyHeader->Tid		= PrimarySession->SessionContext.Tid;
		NdfsReplyHeader->Mid		= Mid;
		NdfsReplyHeader->MessageSize 
				= sizeof(NDFS_REPLY_HEADER) 
				+ (PrimarySession->SessionContext.MessageSecurity ? ADD_ALIGN8(sizeof(NDFS_WINXP_REPLY_HEADER) + ReplyDataSize) : (sizeof(NDFS_WINXP_REPLY_HEADER) + ReplyDataSize));

		ASSERT( NdfsReplyHeader->MessageSize <= PrimarySession->Thread.SessionSlot[Mid].ReplyMessageBufferLength );

		tdiStatus = SendMessage( PrimarySession->ConnectionFileObject,
								 (_U8 *)NdfsReplyHeader,
								 sizeof(NDFS_REPLY_HEADER),
								 NULL );

		if (tdiStatus != STATUS_SUCCESS) {

			return tdiStatus;
		}
		
		if (PrimarySession->SessionContext.MessageSecurity == 0) {

			tdiStatus = SendMessage( PrimarySession->ConnectionFileObject,
									 (_U8 *)NdfsWinxpReplyHeader,
									 NdfsReplyHeader->MessageSize - sizeof(NDFS_REPLY_HEADER),
									 NULL );

			return tdiStatus;
		}
			
#if __NDAS_FAT_DES__

		if (NdfsWinxpReplyHeader->IrpMajorFunction == IRP_MJ_READ)
			DebugTrace2( 0, Dbg,
						("DispatchRequest: PrimarySession->RwDataSecurity = %d\n", PrimarySession->RwDataSecurity) );

		if (NdfsWinxpReplyHeader->IrpMajorFunction == IRP_MJ_READ && PrimarySession->RwDataSecurity == 0)
		{
			RtlCopyMemory(cryptWinxpRequestMessage, NdfsWinxpReplyHeader, sizeof(NDFS_WINXP_REPLY_HEADER));
			RtlZeroMemory(&PrimarySession->DesCbcContext, sizeof(PrimarySession->DesCbcContext));
			RtlZeroMemory(PrimarySession->Iv, sizeof(PrimarySession->Iv));
			//DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartition->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_ENCRYPT);
			DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_ENCRYPT);
			desResult = DES_CBCUpdate(&PrimarySession->DesCbcContext, (_U8 *)NdfsWinxpReplyHeader, cryptWinxpRequestMessage, sizeof(NDFS_WINXP_REPLY_HEADER));
			ASSERT(desResult == IDOK);
			tdiStatus = SendMessage( PrimarySession->ConnectionFileObject,
									 (_U8 *)NdfsWinxpReplyHeader,
									 NdfsReplyHeader->MessageSize - sizeof(NDFS_REPLY_HEADER),
									 NULL );
			}
			else {

			RtlZeroMemory(&PrimarySession->DesCbcContext, sizeof(PrimarySession->DesCbcContext));
			RtlZeroMemory(PrimarySession->Iv, sizeof(PrimarySession->Iv));
			//DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartition->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_ENCRYPT);
			DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_ENCRYPT);
			desResult = DES_CBCUpdate(&PrimarySession->DesCbcContext, cryptWinxpRequestMessage, (_U8 *)NdfsWinxpReplyHeader, NdfsReplyHeader->MessageSize-sizeof(NDFS_REPLY_HEADER));
			ASSERT(desResult == IDOK);

			tdiStatus = SendMessage(
							PrimarySession->ConnectionFileObject,
							cryptWinxpRequestMessage,
							NdfsReplyHeader->MessageSize - sizeof(NDFS_REPLY_HEADER),
							NULL
							);
		}

		return tdiStatus;

#endif
	}

	ASSERT( (_U8 *)NdfsWinxpReplyHeader == PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpReplyMessagePool );
	ASSERT( ReplyDataSize > PrimarySession->SessionContext.SecondaryMaxDataSize );

	RtlCopyMemory(NdfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(NdfsReplyHeader->Protocol));
	NdfsReplyHeader->Status		= NDFS_SUCCESS;
	NdfsReplyHeader->Flags	    = PrimarySession->SessionContext.Flags;
	NdfsReplyHeader->Splitted	= 1;
	NdfsReplyHeader->Uid		= PrimarySession->SessionContext.Uid;
	NdfsReplyHeader->Tid		= PrimarySession->SessionContext.Tid;
	NdfsReplyHeader->Mid		= 0;
	NdfsReplyHeader->MessageSize 
			= sizeof(NDFS_REPLY_HEADER) 
			+ (PrimarySession->SessionContext.MessageSecurity ? ADD_ALIGN8(sizeof(NDFS_WINXP_REPLY_HEADER) + ReplyDataSize) : (sizeof(NDFS_WINXP_REPLY_HEADER) + ReplyDataSize));
		
	tdiStatus = SendMessage( PrimarySession->ConnectionFileObject,
							 (_U8 *)NdfsReplyHeader,
							 sizeof(NDFS_REPLY_HEADER),
							 NULL );

	if (tdiStatus != STATUS_SUCCESS) {
		
		return tdiStatus;
	} 

	if (PrimarySession->SessionContext.MessageSecurity)
	{
#if __NDAS_FAT_DES__

		int desResult;
		_U8 *cryptWinxpRequestMessage = PrimarySession->Thread.SessionSlot[Mid].CryptWinxpMessageBuffer;

		RtlZeroMemory(&PrimarySession->DesCbcContext, sizeof(PrimarySession->DesCbcContext));
		RtlZeroMemory(PrimarySession->Iv, sizeof(PrimarySession->Iv));
		//DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartition->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_ENCRYPT);
		DES_CBCInit(&PrimarySession->DesCbcContext, PrimarySession->NetdiskPartitionInformation.NetdiskInformation.Password, PrimarySession->Iv, DES_ENCRYPT);
		desResult = DES_CBCUpdate(&PrimarySession->DesCbcContext, cryptWinxpRequestMessage, (_U8 *)NdfsWinxpReplyHeader, sizeof(NDFS_WINXP_REPLY_HEADER));
		ASSERT(desResult == IDOK);
		tdiStatus = SendMessage(
					PrimarySession->ConnectionFileObject,
					cryptWinxpRequestMessage,
					sizeof(NDFS_WINXP_REPLY_HEADER),
					NULL
					);
#endif	
	}
	else {

		tdiStatus = SendMessage( PrimarySession->ConnectionFileObject,
								 (_U8 *)NdfsWinxpReplyHeader,
								 sizeof(NDFS_WINXP_REPLY_HEADER),
								 NULL );

		if (tdiStatus != STATUS_SUCCESS)	{

			return tdiStatus;
		}
	} 

	remaninigDataSize = ReplyDataSize;

	while(1) {

		RtlCopyMemory(NdfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(NdfsReplyHeader->Protocol));
		NdfsReplyHeader->Status		= NDFS_SUCCESS;
		NdfsReplyHeader->Flags	    = PrimarySession->SessionContext.Flags;
		NdfsReplyHeader->Uid		= PrimarySession->SessionContext.Uid;
		NdfsReplyHeader->Tid		= PrimarySession->SessionContext.Tid;
		NdfsReplyHeader->Mid		= 0;
		NdfsReplyHeader->MessageSize 
				= sizeof(NDFS_REPLY_HEADER) 
				+ (PrimarySession->SessionContext.MessageSecurity ? ADD_ALIGN8(remaninigDataSize) : remaninigDataSize);

		if (remaninigDataSize > PrimarySession->SessionContext.SecondaryMaxDataSize)
			NdfsReplyHeader->Splitted = 1;

		tdiStatus = SendMessage( PrimarySession->ConnectionFileObject,
								 (_U8 *)NdfsReplyHeader,
								 sizeof(NDFS_REPLY_HEADER),
								 NULL );

		if (tdiStatus != STATUS_SUCCESS) {

			return tdiStatus;
		}

		if (PrimarySession->SessionContext.MessageSecurity)
		{
#if __NDAS_FAT_DES__
			int desResult;
			_U8 *cryptNdfsWinxpReplyHeader = PrimarySession->Thread.SessionSlot[Mid].CryptWinxpMessageBuffer;

			desResult = DES_CBCUpdate(
							&PrimarySession->DesCbcContext, 
							cryptNdfsWinxpReplyHeader, 
							(_U8 *)(NdfsWinxpReplyHeader+1) + (ReplyDataSize - remaninigDataSize), 
							NdfsReplyHeader->Splitted ? PrimarySession->SessionContext.SecondaryMaxDataSize : (NdfsReplyHeader->MessageSize - sizeof(NDFS_REPLY_HEADER))
							);
			ASSERT(desResult == IDOK);

			tdiStatus = SendMessage(
							PrimarySession->ConnectionFileObject,
							cryptNdfsWinxpReplyHeader,
							NdfsReplyHeader->Splitted ? PrimarySession->SessionContext.SecondaryMaxDataSize : (NdfsReplyHeader->MessageSize - sizeof(NDFS_REPLY_HEADER)),
							NULL
							);
#endif
		}
		else
		{	
			tdiStatus = SendMessage( PrimarySession->ConnectionFileObject,
									 (_U8 *)(NdfsWinxpReplyHeader+1) + (ReplyDataSize - remaninigDataSize), 
									 NdfsReplyHeader->Splitted ? PrimarySession->SessionContext.SecondaryMaxDataSize : (NdfsReplyHeader->MessageSize - sizeof(NDFS_REPLY_HEADER)),
									 NULL );
		}
		
		if (tdiStatus != STATUS_SUCCESS) {
			return tdiStatus;
		}

		if (NdfsReplyHeader->Splitted)
			remaninigDataSize -= PrimarySession->SessionContext.SecondaryMaxDataSize;
		else
			return STATUS_SUCCESS;

		ASSERT( (_S32)remaninigDataSize > 0) ;
	}

	return STATUS_SUCCESS;
}
예제 #14
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;
}
예제 #15
0
NTSTATUS
NdasFatSecondaryQueryDirectory (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the query directory operation.  It is responsible
    for either completing of enqueuing the input Irp.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;

    PVCB Vcb;
    PDCB Dcb;
    PCCB Ccb;
    PBCB Bcb;

    ULONG i;
    PUCHAR Buffer;
    CLONG UserBufferLength;

    PUNICODE_STRING UniArgFileName;
    WCHAR LongFileNameBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE];
    UNICODE_STRING LongFileName;
    FILE_INFORMATION_CLASS FileInformationClass;
    ULONG FileIndex;
    BOOLEAN RestartScan;
    BOOLEAN ReturnSingleEntry;
    BOOLEAN IndexSpecified;

    BOOLEAN InitialQuery;
    VBO CurrentVbo;
    BOOLEAN UpdateCcb;
    PDIRENT Dirent;
    UCHAR Fat8Dot3Buffer[12];
    OEM_STRING Fat8Dot3String;
    ULONG DiskAllocSize;

    ULONG NextEntry;
    ULONG LastEntry;

    PFILE_DIRECTORY_INFORMATION DirInfo;
    PFILE_FULL_DIR_INFORMATION FullDirInfo;
    PFILE_BOTH_DIR_INFORMATION BothDirInfo;
    PFILE_ID_FULL_DIR_INFORMATION IdFullDirInfo;
    PFILE_ID_BOTH_DIR_INFORMATION IdBothDirInfo;
    PFILE_NAMES_INFORMATION NamesInfo;

#if 1

	PVOLUME_DEVICE_OBJECT		volDo;
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;
	_U8							*ndfsWinxpRequestData;

	LARGE_INTEGER				timeOut;

	struct QueryDirectory		queryDirectory;
	PVOID						inputBuffer;
	ULONG						inputBufferLength;

	ULONG						returnedDataSize;

#endif

    PAGED_CODE();

    //
    //  Get the current Stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Display the input values.
    //
    DebugTrace(+1, Dbg, "FatQueryDirectory...\n", 0);
    DebugTrace( 0, Dbg, " Wait                   = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
    DebugTrace( 0, Dbg, " Irp                    = %08lx\n", Irp);
    DebugTrace( 0, Dbg, " ->Length               = %08lx\n", IrpSp->Parameters.QueryDirectory.Length);
    DebugTrace( 0, Dbg, " ->FileName             = %08lx\n", IrpSp->Parameters.QueryDirectory.FileName);
    DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
    DebugTrace( 0, Dbg, " ->FileIndex            = %08lx\n", IrpSp->Parameters.QueryDirectory.FileIndex);
    DebugTrace( 0, Dbg, " ->UserBuffer           = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
    DebugTrace( 0, Dbg, " ->RestartScan          = %08lx\n", FlagOn( IrpSp->Flags, SL_RESTART_SCAN ));
    DebugTrace( 0, Dbg, " ->ReturnSingleEntry    = %08lx\n", FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY ));
    DebugTrace( 0, Dbg, " ->IndexSpecified       = %08lx\n", FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED ));

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

    UserBufferLength = IrpSp->Parameters.QueryDirectory.Length;

    FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
    FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;

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

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

    //
    //  Check on the type of open.  We return invalid parameter for all
    //  but UserDirectoryOpens.  Also check that the filename is a valid
    //  UNICODE string.
    //
    
    if (FatDecodeFileObject( IrpSp->FileObject,
                             &Vcb,
                             &Dcb,
                             &Ccb) != UserDirectoryOpen ||
        (UniArgFileName &&
         UniArgFileName->Length % sizeof(WCHAR))) {

        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        DebugTrace(-1, Dbg, "FatQueryDirectory -> STATUS_INVALID_PARAMETER\n", 0);

        return STATUS_INVALID_PARAMETER;
    }

#if 1

	 if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

		 ASSERT( FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) );

		 FatCompleteRequest( IrpContext, Irp, STATUS_FILE_CORRUPT_ERROR );

		 DebugTrace2( -1, Dbg, ("NtfsCommonDirectoryControl -> STATUS_FILE_CORRUPT_ERROR\n") );
		 return STATUS_FILE_CORRUPT_ERROR;
	 }

#endif


    //
    //  Initialize the local variables.
    //

    Bcb = NULL;
    UpdateCcb = TRUE;
    Dirent = NULL;

    Fat8Dot3String.MaximumLength = 12;
    Fat8Dot3String.Buffer = Fat8Dot3Buffer;

    LongFileName.Length = 0;
    LongFileName.MaximumLength = sizeof( LongFileNameBuffer);
    LongFileName.Buffer = LongFileNameBuffer;

    InitialQuery = (BOOLEAN)((Ccb->UnicodeQueryTemplate.Buffer == NULL) &&
                             !FlagOn(Ccb->Flags, CCB_FLAG_MATCH_ALL));
    Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    DiskAllocSize = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;

    //
    //  If this is the initial query, then grab exclusive access in
    //  order to update the search string in the Ccb.  We may
    //  discover that we are not the initial query once we grab the Fcb
    //  and downgrade our status.
    //

    if (InitialQuery) {

        if (!FatAcquireExclusiveFcb( IrpContext, Dcb )) {

            DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0);
            Status = FatFsdPostRequest( IrpContext, Irp );
            DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);

            return Status;
        }

        if (Ccb->UnicodeQueryTemplate.Buffer != NULL) {

            InitialQuery = FALSE;

            FatConvertToSharedFcb( IrpContext, Dcb );
        }

    } else {

        if (!FatAcquireSharedFcb( IrpContext, Dcb )) {

            DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0);
            Status = FatFsdPostRequest( IrpContext, Irp );
            DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);

            return Status;

        }
    }

    try {

        ULONG BaseLength;
        ULONG BytesConverted;

        //
        // If we are in the Fsp now because we had to wait earlier,
        // we must map the user buffer, otherwise we can use the
        // user's buffer directly.
        //

        Buffer = FatMapUserBuffer( IrpContext, Irp );

#if 1

		volDo = CONTAINING_RECORD( Vcb, VOLUME_DEVICE_OBJECT, Vcb );

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

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

			NDASFAT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
			SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
		}

		queryDirectory.FileIndex			= IrpSp->Parameters.QueryDirectory.FileIndex;
		queryDirectory.FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
		queryDirectory.FileName				= IrpSp->Parameters.QueryDirectory.FileName;
		queryDirectory.Length				= IrpSp->Parameters.QueryDirectory.Length;

		inputBuffer			= (queryDirectory.FileName) ? (queryDirectory.FileName->Buffer) : NULL;
		inputBufferLength	= (queryDirectory.FileName) ? (queryDirectory.FileName->Length) : 0;

		if (queryDirectory.FileName) {

			DebugTrace2( 0, Dbg, ("NdNtfsSecondaryQueryDirectory: queryFileName = %wZ\n", queryDirectory.FileName) );
		}

		ASSERT( inputBufferLength <= volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize );
		ASSERT( UserBufferLength <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize );

		secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, 
														  IRP_MJ_DIRECTORY_CONTROL,
														  ((inputBufferLength > UserBufferLength) ? inputBufferLength : UserBufferLength) );

		if (secondaryRequest == NULL) {

			try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
		}

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

		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
		ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );
		INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, Irp, IrpSp, Ccb->PrimaryFileHandle );

		ndfsWinxpRequestHeader->QueryDirectory.Length				= UserBufferLength;
		ndfsWinxpRequestHeader->QueryDirectory.FileInformationClass	= queryDirectory.FileInformationClass;
		ndfsWinxpRequestHeader->QueryDirectory.FileIndex			= queryDirectory.FileIndex;

		ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1);
		if (inputBufferLength)
			RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength );

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

			secondaryRequest = NULL;
			try_return( Status = STATUS_IO_DEVICE_ERROR );
		}

		SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource );		
		secondarySessionResourceAcquired = FALSE;

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

			NDASFAT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
			SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_DONT_POST_REQUEST );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
		}

		ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
		Status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status;
		Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information;
		
		returnedDataSize = secondaryRequest->NdfsReplyHeader.MessageSize - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REPLY_HEADER);

		if (returnedDataSize) {

			ASSERT( ndfsWinxpReplytHeader->Information != 0 );
			ASSERT(returnedDataSize <= ADD_ALIGN8(queryDirectory.Length));
			ASSERT( Buffer );

			RtlCopyMemory( Buffer,
						   (_U8 *)(ndfsWinxpReplytHeader+1),
						   (returnedDataSize < queryDirectory.Length) ? returnedDataSize : queryDirectory.Length );
		}

#endif

#if 0

        //
        //  Make sure the Dcb is still good.
        //

        FatVerifyFcb( IrpContext, Dcb );

        //
        //  Determine where to start the scan.  Highest priority is given
        //  to the file index.  Lower priority is the restart flag.  If
        //  neither of these is specified, then the Vbo offset field in the
        //  Ccb is used.
        //

        if (IndexSpecified) {

            CurrentVbo = FileIndex + sizeof( DIRENT );

        } else if (RestartScan) {

            CurrentVbo = 0;

        } else {

            CurrentVbo = Ccb->OffsetToStartSearchFrom;

        }

        //
        //  If this is the first try then allocate a buffer for the file
        //  name.
        //

        if (InitialQuery) {

            //
            //  If either:
            //
            //  - No name was specified
            //  - An empty name was specified
            //  - We received a '*'
            //  - The user specified the DOS equivolent of ????????.???
            //
            //  then match all names.
            //

            if ((UniArgFileName == NULL) ||
                (UniArgFileName->Length == 0) ||
                (UniArgFileName->Buffer == NULL) ||
                ((UniArgFileName->Length == sizeof(WCHAR)) &&
                 (UniArgFileName->Buffer[0] == L'*')) ||
                ((UniArgFileName->Length == 12*sizeof(WCHAR)) &&
                 (RtlEqualMemory( UniArgFileName->Buffer,
                                  Fat8QMdot3QM,
                                  12*sizeof(WCHAR) )))) {

                Ccb->ContainsWildCards = TRUE;

                SetFlag( Ccb->Flags, CCB_FLAG_MATCH_ALL );

            } else {

                BOOLEAN ExtendedName = FALSE;
                OEM_STRING LocalBestFit;

                //
                //  First and formost, see if the name has wild cards.
                //

                Ccb->ContainsWildCards =
                    FsRtlDoesNameContainWildCards( UniArgFileName );

                //
                //  Now check to see if the name contains any extended
                //  characters
                //

                for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {

                    if (UniArgFileName->Buffer[i] >= 0x80) {

                        ExtendedName = TRUE;
                        break;
                    }
                }

                //
                //  OK, now do the conversions we need.
                //

                if (ExtendedName) {

                    Status = RtlUpcaseUnicodeString( &Ccb->UnicodeQueryTemplate,
                                                     UniArgFileName,
                                                     TRUE );

                    if (!NT_SUCCESS(Status)) {

                        try_return( Status );
                    }

                    SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE );

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

                    Status = RtlUpcaseUnicodeStringToCountedOemString( &LocalBestFit,
                                                                       UniArgFileName,
                                                                       TRUE );

                    //
                    //  If this conversion failed for any reason other than
                    //  an unmappable character fail the request.
                    //

                    if (!NT_SUCCESS(Status)) {

                        if (Status == STATUS_UNMAPPABLE_CHARACTER) {

                            SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE );

                        } else {

                            try_return( Status );
                        }

                    } else {

                        SetFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
                    }

                } else {

                    PVOID Buffers;

                    //
                    //  This case is optimized because I know I only have to
                    //  worry about a-z.
                    //

                    Buffers = FsRtlAllocatePoolWithTag( PagedPool,
                                                        UniArgFileName->Length +
                                                        UniArgFileName->Length / sizeof(WCHAR),
                                                        TAG_FILENAME_BUFFER );

                    Ccb->UnicodeQueryTemplate.Buffer = Buffers;
                    Ccb->UnicodeQueryTemplate.Length = UniArgFileName->Length;
                    Ccb->UnicodeQueryTemplate.MaximumLength = UniArgFileName->Length;

                    LocalBestFit.Buffer = (PUCHAR)Buffers + UniArgFileName->Length;
                    LocalBestFit.Length = UniArgFileName->Length / sizeof(WCHAR);
                    LocalBestFit.MaximumLength = LocalBestFit.Length;

                    SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE );

                    for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {

                        WCHAR c = UniArgFileName->Buffer[i];

                        LocalBestFit.Buffer[i] = (UCHAR)
                        (Ccb->UnicodeQueryTemplate.Buffer[i] =
                             (c < 'a' ? c : c <= 'z' ? c - ('a' - 'A') : c));
                    }
                }

                //
                //  At this point we now have the upcased unicode name,
                //  and the two Oem names if they could be represented in
                //  this code page.
                //
                //  Now determine if the Oem names are legal for what we
                //  going to try and do.  Mark them as not usable is they
                //  are not legal.  Note that we can optimize extended names
                //  since they are actually both the same string.
                //

                if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE ) &&
                    !FatIsNameShortOemValid( IrpContext,
                                             LocalBestFit,
                                             Ccb->ContainsWildCards,
                                             FALSE,
                                             FALSE )) {

                    if (ExtendedName) {

                        RtlFreeOemString( &LocalBestFit );
                        ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
                    }

                    SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE );
                }

                //
                //  OK, now both locals oem strings correctly reflect their
                //  usability.  Now we want to load up the Ccb structure.
                //
                //  Now we will branch on two paths of wheather the name
                //  is wild or not.
                //

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

                    if (Ccb->ContainsWildCards) {

                        Ccb->OemQueryTemplate.Wild = LocalBestFit;

                    } else {

                        FatStringTo8dot3( IrpContext,
                                          LocalBestFit,
                                          &Ccb->OemQueryTemplate.Constant );

                        if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT)) {

                            RtlFreeOemString( &LocalBestFit );
                            ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
                        }
                    }
                }
            }

            //
            //  We convert to shared access.
            //

            FatConvertToSharedFcb( IrpContext, Dcb );
        }

        LastEntry = 0;
        NextEntry = 0;

        switch (FileInformationClass) {

        case FileDirectoryInformation:

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

        case FileFullDirectoryInformation:

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

        case FileIdFullDirectoryInformation:

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

        case FileNamesInformation:

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

        case FileBothDirectoryInformation:

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

        case FileIdBothDirectoryInformation:

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

        default:

            try_return( Status = STATUS_INVALID_INFO_CLASS );
        }

        //
        //  At this point we are about to enter our query loop.  We have
        //  determined the index into the directory file to begin the
        //  search.  LastEntry and NextEntry are used to index into the user
        //  buffer.  LastEntry is the last entry we've added, NextEntry is
        //  current one we're working on.  If NextEntry is non-zero, then
        //  at least one entry was added.
        //

        while ( TRUE ) {

            VBO NextVbo;
            ULONG FileNameLength;
            ULONG BytesRemainingInBuffer;


            DebugTrace(0, Dbg, "FatQueryDirectory -> Top of loop\n", 0);

            //
            //  If the user had requested only a single match and we have
            //  returned that, then we stop at this point.
            //

            if (ReturnSingleEntry && NextEntry != 0) {

                try_return( Status );
            }

            //
            //  We call FatLocateDirent to lock down the next matching dirent.
            //

            FatLocateDirent( IrpContext,
                             Dcb,
                             Ccb,
                             CurrentVbo,
                             &Dirent,
                             &Bcb,
                             &NextVbo,
                             NULL,
                             &LongFileName);

            //
            //  If we didn't receive a dirent, then we are at the end of the
            //  directory.  If we have returned any files, we exit with
            //  success, otherwise we return STATUS_NO_MORE_FILES.
            //

            if (!Dirent) {

                DebugTrace(0, Dbg, "FatQueryDirectory -> No dirent\n", 0);

                if (NextEntry == 0) {

                    UpdateCcb = FALSE;

                    if (InitialQuery) {

                        Status = STATUS_NO_SUCH_FILE;

                    } else {

                        Status = STATUS_NO_MORE_FILES;
                    }
                }

                try_return( Status );
            }

            //
            //  Protect access to the user buffer with an exception handler.
            //  Since (at our request) IO doesn't buffer these requests, we have
            //  to guard against a user messing with the page protection and other
            //  such trickery.
            //
            
            try {
                
                if (LongFileName.Length == 0) {

                    //
                    //  Now we have an entry to return to our caller.  We'll convert
                    //  the name from the form in the dirent to a <name>.<ext> form.
                    //  We'll case on the type of information requested and fill up
                    //  the user buffer if everything fits.
                    //

                    Fat8dot3ToString( IrpContext, Dirent, TRUE, &Fat8Dot3String );
    
                    //
                    //  Determine the UNICODE length of the file name.
                    //
    
                    FileNameLength = RtlOemStringToCountedUnicodeSize(&Fat8Dot3String);

                    //
                    //  Here are the rules concerning filling up the buffer:
                    //
                    //  1.  The Io system garentees that there will always be
                    //      enough room for at least one base record.
                    //
                    //  2.  If the full first record (including file name) cannot
                    //      fit, as much of the name as possible is copied and
                    //      STATUS_BUFFER_OVERFLOW is returned.
                    //
                    //  3.  If a subsequent record cannot completely fit into the
                    //      buffer, none of it (as in 0 bytes) is copied, and
                    //      STATUS_SUCCESS is returned.  A subsequent query will
                    //      pick up with this record.
                    //
    
                    BytesRemainingInBuffer = UserBufferLength - NextEntry;
    
                    if ( (NextEntry != 0) &&
                         ( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
                           (UserBufferLength < NextEntry) ) ) {
    
                        DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
    
                        try_return( Status = STATUS_SUCCESS );
                    }
    
                    ASSERT( BytesRemainingInBuffer >= BaseLength );

                    //
                    //  Zero the base part of the structure.
                    //

                    RtlZeroMemory( &Buffer[NextEntry], BaseLength );

                    switch ( FileInformationClass ) {
    
                    //
                    //  Now fill the base parts of the strucure that are applicable.
                    //
    
                    case FileBothDirectoryInformation:
                    case FileFullDirectoryInformation:
                    case FileIdBothDirectoryInformation:
                    case FileIdFullDirectoryInformation:

                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
    
                        //
                        //  Get the Ea file length.
                        //
    
                        FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
    
                        //
                        //  If the EAs are corrupt, ignore the error.  We don't want
                        //  to abort the directory query.
                        //
    
                        try {
    
                            FatGetEaLength( IrpContext,
                                            Vcb,
                                            Dirent,
                                            &FullDirInfo->EaSize );
    
                        } except(EXCEPTION_EXECUTE_HANDLER) {
    
                              FatResetExceptionState( IrpContext );
                              FullDirInfo->EaSize = 0;
                        }
                        
                    case FileDirectoryInformation:
    
                        DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
    
                        FatGetDirTimes( IrpContext, Dirent, DirInfo );
    
                        DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
    
                        if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
    
                            DirInfo->AllocationSize.QuadPart =
                               (((Dirent->FileSize + DiskAllocSize - 1) / DiskAllocSize) *
                                DiskAllocSize );
                        }
    
                        DirInfo->FileAttributes = Dirent->Attributes != 0 ?
                                                  Dirent->Attributes :
                                                  FILE_ATTRIBUTE_NORMAL;
    
                        DirInfo->FileIndex = NextVbo;
    
                        DirInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
    
                        break;
    
                    case FileNamesInformation:
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
    
                        NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
    
                        NamesInfo->FileIndex = NextVbo;
    
                        NamesInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
    
                        break;
    
                    default:
    
                        FatBugCheck( FileInformationClass, 0, 0 );
                    }

                    BytesConverted = 0;
    
                    Status = RtlOemToUnicodeN( (PWCH)&Buffer[NextEntry + BaseLength],
                                               BytesRemainingInBuffer - BaseLength,
                                               &BytesConverted,
                                               Fat8Dot3String.Buffer,
                                               Fat8Dot3String.Length );
                    
                    //
                    //  Check for the case that a single entry doesn't fit.
                    //  This should only get this far on the first entry
                    //
    
                    if (BytesConverted < FileNameLength) {
    
                        ASSERT( NextEntry == 0 );
                        Status = STATUS_BUFFER_OVERFLOW;
                    }
    
                    //
                    //  Set up the previous next entry offset
                    //
    
                    *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;
    
                    //
                    //  And indicate how much of the user buffer we have currently
                    //  used up.  We must compute this value before we long align
                    //  ourselves for the next entry
                    //
    
                    Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
                                                BaseLength + BytesConverted;
    
                    //
                    //  If something happened with the conversion, bail here.
                    //
    
                    if ( !NT_SUCCESS( Status ) ) {
    
                        try_return( NOTHING );
                    }

                } else {

                    ULONG ShortNameLength;
    
                    FileNameLength = LongFileName.Length;
    
                    //
                    //  Here are the rules concerning filling up the buffer:
                    //
                    //  1.  The Io system garentees that there will always be
                    //      enough room for at least one base record.
                    //
                    //  2.  If the full first record (including file name) cannot
                    //      fit, as much of the name as possible is copied and
                    //      STATUS_BUFFER_OVERFLOW is returned.
                    //
                    //  3.  If a subsequent record cannot completely fit into the
                    //      buffer, none of it (as in 0 bytes) is copied, and
                    //      STATUS_SUCCESS is returned.  A subsequent query will
                    //      pick up with this record.
                    //
    
                    BytesRemainingInBuffer = UserBufferLength - NextEntry;
    
                    if ( (NextEntry != 0) &&
                         ( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
                           (UserBufferLength < NextEntry) ) ) {
    
                        DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
    
                        try_return( Status = STATUS_SUCCESS );
                    }
    
                    ASSERT( BytesRemainingInBuffer >= BaseLength );
    
                    //
                    //  Zero the base part of the structure.
                    //

                    RtlZeroMemory( &Buffer[NextEntry], BaseLength );

                    switch ( FileInformationClass ) {
    
                    //
                    //  Now fill the base parts of the strucure that are applicable.
                    //
    
                    case FileBothDirectoryInformation:
                    case FileIdBothDirectoryInformation:
    
                        BothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&Buffer[NextEntry];
    
                        //
                        //  Now we have an entry to return to our caller.  We'll convert
                        //  the name from the form in the dirent to a <name>.<ext> form.
                        //  We'll case on the type of information requested and fill up
                        //  the user buffer if everything fits.
                        //
    
                        Fat8dot3ToString( IrpContext, Dirent, FALSE, &Fat8Dot3String );
    
                        ASSERT( Fat8Dot3String.Length <= 12 );
    
                        Status = RtlOemToUnicodeN( &BothDirInfo->ShortName[0],
                                                   12*sizeof(WCHAR),
                                                   &ShortNameLength,
                                                   Fat8Dot3String.Buffer,
                                                   Fat8Dot3String.Length );
    
                        ASSERT( Status != STATUS_BUFFER_OVERFLOW );
                        ASSERT( ShortNameLength <= 12*sizeof(WCHAR) );
    
                        //
                        //  Copy the length into the dirinfo structure.  Note
                        //  that the LHS below is a USHORT, so it can not
                        //  be specificed as the OUT parameter above.
                        //
    
                        BothDirInfo->ShortNameLength = (UCHAR)ShortNameLength;
    
                        //
                        //  If something happened with the conversion, bail here.
                        //
    
                        if ( !NT_SUCCESS( Status ) ) {
    
                            try_return( NOTHING );
                        }
    
                    case FileFullDirectoryInformation:
                    case FileIdFullDirectoryInformation:
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
    
                        //
                        //  Get the Ea file length.
                        //
    
                        FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
    
                        //
                        //  If the EAs are corrupt, ignore the error.  We don't want
                        //  to abort the directory query.
                        //
    
                        try {
    
                            FatGetEaLength( IrpContext,
                                            Vcb,
                                            Dirent,
                                            &FullDirInfo->EaSize );
    
                        } except(EXCEPTION_EXECUTE_HANDLER) {
    
                              FatResetExceptionState( IrpContext );
                              FullDirInfo->EaSize = 0;
                        }
    
                    case FileDirectoryInformation:
    
                        DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
    
                        FatGetDirTimes( IrpContext, Dirent, DirInfo );
    
                        DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
    
                        if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
    
                            DirInfo->AllocationSize.QuadPart = (
                                                            (( Dirent->FileSize
                                                               + DiskAllocSize - 1 )
                                                             / DiskAllocSize )
                                                            * DiskAllocSize );
                        }
    
                        DirInfo->FileAttributes = Dirent->Attributes != 0 ?
                                                  Dirent->Attributes :
                                                  FILE_ATTRIBUTE_NORMAL;
    
                        DirInfo->FileIndex = NextVbo;
    
                        DirInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
    
                        break;
    
                    case FileNamesInformation:
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
    
                        NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
    
                        NamesInfo->FileIndex = NextVbo;
    
                        NamesInfo->FileNameLength = FileNameLength;
    
                        DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
    
                        break;
    
                    default:
    
                        FatBugCheck( FileInformationClass, 0, 0 );
                    }

                    BytesConverted = BytesRemainingInBuffer - BaseLength >= FileNameLength ?
                                     FileNameLength :
                                     BytesRemainingInBuffer - BaseLength;
    
                    RtlCopyMemory( &Buffer[NextEntry + BaseLength],
                                   &LongFileName.Buffer[0],
                                   BytesConverted );
    
                    //
                    //  Set up the previous next entry offset
                    //
    
                    *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;

                    //
                    //  And indicate how much of the user buffer we have currently
                    //  used up.  We must compute this value before we long align
                    //  ourselves for the next entry
                    //
    
                    Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
                                                BaseLength + BytesConverted;

                    //
                    //  Check for the case that a single entry doesn't fit.
                    //  This should only get this far on the first entry.
                    //

                    if (BytesConverted < FileNameLength) {

                        ASSERT( NextEntry == 0 );

                        try_return( Status = STATUS_BUFFER_OVERFLOW );
                    }
                }

                //
                //  Finish up by filling in the FileId
                //

                switch ( FileInformationClass ) {

                case FileIdBothDirectoryInformation:

                    IdBothDirInfo = (PFILE_ID_BOTH_DIR_INFORMATION)&Buffer[NextEntry];
                    IdBothDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo );
                    break;

                case FileIdFullDirectoryInformation:

                    IdFullDirInfo = (PFILE_ID_FULL_DIR_INFORMATION)&Buffer[NextEntry];
                    IdFullDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo );
                    break;

                default:
                    break;
                }
            
            }  except (EXCEPTION_EXECUTE_HANDLER) {

                  //
                  //  We had a problem filling in the user's buffer, so stop and
                  //  fail this request.  This is the only reason any exception
                  //  would have occured at this level.
                  //
                  
                  Irp->IoStatus.Information = 0;
                  UpdateCcb = FALSE;
                  try_return( Status = GetExceptionCode());
            }

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

            LastEntry = NextEntry;
            NextEntry += (ULONG)QuadAlign(BaseLength + BytesConverted);

            CurrentVbo = NextVbo + sizeof( DIRENT );
        }

#endif

    try_exit: NOTHING;
    } finally {
예제 #16
0
VOID
SecondaryTryClose (
	IN PSECONDARY	Secondary
	)
{
	PIRP_CONTEXT	irpContext;

	BOOLEAN			secondaryResourceAcquired = FALSE;
	BOOLEAN			acquiredVcb = FALSE;
	BOOLEAN			wait;

	irpContext = FatAllocateIrpContext();

	if (irpContext == NULL) {

		return;
	}

	DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles start\n") );

	try {

		RtlZeroMemory( irpContext, sizeof(IRP_CONTEXT) );
		SetFlag( irpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
		SetFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		irpContext->Vcb = &Secondary->VolDo->Vcb;

		secondaryResourceAcquired = SecondaryAcquireResourceSharedLite( irpContext, 
																		&Secondary->VolDo->Resource, 
																		FALSE );
		if (secondaryResourceAcquired == FALSE) {

			leave;
		}

		wait = BooleanFlagOn( irpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

		acquiredVcb = FatAcquireExclusiveVcb( irpContext, irpContext->Vcb );

		if (acquiredVcb == FALSE) {

			leave;
		}

		FsRtlEnterFileSystem();
		FatFspClose( &Secondary->VolDo->Vcb );
		FsRtlExitFileSystem();

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles FatFspClose, Secondary->VolDo->Vcb.SecondaryOpenCount = %d\n", 
							    Secondary->VolDo->Vcb.SecondaryOpenFileCount) );

		SetFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		Secondary_TryCloseFilExts( Secondary );

	} finally {

		ClearFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		if (acquiredVcb) {

			FatReleaseVcb( irpContext, irpContext->Vcb );
		}

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles exit\n") );

		ExAcquireFastMutex( &Secondary->FastMutex );		
		Secondary->TryCloseActive = FALSE;
		ExReleaseFastMutex( &Secondary->FastMutex );

		if (secondaryResourceAcquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->Resource );

		Secondary_Dereference(Secondary);

		FatFreeIrpContext(irpContext);
	}

	return;
}
예제 #17
0
VOID
VolDoThreadProc(
	IN	PVOLUME_DEVICE_OBJECT	VolDo
	)
{
	BOOLEAN		volDoThreadTerminate = FALSE;


	DebugTrace2( 0, Dbg2, ("VolDoThreadProc: Start VolDo = %p\n", VolDo) );
	
	VolDo_Reference( VolDo );
	
	VolDo->Thread.Flags = VOLDO_THREAD_FLAG_INITIALIZING;

	DebugTrace2( 0, Dbg2, ("VolDoThreadProc: Start VolDo = %p\n", VolDo) );

	ExAcquireFastMutex( &VolDo->FastMutex );		
	ClearFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_INITIALIZING );
	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_START );
	ExReleaseFastMutex( &VolDo->FastMutex );
			
	KeSetEvent( &VolDo->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	volDoThreadTerminate = FALSE;
	
	while (volDoThreadTerminate == FALSE) {

		PKEVENT			events[2];
		LONG			eventCount;
		NTSTATUS		eventStatus;
		LARGE_INTEGER	timeOut;
		

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;
		events[eventCount++] = &VolDo->RequestEvent;

		timeOut.QuadPart = -NDFAT_VOLDO_THREAD_FLAG_TIME_OUT;

		eventStatus = KeWaitForMultipleObjects(	eventCount,
												events,
												WaitAny,
												Executive,
												KernelMode,
												TRUE,
												&timeOut,
												NULL );


		if (eventStatus == STATUS_TIMEOUT) {

			LARGE_INTEGER	currentTime;

			KeQuerySystemTime( &currentTime );

			if (FlagOn(VolDo->NdFatFlags, ND_FAT_DEVICE_FLAG_SHUTDOWN) || 
				!(FlagOn(VolDo->NdFatFlags, ND_FAT_DEVICE_FLAG_MOUNTED) /*&& !FlagOn(LfsDeviceExt->Flags, LFS_DEVICE_STOP)*/)) {
				
				continue;
			}

			if ((VolDo->NetdiskEnableMode == NETDISK_READ_ONLY || VolDo->ReceiveWriteCommand == TRUE) && 
				(VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || 
				(currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDFAT_TRY_FLUSH_OR_PURGE_DURATION)) {

				if (VolDo->NetdiskEnableMode != NETDISK_READ_ONLY && 
					(currentTime.QuadPart - VolDo->CommandReceiveTime.QuadPart) <=  NDFAT_TRY_FLUSH_OR_PURGE_DURATION /*&& 
					(currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) <= (100*NDFAT_TRY_FLUSH_OR_PURGE_DURATION)*/) {

					continue;
				}

				do {
				
					HANDLE					eventHandle = NULL;

					HANDLE					fileHandle = NULL;
					ACCESS_MASK				desiredAccess;
					ULONG					attributes;
					OBJECT_ATTRIBUTES		objectAttributes;
					IO_STATUS_BLOCK			ioStatusBlock;
					LARGE_INTEGER			allocationSize;
					ULONG					fileAttributes;
					ULONG					shareAccess;
				    ULONG					createDisposition;
					ULONG					createOptions;
				    PVOID					eaBuffer;
					ULONG					eaLength;

					NTSTATUS				createStatus;
					NTSTATUS				fileSystemControlStatus;

					PIRP					topLevelIrp;
					PRIMARY_REQUEST_INFO	primaryRequestInfo;


					ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

					if (VolDo->NetdiskEnableMode == NETDISK_SECONDARY)
						break;

					DebugTrace2( 0, Dbg, ("VolDoThreadProc: VolDo = %p, VolDo->NetdiskPartitionInformation.VolumeName = %wZ\n", 
											VolDo, &VolDo->NetdiskPartitionInformation.VolumeName) );

					desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA 
									| FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA;

					ASSERT( desiredAccess == 0x0012019F );

					attributes  = OBJ_KERNEL_HANDLE;
					attributes |= OBJ_CASE_INSENSITIVE;

					InitializeObjectAttributes( &objectAttributes,
											    &VolDo->NetdiskPartitionInformation.VolumeName,
												attributes,
												NULL,
												NULL );
		
					allocationSize.LowPart  = 0;
					allocationSize.HighPart = 0;

					fileAttributes	  = 0;		
					shareAccess		  = FILE_SHARE_READ | FILE_SHARE_WRITE;
					createDisposition = FILE_OPEN;
					createOptions     = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE;
					eaBuffer		  = NULL;
					eaLength		  = 0;

					RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) );

					createStatus = ZwCreateFile( &fileHandle,
												 desiredAccess,
												 &objectAttributes,
												 &ioStatusBlock,
												 &allocationSize,
												 fileAttributes,
												 shareAccess,
												 createDisposition,
												 createOptions,
												 eaBuffer,
												 eaLength );

					if (createStatus != STATUS_SUCCESS) 
						break;
						
					ASSERT( ioStatusBlock.Information == FILE_OPENED);
	
					createStatus = ZwCreateEvent( &eventHandle,
												  GENERIC_READ,
												  NULL,
												  SynchronizationEvent,
												  FALSE );

					if (createStatus != STATUS_SUCCESS) {

						ASSERT( NDFAT_UNEXPECTED );
						ZwClose( fileHandle );
						break;
					}


					primaryRequestInfo.PrimaryTag				= 0xe2027482;
					primaryRequestInfo.PrimarySession			= NULL;
					primaryRequestInfo.NdfsWinxpRequestHeader	= NULL;

					topLevelIrp = IoGetTopLevelIrp();
					ASSERT( topLevelIrp == NULL );
					IoSetTopLevelIrp( (PIRP)&primaryRequestInfo );

					RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) );

					fileSystemControlStatus = ZwFsControlFile( fileHandle,
															   NULL, //&eventHandle,
															   NULL,
															   NULL,
															   &ioStatusBlock,
															   FSCTL_ND_FAT_FLUSH_OR_PURGE,
															   NULL,
															   0,
															   NULL,
															   0 );

					DebugTrace2( 0, Dbg, ("VolDoThreadProc: VolDo = %p, createStatus = %x, ioStatusBlock = %x\n", 
											VolDo, fileSystemControlStatus, ioStatusBlock.Information) );

					if (fileSystemControlStatus == STATUS_PENDING) {
			
						LARGE_INTEGER			timeOut;
			
						timeOut.QuadPart = -3*HZ;

						ASSERT( FALSE );
						//fileSystemControlStatus = ZwWaitForSingleObject( eventHandle, TRUE,NULL /*, &timeOut*/ );
					}

					IoSetTopLevelIrp( topLevelIrp );

					if (fileSystemControlStatus != STATUS_SUCCESS)
						DebugTrace2( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, fileSystemControlStatus = %x, ioStatusBlock = %x\n", 
												VolDo, fileSystemControlStatus, ioStatusBlock.Information) );

					ZwClose( eventHandle );
					ZwClose( fileHandle );
					
					break;
				
				} while (0);
			}

			KeQuerySystemTime( &VolDo->TryFlushOrPurgeTime );
			VolDo->ReceiveWriteCommand = TRUE;

			continue;
		}
		
		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
		ASSERT( eventCount < THREAD_WAIT_OBJECTS );
		
		if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) {

			ASSERT( NDFAT_UNEXPECTED );
			SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_ERROR );
			volDoThreadTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			volDoThreadTerminate = TRUE;
			break;
		
		} else
			ASSERT( NDFAT_BUG );
	}

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	ExAcquireFastMutex( &VolDo->FastMutex );

	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_STOPED );

	ExReleaseFastMutex( &VolDo->FastMutex );

	DebugTrace2( 0, Dbg2, ("VolDoThreadProc: PsTerminateSystemThread VolDo = %p\n", VolDo) );
	
	ExAcquireFastMutex( &VolDo->FastMutex );
	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_TERMINATED );
	ExReleaseFastMutex( &VolDo->FastMutex );
	
	VolDo_Dereference( VolDo );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
	
	PsTerminateSystemThread( STATUS_SUCCESS );
}
static VOID
DispatchWinXpRequestWorker (
	IN  PPRIMARY_SESSION	PrimarySession,
	IN  UINT16				Mid
    )
{
	PNDFS_REQUEST_HEADER		ndfsRequestHeader = (PNDFS_REQUEST_HEADER)PrimarySession->Thread.SessionSlot[Mid].RequestMessageBuffer;
	PNDFS_REPLY_HEADER			ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[Mid].ReplyMessageBuffer; 
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader = PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpRequestHeader;
	
	UINT32						replyDataSize;

	
	ASSERT(Mid == NTOHS(ndfsRequestHeader->Mid2));
	
    DebugTrace2( 0, Dbg, ("DispatchWinXpRequestWorker: entered PrimarySession = %p, ndfsRequestHeader->Command = %d\n", 
						  PrimarySession, ndfsRequestHeader->Command));

	ASSERT( PrimarySession->Thread.SessionSlot[Mid].State == SLOT_EXECUTING );


	replyDataSize = CaculateReplyDataLength(PrimarySession, ndfsWinxpRequestHeader);

	if (replyDataSize <= (ULONG)(PrimarySession->SessionContext.SecondaryMaxDataSize || 
	    sizeof(PrimarySession->Thread.SessionSlot[Mid].ReplyMessageBuffer) - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REQUEST_HEADER))) {

		if (ndfsRequestHeader->MessageSecurity == 1) {

			if (ndfsWinxpRequestHeader->IrpMajorFunction == IRP_MJ_READ && PrimarySession->SessionContext.RwDataSecurity == 0)
				PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpReplyHeader = (PNDFS_WINXP_REPLY_HEADER)(ndfsReplyHeader+1);
			else
				PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpReplyHeader = (PNDFS_WINXP_REPLY_HEADER)PrimarySession->Thread.SessionSlot[Mid].CryptWinxpMessageBuffer;
		}
		else
			PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpReplyHeader = (PNDFS_WINXP_REPLY_HEADER)(ndfsReplyHeader+1);
	
	} else {

		PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpReplyMessagePoolLength = 
			ADD_ALIGN8(sizeof(NDFS_WINXP_REPLY_HEADER) + replyDataSize);
		PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpReplyMessagePool = 
			ExAllocatePoolWithTag( NonPagedPool,
								   PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpReplyMessagePoolLength,
								   PRIMARY_SESSION_BUFFERE_TAG );

		ASSERT( PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpReplyMessagePool );

		if (PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpReplyMessagePool == NULL) {
	
			DebugTrace2( 0, Dbg, ("failed to allocate ExtendWinxpReplyMessagePool\n"));
			goto fail_replypoolalloc;
		}

		PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpReplyHeader 
			= (PNDFS_WINXP_REPLY_HEADER)PrimarySession->Thread.SessionSlot[Mid].ExtendWinxpReplyMessagePool;
	}
	
    DebugTrace2( 0, Dbg,
				 ("DispatchWinXpRequestWorker: PrimarySession = %p, ndfsRequestHeader->Command = %d\n", 
				  PrimarySession, ndfsRequestHeader->Command) );

	PrimarySession->Thread.SessionSlot[Mid].Status = 
		DispatchWinXpRequest( PrimarySession, 
							  ndfsWinxpRequestHeader,
							  PrimarySession->Thread.SessionSlot[Mid].NdfsWinxpReplyHeader,
							  NTOHL(ndfsRequestHeader->MessageSize4) - sizeof(NDFS_REQUEST_HEADER) - sizeof(NDFS_WINXP_REQUEST_HEADER),
							  &PrimarySession->Thread.SessionSlot[Mid].ReplyDataSize );

    DebugTrace2( 0, Dbg, ("DispatchWinXpRequestWorker: Return PrimarySession = %p, ndfsRequestHeader->Command = %d\n", 
						  PrimarySession, ndfsRequestHeader->Command) );

fail_replypoolalloc:
	PrimarySession->Thread.SessionSlot[Mid].State = SLOT_FINISH;

	KeSetEvent( &PrimarySession->Thread.WorkCompletionEvent, IO_NO_INCREMENT, FALSE );

	return;
}
예제 #19
0
NTSTATUS
FatFsdDeviceControl (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Device control operations

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

#ifdef	__NDAS_FAT__

	PIO_STACK_LOCATION	irpSp = IoGetCurrentIrpStackLocation( Irp );

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		Irp->IoStatus.Information = 0;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

	if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && FatData.DiskFileSystemDeviceObject == (PDEVICE_OBJECT)VolumeDeviceObject) {

		switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {

		case IOCTL_REGISTER_NDFS_CALLBACK: {

			PNDFS_CALLBACK	inputBuffer			= (PNDFS_CALLBACK)Irp->AssociatedIrp.SystemBuffer;
			ULONG			inputBufferLength	= irpSp->Parameters.DeviceIoControl.InputBufferLength;


			if ( inputBufferLength != sizeof( VolumeDeviceObject->NdfsCallback ) ) {

				Status = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
				Irp->IoStatus.Information = 0;
				break;
			} 
			
			DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: IOCTL_REGISTER_NDFS_CALLBACK, size = %d\n", inputBuffer->Size) );		

			RtlCopyMemory( &VolumeDeviceObject->NdfsCallback, inputBuffer, sizeof(VolumeDeviceObject->NdfsCallback) );

			//ASSERT( FALSE );
			Status = Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = 0;
			
			break;
		}
	
		case IOCTL_UNREGISTER_NDFS_CALLBACK:

			DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: IOCTL_UNREGISTER_NDFS_CALLBACK\n") );		

			RtlZeroMemory( &VolumeDeviceObject->NdfsCallback, sizeof(VolumeDeviceObject->NdfsCallback) );

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

			break;

		case IOCTL_SHUTDOWN: {
			
			PLIST_ENTRY				vcbListEntry;

			DebugTrace2( 0, Dbg2, ("FatFsdDeviceControl: IOCTL_SHUTDOWN\n") );		

	        for (vcbListEntry = FatData.VcbQueue.Flink;
			     vcbListEntry != &FatData.VcbQueue;
				 vcbListEntry = vcbListEntry->Flink) {

				PVCB					vcb = NULL;
#if __NDAS_FAT_PRIMARY__
				PLIST_ENTRY				primarySessionListEntry;
#endif
				PVOLUME_DEVICE_OBJECT	volDo = NULL;


				DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: volDo = %p, KeGetCurrentIrql() = %d\n", volDo, KeGetCurrentIrql()) );		

				vcb = CONTAINING_RECORD(vcbListEntry, VCB, VcbLinks);
				volDo = CONTAINING_RECORD( vcb, VOLUME_DEVICE_OBJECT, Vcb );

				DebugTrace2( 0, Dbg2, ("FatFsdDeviceControl: ND_FAT_DEVICE_FLAG_SHUTDOWN\n") );		
				SetFlag( volDo->NdFatFlags, ND_FAT_DEVICE_FLAG_SHUTDOWN );

		
#if __NDAS_FAT_PRIMARY__

				for (primarySessionListEntry = volDo->PrimarySessionQueue.Flink;
					 primarySessionListEntry != &volDo->PrimarySessionQueue; ) {

					PPRIMARY_SESSION primarySession;

					primarySession = CONTAINING_RECORD( primarySessionListEntry, PRIMARY_SESSION, ListEntry );
					primarySessionListEntry = primarySessionListEntry->Flink;
					PrimarySession_Reference( primarySession );
		
					PrimarySession_FileSystemShutdown( primarySession );

					RemoveEntryList( &primarySession->ListEntry );
					InitializeListHead(  &primarySession->ListEntry );
					PrimarySession_Dereference( primarySession );
				}
#endif
			}

			Status = Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = 0;
			DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: IOCTL_SHUTDOWN return\n") );		

			break;
		}

		default:
				
			ASSERT( FALSE );
			Status = Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
			Irp->IoStatus.Information = 0;
		}

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );
		return Status;
	}

	//if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && 
	//	IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode == IOCTL_INSERT_PRIMARY_SESSION) {

    //    return NtfsFsdDispatchSwitch( NULL, Irp, FALSE );
	//}

#endif

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

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

#if __NDAS_FAT__

		if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_DEVICE_CONTROL && 
			IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode == IOCTL_INSERT_PRIMARY_SESSION) {

			IrpContext = FatCreateIrpContext( Irp, FALSE );
		
		} else {

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

#else
		IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ));
#endif

        Status = FatCommonDeviceControl( IrpContext, Irp );

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

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

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

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
NTSTATUS
DispatchRequest (
	IN PPRIMARY_SESSION	PrimarySession
	)
{
	NTSTATUS				status;
	IN PNDFS_REQUEST_HEADER	ndfsRequestHeader;


	ASSERT( NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2) < PrimarySession->SessionContext.SessionSlotCount );
	ASSERT( PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].State == SLOT_WAIT );
	ASSERT( PrimarySession->Thread.ReceiveOverlapped.Request[0].IoStatusBlock.Information == sizeof(NDFS_REQUEST_HEADER) );

	RtlCopyMemory( PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].RequestMessageBuffer,
				   &PrimarySession->Thread.NdfsRequestHeader,
				   sizeof(NDFS_REQUEST_HEADER) );

	ndfsRequestHeader = (PNDFS_REQUEST_HEADER)PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].RequestMessageBuffer;
   
    DebugTrace2( 0, Dbg,
				("DispatchRequest: ndfsRequestHeader->Command = %d\n", 
				ndfsRequestHeader->Command) );

	switch (ndfsRequestHeader->Command) {

	case NDFS_COMMAND_LOGOFF: {

		PNDFS_REQUEST_LOGOFF	ndfsRequestLogoff;
		PNDFS_REPLY_HEADER		ndfsReplyHeader;
		PNDFS_REPLY_LOGOFF		ndfsReplyLogoff;
		

		if (PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

			ASSERT(NDASNTFS_BUG);
			status = STATUS_UNSUCCESSFUL;
			break;
		}

		if (!(NTOHS(ndfsRequestHeader->Uid2) == PrimarySession->SessionContext.Uid && 
			 NTOHS(ndfsRequestHeader->Tid2) == PrimarySession->SessionContext.Tid)) {

			ASSERT(NDASNTFS_BUG);
			status = STATUS_UNSUCCESSFUL;
			break;
		}
		
		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_LOGOFF) );

		ndfsRequestLogoff = (PNDFS_REQUEST_LOGOFF)(ndfsRequestHeader+1);
		
		status = RecvMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->RecvNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsRequestLogoff,
							  sizeof(NDFS_REQUEST_LOGOFF) );
	
		if (status != STATUS_SUCCESS) {

			ASSERT(NDASNTFS_BUG);
			break;
		}

		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestLogoff+1);

		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );
		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = 0;
		ndfsReplyHeader->Uid2		= HTONS(PrimarySession->SessionContext.Uid);
		ndfsReplyHeader->Tid2		= 0;
		ndfsReplyHeader->Mid2		= 0;
		ndfsReplyHeader->MessageSize4 = HTONL((UINT32)(sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_LOGOFF)));

		ndfsReplyLogoff = (PNDFS_REPLY_LOGOFF)(ndfsReplyHeader+1);

		if (NTOHL(ndfsRequestLogoff->SessionKey4) != PrimarySession->SessionContext.SessionKey) {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_UNSUCCESSFUL;
		
		} else {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_SUCCESS;
		}

		status = SendMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->SendNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsReplyHeader,
							  NTOHL(ndfsReplyHeader->MessageSize4) );

		if (status != STATUS_SUCCESS) {

			break;
		}

		PrimarySession->Thread.SessionState = SESSION_CLOSED;

		status = STATUS_SUCCESS;

		break;
	}

	case NDFS_COMMAND_EXECUTE: {

		UINT16	mid;

		if(PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

			if (PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

				ASSERT( NDASNTFS_BUG );
				status = STATUS_UNSUCCESSFUL;
				break;
			}
		}

		if (!(NTOHS(ndfsRequestHeader->Uid2) == PrimarySession->SessionContext.Uid && 
			NTOHS(ndfsRequestHeader->Tid2) == PrimarySession->SessionContext.Tid)) {

			ASSERT( NDASNTFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}

		mid = NTOHS(ndfsRequestHeader->Mid2);

		PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength = sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) + DEFAULT_NDAS_MAX_DATA_SIZE;
		RtlZeroMemory( &PrimarySession->Thread.SessionSlot[mid].RequestMessageBuffer[sizeof(NDFS_REQUEST_HEADER)], 
					   PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength - sizeof(NDFS_REQUEST_HEADER) );

		PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength = sizeof(NDFS_REPLY_HEADER) + sizeof(NDFS_WINXP_REPLY_HEADER) + DEFAULT_NDAS_MAX_DATA_SIZE;
		RtlZeroMemory( PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer, 
					   PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength );

		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) >= sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) );

		status = ReceiveNdfsWinxpMessage( PrimarySession, mid );

		if (status != STATUS_SUCCESS)
			break;

		if (PrimarySession->Thread.SessionSlot[mid].State != SLOT_WAIT) {

			break;
		}
	
		PrimarySession->Thread.SessionSlot[mid].State = SLOT_EXECUTING;
		PrimarySession->Thread.IdleSlotCount --;

		if (PrimarySession->SessionContext.SessionSlotCount == 1) {

			ASSERT( mid == 0 );

			DispatchWinXpRequestWorker( PrimarySession, mid );

			PrimarySession->Thread.SessionSlot[mid].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount ++;

			if (PrimarySession->Thread.SessionSlot[mid].Status == STATUS_SUCCESS) {

				PNDFS_REPLY_HEADER		ndfsReplyHeader;

				ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer;
				
				PrimarySession->Thread.SessionSlot[mid].Status = 
					SendNdfsWinxpMessage( PrimarySession,
										  ndfsReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].NdfsWinxpReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].ReplyDataSize,
										  mid );

			}
	
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}

			NDAS_ASSERT( PrimarySession->Thread.SessionSlot[mid].Status != STATUS_PENDING );
			
			if (PrimarySession->Thread.SessionSlot[mid].Status != STATUS_SUCCESS) {

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
										
				status = PrimarySession->Thread.SessionSlot[mid].Status;
				break;		
			}
				
			status = STATUS_SUCCESS;
			break;
		}

		if (mid == 0)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker0,
								  PrimarySession );
		
		if (mid == 1)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker1,
								  PrimarySession );
		
		if (mid == 2)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker2,
								  PrimarySession );

		
		if (mid == 3)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker3,
								  PrimarySession );

		ExQueueWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem, DelayedWorkQueue );	

		status = STATUS_PENDING;
		break;
	}

	default:

		NDAS_ASSERT( FALSE );			
		status = STATUS_UNSUCCESSFUL;
		
		break;
	}

	return status;
}
예제 #21
0
NTSTATUS
FatFsdCleanup (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

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

Arguments:

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

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

#if __NDAS_FAT__

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

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

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

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

    if ( FatDeviceIsFatFsdo( VolumeDeviceObject))  {

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

        IoCompleteRequest( Irp, IO_DISK_INCREMENT );

        return STATUS_SUCCESS;
    }

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

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

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#if (__NDAS_FAT_PRIMARY__ || __NDAS_FAT_SECONDARY__)

	do {
	
		try {

			if (IrpContext == NULL) { 

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

#if __NDAS_FAT_PRIMARY__
			{
				ULONG_PTR				stackBottom;
				ULONG_PTR				stackTop;
			    BOOLEAN					validPrimaryRequest = FALSE;
				PPRIMARY_REQUEST_INFO	primaryRequestInfo;
				PIO_STACK_LOCATION		irpSp = IoGetCurrentIrpStackLocation( Irp );
    
				primaryRequestInfo = (PPRIMARY_REQUEST_INFO)IoGetTopLevelIrp();
			    IoGetStackLimits( &stackTop, &stackBottom );

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

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

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

					if (IsListEmpty(&VolumeDeviceObject->PrimarySessionQueue)) {

						NDAS_ASSERT( FALSE );
					}

					IrpContext->PrimaryRequestInfo = *primaryRequestInfo;

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

#if __NDAS_FAT_SECONDARY__

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

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

				Status = STATUS_SUCCESS;

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

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

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

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

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}

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

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

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

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

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

						continue;
					}

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

					if (secondaryResourceAcquired == FALSE) {

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

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

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

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

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

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

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

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

	} while (Status == STATUS_CANT_WAIT);
예제 #22
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;
}
예제 #23
0
NTSTATUS
SecondaryRecoverySession (
	IN  PSECONDARY		Secondary
	)
{
	NTSTATUS			status;
	LONG				slotIndex;

	LARGE_INTEGER		timeOut;
	OBJECT_ATTRIBUTES	objectAttributes;

	ULONG				reconnectionTry;
    PLIST_ENTRY			ccblistEntry;
	BOOLEAN				isLocalAddress;


	SetFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

	ASSERT( FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); 
	ASSERT( Secondary->ThreadHandle );

	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	for (slotIndex=0; slotIndex < Secondary->Thread.SessionContext.SessionSlotCount; slotIndex++) {

		ASSERT( Secondary->Thread.SessionSlot[slotIndex] == NULL );
	}	

	if (Secondary->ThreadHandle) {

		ASSERT( Secondary->ThreadObject );
		
		timeOut.QuadPart = -NDASNTFS_TIME_OUT;
		status = KeWaitForSingleObject( Secondary->ThreadObject,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );

		if(status != STATUS_SUCCESS) {

			ASSERT( NDASNTFS_BUG );
			return status;
		}

		DebugTrace( 0, Dbg2, ("Secondary_Stop: thread stoped\n") );

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = 0;
		Secondary->ThreadObject = 0;

		RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );
	}

	for (status = STATUS_UNSUCCESSFUL, reconnectionTry = 0; reconnectionTry < MAX_RECONNECTION_TRY; reconnectionTry++) {

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN)) {

			//DebugTrace( 0, Dbg2, ("SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n") ); 
			//DbgPrint( "SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n" ); 

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY) {

			status = STATUS_SUCCESS;

		} else {

			status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)->
						NdfsCallback.SecondaryToPrimary( Secondary->VolDo->Vcb.Vpb->RealDevice, TRUE );

			if (status == STATUS_NO_SUCH_DEVICE) {

				NDAS_ASSERT( FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED) );
				ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

				return STATUS_UNSUCCESSFUL;
			}
		}


		//NtfsDebugTraceLevel = 0;

		DebugTrace( 0, Dbg2, ("SecondaryToPrimary status = %x\n", status) ); 

		if (status == STATUS_SUCCESS) {

			PVCB				vcb = &Secondary->VolDo->Vcb;
			TOP_LEVEL_CONTEXT	topLevelContext;
			PTOP_LEVEL_CONTEXT	threadTopLevelContext;
			PIRP_CONTEXT		tempIrpContext = NULL;

			SetFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	


			DebugTrace( 0, Dbg2, ("Vcb->State = %X\n", vcb->VcbState) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );

			tempIrpContext = NULL;

			threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			SetFlag( tempIrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
						
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			try {
			
				status = CleanUpVcb( tempIrpContext, vcb );
			
			} finally {
                
				NtfsCompleteRequest( tempIrpContext, NULL, 0 );
				ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			ASSERT( status == STATUS_SUCCESS );
			ASSERT( FlagOn(vcb->VcbState, VCB_STATE_MOUNT_COMPLETED) );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );


			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) );

			Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; 

			tempIrpContext = NULL;

			threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
			
			//tempIrpContext->TopLevelIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			//tempIrpContext->TopLevelIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			try {
			
				status = NdasNtfsMountVolume( tempIrpContext, vcb );
			
			} finally {
                
				NtfsCompleteRequest( tempIrpContext, NULL, 0 );
				ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			NDAS_ASSERT( status == STATUS_SUCCESS );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) );

			if (vcb->MftScb) {
			
				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftScb->Header.Resource) );	
			}

			if (vcb->Mft2Scb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->Mft2Scb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->Mft2Scb->Header.Resource) );	
			}

			if (vcb->LogFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->LogFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->LogFileScb->Header.Resource) );			
			}

			if (vcb->VolumeDasdScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->VolumeDasdScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->VolumeDasdScb->Header.Resource) );			
			}

			if (vcb->AttributeDefTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->AttributeDefTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->AttributeDefTableScb->Header.Resource) );			
			}

			if (vcb->UpcaseTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UpcaseTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UpcaseTableScb->Header.Resource) );			
			}

			if (vcb->RootIndexScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->RootIndexScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->RootIndexScb->Header.Resource) );			
			}

			if (vcb->BitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BitmapScb->Header.Resource) );			
			}

			if (vcb->BadClusterFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BadClusterFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BadClusterFileScb->Header.Resource) );		
			}

			if (vcb->MftBitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftBitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftBitmapScb->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorStream) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorStream->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorStream->Header.Resource) );			
			}

			if (vcb->UsnJournal) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UsnJournal->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UsnJournal->Header.Resource) );			
			}

			if (vcb->ExtendDirectory) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->ExtendDirectory->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->ExtendDirectory->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorHashIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
			}

			if (vcb->SecurityIdIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityIdIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityIdIndex->Header.Resource) );			
			}
		}

		Secondary->NumberOfPrimaryAddress = 0;

		status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)->
						NdfsCallback.QueryPrimaryAddress( &Secondary->VolDo->NetdiskPartitionInformation, 
														  Secondary->PrimaryAddressList, 
														  &Secondary->NumberOfPrimaryAddress, 
														  &isLocalAddress );

		DebugTrace2( 0, Dbg2, ("RecoverySession: QueryPrimaryAddress status = %X\n", status) );

		if (status == STATUS_SUCCESS && !(Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY && isLocalAddress)) {

			LONG i;

			NDAS_ASSERT( Secondary->NumberOfPrimaryAddress );

			for (i = 0; i < Secondary->NumberOfPrimaryAddress; i++) {

				DebugTrace2( 0, Dbg, 
							   ("RecoverySession: Secondary = %p Found PrimaryAddress[%d] :%02x:%02x:%02x:%02x:%02x:%02x/%d\n",
							    Secondary, i,
								Secondary->PrimaryAddressList[i].Node[0], Secondary->PrimaryAddressList[i].Node[1],
								Secondary->PrimaryAddressList[i].Node[2], Secondary->PrimaryAddressList[i].Node[3],
								Secondary->PrimaryAddressList[i].Node[4], Secondary->PrimaryAddressList[i].Node[5],
								NTOHS(Secondary->PrimaryAddressList[i].Port)) );
			}
		
		} else {

			continue;
		}	

		KeInitializeEvent( &Secondary->ReadyEvent, NotificationEvent, FALSE );
		KeInitializeEvent( &Secondary->RequestEvent, NotificationEvent, FALSE );

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

		status = PsCreateSystemThread( &Secondary->ThreadHandle,
									   THREAD_ALL_ACCESS,
									   &objectAttributes,
									   NULL,
									   NULL,
									   SecondaryThreadProc,
									   Secondary );

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASNTFS_UNEXPECTED );
			break;
		}

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

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASNTFS_INSUFFICIENT_RESOURCES );
			break;
		}

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

		if(status != STATUS_SUCCESS) {

			ASSERT( NDASNTFS_BUG );
			break;
		}

		KeClearEvent( &Secondary->ReadyEvent );

		InterlockedIncrement( &Secondary->SessionId );	

		ExAcquireFastMutex( &Secondary->FastMutex );

		if (!FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_START) || FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_STOPED)) {

			ExReleaseFastMutex( &Secondary->FastMutex );

			if(Secondary->Thread.SessionStatus == STATUS_DISK_CORRUPT_ERROR) {

				status = STATUS_SUCCESS;
				break;
			}

			timeOut.QuadPart = -NDASNTFS_TIME_OUT;
			status = KeWaitForSingleObject( Secondary->ThreadObject,
											Executive,
											KernelMode,
											FALSE,
											&timeOut );

			if(status != STATUS_SUCCESS) {

				ASSERT( NDASNTFS_BUG );
				return status;
			}

			DebugTrace( 0, Dbg, ("Secondary_Stop: thread stoped\n") );

			ObDereferenceObject( Secondary->ThreadObject );

			Secondary->ThreadHandle = 0;
			Secondary->ThreadObject = 0;

			RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );

			continue;
		} 

		ExReleaseFastMutex( &Secondary->FastMutex );

		status = STATUS_SUCCESS;

		DebugTrace( 0, Dbg2, ("SessionRecovery Success Secondary = %p\n", Secondary) );

		break;
	}
예제 #24
0
NTSTATUS
NdFatSecondaryCommonWrite (
	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;


	ASSERT( KeGetCurrentIrql() == PASSIVE_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 (irpSp->Parameters.Write.ByteOffset.QuadPart == FILE_WRITE_TO_END_OF_FILE && 
		irpSp->Parameters.Write.ByteOffset.HighPart == -1) {

		write.ByteOffset = fcb->Header.FileSize;

	} else {

		write.ByteOffset = irpSp->Parameters.Write.ByteOffset;
	}

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

	if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
		
		ASSERT( (write.ByteOffset.QuadPart + write.Length) <= 
				((fcb->Header.AllocationSize.QuadPart + PAGE_SIZE - 1) & ~((LONGLONG) (PAGE_SIZE-1))) );

		return STATUS_SUCCESS;
	}

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

	if ( (write.ByteOffset.QuadPart + write.Length) <= fcb->Header.FileSize.LowPart) {

		return STATUS_SUCCESS;
	}

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

		return STATUS_PENDING;

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

		status = FatFsdPostRequest( IrpContext, Irp );

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

		DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart + write.Length > fcb->Header.AllocationSize.QuadPart = %d "
								 "ExIsResourceAcquiredSharedLite(fcb->Header.Resource) = %d\n",
							   ((write.ByteOffset.QuadPart + write.Length) > fcb->Header.AllocationSize.QuadPart),
							   ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) );

	if ((write.ByteOffset.QuadPart + write.Length) > fcb->Header.AllocationSize.QuadPart) {

		FatAcquireExclusiveFcb( 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 );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );	
		}


		secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, 
														  IRP_MJ_SET_INFORMATION,
														  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_SET_INFORMATION, 0 );

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

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

		ndfsWinxpRequestHeader->FileHandle = ccb->PrimaryFileHandle;

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

		ndfsWinxpRequestHeader->SetFile.FileHandle				= 0;
		ndfsWinxpRequestHeader->SetFile.Length					= sizeof( FILE_END_OF_FILE_INFORMATION );
		ndfsWinxpRequestHeader->SetFile.FileInformationClass	= FileEndOfFileInformation;

		ndfsWinxpRequestHeader->SetFile.EndOfFileInformation.EndOfFile = write.ByteOffset.QuadPart + write.Length;


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

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

			secondaryRequest = NULL;
			status = STATUS_IO_DEVICE_ERROR;
			leave;
		}

		KeClearEvent( &secondaryRequest->CompleteEvent );

		if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

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

			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
		}

		ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
		status = ndfsWinxpReplytHeader->Status;
		Irp->IoStatus.Information = write.Length;

		if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg2, ("NdNtfsSecondaryCommonWrite: ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );
			ASSERT( ndfsWinxpReplytHeader->Information == 0 );
		
		} else
			ASSERT( ndfsWinxpReplytHeader->FileInformationSet );
	
		if (ndfsWinxpReplytHeader->FileInformationSet) {

			PNDFS_FAT_MCB_ENTRY	mcbEntry;
			ULONG			index;

			BOOLEAN			lookupResut;
			VBO				vcn;
			LBO				lcn;
			//LBO			startingLcn;
			ULONG			clusterCount;

			//DbgPrint( "w ndfsWinxpReplytHeader->FileSize = %x\n", ndfsWinxpReplytHeader->FileSize );

			if (ndfsWinxpReplytHeader->AllocationSize != fcb->Header.AllocationSize.QuadPart) {

				ASSERT( ExIsResourceAcquiredExclusiveLite(fcb->Header.Resource) );

				ASSERT( ndfsWinxpReplytHeader->AllocationSize > fcb->Header.AllocationSize.QuadPart );

				mcbEntry = (PNDFS_FAT_MCB_ENTRY)( ndfsWinxpReplytHeader+1 );

				for (index=0, vcn=0; index < ndfsWinxpReplytHeader->NumberOfMcbEntry; index++, mcbEntry++) {

					lookupResut = FatLookupMcbEntry( vcb, &fcb->Mcb, vcn, &lcn, &clusterCount, NULL );
					
					if (lookupResut == TRUE && vcn < fcb->Header.AllocationSize.QuadPart) {

						ASSERT( lookupResut == TRUE );
						//ASSERT( startingLcn == lcn );
						ASSERT( vcn == mcbEntry->Vcn );
						ASSERT( lcn == (((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector) );
						ASSERT( clusterCount <= mcbEntry->ClusterCount );

						if (clusterCount < mcbEntry->ClusterCount) {

							FatAddMcbEntry ( vcb, 
											 &fcb->Mcb, 
											 (VBO)mcbEntry->Vcn, 
											 ((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector, 
											 (ULONG)mcbEntry->ClusterCount );

							lookupResut = FatLookupMcbEntry( vcb, &fcb->Mcb, vcn, &lcn, &clusterCount, NULL );

							ASSERT( lookupResut == TRUE );
							//ASSERT( startingLcn == lcn );
							ASSERT( vcn == mcbEntry->Vcn );
							ASSERT( lcn == (((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector) );
							ASSERT( clusterCount == mcbEntry->ClusterCount );
						}
					
					} else { 

						ASSERT( lookupResut == FALSE || lcn == 0 );

						FatAddMcbEntry ( vcb, 
										 &fcb->Mcb, 
										 (VBO)mcbEntry->Vcn, 
										 ((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector, 
										 (ULONG)mcbEntry->ClusterCount );
					}

					vcn += (ULONG)mcbEntry->ClusterCount;
				}

				ASSERT( vcn == ndfsWinxpReplytHeader->AllocationSize );

				fcb->Header.AllocationSize.QuadPart = ndfsWinxpReplytHeader->AllocationSize;
				SetFlag( fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE );		

				if (CcIsFileCached(fileObject)) {

					ASSERT( fileObject->SectionObjectPointer->SharedCacheMap != NULL );
					CcSetFileSizes( fileObject, (PCC_FILE_SIZES)&fcb->Header.AllocationSize );
				}
			}

			DebugTrace2(0, Dbg, ("write scb->Header.FileSize.LowPart = %I64x, scb->Header.ValidDataLength.QuadPart = %I64x\n", 
								 fcb->Header.FileSize.LowPart, fcb->Header.ValidDataLength.QuadPart) );

		}

#if DBG
		{
			BOOLEAN			lookupResut;
			VBO				vcn;
			LBO				lcn;
			//LCN				startingLcn;
			ULONG			clusterCount;

			vcn = 0;
			while (1) {

				lookupResut = FatLookupMcbEntry( vcb, &fcb->Mcb, vcn, &lcn, &clusterCount, NULL );
				if (lookupResut == FALSE || lcn == 0)
					break;

				vcn += clusterCount;
			}

			ASSERT( vcn == fcb->Header.AllocationSize.QuadPart );
		}

#endif

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

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

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}
			
	return status;
}
예제 #25
0
VOID
Secondary_Stop (
	IN  PSECONDARY	Secondary
	)
{
	NTSTATUS		status;
	LARGE_INTEGER	timeOut;

	PLIST_ENTRY			secondaryRequestEntry;
	PSECONDARY_REQUEST	secondaryRequest;


	DebugTrace2( 0, Dbg2, ("Secondary stop\n") );

	ExAcquireFastMutex( &Secondary->FastMutex );

	if (FlagOn(Secondary->Flags, SECONDARY_FLAG_CLOSED)) {

		ASSERT( FALSE );
		ExReleaseFastMutex( &Secondary->FastMutex );
		return;
	}

	SetFlag( Secondary->Flags, SECONDARY_FLAG_CLOSED );

	ExReleaseFastMutex( &Secondary->FastMutex );

	if (Secondary->ThreadHandle == NULL) {

		Secondary_Dereference(Secondary);
		return;
	}

	ASSERT( Secondary->ThreadObject != NULL );


	secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE );
	secondaryRequest->RequestType = SECONDARY_REQ_DISCONNECT;

	QueueingSecondaryRequest( Secondary, secondaryRequest );

	secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE );
	secondaryRequest->RequestType = SECONDARY_REQ_DOWN;

	QueueingSecondaryRequest( Secondary, secondaryRequest );

	timeOut.QuadPart = - NDFAT_TIME_OUT;

	status = KeWaitForSingleObject( Secondary->ThreadObject,
									Executive,
									KernelMode,
									FALSE,
									&timeOut );

	if (status == STATUS_SUCCESS) {
	   
		DebugTrace2( 0, Dbg, ("Secondary_Stop: thread stoped Secondary = %p\n", Secondary));

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = NULL;
		Secondary->ThreadObject = NULL;
	
	} else {

		ASSERT( NDFAT_BUG );
		return;
	}

	ASSERT( IsListEmpty(&Secondary->RecoveryCcbQueue) );
	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	while (secondaryRequestEntry = ExInterlockedRemoveHeadList(&Secondary->RequestQueue,
															   &Secondary->RequestQSpinLock)) {

		PSECONDARY_REQUEST secondaryRequest;
			
		secondaryRequest = CONTAINING_RECORD( secondaryRequestEntry,
											  SECONDARY_REQUEST,
											  ListEntry );
        
		secondaryRequest->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (secondaryRequest->Synchronous == TRUE)
			KeSetEvent( &secondaryRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceSecondaryRequest( secondaryRequest );
	}
	
	return;
}
예제 #26
0
NTSTATUS
FatCommonPnp (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for doing PnP 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;

    PVOLUME_DEVICE_OBJECT OurDeviceObject;
    PVCB Vcb;

    //
    //  Force everything to wait.
    //
    
    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    
    //
    //  Get the current Irp stack location.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Find our Vcb.  This is tricky since we have no file object in the Irp.
    //

    OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject;

    //
    //  Take the global lock to synchronise against volume teardown.
    //

    FatAcquireExclusiveGlobal( IrpContext );    
    
    //
    //  Make sure this device object really is big enough to be a volume device
    //  object.  If it isn't, we need to get out before we try to reference some
    //  field that takes us past the end of an ordinary device object.
    //
    
    if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) ||
        NodeType( &OurDeviceObject->Vcb ) != FAT_NTC_VCB) {
        
        //
        //  We were called with something we don't understand.
        //

        FatReleaseGlobal( IrpContext );
        
        Status = STATUS_INVALID_PARAMETER;
        FatCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }

#if __NDAS_FAT__
	if (OurDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY)
		SetFlag( IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
#endif

    Vcb = &OurDeviceObject->Vcb;

    //
    //  Case on the minor code.
    //
 
#if __NDAS_FAT_SECONDARY__

		if ( ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Secondary &&
		   	( ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode == NETDISK_SECONDARY || 
			  ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY )  )
		{
			PSECONDARY	Secondary = ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Secondary;

			Status = STATUS_SUCCESS;

			Secondary_Reference( Secondary );

			switch ( IrpSp->MinorFunction ) {

			case IRP_MN_QUERY_REMOVE_DEVICE: {

				DebugTrace2( 0, Dbg, ("FatCommonPnp: IRP_MN_QUERY_REMOVE_DEVICE NetdiskEnableMode = %d\n", ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) );

				ExAcquireFastMutex( &Secondary->FastMutex );	

				if (!Secondary->TryCloseActive) {
				
					Secondary->TryCloseActive = TRUE;
					ExReleaseFastMutex( &Secondary->FastMutex );
					Secondary_Reference( Secondary );
					//FatDebugTraceLevel |= DEBUG_TRACE_CLOSE;
					SecondaryTryClose( IrpContext, Secondary );
					//FatDebugTraceLevel &= ~DEBUG_TRACE_CLOSE;
				
				} else {
				
					ExReleaseFastMutex( &Secondary->FastMutex );
				}

				if (Vcb->SecondaryOpenFileCount) {

					LARGE_INTEGER interval;

					// Wait all files closed
					interval.QuadPart = (1 * HZ);      //delay 1 seconds
					KeDelayExecutionThread(KernelMode, FALSE, &interval);
				}

#if 0
				if (Vcb->SecondaryOpenFileCount) {

					LONG		ccbCount;
					PLIST_ENTRY	ccbListEntry;
					PVOID		restartKey;
					PFCB		fcb;

					ExAcquireFastMutex( &Secondary->RecoveryCcbQMutex );

				    for (ccbCount = 0, ccbListEntry = Secondary->RecoveryCcbQueue.Flink; 
						 ccbListEntry != &Secondary->RecoveryCcbQueue; 
						 ccbListEntry = ccbListEntry->Flink, ccbCount++);

					ExReleaseFastMutex( &Secondary->RecoveryCcbQMutex );

					ASSERT( !IsListEmpty(&Secondary->RecoveryCcbQueue) );
					ASSERT( ccbCount == Vcb->SecondaryOpenFileCount );

					DebugTrace2( 0, Dbg, ("IRP_MN_QUERY_REMOVE_DEVICE: Vcb->SecondaryCloseCount = %d, Vcb->CloseCount = %d, ccbCount = %d\n",
                                         Vcb->SecondaryOpenFileCount, Vcb->OpenCount, ccbCount) );

					restartKey = NULL;
					fcb = NdFatGetNextFcbTableEntry( &Secondary->VolDo->Vcb, &restartKey );
					ASSERT( fcb != NULL || !IsListEmpty(&Secondary->DeletedFcbQueue) );

					Status = STATUS_UNSUCCESSFUL;
				}
#endif

				break;
			}

			case IRP_MN_REMOVE_DEVICE: {

				PVOID			restartKey;
				PFCB			fcb;

				DebugTrace2( 0, Dbg, ("FatCommonPnp: IRP_MN_REMOVE_DEVICE NetdiskEnableMode = %d\n", ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) );

#if 0
				restartKey = NULL;
				fcb = NdFatGetNextFcbTableEntry( &Secondary->VolDo->Vcb, &restartKey );
				
				ASSERT( fcb == NULL && IsListEmpty(&Secondary->DeletedFcbQueue) );

#endif

				if (Vcb->SecondaryOpenFileCount) {

					ASSERT( NDFAT_BUG );
					Status =  STATUS_UNSUCCESSFUL;
				}

				break;
			
			}
			default: {

				DebugTrace2( 0, Dbg, ("FatCommonPnp: IrpSp-MinorFunction = %d NetdiskEnableMode = %d\n", 
									   IrpSp->MinorFunction, ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) );


				if (IrpSp->MinorFunction != IRP_MN_QUERY_DEVICE_RELATIONS) {

					if (IrpSp->FileObject && IS_SECONDARY_FILEOBJECT(IrpSp->FileObject)) {

						ASSERT( FALSE );
					}
				}
				
				Status =  STATUS_SUCCESS;
				break;
			}
			}

			Secondary_Dereference( Secondary );	

			if (!NT_SUCCESS(Status)) {

				FatCompleteRequest( NULL, Irp, Status );
				return Status;
			} 
		}

#endif

    switch ( IrpSp->MinorFunction ) {

        case IRP_MN_QUERY_REMOVE_DEVICE:
            
            Status = FatPnpQueryRemove( IrpContext, Irp, Vcb );
            break;
        
        case IRP_MN_SURPRISE_REMOVAL:
        
            Status = FatPnpSurpriseRemove( IrpContext, Irp, Vcb );
            break;

        case IRP_MN_REMOVE_DEVICE:

            Status = FatPnpRemove( IrpContext, Irp, Vcb );
            break;

        case IRP_MN_CANCEL_REMOVE_DEVICE:
    
            Status = FatPnpCancelRemove( IrpContext, Irp, Vcb );
            break;

        default:

            FatReleaseGlobal( IrpContext );
            
            //
            //  Just pass the IRP on.  As we do not need to be in the
            //  way on return, ellide ourselves out of the stack.
            //
            
            IoSkipCurrentIrpStackLocation( Irp );
    
            Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
            
            //
            //  Cleanup our Irp Context.  The driver has completed the Irp.
            //
        
            FatCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
            
            break;
    }
        
    return Status;
}
예제 #27
0
VOID
SecondaryTryClose(
	IN PIRP_CONTEXT	IrpContext2  OPTIONAL,
	IN PSECONDARY	Secondary
	)
{
	IRP_CONTEXT			irpContext;

	BOOLEAN				secondaryResourceAcquired = FALSE;
	BOOLEAN				acquiredVcb = FALSE;
	BOOLEAN				wait;

	PFCB				fcb;
	BOOLEAN				acquiredFcb = FALSE;
	BOOLEAN				removedFcb;
	PFCB				nextFcb = NULL;
	PVOID				restartKey;
	PLIST_ENTRY			deletedFcbListEntry;


	DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles start\n") );

	try {

		RtlZeroMemory( &irpContext, sizeof(IRP_CONTEXT) );
		SetFlag( irpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
		SetFlag( irpContext.NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		irpContext.Vcb = &Secondary->VolDo->Vcb;

		secondaryResourceAcquired = SecondaryAcquireResourceSharedLite( &irpContext, 
																		&Secondary->Resource, 
																		FALSE );
		if (secondaryResourceAcquired == FALSE)
			leave;
		
		wait = BooleanFlagOn( irpContext.Flags, IRP_CONTEXT_FLAG_WAIT );

		acquiredVcb = FatAcquireExclusiveSecondaryVcb( &irpContext, irpContext.Vcb );

		if (acquiredVcb == FALSE)
			leave;

		SetFlag( Secondary->VolDo->Vcb.NdFatFlags, ND_FAT_VCB_FLAG_TRY_CLOSE_FILES );
		FatFspClose( &Secondary->VolDo->Vcb );
		ClearFlag( Secondary->VolDo->Vcb.NdFatFlags, ND_FAT_VCB_FLAG_TRY_CLOSE_FILES );

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles FatFspClose, Secondary->VolDo->Vcb.SecondaryOpenCount = %d\n", 
							    Secondary->VolDo->Vcb.SecondaryOpenFileCount) );

		SetFlag( irpContext.NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		Secondary_TryCloseFilExts( Secondary );

	} finally {

		ASSERT( nextFcb == NULL );

		ClearFlag( irpContext.NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		if (acquiredVcb)
			FatReleaseSecondaryVcb( &irpContext, irpContext.Vcb );
		
		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles exit\n") );

		ExAcquireFastMutex( &Secondary->FastMutex );		
		Secondary->TryCloseActive = FALSE;
		ExReleaseFastMutex( &Secondary->FastMutex );

		if (secondaryResourceAcquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->Resource );

		Secondary_Dereference( Secondary );
	}

	return;
}
예제 #28
0
파일: auxfile.cpp 프로젝트: gambineri/Attic
//----------- SQLTrace
void SQLTrace(itxSQLConnection* conn)
{
  int error_condition = DEFAULT;
  itxString errormsg;

  memset(conn->m_sqlstate, '\0', ITX_SQL_STATUS_LEN);
  memset(conn->m_message, '\0', ITX_SQL_MAX_ERRMSG);
  errormsg = "<br>";

  //Diagnostic environment errors
  SQLGetDiagRec(SQL_HANDLE_ENV, conn->m_henv, 1, conn->m_sqlstate, &(conn->m_nativerr), conn->m_message, 
                ITX_SQL_MAX_ERRMSG - 1, &(conn->m_msglength));

  if (!ISNULL((const char*) conn->m_sqlstate))
  {
    error_condition = IN_WARNING;
    errormsg += "   SQL_HANDLE_ENV : ";
    errormsg += (char*) conn->m_sqlstate;
    errormsg += "<br>";
    errormsg += (char*) conn->m_message;
    errormsg += "<br>";
  }

  //Diagnostic db connection errors
  SQLGetDiagRec(SQL_HANDLE_DBC, conn->m_hdbc, 1, conn->m_sqlstate, &(conn->m_nativerr), conn->m_message, 
                ITX_SQL_MAX_ERRMSG - 1, &(conn->m_msglength));

  if (!ISNULL((const char*) conn->m_sqlstate))
  {
    error_condition = IN_WARNING;
    errormsg += "   SQL_HANDLE_DBC : ";
    errormsg += (char*) conn->m_sqlstate;
    errormsg += "<br>";
    errormsg += (char*) conn->m_message;
    errormsg += "<br>";
  }

  //Diagnostic sql statement errors
  SQLGetDiagRec(SQL_HANDLE_STMT, conn->m_hstmt, 1, conn->m_sqlstate, &(conn->m_nativerr), conn->m_message, 
                ITX_SQL_MAX_ERRMSG - 1, &(conn->m_msglength));

  if (!ISNULL((const char*) conn->m_sqlstate))
  {
    error_condition = IN_WARNING;
    errormsg += "   SQL_HANDLE_STMT : ";
    errormsg += (char*) conn->m_sqlstate;
    errormsg += "<br>";
    errormsg += (char*) conn->m_message;
    errormsg += "<br>";
  }

  try
  {
    errormsg += "Last Executed Query: <br>";
    errormsg += conn->m_statement;
    errormsg += "<br>";
    if (error_condition == DEFAULT)
    {
      errormsg += "ODBC statement completed successfully<br>";
    }
  }
  catch(...)
  {
    DebugTrace("CATCH INSIDE itxSQLConnection::DebugTrace\n");
  }

  DebugTrace2(error_condition, "%s", errormsg.GetBuffer());  
}
예제 #29
0
VOID
PrimarySessionThreadProc (
	IN PPRIMARY_SESSION PrimarySession
	)
{
	BOOLEAN		primarySessionTerminate = FALSE;
	NTSTATUS	status;
	_U16		slotIndex;
	PLIST_ENTRY	primarySessionRequestEntry;


	ASSERT( SESSION_SLOT_COUNT == 1 );
	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	DebugTrace2( 0, Dbg2, ("PrimarySessionThreadProc: Start PrimarySession = %p\n", PrimarySession) );
	
	PrimarySession_Reference( PrimarySession );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	
	InitializeListHead( &PrimarySession->Thread.OpenedFileQueue );
	KeInitializeSpinLock( &PrimarySession->Thread.OpenedFileQSpinLock );

	KeInitializeEvent( &PrimarySession->Thread.WorkCompletionEvent, NotificationEvent, FALSE );

	PrimarySession->SessionContext.SessionSlotCount = SESSION_SLOT_COUNT;

	for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

		PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
		PrimarySession->Thread.IdleSlotCount ++;
	}

	ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_START );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );

	KeSetEvent( &PrimarySession->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
										    &PrimarySession->Thread.TdiReceiveContext,
										    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
										    sizeof(NDFS_REQUEST_HEADER),
										    0,
										    NULL,
										    NULL );

	if (NT_SUCCESS(status)) {

		PrimarySession->Thread.TdiReceiving = TRUE;
	
	} else {
	
		ASSERT( NDASFAT_BUG );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
		primarySessionTerminate = TRUE;
	} 

	while (primarySessionTerminate == FALSE) {

		PKEVENT				events[3];
		LONG				eventCount;
		NTSTATUS			eventStatus;
		LARGE_INTEGER		timeOut;


		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;

		events[eventCount++] = &PrimarySession->RequestEvent;

		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			events[eventCount++] = &PrimarySession->Thread.WorkCompletionEvent;

			if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN)) {
			
				if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount) {

					CloseOpenFiles( PrimarySession, TRUE );
				
					KeSetEvent( &PrimarySession->Thread.ShutdownPrimarySessionRequest->CompleteEvent, 
								IO_DISK_INCREMENT, 
								FALSE );

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT );
					ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );
				}
			}	 
		
			if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT)) {

				if (PrimarySession->Thread.TdiReceiving == TRUE) {

					ASSERT( PrimarySession->Thread.IdleSlotCount != 0 );
					events[eventCount++] = &PrimarySession->Thread.TdiReceiveContext.CompletionEvent;
				}
			}

			ASSERT( eventCount <= THREAD_WAIT_OBJECTS );
		}

		timeOut.QuadPart = -5*HZ;
		eventStatus = KeWaitForMultipleObjects( eventCount, 
												events, 
												WaitAny, 
												Executive, 
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

#if 0
		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			if (eventStatus == STATUS_TIMEOUT || eventStatus == 2) {
			
				if (PrimarySession->Thread.SessionState == SESSION_TREE_CONNECT) {
				
					ASSERT( PrimarySession->NetdiskPartition );
				
					if (!(PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_PRIMARY].VolumeState == VolumeMounted || 
						  PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_SECONDARY2PRIMARY].VolumeState == VolumeMounted)) {

						DebugTrace2( 0, Dbg2,
									   ("Netdisk Volume is unmounted\n") );

						if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT))
							primarySessionTerminate = TRUE;
		
						continue;
					}
				}
			}
		}

#endif

		if (eventStatus == STATUS_TIMEOUT) {

			continue;
		}

		if (!NT_SUCCESS(eventStatus) || eventStatus >= eventCount) {

			NDASFAT_ASSERT( FALSE );
			SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
			primarySessionTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																			 &PrimarySession->RequestQSpinLock)) {

				PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
				primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
														   PRIMARY_SESSION_REQUEST,
														   ListEntry );

				if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT ||
					primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE) {

					DebugTrace2( 0, Dbg2, 
								   ((primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT) ?
								   ("PRIMARY_SESSION_REQ_DISCONNECT: DisconnectFromSecondary\n") :
									("PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE: DisconnectFromSecondary\n")) );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE)
						primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DOWN) {
					
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
					primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );
				
				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_SHUTDOWN) {

					DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN\n") );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );

					ASSERT (primarySessionRequest->Synchronous == TRUE);

					PrimarySession->Thread.ShutdownPrimarySessionRequest = primarySessionRequest;

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_STOPPING) {

					SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );
					
					if (PrimarySession->IsLocalAddress == FALSE) {

						CloseOpenFiles( PrimarySession, FALSE );
					}

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_CANCEL_STOPPING) {

					ClearFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else {

					ASSERT( NDASFAT_BUG );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
				}
			}

			continue;
		
		} else if (eventStatus == 1) {

			while (TRUE) {
	
				for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

					if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
						break;
				}

				if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
					break;
			
				PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
				PrimarySession->Thread.IdleSlotCount ++;

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					PNDFS_REPLY_HEADER		ndfsReplyHeader;

					ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[slotIndex].ReplyMessageBuffer;
										
					PrimarySession->Thread.SessionSlot[slotIndex].Status
						= SendNdfsWinxpMessage( PrimarySession,
												ndfsReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].NdfsWinxpReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].ReplyDataSize,
												slotIndex );

				}
	
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}
		
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}

				if (!(PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS || 
					  PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_PENDING)) {

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );

						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				 }
				
				if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );
	
						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				}

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					if (PrimarySession->Thread.TdiReceiving == FALSE) {

						status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
															    &PrimarySession->Thread.TdiReceiveContext,
															    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
															    sizeof(NDFS_REQUEST_HEADER),
															    0,
															    NULL,
															    NULL );

						if (!NT_SUCCESS(status)) {

							ASSERT( NDASFAT_BUG );

							SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
							primarySessionTerminate = TRUE;
							break;
						}
						
						PrimarySession->Thread.TdiReceiving = TRUE;
					}
				}
			}		
		
			continue;
		
		} else {

			ASSERT( eventStatus == 2 );  // Receive Event
			ASSERT( !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT) &&
				    !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN) );

			if (PrimarySession->Thread.TdiReceiveContext.Result != sizeof(NDFS_REQUEST_HEADER)) {

				DebugTrace2( 0, Dbg,
							   ("DispatchRequest: Disconnected, PrimarySession = Data received:%d\n",
							   PrimarySession->Thread.TdiReceiveContext.Result) );

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
				primarySessionTerminate = TRUE;
				
				continue;		
			}

			PrimarySession->Thread.TdiReceiving = FALSE;

#if 0
			if (PrimarySession->NetdiskPartition) {

				PENABLED_NETDISK EnabledNetdisk = PrimarySession->NetdiskPartition->EnabledNetdisk;
				
				ASSERT( EnabledNetdisk );

				if (NetdiskManager_IsStoppedNetdisk(GlobalLfs.NetdiskManager, EnabledNetdisk)) {
				    
					DebugTrace2( 0, Dbg2,
								   ("PrimarySessionThread: %p Netdisk is stopped\n", PrimarySession) );

					DebugTrace2( 0, Dbg2, ("DispatchWinXpRequest: Netdisk is stopped.\n") );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { 
					
						// no other way to notify secondary about unmount without break backward compatability.
						
						DebugTrace2( 0, Dbg2, ("IsStoppedNetdisk: DisconnectFromSecondary\n") );
						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					primarySessionTerminate = TRUE;
					continue;
				}
			} 

#endif

			status = DispatchRequest( PrimarySession );

			if (!(status == STATUS_SUCCESS || status == STATUS_PENDING)) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (status == STATUS_SUCCESS) {

				if (PrimarySession->Thread.TdiReceiving == FALSE) {

					status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
														    &PrimarySession->Thread.TdiReceiveContext,
														    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
														    sizeof(NDFS_REQUEST_HEADER),
														    0,
														    NULL,
														    NULL );

					if (!NT_SUCCESS(status)) {

						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
						primarySessionTerminate = TRUE;
					}

					PrimarySession->Thread.TdiReceiving = TRUE;
				}
			}
			
			continue;
		}
	}

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );

	while (TRUE) {

		LARGE_INTEGER	timeOut;
		NTSTATUS		eventStatus;


		if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount)
			break;

		timeOut.QuadPart = -10*HZ;
		eventStatus = KeWaitForSingleObject( &PrimarySession->Thread.WorkCompletionEvent,
											 Executive,
											 KernelMode,
											 FALSE,
											 &timeOut );

		KeClearEvent( &PrimarySession->Thread.WorkCompletionEvent );

		if (eventStatus == STATUS_TIMEOUT) {

			ASSERT( NDASFAT_UNEXPECTED );
			continue;
		}

		while (TRUE) {
	
			for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex++) {

				if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
					break;
			}

			if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
				break;

			DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: eventStatus = %d\n", eventStatus) );
			
			PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount++;

			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		}		
	}
	
	if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

		DebugTrace2( 0, Dbg2, ("PsTerminateSystemThread: DisconnectFromSecondary\n") );
		DisconnectFromSecondary( PrimarySession );
		ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
	}

	CloseOpenFiles( PrimarySession, TRUE );

	while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																	 &PrimarySession->RequestQSpinLock)) {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
		primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
												   PRIMARY_SESSION_REQUEST,
												   ListEntry );

		if (primarySessionRequest->Synchronous == TRUE)
			KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferencePrimarySessionRequest( primarySessionRequest );
	}

#if 0
	if (PrimarySession->NetdiskPartition) {

		NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager,
											   PrimarySession,
											   PrimarySession->NetdiskPartition, 
											   PrimarySession->IsLocalAddress );

		PrimarySession->NetdiskPartition = NULL;
	}
#endif

	DebugTrace2( 0, Dbg2,
				   ("PrimarySessionThreadProc: PsTerminateSystemThread PrimarySession = %p\n", 
				    PrimarySession) );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED );

	PrimarySession_Dereference( PrimarySession );

	PsTerminateSystemThread( STATUS_SUCCESS );
}
예제 #30
0
파일: parser.cpp 프로젝트: gambineri/Attic
/*-----------------------------------------------------------------
attivita'	:
    scandisce i dati letti in tplString e li scrive su outputString.
*/
int Parser::ProcTplData(char* tplString, itxString* outputString)
{
  BaseCommand*  basecmd = NULL;
	itxString     commandRetStr;	  //stringa restituita dal comando eseguito (l'allocazione spetta al comando)
	itxString     transfArg;				//argomento di una funzione trasformato dalla chiamata ricorsiva
	itxString     argStr;						//argomento grezzo del comando
	char*         cmdStart;
	char*         paux;
	int	          dataIsChar = 1; 	//flag che indica se il dato da restituire � un semplice carattere
  int           i = 0;
	int		        cmdOrd = 0;
	int		        retStrLen = 0;

  if (tplString == NULL)
    return 0;
  transfArg.SetGranularity(1024);

  try
  {
	  while (*tplString != 0 && m_ForceExit == 0 && m_ForceReturn == 0)
	  { 
		  dataIsChar=1; // Di default non mi aspetto un comando: assumo che il dato 
		                // sia un carattere da copiare in uscita cos� come �

      if (m_CurTpl->m_RecursionZero == 0)
      {
        paux = tplString;
        tplString = strchr(paux, m_StartCommandTag);
        
        if (m_CurTpl->MustExec())
        {
          if(tplString == NULL)
          {
            *outputString += paux;
            return 0; //Reached the end of template
          }
          else
          {
            *tplString = '\0';
            *outputString += paux;
            *tplString = m_StartCommandTag;
          }
        }
      }

		  // se incontro il carattere di segnalazione comando
		  if (*tplString == m_StartCommandTag)
		  {
			  // verifico la sintassi del comando e metto i puntatori su tplString
			  // all'inizio del nome del comando e dell'argomento (termino le stringhe ponendo
			  // a zero i caratteri di inizio e fine argomento); tplString viene spostato a fine comando    
        if (VerifyCmdSynt(&tplString, &cmdOrd, &argStr, &cmdStart) == 1)
			  {
          if (cmdOrd < m_BaseCount)
          {
            if (m_CurTpl->CheckStartBlock(((BaseCommand*)m_Command[cmdOrd])->m_Type, cmdStart))
		          dataIsChar = 0; // si disattiva il flag che segnala la presenza di un singolo carattere
          }

				  // esecuzione comando
				  if (m_CurTpl->MustExec())
				  {
        	  // chiamata ricorsiva: l'argomento del comando viene interpretato e restituito su
					  // transfArg; il file pointer (secondo argomento) viene passato NULL per permettere
					  // il riconoscimento del livello interno di ricorsione
            transfArg = "";
            m_CurTpl->m_RecursionZero++;
					  ProcTplData(argStr.GetBuffer(), &transfArg);
            m_CurTpl->m_RecursionZero--;

            try //Esecuzione
            {
              TimeTrace("PRIMA DEL COMANDO");              
					    DebugTrace2(DEFAULT, "Executing: %s(%s)\n", m_Command[cmdOrd]->GetName(), transfArg.GetBuffer());
              commandRetStr = m_Command[cmdOrd]->Execute(transfArg.GetBuffer());
              TimeTrace("DOPO IL COMANDO");

              m_Command[cmdOrd]->Deallocate();
            }
            catch(char* msg)
            {
					    DebugTrace2(IN_ERROR, "Propagated message: '%s'\n", msg);
              throw;
            }
            catch(...)
            {
              itxSystem sys;
					    DebugTrace2((cmdOrd < m_BaseCount ? IN_ERROR : IN_WARNING),
                          "Parser::ProcTplData: Unhandled Exception during '%s - %d' COMMAND\n",
                          m_Command[cmdOrd]->GetName(), sys.BSGetLastError());
              throw;
            }

            // si disattiva il flag che segnala la presenza di un singolo carattere
					  dataIsChar = 0;
				  }

          if (cmdOrd < m_BaseCount)
          {
            if (m_CurTpl->CheckEndBlock(((BaseCommand*)m_Command[cmdOrd])->m_Type, &tplString))
		          dataIsChar = 0; // si disattiva il flag che segnala la presenza di un singolo carattere
          }
			  }
		  }

		  if (m_CurTpl->MustExec())
		  {
			  // se il carattere letto non � il principio di un comando va scritto in output cos� come �
			  if (dataIsChar) //&& *tplString != '\x0A')
					*outputString += (char) *tplString;
			  // il dato non � un singolo carattere ma una stringa
			  // risultato dell'elaborazione di un comando
			  else
			  {
				  // si copia la stringa di ritorno del comando sullo stream di uscita
					if (!commandRetStr.IsNull() && !commandRetStr.IsEmpty())
            *outputString += commandRetStr;
				  commandRetStr = "";					
			  }
		  }

		  tplString++;
	  } // while (*tplString != 0)
  }
  catch (...)
  {
		DebugTrace2(IN_ERROR, "Parser::ProcTplData: recursion level %d.\n", m_CurTpl->m_RecursionZero);
		DebugTrace2(IN_ERROR, "Parser::ProcTplData: transfArg = '%s'\n", transfArg.GetBuffer());
		DebugTrace2(IN_ERROR, "Parser::ProcTplData: commandRetStr = '%s'\n", commandRetStr.GetBuffer());
    m_ForceExit = 1;
    throw;
  }
   
	return 0;
}