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; }
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 ); } }
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 ); }
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; }
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; }
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; }
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 }
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 ); }
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; }
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 {
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; } }
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; }
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; }
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 {
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; }
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( ¤tTime ); 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; }
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; }
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);
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; }
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; }
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; }
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; }
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; }
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; }
//----------- 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()); }
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 ); }
/*----------------------------------------------------------------- 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; }