VOID NtfsAcquireSharedGlobal ( IN PIRP_CONTEXT IrpContext ) /*++ Routine Description: This routine acquires shared access to the global resource. This routine will raise if it cannot acquire the resource and wait in the IrpContext is false. Arguments: Return Value: None. --*/ { ASSERT_IRP_CONTEXT(IrpContext); PAGED_CODE(); if (!ExAcquireResourceShared( &NtfsData.Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } return; }
BOOLEAN NtfsAcquireSharedVcb ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN RaiseOnCantWait ) /*++ Routine Description: This routine acquires shared access to the Vcb. This routine will raise if it cannot acquire the resource and wait in the IrpContext is false. Arguments: Vcb - Supplies the Vcb to acquire RaiseOnCantWait - Indicates if we should raise on an acquisition error or simply return a BOOLEAN indicating that we couldn't get the resource. Return Value: None. --*/ { ASSERT_IRP_CONTEXT(IrpContext); ASSERT_VCB(Vcb); PAGED_CODE(); if (ExAcquireResourceShared( &Vcb->Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { return TRUE; } if (RaiseOnCantWait) { NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } else { return FALSE; } }
static NTSTATUS NdasNtfsSecondaryUserFsRequest ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; ULONG FsControlCode; ULONG FsControlCodeFunction; PIO_STACK_LOCATION IrpSp; PVOLUME_DEVICE_OBJECT volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb ); BOOLEAN secondarySessionResourceAcquired = FALSE; TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB fcb; PSCB scb; PCCB ccb; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; _U8 *ndfsWinxpRequestData; LARGE_INTEGER timeOut; struct FileSystemControl fileSystemControl; PVOID inputBuffer = NULL; ULONG inputBufferLength; PVOID outputBuffer = NULL; ULONG outputBufferLength; ULONG bufferLength; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_IRP( Irp ); PAGED_CODE(); ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); IrpSp = IoGetCurrentIrpStackLocation( Irp ); FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode; FsControlCodeFunction = (FsControlCode & 0x00003FFC) >> 2; DebugTrace( +1, Dbg, ("NtfsUserFsRequest, FsControlCode = %08lx, FsControlCodeFunction = %d\n", FsControlCode, FsControlCodeFunction) ); switch ( FsControlCode ) { case FSCTL_REQUEST_OPLOCK_LEVEL_1: case FSCTL_REQUEST_OPLOCK_LEVEL_2: case FSCTL_REQUEST_BATCH_OPLOCK: case FSCTL_REQUEST_FILTER_OPLOCK: case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE: case FSCTL_OPLOCK_BREAK_NOTIFY: case FSCTL_OPBATCH_ACK_CLOSE_PENDING : case FSCTL_OPLOCK_BREAK_ACK_NO_2: ASSERT( FALSE ); //Status = NtfsOplockRequest( IrpContext, Irp ); break; case FSCTL_LOCK_VOLUME: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsLockVolume( IrpContext, Irp ); break; case FSCTL_UNLOCK_VOLUME: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsUnlockVolume( IrpContext, Irp ); break; case FSCTL_DISMOUNT_VOLUME: { #if 0 NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; #else BOOLEAN secondaryCreateResourceAcquired = FALSE; ASSERT( IS_WINDOWSVISTA_OR_LATER() ); do { BOOLEAN secondaryRecoveryResourceAcquired; DebugTrace( 0, Dbg, ("%s: IRP_MN_QUERY_REMOVE_DEVICE volDo = %p, NetdiskEnableMode = %d\n", __FUNCTION__, volDo, volDo->NetdiskEnableMode) ); secondaryRecoveryResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->RecoveryResource, FALSE ); if (secondaryRecoveryResourceAcquired == FALSE) { Status = STATUS_ACCESS_DENIED; break; } SecondaryReleaseResourceLite( IrpContext, &volDo->RecoveryResource ); ExAcquireFastMutex( &volDo->Secondary->FastMutex ); if (!volDo->Secondary->TryCloseActive) { volDo->Secondary->TryCloseActive = TRUE; ExReleaseFastMutex( &volDo->Secondary->FastMutex ); Secondary_Reference( volDo->Secondary ); //NtfsDebugTraceLevel |= DEBUG_TRACE_CLOSE; SecondaryTryClose( &IrpContext, volDo->Secondary ); //NtfsDebugTraceLevel &= ~DEBUG_TRACE_CLOSE; } else { ExReleaseFastMutex( &volDo->Secondary->FastMutex ); } if (volDo->Vcb.SecondaryCloseCount) { LARGE_INTEGER interval; // Wait all files closed interval.QuadPart = (-1 * HZ); //delay 1 seconds KeDelayExecutionThread(KernelMode, FALSE, &interval); } CcWaitForCurrentLazyWriterActivity(); secondaryCreateResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->CreateResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); if (secondaryCreateResourceAcquired == FALSE) { Status = STATUS_ACCESS_DENIED; break; } if (volDo->Vcb.SecondaryCloseCount) { LONG ccbCount; PLIST_ENTRY ccbListEntry; PVOID restartKey; PFCB fcb; ExAcquireFastMutex( &volDo->Secondary->RecoveryCcbQMutex ); for (ccbCount = 0, ccbListEntry = volDo->Secondary->RecoveryCcbQueue.Flink; ccbListEntry != &volDo->Secondary->RecoveryCcbQueue; ccbListEntry = ccbListEntry->Flink, ccbCount++); ExReleaseFastMutex( &volDo->Secondary->RecoveryCcbQMutex ); ASSERT( !IsListEmpty(&volDo->Secondary->RecoveryCcbQueue) ); ASSERT( ccbCount == volDo->Vcb.SecondaryCloseCount ); DebugTrace( 0, Dbg, ("IRP_MN_QUERY_REMOVE_DEVICE: Vcb->SecondaryCloseCount = %d, Vcb->SecondaryCleanupCount = %d, Vcb->CloseCount = %d, ccbCount = %d\n", volDo->Vcb.SecondaryCloseCount, volDo->Vcb.SecondaryCleanupCount, volDo->Vcb.CloseCount, ccbCount) ); restartKey = NULL; fcb = NdasNtfsGetNextFcbTableEntry( &volDo->Vcb, &restartKey ); ASSERT( fcb != NULL || !IsListEmpty(&volDo->Secondary->DeletedFcbQueue) ); Status = STATUS_ACCESS_DENIED; break; } else { Status = STATUS_SUCCESS; SetFlag( volDo->Secondary->Flags, SECONDARY_FLAG_DISMOUNTING ); } } while(0); if (Status != STATUS_SUCCESS) { if (secondaryCreateResourceAcquired) { SecondaryReleaseResourceLite( IrpContext, &volDo->CreateResource ); secondaryCreateResourceAcquired = FALSE; } NtfsCompleteRequest( IrpContext, Irp, Status ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; } Status = NtfsDismountVolume( IrpContext, Irp ); SecondaryReleaseResourceLite( IrpContext, &volDo->CreateResource ); return Status; #endif break; } case FSCTL_IS_VOLUME_MOUNTED: Status = NtfsIsVolumeMounted( IrpContext, Irp ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; break; case FSCTL_MARK_VOLUME_DIRTY: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsDirtyVolume( IrpContext, Irp ); break; case FSCTL_IS_PATHNAME_VALID: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_SUCCESS ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; break; case FSCTL_QUERY_RETRIEVAL_POINTERS: Status = NtfsQueryRetrievalPointers( IrpContext, Irp ); break; case FSCTL_GET_COMPRESSION: //NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST ); //DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); //return Status; Status = NtfsGetCompression( IrpContext, Irp ); break; case FSCTL_SET_COMPRESSION: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; Status = NtfsSetCompression( IrpContext, Irp ); break; case FSCTL_MARK_AS_SYSTEM_HIVE: Status = NtfsMarkAsSystemHive( IrpContext, Irp ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; break; case FSCTL_FILESYSTEM_GET_STATISTICS: Status = NtfsGetStatistics( IrpContext, Irp ); break; case FSCTL_GET_NTFS_VOLUME_DATA: Status = NtfsGetVolumeData( IrpContext, Irp ); break; case FSCTL_GET_VOLUME_BITMAP: Status = NtfsGetVolumeBitmap( IrpContext, Irp ); break; case FSCTL_GET_RETRIEVAL_POINTERS: Status = NtfsGetRetrievalPointers( IrpContext, Irp ); break; case FSCTL_GET_NTFS_FILE_RECORD: Status = NtfsGetMftRecord( IrpContext, Irp ); break; case FSCTL_MOVE_FILE: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; Status = NtfsDefragFile( IrpContext, Irp ); if (Status == STATUS_SUCCESS) { PMOVE_FILE_DATA moveFileData = IrpContext->InputBuffer; PFILE_OBJECT moveFileObject; Status = ObReferenceObjectByHandle( moveFileData->FileHandle, FILE_READ_DATA, 0, KernelMode, &moveFileObject, NULL ); if (Status != STATUS_SUCCESS) { break; } ObDereferenceObject( moveFileObject ); if (!IS_SECONDARY_FILEOBJECT(moveFileObject)) { ASSERT( FALSE ); Status = STATUS_INVALID_PARAMETER; } } if (Status != STATUS_SUCCESS) DebugTrace( 0, Dbg2, ("NtfsDefragFile: status = %x\n", Status) ); break; case FSCTL_IS_VOLUME_DIRTY: Status = NtfsIsVolumeDirty( IrpContext, Irp ); break; case FSCTL_ALLOW_EXTENDED_DASD_IO: Status = NtfsSetExtendedDasdIo( IrpContext, Irp ); break; case FSCTL_SET_REPARSE_POINT: Status = NtfsSetReparsePoint( IrpContext, Irp ); break; case FSCTL_GET_REPARSE_POINT: Status = NtfsGetReparsePoint( IrpContext, Irp ); break; case FSCTL_DELETE_REPARSE_POINT: Status = NtfsDeleteReparsePoint( IrpContext, Irp ); break; case FSCTL_SET_OBJECT_ID: Status = NtfsSetObjectId( IrpContext, Irp ); // In ObjIdSup.c break; case FSCTL_GET_OBJECT_ID: Status = NtfsGetObjectId( IrpContext, Irp ); // In ObjIdSup.c break; case FSCTL_DELETE_OBJECT_ID: Status = NtfsDeleteObjectId( IrpContext, Irp ); // In ObjIdSup.c break; case FSCTL_SET_OBJECT_ID_EXTENDED: Status = NtfsSetObjectIdExtendedInfo( IrpContext, Irp ); // In ObjIdSup.c break; case FSCTL_CREATE_OR_GET_OBJECT_ID: Status = NtfsCreateOrGetObjectId( IrpContext, Irp ); if (IrpSp->Parameters.FileSystemControl.InputBufferLength) IrpContext->InputBuffer = Irp->AssociatedIrp.SystemBuffer; else IrpContext->InputBuffer = NULL; break; case FSCTL_READ_USN_JOURNAL: Status = NtfsReadUsnJournal( IrpContext, Irp, TRUE ); // In UsnSup.c break; case FSCTL_CREATE_USN_JOURNAL: Status = NtfsCreateUsnJournal( IrpContext, Irp ); break; case FSCTL_ENUM_USN_DATA: Status = NtfsReadFileRecordUsnData( IrpContext, Irp ); break; case FSCTL_READ_FILE_USN_DATA: Status = NtfsReadFileUsnData( IrpContext, Irp ); break; case FSCTL_WRITE_USN_CLOSE_RECORD: Status = NtfsWriteUsnCloseRecord( IrpContext, Irp ); break; case FSCTL_QUERY_USN_JOURNAL: Status = NtfsQueryUsnJournal( IrpContext, Irp ); break; case FSCTL_DELETE_USN_JOURNAL: Status = NtfsDeleteUsnJournal( IrpContext, Irp ); break; case FSCTL_MARK_HANDLE: Status = NtfsMarkHandle( IrpContext, Irp ); if (Status == STATUS_SUCCESS) { PMARK_HANDLE_INFO markHandleInfo = inputBuffer; PFILE_OBJECT volumeFileObject; Status = ObReferenceObjectByHandle( markHandleInfo->VolumeHandle, FILE_READ_DATA, 0, KernelMode, &volumeFileObject, NULL ); if (Status != STATUS_SUCCESS) { break; } ObDereferenceObject( volumeFileObject ); if (!IS_SECONDARY_FILEOBJECT(volumeFileObject)) { Status = STATUS_INVALID_PARAMETER; } } break; case FSCTL_SECURITY_ID_CHECK: Status = NtfsBulkSecurityIdCheck( IrpContext, Irp ); break; case FSCTL_FIND_FILES_BY_SID: Status = NtfsFindFilesOwnedBySid( IrpContext, Irp ); break; case FSCTL_SET_SPARSE : NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsSetSparse( IrpContext, Irp ); break; case FSCTL_SET_ZERO_DATA : NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; Status = NtfsZeroRange( IrpContext, Irp ); break; case FSCTL_QUERY_ALLOCATED_RANGES : Status = NtfsQueryAllocatedRanges( IrpContext, Irp ); break; case FSCTL_ENCRYPTION_FSCTL_IO : NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsEncryptionFsctl( IrpContext, Irp ); break; case FSCTL_SET_ENCRYPTION : NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsSetEncryption( IrpContext, Irp ); break; case FSCTL_READ_RAW_ENCRYPTED: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsReadRawEncrypted( IrpContext, Irp ); break; case FSCTL_WRITE_RAW_ENCRYPTED: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsWriteRawEncrypted( IrpContext, Irp ); break; case FSCTL_EXTEND_VOLUME: NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; //Status = NtfsExtendVolume( IrpContext, Irp ); break; case FSCTL_READ_FROM_PLEX: Status = NtfsReadFromPlex( IrpContext, Irp ); DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; break; case FSCTL_FILE_PREFETCH: Status = NtfsPrefetchFile( IrpContext, Irp ); break; default : DebugTrace( 0, DEBUG_TRACE_ALL, ("NtfsUserFsRequest: Invalid control code FsControlCode = %08lx, FsControlCodeFunction = %d\n", FsControlCode, FsControlCodeFunction) ); NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST ); break; } ASSERT( !ExIsResourceAcquiredSharedLite(&volDo->Vcb.Resource) ); if (Status != STATUS_SUCCESS) { DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) ); return Status; } if (IrpSp->Parameters.FileSystemControl.InputBufferLength >= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize || IrpSp->Parameters.FileSystemControl.OutputBufferLength >= volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize) { ASSERT( FALSE ); NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST ); 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->State, IRP_CONTEXT_STATE_WAIT)) { return NtfsPostRequest( IrpContext, Irp ); } try { secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->SessionResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) { PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } ASSERT( IS_SECONDARY_FILEOBJECT(IrpSp->FileObject) ); typeOfOpen = NtfsDecodeFileObject( IrpContext, IrpSp->FileObject, &vcb, &fcb, &scb, &ccb, TRUE ); if (FlagOn(ccb->NdasNtfsFlags, ND_NTFS_CCB_FLAG_UNOPENED)) { ASSERT( FlagOn(ccb->NdasNtfsFlags, ND_NTFS_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) { 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 (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 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 = (_U8 *)(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 = -NDASNTFS_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 ); DebugTrace( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; Status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status; Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information; if (FsControlCode == FSCTL_GET_NTFS_VOLUME_DATA && Status != STATUS_SUCCESS) DebugTrace( 0, Dbg2, ("FSCTL_GET_NTFS_VOLUME_DATA: Status = %x, Irp->IoStatus.Information = %d\n", Status, Irp->IoStatus.Information) ); if (secondaryRequest->NdfsReplyHeader.MessageSize - 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, (_U8 *)(ndfsWinxpReplytHeader+1), Irp->IoStatus.Information ); } if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE && Status != STATUS_SUCCESS) DebugTrace( 0, Dbg2, ("NtfsDefragFile: status = %x\n", Status) ); 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 && ndfsWinxpReplytHeader->FileInformationSet && ndfsWinxpReplytHeader->AllocationSize) { PNDFS_NTFS_MCB_ENTRY mcbEntry; ULONG index; VCN testVcn; SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ACQUIRE_PAGING ); NtfsAcquireFcbWithPaging( IrpContext, moveFcb, 0 ); NtfsAcquireNtfsMcbMutex( &moveScb->Mcb ); mcbEntry = (PNDFS_NTFS_MCB_ENTRY)( ndfsWinxpReplytHeader+1 ); if (moveScb->Header.AllocationSize.QuadPart) { NtfsRemoveNtfsMcbEntry( &moveScb->Mcb, 0, 0xFFFFFFFF ); } for (index=0, testVcn=0; index < ndfsWinxpReplytHeader->NumberOfMcbEntry; index++) { ASSERT( mcbEntry[index].Vcn == testVcn ); testVcn += (LONGLONG)mcbEntry[index].ClusterCount; NtfsAddNtfsMcbEntry( &moveScb->Mcb, mcbEntry[index].Vcn, mcbEntry[index].Lcn, (LONGLONG)mcbEntry[index].ClusterCount, TRUE ); } ASSERT( LlBytesFromClusters(vcb, testVcn) == ndfsWinxpReplytHeader->AllocationSize ); if (moveScb->Header.AllocationSize.QuadPart != ndfsWinxpReplytHeader->AllocationSize) SetFlag( moveScb->ScbState, SCB_STATE_TRUNCATE_ON_CLOSE ); moveScb->Header.FileSize.QuadPart = ndfsWinxpReplytHeader->FileSize; moveScb->Header.AllocationSize.QuadPart = ndfsWinxpReplytHeader->AllocationSize; ASSERT( moveScb->Header.AllocationSize.QuadPart >= moveScb->Header.FileSize.QuadPart ); if (moveFileObject->SectionObjectPointer->DataSectionObject != NULL && moveFileObject->PrivateCacheMap == NULL) { CcInitializeCacheMap( moveFileObject, (PCC_FILE_SIZES)&moveScb->Header.AllocationSize, FALSE, &NtfsData.CacheManagerCallbacks, moveScb ); } if (CcIsFileCached(moveFileObject)) { NtfsSetBothCacheSizes( moveFileObject, (PCC_FILE_SIZES)&scb->Header.AllocationSize, moveScb ); } NtfsReleaseNtfsMcbMutex( &moveScb->Mcb ); NtfsReleaseFcb( IrpContext, moveFcb ); } } try_exit: NOTHING; } finally { if (secondarySessionResourceAcquired == TRUE) { SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource ); } if (secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); } NtfsCompleteRequest( IrpContext, Irp, Status ); return Status; }
NTSTATUS NdNtfsSecondaryCommonQueryEa ( 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; TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB fcb; PSCB scb; PCCB ccb; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; _U8 *ndfsWinxpRequestData; LARGE_INTEGER timeOut; struct QueryEa queryEa; PVOID inputBuffer; ULONG inputBufferLength; PVOID outputBuffer = NtfsMapUserBuffer (Irp ); ULONG outputBufferLength; ULONG bufferLength; ULONG returnedDataSize; ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); if (!FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT )) { return NtfsPostRequest( IrpContext, Irp ); } if(volDo->Secondary == NULL) { status = Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; Irp->IoStatus.Information = 0; return status; } try { secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->Secondary->SessionResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) { PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } typeOfOpen = NtfsDecodeFileObject( IrpContext, fileObject, &vcb, &fcb, &scb, &ccb, TRUE ); if(FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_UNOPENED)) { ASSERT( FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_CORRUPTED) ); try_return( status = STATUS_FILE_CORRUPT_ERROR ); } queryEa.EaIndex = irpSp->Parameters.QueryEa.EaIndex; queryEa.EaList = irpSp->Parameters.QueryEa.EaList; queryEa.EaListLength = irpSp->Parameters.QueryEa.EaListLength; queryEa.Length = irpSp->Parameters.QueryEa.Length; inputBuffer = queryEa.EaList; outputBufferLength = queryEa.Length; if(inputBuffer != NULL) { PFILE_GET_EA_INFORMATION fileGetEa = (PFILE_GET_EA_INFORMATION)inputBuffer; inputBufferLength = 0; while(fileGetEa->NextEntryOffset) { inputBufferLength += fileGetEa->NextEntryOffset; fileGetEa = (PFILE_GET_EA_INFORMATION)((_U8 *)fileGetEa + fileGetEa->NextEntryOffset); } inputBufferLength += (sizeof(FILE_GET_EA_INFORMATION) - sizeof(CHAR) + fileGetEa->EaNameLength); } else inputBufferLength = 0; DebugTrace( 0, Dbg, ("NdNtfsSecondaryCommonQueryEa: BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED) = %d queryEa.EaIndex = %d queryEa.EaList = %p queryEa.Length = %d, inputBufferLength = %d\n", BooleanFlagOn(irpSp->Flags, SL_INDEX_SPECIFIED), queryEa.EaIndex, queryEa.EaList, queryEa.EaListLength, inputBufferLength) ); bufferLength = (inputBufferLength >= outputBufferLength) ? inputBufferLength : outputBufferLength; ASSERT( bufferLength <= volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize ); secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, IRP_MJ_QUERY_EA, bufferLength ); if(secondaryRequest == NULL) { 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_QUERY_EA, 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->QueryEa.Length = queryEa.Length; ndfsWinxpRequestHeader->QueryEa.EaIndex = queryEa.EaIndex; ndfsWinxpRequestHeader->QueryEa.EaListLength = queryEa.EaListLength; ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1); RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength ); secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE; QueueingSecondaryRequest( volDo->Secondary, secondaryRequest ); timeOut.QuadPart = -NDNTFS_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 ); DebugTrace( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } 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) { PFILE_FULL_EA_INFORMATION fileFullEa = (PFILE_FULL_EA_INFORMATION)(ndfsWinxpReplytHeader+1); while(fileFullEa->NextEntryOffset) { DebugTrace( 0, Dbg, ("getEa scb->FullPathName = %Z, fileFullea->EaName = %ws\n", &ccb->Lcb->ExactCaseLink.LinkName, &fileFullEa->EaName[0]) ); fileFullEa = (PFILE_FULL_EA_INFORMATION)((_U8 *)fileFullEa + fileFullEa->NextEntryOffset); } DebugTrace( 0, Dbg, ("getEa scb->FullPathName = %Z, fileFullea->EaName = %ws\n", &ccb->Lcb->ExactCaseLink.LinkName, &fileFullEa->EaName[0]) ); ASSERT( returnedDataSize <= ADD_ALIGN8(queryEa.Length) ); ASSERT( outputBuffer ); RtlCopyMemory( outputBuffer, (_U8 *)(ndfsWinxpReplytHeader+1), (returnedDataSize < queryEa.Length) ? returnedDataSize : queryEa.Length ); } try_exit: NOTHING; } finally { if( secondarySessionResourceAcquired == TRUE ) { SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource ); } if(secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); } return status; }
NTSTATUS NdNtfsSecondaryCommonSetSecurityInfo ( 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; TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB fcb; PSCB scb; PCCB ccb; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; _U8 *ndfsWinxpRequestData; LARGE_INTEGER timeOut; struct SetSecurity setSecurity; PVOID inputBuffer = NULL; ULONG inputBufferLength = 0; ULONG securityLength = 0; ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); if(volDo->Secondary == NULL) { status = Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; Irp->IoStatus.Information = 0; return status; } try { secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->Secondary->SessionResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) { PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } typeOfOpen = NtfsDecodeFileObject( IrpContext, fileObject, &vcb, &fcb, &scb, &ccb, TRUE ); if(FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_UNOPENED)) { ASSERT( FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_CORRUPTED) ); try_return( status = STATUS_FILE_CORRUPT_ERROR ); } setSecurity.SecurityDescriptor = irpSp->Parameters.SetSecurity.SecurityDescriptor; setSecurity.SecurityInformation = irpSp->Parameters.SetSecurity.SecurityInformation; status = SeQuerySecurityDescriptorInfo( &setSecurity.SecurityInformation, NULL, &securityLength, &setSecurity.SecurityDescriptor ); DebugTrace( 0, Dbg, ("NdNtfsSecondaryCommonSetSecurityInfo: The length of the security desc:%lu\n",securityLength) ); if( (!securityLength && status == STATUS_BUFFER_TOO_SMALL ) || (securityLength && status != STATUS_BUFFER_TOO_SMALL )) { ASSERT(NDASNTFS_UNEXPECTED); NtfsRaiseStatus( IrpContext, status, NULL, NULL ); } inputBufferLength = securityLength; secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, IRP_MJ_SET_SECURITY, inputBufferLength ); if(secondaryRequest == NULL) { 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_SET_SECURITY, 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->SetSecurity.Length = inputBufferLength; ndfsWinxpRequestHeader->SetSecurity.SecurityInformation = setSecurity.SecurityInformation; ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1); status = SeQuerySecurityDescriptorInfo( &setSecurity.SecurityInformation, (PSECURITY_DESCRIPTOR)ndfsWinxpRequestData, &securityLength, &setSecurity.SecurityDescriptor ); if(status != STATUS_SUCCESS) { ASSERT(NDASNTFS_UNEXPECTED); DereferenceSecondaryRequest( secondaryRequest ); secondaryRequest = NULL; try_return( status ); } secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE; QueueingSecondaryRequest( volDo->Secondary, secondaryRequest ); timeOut.QuadPart = -NDNTFS_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 ); DebugTrace( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status; Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information; try_exit: NOTHING; } finally { if( secondarySessionResourceAcquired == TRUE ) { SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource ); } if(secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); } return status; }
NTSTATUS NdNtfsSecondaryCommonQueryVolumeInfo ( 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; TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB fcb; PSCB scb; PCCB ccb; PSECONDARY_REQUEST secondaryRequest = NULL; PNDFS_REQUEST_HEADER ndfsRequestHeader; PNDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PNDFS_WINXP_REPLY_HEADER ndfsWinxpReplytHeader; LARGE_INTEGER timeOut; struct QueryVolume queryVolume; PVOID inputBuffer = NULL; ULONG inputBufferLength = 0; PVOID outputBuffer = Irp->AssociatedIrp.SystemBuffer; ULONG outputBufferLength; ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); if(volDo->Secondary == NULL) { status = Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; Irp->IoStatus.Information = 0; return status; } try { secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->Secondary->SessionResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) { PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } typeOfOpen = NtfsDecodeFileObject( IrpContext, fileObject, &vcb, &fcb, &scb, &ccb, TRUE ); if(FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_UNOPENED)) { ASSERT( FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_CORRUPTED) ); try_return( status = STATUS_FILE_CORRUPT_ERROR ); } queryVolume.FsInformationClass = irpSp->Parameters.QueryVolume.FsInformationClass; queryVolume.Length = irpSp->Parameters.QueryVolume.Length; outputBufferLength = queryVolume.Length; secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, IRP_MJ_QUERY_VOLUME_INFORMATION, outputBufferLength ); if(secondaryRequest == NULL) { 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_QUERY_VOLUME_INFORMATION, 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->QueryVolume.Length = outputBufferLength; ndfsWinxpRequestHeader->QueryVolume.FsInformationClass = queryVolume.FsInformationClass; secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE; QueueingSecondaryRequest( volDo->Secondary, secondaryRequest ); timeOut.QuadPart = -NDNTFS_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 ); } if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) { if (IrpContext->OriginatingIrp) PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp ); DebugTrace( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status; Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information; if (status != STATUS_SUCCESS) DebugTrace( 0, Dbg, ("Status = %x, Irp->IoStatus.Information = %d, queryVolume.FsInformationClass =%d\n", status, Irp->IoStatus.Information, queryVolume.FsInformationClass) ); if(secondaryRequest->NdfsReplyHeader.MessageSize - 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, (_U8 *)(ndfsWinxpReplytHeader+1), Irp->IoStatus.Information ); } else ASSERT( ndfsWinxpReplytHeader->Information == 0 ); try_exit: NOTHING; } finally { if( secondarySessionResourceAcquired == TRUE ) { SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource ); } if(secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); } return status; }
NTSTATUS SecondaryRecoverySessionStart ( IN PSECONDARY Secondary, IN PIRP_CONTEXT IrpContext ) { NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; LARGE_INTEGER timeOut; if (Secondary->RecoveryThreadHandle) return STATUS_SUCCESS; ASSERT( ExIsResourceAcquiredExclusiveLite(&Secondary->VolDo->RecoveryResource) && ExIsResourceAcquiredExclusiveLite(&Secondary->VolDo->Resource) ); ASSERT( NtfsIsTopLevelRequest(IrpContext) || NtfsIsTopLevelNtfs( IrpContext) && NtfsGetTopLevelContext()->SavedTopLevelIrp == (PIRP)FSRTL_FSP_TOP_LEVEL_IRP || FlagOn(IrpContext->State, IRP_CONTEXT_STATE_IN_FSP) ); if (IrpContext->OriginatingIrp) PrintIrp( Dbg2, "SecondaryRecoverySessionStart", NULL, IrpContext->OriginatingIrp ); 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" ); NtfsRaiseStatus( IrpContext, STATUS_TOO_LATE, NULL, NULL ); } InitializeObjectAttributes( &objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL ); status = PsCreateSystemThread( &Secondary->RecoveryThreadHandle, THREAD_ALL_ACCESS, &objectAttributes, NULL, NULL, SecondaryRecoveryThreadProc, Secondary ); if (!NT_SUCCESS(status)) { return status; } timeOut.QuadPart = -NDASNTFS_TIME_OUT; status = KeWaitForSingleObject( &Secondary->RecoveryReadyEvent, Executive, KernelMode, FALSE, &timeOut ); if (status != STATUS_SUCCESS) { return status; } KeClearEvent( &Secondary->RecoveryReadyEvent ); if (IrpContext->OriginatingIrp) PrintIrp( Dbg2, "SecondaryRecoverySessionStart returned", NULL, IrpContext->OriginatingIrp ); return status; }
NTSTATUS NtfsFsdPnp ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine implements the FSD entry point for plug and play (Pnp). 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 = STATUS_SUCCESS; TOP_LEVEL_CONTEXT TopLevelContext; PTOP_LEVEL_CONTEXT ThreadTopLevelContext; PIRP_CONTEXT IrpContext = NULL; #if __NDAS_NTFS__ if ((PVOID)NdasNtfsControlDeviceObject == VolumeDeviceObject) { Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_DISK_INCREMENT ); return Status; } #endif ASSERT_IRP( Irp ); UNREFERENCED_PARAMETER( VolumeDeviceObject ); #ifdef NTFSPNPDBG if (NtfsDebugTraceLevel != 0) SetFlag( NtfsDebugTraceLevel, DEBUG_TRACE_PNP ); #endif DebugTrace( +1, Dbg, ("NtfsFsdPnp\n") ); // // Call the common Pnp routine // FsRtlEnterFileSystem(); switch( IoGetCurrentIrpStackLocation( Irp )->MinorFunction ) { case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_SURPRISE_REMOVAL: ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, FALSE, FALSE ); break; default: ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, TRUE, TRUE ); break; } do { try { // // We are either initiating this request or retrying it. // if (IrpContext == NULL) { // // Allocate and initialize the Irp. // NtfsInitializeIrpContext( Irp, TRUE, &IrpContext ); // // Initialize the thread top level structure, if needed. // NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext ); } else if (Status == STATUS_LOG_FILE_FULL) { NtfsCheckpointForLogFileFull( IrpContext ); } #if __NDAS_NTFS_SECONDARY__ if (!FlagOn(VolumeDeviceObject->NetdiskPartitionInformation.Flags, NETDISK_PARTITION_INFORMATION_FLAG_INDIRECT) && VolumeDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY) { if ((IrpContext->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE || IrpContext->MinorFunction == IRP_MN_SURPRISE_REMOVAL || IrpContext->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE)) { BOOLEAN secondaryResourceAcquired = FALSE; BOOLEAN secondaryRecoveryResourceAcquired = FALSE; ASSERT( NtfsIsTopLevelRequest(IrpContext) ); Status = STATUS_SUCCESS; for (;;) { NDAS_ASSERT( secondaryRecoveryResourceAcquired == FALSE ); NDAS_ASSERT( secondaryResourceAcquired == FALSE ); if (!FlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT)) { Status = NtfsPostRequest( IrpContext, Irp ); break; } if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) { secondaryRecoveryResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &VolumeDeviceObject->RecoveryResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_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->State, IRP_CONTEXT_STATE_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->State, IRP_CONTEXT_STATE_WAIT) ); NDAS_ASSERT( secondaryResourceAcquired == TRUE ); break; } if (Status == STATUS_SUCCESS) { try { if (VolumeDeviceObject->NetdiskEnableMode != NETDISK_SECONDARY) { NDAS_ASSERT( VolumeDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT ); Status = NtfsCommonPnp( IrpContext, &Irp ); } finally { ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) ); SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource ); } } } else { if (VolumeDeviceObject->NetdiskEnableMode != NETDISK_SECONDARY) { NDAS_ASSERT( VolumeDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT ); Status = NtfsCommonPnp( IrpContext, &Irp ); } } else { Status = NtfsCommonPnp( IrpContext, &Irp ); } #else Status = NtfsCommonPnp( IrpContext, &Irp ); #endif break; } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {
VOID NtfsAcquireSharedFcb ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PSCB Scb OPTIONAL, IN BOOLEAN NoDeleteCheck ) /*++ Routine Description: This routine acquires shared access to the Fcb. This routine will raise if it cannot acquire the resource and wait in the IrpContext is false. Arguments: Fcb - Supplies the Fcb to acquire Scb - This is the Scb for which we are acquiring the Fcb NoDeleteCheck - If TRUE then acquire the file even if it has been deleted. Return Value: None. --*/ { NTSTATUS Status; ASSERT_IRP_CONTEXT(IrpContext); ASSERT_FCB(Fcb); Status = STATUS_CANT_WAIT; if (ExAcquireResourceShared( Fcb->Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) { // // The link count should be non-zero or the file has been // deleted. // if (NoDeleteCheck || (!FlagOn( Fcb->FcbState, FCB_STATE_FILE_DELETED ) && (!ARGUMENT_PRESENT( Scb ) || !FlagOn( Scb->ScbState, SCB_STATE_ATTRIBUTE_DELETED )))) { // // It's possible that this is a recursive shared aquisition of an // Fcb we own exclusively at the top level. In that case we // need to bump the acquisition count. // if (Fcb->ExclusiveFcbLinks.Flink != NULL) { Fcb->BaseExclusiveCount += 1; } return; } // // We need to release the Fcb and remember the status code. // ExReleaseResource( Fcb->Resource ); Status = STATUS_FILE_DELETED; } NtfsRaiseStatus( IrpContext, Status, NULL, NULL ); }
BOOLEAN NtfsAcquireExclusiveFcb ( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PSCB Scb OPTIONAL, IN BOOLEAN NoDeleteCheck, IN BOOLEAN DontWait ) /*++ Routine Description: This routine acquires exclusive access to the Fcb. This routine will raise if it cannot acquire the resource and wait in the IrpContext is false. Arguments: Fcb - Supplies the Fcb to acquire Scb - This is the Scb for which we are acquiring the Fcb NoDeleteCheck - If TRUE, we don't do any check for deleted files but always acquire the Fcb. DontWait - If TRUE this overrides the wait value in the IrpContext. We won't wait for the resource and return whether the resource was acquired. Return Value: BOOLEAN - TRUE if acquired. FALSE otherwise. --*/ { NTSTATUS Status; BOOLEAN Wait; ASSERT_IRP_CONTEXT(IrpContext); ASSERT_FCB(Fcb); PAGED_CODE(); Status = STATUS_CANT_WAIT; if (DontWait || !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { Wait = FALSE; } else { Wait = TRUE; } if (ExAcquireResourceExclusive( Fcb->Resource, Wait )) { // // The link count should be non-zero or the file has been // deleted. We allow deleted files to be acquired for close and // also allow them to be acquired recursively in case we // acquire them a second time after marking them deleted (i.e. rename) // if (NoDeleteCheck || (IrpContext->MajorFunction == IRP_MJ_CLOSE) || (IrpContext->MajorFunction == IRP_MJ_CREATE) || (!FlagOn( Fcb->FcbState, FCB_STATE_FILE_DELETED ) && (!ARGUMENT_PRESENT( Scb ) || !FlagOn( Scb->ScbState, SCB_STATE_ATTRIBUTE_DELETED )))) { // // Put Fcb in the exclusive Fcb list for this IrpContext, // excluding the bitmap for the volume, since we do not need // to modify its file record and do not want unnecessary // serialization/deadlock problems. // if ((Fcb->Vcb->BitmapScb == NULL) || (Fcb->Vcb->BitmapScb->Fcb != Fcb)) { // // We need to check if this Fcb is already in an // exclusive list. If it is then we want to attach // the current IrpContext to the IrpContext holding // this Fcb. // if (Fcb->ExclusiveFcbLinks.Flink == NULL) { ASSERT( Fcb->BaseExclusiveCount == 0 ); InsertTailList( &IrpContext->ExclusiveFcbList, &Fcb->ExclusiveFcbLinks ); } Fcb->BaseExclusiveCount += 1; } return TRUE; } // // We need to release the Fcb and remember the status code. // ExReleaseResource( Fcb->Resource ); Status = STATUS_FILE_DELETED; } else if (DontWait) { return FALSE; } NtfsRaiseStatus( IrpContext, Status, NULL, NULL ); }
VOID NtfsPreparePinWriteStream ( IN PIRP_CONTEXT IrpContext, IN PSCB Scb, IN LONGLONG FileOffset, IN ULONG Length, IN BOOLEAN Zero, OUT PVOID *Bcb, OUT PVOID *Buffer ) /*++ Routine Description: Arguments: Return Value: --*/ { ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_SCB( Scb ); PAGED_CODE(); DebugTrace( +1, Dbg, ("NtfsPreparePinWriteStream\n") ); DebugTrace( 0, Dbg, ("Scb = %08lx\n", Scb) ); DebugTrace( 0, Dbg, ("FileOffset = %016I64x\n", FileOffset) ); DebugTrace( 0, Dbg, ("Length = %08lx\n", Length) ); // // The file object should already exist in the Scb. // ASSERT( Scb->FileObject != NULL ); // // If we are trying to go beyond the end of the allocation, assume // we have some corruption. // if ((FileOffset + Length) > Scb->Header.AllocationSize.QuadPart) { NtfsRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Scb->Fcb ); } // // Call the cache manager to do it. This call may raise, or // will return FALSE if waiting is required. // if (!CcPreparePinWrite( Scb->FileObject, (PLARGE_INTEGER)&FileOffset, Length, Zero, FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ), Bcb, Buffer )) { ASSERT( !FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT )); // // Could not pin the data without waiting (cache miss). // NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } #ifdef MAPCOUNT_DBG IrpContext->MapCount++; #endif DebugTrace( 0, Dbg, ("Bcb -> %08lx\n", *Bcb) ); DebugTrace( 0, Dbg, ("Buffer -> %08lx\n", *Buffer) ); DebugTrace( -1, Dbg, ("NtfsPreparePinWriteStream -> VOID\n") ); return; }
VOID NtfsPinStream ( IN PIRP_CONTEXT IrpContext, IN PSCB Scb, IN LONGLONG FileOffset, IN ULONG Length, OUT PVOID *Bcb, OUT PVOID *Buffer ) /*++ Routine Description: This routine is called to pin a range of bytes within the stream file for an Scb. The allowed range to pin is bounded by the allocation size for the Scb. This operation is only valid on a non-resident Scb. TEMPCODE - The following need to be resolved for this routine. - Can the caller specify either an empty range or an invalid range. In that case we need to able to return the actual length of the pinned range. Arguments: Scb - This is the Scb for the operation. FileOffset - This is the offset within the Scb where the data is to be pinned. Length - This is the number of bytes to pin. Bcb - Returns a pointer to the Bcb for this range of bytes. Buffer - Returns a pointer to the range of bytes pinned in memory. Return Value: None. --*/ { NTSTATUS OldStatus = IrpContext->ExceptionStatus; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_SCB( Scb ); ASSERT( Length != 0 ); PAGED_CODE(); DebugTrace( +1, Dbg, ("NtfsPinStream\n") ); DebugTrace( 0, Dbg, ("Scb = %08lx\n", Scb) ); DebugTrace( 0, Dbg, ("FileOffset = %016I64x\n", FileOffset) ); DebugTrace( 0, Dbg, ("Length = %08lx\n", Length) ); // // The file object should already exist in the Scb. // ASSERT( Scb->FileObject != NULL ); // // If we are trying to go beyond the end of the allocation, assume // we have some corruption. // if ((FileOffset + Length) > Scb->Header.AllocationSize.QuadPart) { NtfsRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Scb->Fcb ); } // // Call the cache manager to map the data. This call may raise, or // will return FALSE if waiting is required. // if (FlagOn( Scb->ScbPersist, SCB_PERSIST_USN_JOURNAL )) { FileOffset -= Scb->Vcb->UsnCacheBias; } if (!CcPinRead( Scb->FileObject, (PLARGE_INTEGER)&FileOffset, Length, FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ), Bcb, Buffer )) { ASSERT( !FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT )); // // Could not pin the data without waiting (cache miss). // NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } // // We don't want to propagate wether or not we hit eof. Its assumed the code pinning is // already filesize synchronized // if (IrpContext->ExceptionStatus == STATUS_END_OF_FILE) { IrpContext->ExceptionStatus = OldStatus; } #ifdef MAPCOUNT_DBG IrpContext->MapCount++; #endif DebugTrace( 0, Dbg, ("Bcb -> %08lx\n", *Bcb) ); DebugTrace( 0, Dbg, ("Buffer -> %08lx\n", *Buffer) ); DebugTrace( -1, Dbg, ("NtfsMapStream -> VOID\n") ); return; }
VOID NtfsPinMappedData ( IN PIRP_CONTEXT IrpContext, IN PSCB Scb, IN LONGLONG FileOffset, IN ULONG Length, IN OUT PVOID *Bcb ) /*++ Routine Description: This routine is called to pin a previously mapped range of bytes within the stream file for an Scb, for the purpose of subsequently modifying this byte range. The allowed range to map is bounded by the allocation size for the Scb. This operation is only valid on a non-resident Scb. The data is guaranteed to stay at the same virtual address as previously returned from NtfsMapStream. TEMPCODE - The following need to be resolved for this routine. - Can the caller specify either an empty range or an invalid range. In that case we need to able to return the actual length of the mapped range. Arguments: Scb - This is the Scb for the operation. FileOffset - This is the offset within the Scb where the data is to be pinned. Length - This is the number of bytes to pin. Bcb - Returns a pointer to the Bcb for this range of bytes. Return Value: None. --*/ { ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_SCB( Scb ); ASSERT( Length != 0 ); PAGED_CODE(); DebugTrace( +1, Dbg, ("NtfsPinMappedData\n") ); DebugTrace( 0, Dbg, ("Scb = %08lx\n", Scb) ); DebugTrace( 0, Dbg, ("FileOffset = %016I64x\n", FileOffset) ); DebugTrace( 0, Dbg, ("Length = %08lx\n", Length) ); // // The file object should already exist in the Scb. // ASSERT( Scb->FileObject != NULL ); // // If we are trying to go beyond the end of the allocation, assume // we have some corruption. // if ((FileOffset + Length) > Scb->Header.AllocationSize.QuadPart) { NtfsRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Scb->Fcb ); } // // Call the cache manager to map the data. This call may raise, but // will never return an error (including CANT_WAIT). // if (!CcPinMappedData( Scb->FileObject, (PLARGE_INTEGER)&FileOffset, Length, FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ), Bcb )) { NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } DebugTrace( -1, Dbg, ("NtfsMapStream -> VOID\n") ); return; }
VOID NtfsMapStream ( IN PIRP_CONTEXT IrpContext, IN PSCB Scb, IN LONGLONG FileOffset, IN ULONG Length, OUT PVOID *Bcb, OUT PVOID *Buffer ) /*++ Routine Description: This routine is called to map a range of bytes within the stream file for an Scb. The allowed range to map is bounded by the allocation size for the Scb. This operation is only valid on a non-resident Scb. TEMPCODE - The following need to be resolved for this routine. - Can the caller specify either an empty range or an invalid range. In that case we need to able to return the actual length of the mapped range. Arguments: Scb - This is the Scb for the operation. FileOffset - This is the offset within the Scb where the data is to be pinned. Length - This is the number of bytes to pin. Bcb - Returns a pointer to the Bcb for this range of bytes. Buffer - Returns a pointer to the range of bytes. We can fault them in by touching them, but they aren't guaranteed to stay unless we pin them via the Bcb. Return Value: None. --*/ { ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_SCB( Scb ); ASSERT( Length != 0 ); PAGED_CODE(); DebugTrace( +1, Dbg, ("NtfsMapStream\n") ); DebugTrace( 0, Dbg, ("Scb = %08lx\n", Scb) ); DebugTrace( 0, Dbg, ("FileOffset = %016I64x\n", FileOffset) ); DebugTrace( 0, Dbg, ("Length = %08lx\n", Length) ); // // The file object should already exist in the Scb. // ASSERT( Scb->FileObject != NULL ); // // If we are trying to go beyond the end of the allocation, assume // we have some corruption. // if ((FileOffset + Length) > Scb->Header.AllocationSize.QuadPart) { NtfsRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Scb->Fcb ); } // // Call the cache manager to map the data. This call may raise, but // will never return an error (including CANT_WAIT). // if (!CcMapData( Scb->FileObject, (PLARGE_INTEGER)&FileOffset, Length, TRUE, Bcb, Buffer )) { NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } #ifdef MAPCOUNT_DBG IrpContext->MapCount++; #endif DebugTrace( 0, Dbg, ("Buffer -> %08lx\n", *Buffer) ); DebugTrace( -1, Dbg, ("NtfsMapStream -> VOID\n") ); return; }
NTSTATUS NdNtfsSecondaryCommonWrite ( 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; PSCB scb; PCCB ccb; BOOLEAN scbAcquired = FALSE; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); typeOfOpen = NtfsDecodeFileObject( IrpContext, fileObject, &vcb, &fcb, &scb, &ccb, TRUE ); ASSERT( typeOfOpen == UserFileOpen ); if (FlagOn(ccb->NdNtfsFlags, ND_NTFS_CCB_FLAG_UNOPENED)) { if (FlagOn( scb->ScbState, SCB_STATE_ATTRIBUTE_DELETED )) { ASSERT( FALSE ); NtfsRaiseStatus( IrpContext, STATUS_FILE_DELETED, NULL, NULL ); } else { ASSERT( FlagOn(ccb->NdNtfsFlags, ND_NTFS_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 = scb->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) <= ((scb->Header.AllocationSize.QuadPart + PAGE_SIZE - 1) & ~((LONGLONG) (PAGE_SIZE-1))) ); return STATUS_SUCCESS; } ASSERT( FlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); ASSERT( !FlagOn( IrpContext->State, IRP_CONTEXT_STATE_LAZY_WRITE ) ); if ( (write.ByteOffset.QuadPart + write.Length) <= scb->Header.FileSize.QuadPart) { return STATUS_SUCCESS; } if ((write.ByteOffset.QuadPart + write.Length) > scb->Header.AllocationSize.QuadPart) { NtfsAcquireExclusiveScb( IrpContext, scb ); scbAcquired = TRUE; } try { secondarySessionResourceAcquired = SecondaryAcquireResourceExclusiveLite( IrpContext, &volDo->Secondary->SessionResource, BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) ); if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) { PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, IRP_MJ_SET_INFORMATION, volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize ); if(secondaryRequest == NULL) { NtfsRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES, NULL, NULL ); } 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 = -NDNTFS_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 ); DebugTrace( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) ); NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL ); } ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData; status = ndfsWinxpReplytHeader->Status; Irp->IoStatus.Information = write.Length; if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) { DebugTrace( 0, Dbg2, ("NdNtfsSecondaryCommonWrite: ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) ); ASSERT( ndfsWinxpReplytHeader->Information == 0 ); } else ASSERT( ndfsWinxpReplytHeader->FileInformationSet ); if (ndfsWinxpReplytHeader->FileInformationSet) { PNDFS_MCB_ENTRY mcbEntry; ULONG index; BOOLEAN lookupResut; VCN vcn; LCN lcn; LCN startingLcn; LONGLONG clusterCount; if (ndfsWinxpReplytHeader->AllocationSize != scb->Header.AllocationSize.QuadPart) { ASSERT( NtfsIsExclusiveScb(scb) ); ASSERT( ndfsWinxpReplytHeader->AllocationSize > scb->Header.AllocationSize.QuadPart ); mcbEntry = (PNDFS_MCB_ENTRY)( ndfsWinxpReplytHeader+1 ); for (index=0, vcn=0; index < ndfsWinxpReplytHeader->NumberOfMcbEntry; index++, mcbEntry++) { lookupResut = NtfsLookupNtfsMcbEntry( &scb->Mcb, vcn, &lcn, &clusterCount, &startingLcn, NULL, NULL, NULL ); if (vcn < LlClustersFromBytes(&volDo->Secondary->VolDo->Vcb, scb->Header.AllocationSize.QuadPart)) { ASSERT( lookupResut == TRUE ); ASSERT( startingLcn == lcn ); ASSERT( vcn == mcbEntry->Vcn ); ASSERT( lcn == mcbEntry->Lcn ); ASSERT( clusterCount <= mcbEntry->ClusterCount ); if (clusterCount < mcbEntry->ClusterCount) { NtfsAddNtfsMcbEntry( &scb->Mcb, mcbEntry->Vcn, mcbEntry->Lcn, (LONGLONG)mcbEntry->ClusterCount, FALSE ); lookupResut = NtfsLookupNtfsMcbEntry( &scb->Mcb, vcn, &lcn, &clusterCount, &startingLcn, NULL, NULL, NULL ); ASSERT( lookupResut == TRUE ); ASSERT( startingLcn == lcn ); ASSERT( vcn == mcbEntry->Vcn ); ASSERT( lcn == mcbEntry->Lcn ); ASSERT( clusterCount == mcbEntry->ClusterCount ); } } else { ASSERT( lookupResut == FALSE || lcn == UNUSED_LCN ); NtfsAddNtfsMcbEntry( &scb->Mcb, mcbEntry->Vcn, mcbEntry->Lcn, (LONGLONG)mcbEntry->ClusterCount, FALSE ); } vcn += mcbEntry->ClusterCount; } ASSERT( LlBytesFromClusters(&volDo->Secondary->VolDo->Vcb, vcn) == ndfsWinxpReplytHeader->AllocationSize ); scb->Header.AllocationSize.QuadPart = ndfsWinxpReplytHeader->AllocationSize; SetFlag( scb->ScbState, SCB_STATE_TRUNCATE_ON_CLOSE ); if (CcIsFileCached(fileObject)) { ASSERT( fileObject->SectionObjectPointer->SharedCacheMap != NULL ); NtfsSetBothCacheSizes( fileObject, (PCC_FILE_SIZES)&scb->Header.AllocationSize, scb ); } } DebugTrace(0, Dbg, ("write scb->Header.FileSize.QuadPart = %I64x, scb->Header.ValidDataLength.QuadPart = %I64x\n", scb->Header.FileSize.QuadPart, scb->Header.ValidDataLength.QuadPart) ); } #if DBG { BOOLEAN lookupResut; VCN vcn; LCN lcn; LCN startingLcn; LONGLONG clusterCount; vcn = 0; while (1) { lookupResut = NtfsLookupNtfsMcbEntry( &scb->Mcb, vcn, &lcn, &clusterCount, &startingLcn, NULL, NULL, NULL ); if (lookupResut == FALSE || lcn == UNUSED_LCN) break; vcn += clusterCount; } ASSERT( LlBytesFromClusters(&volDo->Secondary->VolDo->Vcb, vcn) == scb->Header.AllocationSize.QuadPart ); } #endif } finally { if (secondarySessionResourceAcquired == TRUE) SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource ); if (scbAcquired) { NtfsReleaseScb( IrpContext, scb ); } if(secondaryRequest) DereferenceSecondaryRequest( secondaryRequest ); } return status; }