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 __ND_FAT__ PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp ); 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) ); 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, ("NtfsFsdDispatch: IOCTL_SHUTDOWN\n") ); for (vcbListEntry = FatData.VcbQueue.Flink; vcbListEntry != &FatData.VcbQueue; vcbListEntry = vcbListEntry->Flink) { PVCB vcb = NULL; #ifdef __ND_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 ); //DbgPrint( "NtfsFsdDispatch: ND_FAT_DEVICE_FLAG_SHUTDOWN\n" ); SetFlag( volDo->NdFatFlags, ND_FAT_DEVICE_FLAG_SHUTDOWN ); #ifdef __ND_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 { #ifdef __ND_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; }
VOID CdFspDispatch ( IN PIRP_CONTEXT IrpContext ) /*++ Routine Description: This is the main FSP thread routine that is executed to receive and dispatch IRP requests. Each FSP thread begins its execution here. There is one thread created at system initialization time and subsequent threads created as needed. Arguments: IrpContext - IrpContext for a request to process. Return Value: None --*/ { THREAD_CONTEXT ThreadContext; NTSTATUS Status; PIRP Irp = IrpContext->Irp; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PVOLUME_DEVICE_OBJECT VolDo = NULL; // // If this request has an associated volume device object, remember it. // if (IrpSp->FileObject != NULL) { VolDo = CONTAINING_RECORD( IrpSp->DeviceObject, VOLUME_DEVICE_OBJECT, DeviceObject ); } // // Now case on the function code. For each major function code, // either call the appropriate worker routine. This routine that // we call is responsible for completing the IRP, and not us. // That way the routine can complete the IRP and then continue // post processing as required. For example, a read can be // satisfied right away and then read can be done. // // We'll do all of the work within an exception handler that // will be invoked if ever some underlying operation gets into // trouble. // while ( TRUE ) { // // Set all the flags indicating we are in the Fsp. // SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS ); FsRtlEnterFileSystem(); CdSetThreadContext( IrpContext, &ThreadContext ); while (TRUE) { try { // // Reinitialize for the next try at completing this // request. // Status = IrpContext->ExceptionStatus = STATUS_SUCCESS; // // Initialize the Io status field in the Irp. // Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; // // Case on the major irp code. // switch (IrpContext->MajorFunction) { case IRP_MJ_CREATE : CdCommonCreate( IrpContext, Irp ); break; case IRP_MJ_CLOSE : ASSERT( FALSE ); break; case IRP_MJ_READ : CdCommonRead( IrpContext, Irp ); break; case IRP_MJ_QUERY_INFORMATION : CdCommonQueryInfo( IrpContext, Irp ); break; case IRP_MJ_SET_INFORMATION : CdCommonQueryInfo( IrpContext, Irp ); break; case IRP_MJ_QUERY_VOLUME_INFORMATION : CdCommonQueryVolInfo( IrpContext, Irp ); break; case IRP_MJ_DIRECTORY_CONTROL : CdCommonDirControl( IrpContext, Irp ); break; case IRP_MJ_FILE_SYSTEM_CONTROL : CdCommonFsControl( IrpContext, Irp ); break; case IRP_MJ_DEVICE_CONTROL : CdCommonDevControl( IrpContext, Irp ); break; case IRP_MJ_LOCK_CONTROL : CdCommonLockControl( IrpContext, Irp ); break; case IRP_MJ_CLEANUP : CdCommonCleanup( IrpContext, Irp ); break; default : Status = STATUS_INVALID_DEVICE_REQUEST; CdCompleteRequest( IrpContext, Irp, Status ); } } except( CdExceptionFilter( IrpContext, GetExceptionInformation() )) { Status = CdProcessException( IrpContext, Irp, GetExceptionCode() ); } // // Break out of the loop if we didn't get CANT_WAIT. // if (Status != STATUS_CANT_WAIT) { break; } // // We are retrying this request. Cleanup the IrpContext for the retry. // SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); CdCleanupIrpContext( IrpContext, FALSE ); } FsRtlExitFileSystem(); // // If there are any entries on this volume's overflow queue, service // them. // if (VolDo != NULL) { KIRQL SavedIrql; PVOID Entry = NULL; // // We have a volume device object so see if there is any work // left to do in its overflow queue. // KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql ); if (VolDo->OverflowQueueCount > 0) { // // There is overflow work to do in this volume so we'll // decrement the Overflow count, dequeue the IRP, and release // the Event // VolDo->OverflowQueueCount -= 1; Entry = RemoveHeadList( &VolDo->OverflowQueue ); } KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql ); // // There wasn't an entry, break out of the loop and return to // the Ex Worker thread. // if (Entry == NULL) { break; } // // Extract the IrpContext , Irp, set wait to TRUE, and loop. // IrpContext = CONTAINING_RECORD( Entry, IRP_CONTEXT, WorkQueueItem.List ); Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation( Irp ); continue; } break; } // // Decrement the PostedRequestCount if there was a volume device object. // if (VolDo) { InterlockedDecrement( &VolDo->PostedRequestCount ); } return; }
BOOLEAN UdfFastQueryNetworkInfo ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This routine is for the fast query call for network file information. Arguments: FileObject - Supplies the file object used in this operation Wait - Indicates if we are allowed to wait for the information Buffer - Supplies the output buffer to receive the basic information IoStatus - Receives the final status of the operation Return Value: BOOLEAN - TRUE if the operation succeeded and FALSE if the caller needs to take the long route. --*/ { BOOLEAN Result = FALSE; TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PCCB Ccb; PAGED_CODE(); ASSERT_FILE_OBJECT( FileObject ); FsRtlEnterFileSystem(); // // Decode the file object to find the type of open and the data // structures. // TypeOfOpen = UdfDecodeFileObject( FileObject, &Fcb, &Ccb ); // // We only support this request on user file or directory objects. // if (TypeOfOpen != UserFileOpen && TypeOfOpen != UserDirectoryOpen) { FsRtlExitFileSystem(); return FALSE; } // // Acquire the file shared to access the Fcb. // if (!ExAcquireResourceShared( Fcb->Resource, Wait )) { FsRtlExitFileSystem(); return FALSE; } // // Use a try-finally to facilitate cleanup. // try { // // Only deal with 'good' Fcb's. // if (UdfVerifyFcbOperation( NULL, Fcb )) { // // Fill in the input buffer from the Fcb fields. // Buffer->CreationTime = Fcb->Timestamps.CreationTime; Buffer->LastWriteTime = Buffer->ChangeTime = Fcb->Timestamps.ModificationTime; Buffer->LastAccessTime = Fcb->Timestamps.AccessTime; Buffer->FileAttributes = Fcb->FileAttributes | UdfGetExtraFileAttributes( Ccb ); // // Check whether this is a directory. // if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { Buffer->AllocationSize.QuadPart = Buffer->EndOfFile.QuadPart = 0; } else { Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; } // // Update the IoStatus block with the size of this data. // IoStatus->Status = STATUS_SUCCESS; IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION ); Result = TRUE; } } finally { ExReleaseResource( Fcb->Resource ); FsRtlExitFileSystem(); } return Result; }
NTSTATUS NtfsFsdQuerySecurityInfo ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine implements the FSD part of the Query Security Information API calls. Arguments: VolumeDeviceObject - Supplies the device object to use. Irp - Supplies the Irp being processed Return Value: NTSTATUS - The Fsd status for the Irp --*/ { TOP_LEVEL_CONTEXT TopLevelContext; PTOP_LEVEL_CONTEXT ThreadTopLevelContext; NTSTATUS Status = STATUS_SUCCESS; PIRP_CONTEXT IrpContext = NULL; ASSERT_IRP( Irp ); UNREFERENCED_PARAMETER( VolumeDeviceObject ); PAGED_CODE(); DebugTrace( +1, Dbg, ("NtfsFsdQuerySecurityInfo\n") ); // // Call the common query Information routine // FsRtlEnterFileSystem(); ThreadTopLevelContext = NtfsSetTopLevelIrp( &TopLevelContext, FALSE, FALSE ); do { try { // // We are either initiating this request or retrying it. // if (IrpContext == NULL) { IrpContext = NtfsCreateIrpContext( Irp, CanFsdWait( Irp ) ); NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext ); } else if (Status == STATUS_LOG_FILE_FULL) { NtfsCheckpointForLogFileFull( IrpContext ); } Status = NtfsCommonQuerySecurityInfo( IrpContext, Irp ); break; } except(NtfsExceptionFilter( 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 = NtfsProcessException( IrpContext, Irp, GetExceptionCode() ); } } while (Status == STATUS_CANT_WAIT || Status == STATUS_LOG_FILE_FULL); if (ThreadTopLevelContext == &TopLevelContext) { NtfsRestoreTopLevelIrp( ThreadTopLevelContext ); } FsRtlExitFileSystem(); // // And return to our caller // DebugTrace( -1, Dbg, ("NtfsFsdQuerySecurityInfo -> %08lx\n", Status) ); return Status; }
NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); device_extension* Vcb = DeviceObject->DeviceExtension; NTSTATUS Status; BOOL top_level; FsRtlEnterFileSystem(); top_level = is_top_level(Irp); Status = STATUS_NOT_IMPLEMENTED; switch (IrpSp->MinorFunction) { case IRP_MN_CANCEL_REMOVE_DEVICE: Status = pnp_cancel_remove_device(DeviceObject, Irp); break; case IRP_MN_QUERY_REMOVE_DEVICE: Status = pnp_query_remove_device(DeviceObject, Irp); break; case IRP_MN_REMOVE_DEVICE: Status = pnp_remove_device(DeviceObject, Irp); break; case IRP_MN_START_DEVICE: Status = pnp_start_device(DeviceObject, Irp); break; case IRP_MN_SURPRISE_REMOVAL: Status = pnp_surprise_removal(DeviceObject, Irp); break; default: TRACE("passing minor function 0x%x on\n", IrpSp->MinorFunction); IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(Vcb->devices[0].devobj, Irp); goto end; } // // Irp->IoStatus.Status = Status; // // Irp->IoStatus.Information = 0; // // IoSkipCurrentIrpStackLocation(Irp); // // Status = IoCallDriver(Vcb->devices[0].devobj, Irp); // // // IoCompleteRequest(Irp, IO_NO_INCREMENT); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); end: if (top_level) IoSetTopLevelIrp(NULL); FsRtlExitFileSystem(); return Status; }
BOOLEAN Ext2FastIoCheckIfPossible ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { BOOLEAN bPossible = FastIoIsNotPossible; PEXT2_FCB Fcb; PEXT2_CCB Ccb; LARGE_INTEGER lLength; lLength.QuadPart = Length; __try { FsRtlEnterFileSystem(); __try { if (IsExt2FsDevice(DeviceObject)) { __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsDirectory(Fcb)) { __leave; } Ccb = (PEXT2_CCB) FileObject->FsContext2; if (Ccb == NULL) { __leave; } if (CheckForReadOperation) { bPossible = FsRtlFastCheckLockForRead( &Fcb->FileLockAnchor, FileOffset, &lLength, LockKey, FileObject, PsGetCurrentProcess()); } else { if (!(IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) || IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED))) { bPossible = FsRtlFastCheckLockForWrite( &Fcb->FileLockAnchor, FileOffset, &lLength, LockKey, FileObject, PsGetCurrentProcess()); } } #if EXT2_DEBUG DEBUG(DL_INF, ("Ext2FastIIOCheckPossible: %s %s %wZ\n", Ext2GetCurrentProcessName(), "FASTIO_CHECK_IF_POSSIBLE", &Fcb->Mcb->FullName )); DEBUG(DL_INF, ( "Ext2FastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n", FileOffset->QuadPart, Length, LockKey, (CheckForReadOperation ? "CheckForReadOperation:" : "CheckForWriteOperation:"), (bPossible ? "Succeeded" : "Failed"))); #endif } __except (EXCEPTION_EXECUTE_HANDLER) { bPossible = FastIoIsNotPossible; } } __finally { FsRtlExitFileSystem(); } return bPossible; }
BOOLEAN Ext2FastIoQueryNetworkOpenInfo ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN OUT PFILE_NETWORK_OPEN_INFORMATION PFNOI, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { BOOLEAN bResult = FALSE; PEXT2_FCB Fcb = NULL; BOOLEAN FcbResourceAcquired = FALSE; __try { FsRtlEnterFileSystem(); if (IsExt2FsDevice(DeviceObject)) { IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { DbgBreak(); IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); #if EXT2_DEBUG DEBUG(DL_INF, ( "%-31s %wZ\n", "FASTIO_QUERY_NETWORK_OPEN_INFO", &Fcb->Mcb->FullName )); #endif if (FileObject->FsContext2) { __leave; } if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) { if (!ExAcquireResourceSharedLite( &Fcb->MainResource, Wait )) { __leave; } FcbResourceAcquired = TRUE; } if (IsDirectory(Fcb)) { PFNOI->AllocationSize.QuadPart = 0; PFNOI->EndOfFile.QuadPart = 0; } else { PFNOI->AllocationSize = Fcb->Header.AllocationSize; PFNOI->EndOfFile = Fcb->Header.FileSize; } PFNOI->FileAttributes = Fcb->Mcb->FileAttr; if (PFNOI->FileAttributes == 0) { PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL; } if (IsRoot(Fcb)) { PFNOI->CreationTime = PFNOI->LastAccessTime = PFNOI->LastWriteTime = PFNOI->ChangeTime = Ext2NtTime(0); } else { PFNOI->CreationTime = Fcb->Mcb->CreationTime; PFNOI->LastAccessTime = Fcb->Mcb->LastAccessTime; PFNOI->LastWriteTime = Fcb->Mcb->LastWriteTime; PFNOI->ChangeTime = Fcb->Mcb->ChangeTime; } bResult = TRUE; IoStatus->Status = STATUS_SUCCESS; IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION); } __finally { if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } FsRtlExitFileSystem(); } return bResult; }
VOID SecondaryTryClose ( IN PSECONDARY Secondary ) { IRP_CONTEXT irpContext; BOOLEAN secondaryResourceAcquired = FALSE; BOOLEAN acquiredVcb = FALSE; BOOLEAN wait; 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 ); } return; }
static NTSTATUS CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDEVICE_EXTENSION DeviceExt; PIO_STACK_LOCATION Stack; NTSTATUS Status; CDINFO CdInfo; PLIST_ENTRY Entry; PFCB Fcb; PVPB VpbToVerify; DPRINT1 ("CdfsVerifyVolume() called\n"); DeviceExt = DeviceObject->DeviceExtension; Stack = IoGetCurrentIrpStackLocation (Irp); VpbToVerify = Stack->Parameters.VerifyVolume.Vpb; FsRtlEnterFileSystem(); ExAcquireResourceExclusiveLite (&DeviceExt->VcbResource, TRUE); if (!(VpbToVerify->RealDevice->Flags & DO_VERIFY_VOLUME)) { DPRINT1 ("Volume has been verified!\n"); ExReleaseResourceLite (&DeviceExt->VcbResource); FsRtlExitFileSystem(); return STATUS_SUCCESS; } DPRINT1("Device object %p Device to verify %p\n", DeviceObject, VpbToVerify->RealDevice); Status = CdfsGetVolumeData(VpbToVerify->RealDevice, &CdInfo); if (NT_SUCCESS(Status) && CdInfo.SerialNumber == VpbToVerify->SerialNumber && CdInfo.VolumeLabelLength == VpbToVerify->VolumeLabelLength && !wcsncmp(CdInfo.VolumeLabel, VpbToVerify->VolumeLabel, CdInfo.VolumeLabelLength)) { DPRINT1 ("Same volume!\n"); /* FIXME: Flush and purge metadata */ Status = STATUS_SUCCESS; } else { DPRINT1 ("Different volume!\n"); /* FIXME: force volume dismount */ Entry = DeviceExt->FcbListHead.Flink; while (Entry != &DeviceExt->FcbListHead) { Fcb = (PFCB)CONTAINING_RECORD(Entry, FCB, FcbListEntry); DPRINT1("OpenFile %wZ RefCount %ld\n", &Fcb->PathName, Fcb->RefCount); Entry = Entry->Flink; } Status = STATUS_WRONG_VOLUME; } VpbToVerify->RealDevice->Flags &= ~DO_VERIFY_VOLUME; ExReleaseResourceLite (&DeviceExt->VcbResource); FsRtlExitFileSystem(); return Status; }
NTSTATUS DokanDispatchClose( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: This device control dispatcher handles create & close IRPs. Arguments: DeviceObject - Context for the activity. Irp - The device control argument block. Return Value: NTSTATUS --*/ { PDokanVCB vcb; PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_INVALID_PARAMETER; PFILE_OBJECT fileObject; PDokanCCB ccb; PEVENT_CONTEXT eventContext; ULONG eventLength; PDokanFCB fcb; PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanClose\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject is NULL\n"); status = STATUS_SUCCESS; __leave; } DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { if (fileObject->FsContext2) { ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); DDbgPrint(" Free CCB:%X\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); } status = STATUS_SUCCESS; __leave; } ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { //status = STATUS_INSUFFICIENT_RESOURCES; DDbgPrint(" eventContext == NULL\n"); DDbgPrint(" Free CCB:%X\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); status = STATUS_SUCCESS; __leave; } eventContext->Context = ccb->UserContext; DDbgPrint(" UserContext:%X\n", (ULONG)ccb->UserContext); // copy the file name to be closed eventContext->Close.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Close.FileName, fcb->FileName.Buffer, fcb->FileName.Length); DDbgPrint(" Free CCB:%X\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); // Close can not be pending status // don't register this IRP //status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext->SerialNumber, 0); // inform it to user-mode DokanEventNotification(&vcb->Dcb->NotifyEvent, eventContext); status = STATUS_SUCCESS; } __finally { if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } DDbgPrint("<== DokanClose\n"); FsRtlExitFileSystem(); } return status; }
NTSTATUS NTAPI VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS Status; PLIST_ENTRY ListEntry; PDEVICE_EXTENSION DeviceExt; ULONG eocMark; DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp); FsRtlEnterFileSystem(); /* FIXME: block new mount requests */ if (DeviceObject == VfatGlobalData->DeviceObject) { Irp->IoStatus.Status = STATUS_SUCCESS; ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE); ListEntry = VfatGlobalData->VolumeListHead.Flink; while (ListEntry != &VfatGlobalData->VolumeListHead) { DeviceExt = CONTAINING_RECORD(ListEntry, VCB, VolumeListEntry); ListEntry = ListEntry->Flink; ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE); if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY) { /* set clean shutdown bit */ Status = GetNextCluster(DeviceExt, 1, &eocMark); if (NT_SUCCESS(Status)) { eocMark |= DeviceExt->CleanShutBitMask; if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark))) DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY; } } Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb); if (NT_SUCCESS(Status)) { Status = VfatDiskShutDown(DeviceExt); if (!NT_SUCCESS(Status)) DPRINT1("VfatDiskShutDown failed, status = %x\n", Status); } else { DPRINT1("VfatFlushVolume failed, status = %x\n", Status); } ExReleaseResourceLite(&DeviceExt->DirResource); /* FIXME: Unmount the logical volume */ if (!NT_SUCCESS(Status)) Irp->IoStatus.Status = Status; } ExReleaseResourceLite(&VfatGlobalData->VolumeListLock); /* FIXME: Free all global acquired resources */ Status = Irp->IoStatus.Status; } else { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST; } Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FsRtlExitFileSystem(); return(Status); }
BOOLEAN FatFastUnlockAllByKey ( IN PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast unlock all by key call. Arguments: FileObject - Supplies the file object used in this operation ProcessId - Supplies the process ID used in this operation Key - Supplies the key used in this operation Status - Receives the Status if this operation is successful Return Value: BOOLEAN - TRUE if this operation completed and FALSE if caller needs to take the long route. --*/ { BOOLEAN Results; PVCB Vcb; PFCB Fcb; PCCB Ccb; DebugTrace(+1, Dbg, "FatFastUnlockAllByKey\n", 0); IoStatus->Information = 0; // // Decode the type of file object we're being asked to process and make sure // it is only a user file open. // if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) { IoStatus->Status = STATUS_INVALID_PARAMETER; DebugTrace(-1, Dbg, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; } // // Acquire exclusive access to the Fcb this operation can always wait // FsRtlEnterFileSystem(); (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE ); try { // // We check whether we can proceed based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) { try_return( Results = FALSE ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request. The call will always succeed. // Results = TRUE; IoStatus->Status = FsRtlFastUnlockAllByKey( &Fcb->Specific.Fcb.FileLock, FileObject, ProcessId, Key, NULL ); // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb ); try_exit: NOTHING; } finally { DebugUnwind( FatFastUnlockAllByKey ); // // Release the Fcb, and return to our caller // ExReleaseResource( (Fcb)->Header.Resource ); FsRtlExitFileSystem(); DebugTrace(-1, Dbg, "FatFastUnlockAllByKey -> %08lx\n", Results); } return Results; }
BOOLEAN FatFastLock ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast lock call. Arguments: FileObject - Supplies the file object used in this operation FileOffset - Supplies the file offset used in this operation Length - Supplies the length used in this operation ProcessId - Supplies the process ID used in this operation Key - Supplies the key used in this operation FailImmediately - Indicates if the request should fail immediately if the lock cannot be granted. ExclusiveLock - Indicates if this is a request for an exclusive or shared lock IoStatus - Receives the Status if this operation is successful Return Value: BOOLEAN - TRUE if this operation completed and FALSE if caller needs to take the long route. --*/ { BOOLEAN Results; PVCB Vcb; PFCB Fcb; PCCB Ccb; DebugTrace(+1, Dbg, "FatFastLock\n", 0); // // Decode the type of file object we're being asked to process and make // sure it is only a user file open. // if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) { IoStatus->Status = STATUS_INVALID_PARAMETER; IoStatus->Information = 0; DebugTrace(-1, Dbg, "FatFastLock -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; } // // Acquire exclusive access to the Fcb this operation can always wait // FsRtlEnterFileSystem(); // BUGBUG: kenr // (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE ); try { // // We check whether we can proceed // based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) { try_return( Results = FALSE ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request // if (Results = FsRtlFastLock( &Fcb->Specific.Fcb.FileLock, FileObject, FileOffset, Length, ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, NULL, FALSE )) { // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb ); } try_exit: NOTHING; } finally { DebugUnwind( FatFastLock ); // // Release the Fcb, and return to our caller // // BUGBUG: kenr // ExReleaseResource( (Fcb)->Header.Resource ); FsRtlExitFileSystem(); DebugTrace(-1, Dbg, "FatFastLock -> %08lx\n", Results); } return Results; }
NTSTATUS FatFsdPnp ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine implements the FSD part of PnP 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; BOOLEAN Wait; DebugTrace(+1, Dbg, "FatFsdPnp\n", 0); FsRtlEnterFileSystem(); TopLevel = FatIsIrpTopLevel( Irp ); try { // // We expect there to never be a fileobject, in which case we will always // wait. Since at the moment we don't have any concept of pending Pnp // operations, this is a bit nitpicky. // if (IoGetCurrentIrpStackLocation( Irp )->FileObject == NULL) { Wait = TRUE; } else { Wait = CanFsdWait( Irp ); } IrpContext = FatCreateIrpContext( Irp, Wait ); Status = FatCommonPnp( 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, "FatFsdPnp -> %08lx\n", Status); UNREFERENCED_PARAMETER( VolumeDeviceObject ); return Status; }
BOOLEAN Ext2FastIoQueryStandardInfo ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { BOOLEAN Status = FALSE; PEXT2_VCB Vcb; PEXT2_FCB Fcb; BOOLEAN FcbMainResourceAcquired = FALSE; __try { FsRtlEnterFileSystem(); __try { if (IsExt2FsDevice(DeviceObject)) { IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); #if EXT2_DEBUG DEBUG(DL_INF, ( "Ext2FastIoQueryStandardInfo: %s %s %wZ\n", Ext2GetCurrentProcessName(), "FASTIO_QUERY_STANDARD_INFO", &Fcb->Mcb->FullName )); #endif Vcb = Fcb->Vcb; if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) { if (!ExAcquireResourceSharedLite( &Fcb->MainResource, Wait )) { __leave; } FcbMainResourceAcquired = TRUE; } RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION)); /* typedef struct _FILE_STANDARD_INFORMATION { LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; ULONG NumberOfLinks; BOOLEAN DeletePending; BOOLEAN Directory; } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; */ Buffer->NumberOfLinks = Fcb->Inode->i_nlink; Buffer->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING); if (IsDirectory(Fcb)) { Buffer->Directory = IsDirectory(Fcb); Buffer->AllocationSize.QuadPart = 0; Buffer->EndOfFile.QuadPart = 0; } else { Buffer->Directory = FALSE; Buffer->AllocationSize = Fcb->Header.AllocationSize; Buffer->EndOfFile = Fcb->Header.FileSize; } IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION); IoStatus->Status = STATUS_SUCCESS; #if EXT2_DEBUG DEBUG(DL_INF, ( "Ext2FastIoQueryStandInfo: AllocatieonSize = %I64xh FileSize = %I64xh\n", Buffer->AllocationSize.QuadPart, Buffer->EndOfFile.QuadPart)); #endif Status = TRUE; } __except (EXCEPTION_EXECUTE_HANDLER) { IoStatus->Status = GetExceptionCode(); } } __finally { if (FcbMainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } FsRtlExitFileSystem(); } #if EXT2_DEBUG if (Status == FALSE) { DEBUG(DL_INF, ( "Ext2FastIoQueryStandardInfo: %s %s Status: FALSE ***\n", Ext2GetCurrentProcessName(), "FASTIO_QUERY_STANDARD_INFO" )); } else if (IoStatus->Status != STATUS_SUCCESS) { DEBUG(DL_INF, ( "Ext2FastIoQueryStandardInfo: %s %s Status: %#x ***\n", Ext2GetCurrentProcessName(), "FASTIO_QUERY_STANDARD_INFO", IoStatus->Status )); } #endif return Status; }
VOID FatFspDispatch ( _In_ PVOID Context ) /*++ Routine Description: This is the main FSP thread routine that is executed to receive and dispatch IRP requests. Each FSP thread begins its execution here. There is one thread created at system initialization time and subsequent threads created as needed. Arguments: Context - Supplies the thread id. Return Value: None - This routine never exits --*/ { NTSTATUS Status = STATUS_SUCCESS; PIRP Irp; PIRP_CONTEXT IrpContext; PIO_STACK_LOCATION IrpSp; BOOLEAN VcbDeleted; BOOLEAN ExceptionCompletedIrp = FALSE; PVOLUME_DEVICE_OBJECT VolDo; UCHAR MajorFunction = 0; PAGED_CODE(); IrpContext = (PIRP_CONTEXT)Context; Irp = IrpContext->OriginatingIrp; IrpSp = IoGetCurrentIrpStackLocation( Irp ); // // Now because we are the Fsp we will force the IrpContext to // indicate true on Wait. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP); // // If this request has an associated volume device object, remember it. // if ( IrpSp->FileObject != NULL ) { VolDo = CONTAINING_RECORD( IrpSp->DeviceObject, VOLUME_DEVICE_OBJECT, DeviceObject ); } else { VolDo = NULL; } // // Now case on the function code. For each major function code, // either call the appropriate FSP routine or case on the minor // function and then call the FSP routine. The FSP routine that // we call is responsible for completing the IRP, and not us. // That way the routine can complete the IRP and then continue // post processing as required. For example, a read can be // satisfied right away and then read can be done. // // We'll do all of the work within an exception handler that // will be invoked if ever some underlying operation gets into // trouble (e.g., if FatReadSectorsSync has trouble). // while ( TRUE ) { ExceptionCompletedIrp = FALSE; DebugTrace(0, Dbg, "FatFspDispatch: Irp = %p\n", Irp); // // If this Irp was top level, note it in our thread local storage. // FsRtlEnterFileSystem(); if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) ) { IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP ); } else { IoSetTopLevelIrp( Irp ); } MajorFunction = IrpContext->MajorFunction; try { switch ( MajorFunction ) { // // For Create Operation, // case IRP_MJ_CREATE: Status = FatCommonCreate( IrpContext, Irp ); break; // // For close operations. We do a little kludge here in case // this close causes a volume to go away. It will NULL the // VolDo local variable so that we will not try to look at // the overflow queue. // case IRP_MJ_CLOSE: { PVCB Vcb; PFCB Fcb; PCCB Ccb; TYPE_OF_OPEN TypeOfOpen; // // Extract and decode the file object // TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb ); // // Do the close. We have a slightly different format // for this call because of the async closes. // Status = FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, TRUE, TRUE, &VcbDeleted ); // // If the VCB was deleted, do not try to access it later. // if (VcbDeleted) { VolDo = NULL; } NT_ASSERT(Status == STATUS_SUCCESS); FatCompleteRequest( IrpContext, Irp, Status ); break; } // // For read operations // case IRP_MJ_READ: (VOID) FatCommonRead( IrpContext, Irp ); break; // // For write operations, // case IRP_MJ_WRITE: (VOID) FatCommonWrite( IrpContext, Irp ); break; // // For Query Information operations, // case IRP_MJ_QUERY_INFORMATION: (VOID) FatCommonQueryInformation( IrpContext, Irp ); break; // // For Set Information operations, // case IRP_MJ_SET_INFORMATION: (VOID) FatCommonSetInformation( IrpContext, Irp ); break; // // For Query EA operations, // case IRP_MJ_QUERY_EA: (VOID) FatCommonQueryEa( IrpContext, Irp ); break; // // For Set EA operations, // case IRP_MJ_SET_EA: (VOID) FatCommonSetEa( IrpContext, Irp ); break; // // For Flush buffers operations, // case IRP_MJ_FLUSH_BUFFERS: (VOID) FatCommonFlushBuffers( IrpContext, Irp ); break; // // For Query Volume Information operations, // case IRP_MJ_QUERY_VOLUME_INFORMATION: (VOID) FatCommonQueryVolumeInfo( IrpContext, Irp ); break; // // For Set Volume Information operations, // case IRP_MJ_SET_VOLUME_INFORMATION: (VOID) FatCommonSetVolumeInfo( IrpContext, Irp ); break; // // For File Cleanup operations, // case IRP_MJ_CLEANUP: (VOID) FatCommonCleanup( IrpContext, Irp ); break; // // For Directory Control operations, // case IRP_MJ_DIRECTORY_CONTROL: (VOID) FatCommonDirectoryControl( IrpContext, Irp ); break; // // For File System Control operations, // case IRP_MJ_FILE_SYSTEM_CONTROL: (VOID) FatCommonFileSystemControl( IrpContext, Irp ); break; // // For Lock Control operations, // case IRP_MJ_LOCK_CONTROL: (VOID) FatCommonLockControl( IrpContext, Irp ); break; // // For Device Control operations, // case IRP_MJ_DEVICE_CONTROL: (VOID) FatCommonDeviceControl( IrpContext, Irp ); break; // // For the Shutdown operation, // case IRP_MJ_SHUTDOWN: (VOID) FatCommonShutdown( IrpContext, Irp ); break; // // For plug and play operations. // case IRP_MJ_PNP: // // I don't believe this should ever occur, but allow for the unexpected. // (VOID) FatCommonPnp( IrpContext, Irp ); break; // // For any other major operations, return an invalid // request. // default: FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST ); break; } } 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. // (VOID) FatProcessException( IrpContext, Irp, GetExceptionCode() ); ExceptionCompletedIrp = TRUE; } IoSetTopLevelIrp( NULL ); FsRtlExitFileSystem(); if (MajorFunction == IRP_MJ_CREATE && !ExceptionCompletedIrp && Status != STATUS_PENDING) { // // Creates are completed here. IrpContext is also freed here. // FatCompleteRequest( IrpContext, Irp, Status ); } // // If there are any entries on this volume's overflow queue, service // them. // if ( VolDo != NULL ) { PVOID Entry; // // We have a volume device object so see if there is any work // left to do in its overflow queue. // Entry = FatRemoveOverflowEntry( VolDo ); // // There wasn't an entry, break out of the loop and return to // the Ex Worker thread. // if ( Entry == NULL ) { break; } // // Extract the IrpContext, Irp, and IrpSp, and loop. // IrpContext = CONTAINING_RECORD( Entry, IRP_CONTEXT, WorkQueueItem.List ); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP); Irp = IrpContext->OriginatingIrp; IrpSp = IoGetCurrentIrpStackLocation( Irp ); continue; } else { break; } } return; }
BOOLEAN Ext2FastIoLock ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { BOOLEAN Status = FALSE; PEXT2_FCB Fcb; __try { FsRtlEnterFileSystem(); __try { if (IsExt2FsDevice(DeviceObject)) { IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsDirectory(Fcb)) { DbgBreak(); IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } #if EXT2_DEBUG DEBUG(DL_INF, ( "Ext2FastIoLock: %s %s %wZ\n", Ext2GetCurrentProcessName(), "FASTIO_LOCK", &Fcb->Mcb->FullName )); DEBUG(DL_INF, ( "Ext2FastIoLock: Offset: %I64xh Length: %I64xh Key: %u %s%s\n", FileOffset->QuadPart, Length->QuadPart, Key, (FailImmediately ? "FailImmediately " : ""), (ExclusiveLock ? "ExclusiveLock " : "") )); #endif if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) { __leave; } Status = FsRtlFastLock( &Fcb->FileLockAnchor, FileObject, FileOffset, Length, Process, Key, FailImmediately, ExclusiveLock, IoStatus, NULL, FALSE); if (Status) { Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); } } __except (EXCEPTION_EXECUTE_HANDLER) { IoStatus->Status = GetExceptionCode(); } } __finally { FsRtlExitFileSystem(); } #if EXT2_DEBUG if (Status == FALSE) { DEBUG(DL_ERR, ( "Ext2FastIoLock: %s %s *** Status: FALSE ***\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_LOCK" )); } else if (IoStatus->Status != STATUS_SUCCESS) { DEBUG(DL_ERR, ( "Ext2FastIoLock: %s %s *** Status: %s (%#x) ***\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_LOCK", Ext2NtStatusToString(IoStatus->Status), IoStatus->Status )); } #endif return Status; }
NTSTATUS FatFsdRead ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the driver entry to the common read routine for NtReadFile calls. For synchronous requests, the CommonRead is called with Wait == TRUE, which means the request will always be completed in the current thread, and never passed to the Fsp. If it is not a synchronous request, CommonRead is called with Wait == FALSE, which means the request will be passed to the Fsp only if there is a need to block. Arguments: VolumeDeviceObject - Supplies the volume device object where the file being Read exists Irp - Supplies the Irp being processed Return Value: NTSTATUS - The FSD status for the IRP --*/ { PFCB Fcb; NTSTATUS Status; PIRP_CONTEXT IrpContext = NULL; BOOLEAN TopLevel; DebugTrace(+1, Dbg, "FatFsdRead\n", 0); // // Call the common Read routine, with blocking allowed if synchronous // FsRtlEnterFileSystem(); // // We are first going to do a quick check for paging file IO. // Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext); if ((NodeType(Fcb) == FAT_NTC_FCB) && FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) { // // Do the usual STATUS_PENDING things. // IoMarkIrpPending( Irp ); // // If there is not enough stack to do this read, then post this // read to the overflow queue. // if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) { KEVENT Event; PAGING_FILE_OVERFLOW_PACKET Packet; Packet.Irp = Irp; Packet.Fcb = Fcb; KeInitializeEvent( &Event, NotificationEvent, FALSE ); FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead ); // // And wait for the worker thread to complete the item // (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); } else { // // Perform the actual IO, it will be completed when the io finishes. // FatPagingFileIo( Irp, Fcb ); } FsRtlExitFileSystem(); return STATUS_PENDING; } try { TopLevel = FatIsIrpTopLevel( Irp ); IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) ); // // If this is an Mdl complete request, don't go through // common read. // if ( FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE) ) { DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 ); try_return( Status = FatCompleteMdl( IrpContext, Irp )); } // // We can't handle DPC calls yet, post it. // if ( FlagOn(IrpContext->MinorFunction, IRP_MN_DPC) ) { DebugTrace(0, Dbg, "Passing DPC call to Fsp\n", 0 ); try_return( Status = FatFsdPostRequest( IrpContext, Irp )); } // // Check if we have enough stack space to process this request. If there // isn't enough then we will pass the request off to the stack overflow thread. // if ((IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) && ((NodeType(Fcb) == FAT_NTC_FCB) || (NodeType(Fcb) == FAT_NTC_DCB) || (NodeType(Fcb) == FAT_NTC_ROOT_DCB))) { DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 ); try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) ); } Status = FatCommonRead( IrpContext, Irp ); try_exit: NOTHING; } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) { // // We had some trouble trying to perform the requested // operation, so we'll abort the I/O request with // the error status that we get back from the // execption code // Status = FatProcessException( IrpContext, Irp, GetExceptionCode() ); } if (TopLevel) { IoSetTopLevelIrp( NULL ); } FsRtlExitFileSystem(); // // And return to our caller // DebugTrace(-1, Dbg, "FatFsdRead -> %08lx\n", Status); UNREFERENCED_PARAMETER( VolumeDeviceObject ); return Status; }
BOOLEAN Ext2FastIoUnlockAllByKey ( IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { BOOLEAN Status = FALSE; PEXT2_FCB Fcb; __try { FsRtlEnterFileSystem(); __try { if (IsExt2FsDevice(DeviceObject)) { IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { DbgBreak(); IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsDirectory(Fcb)) { DbgBreak(); IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } #if EXT2_DEBUG DEBUG(DL_INF, ( "Ext2FastIoUnlockAllByKey: %s %s %wZ\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_UNLOCK_ALL_BY_KEY", &Fcb->Mcb->FullName )); DEBUG(DL_INF, ( "Ext2FastIoUnlockAllByKey: Key: %u\n", Key )); #endif if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) { __leave; } IoStatus->Status = FsRtlFastUnlockAllByKey( &Fcb->FileLockAnchor, FileObject, Process, Key, NULL ); IoStatus->Information = 0; Status = TRUE; Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); } __except (EXCEPTION_EXECUTE_HANDLER) { IoStatus->Status = GetExceptionCode(); } } __finally { FsRtlExitFileSystem(); } #if EXT2_DEBUG if (Status == FALSE) { DEBUG(DL_ERR, ( "Ext2FastIoUnlockAllByKey: %s %s *** Status: FALSE ***\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_UNLOCK_ALL_BY_KEY" )); } else if (IoStatus->Status != STATUS_SUCCESS) { DEBUG(DL_ERR, ( "Ext2FastIoUnlockAllByKey: %s %s *** Status: %s (%#x) ***\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_UNLOCK_ALL_BY_KEY", Ext2NtStatusToString(IoStatus->Status), IoStatus->Status )); } #endif return Status; }
NTSTATUS DokanDispatchFileSystemControl( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS status = STATUS_INVALID_PARAMETER; PIO_STACK_LOCATION irpSp; PDokanVCB vcb; PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanFileSystemControl\n"); DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB) { status = STATUS_INVALID_PARAMETER; __leave; } irpSp = IoGetCurrentIrpStackLocation(Irp); switch(irpSp->MinorFunction) { case IRP_MN_KERNEL_CALL: DDbgPrint(" IRP_MN_KERNEL_CALL\n"); break; case IRP_MN_LOAD_FILE_SYSTEM: DDbgPrint(" IRP_MN_LOAD_FILE_SYSTEM\n"); break; case IRP_MN_MOUNT_VOLUME: { PVPB vpb; DDbgPrint(" IRP_MN_MOUNT_VOLUME\n"); if (irpSp->Parameters.MountVolume.DeviceObject != vcb->Dcb->DeviceObject) { DDbgPrint(" Not DokanDiskDevice\n"); status = STATUS_INVALID_PARAMETER; } vpb = irpSp->Parameters.MountVolume.Vpb; vpb->DeviceObject = vcb->DeviceObject; vpb->RealDevice = vcb->DeviceObject; vpb->Flags |= VPB_MOUNTED; vpb->VolumeLabelLength = wcslen(VOLUME_LABEL) * sizeof(WCHAR); RtlStringCchCopyW(vpb->VolumeLabel, sizeof(vpb->VolumeLabel) / sizeof(WCHAR), VOLUME_LABEL); vpb->SerialNumber = 0x19831116; status = STATUS_SUCCESS; } break; case IRP_MN_USER_FS_REQUEST: DDbgPrint(" IRP_MN_USER_FS_REQUEST\n"); status = DokanUserFsRequest(DeviceObject, Irp); break; case IRP_MN_VERIFY_VOLUME: DDbgPrint(" IRP_MN_VERIFY_VOLUME\n"); break; default: DDbgPrint(" unknown %d\n", irpSp->MinorFunction); status = STATUS_INVALID_PARAMETER; break; } } __finally { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); DDbgPrint("<== DokanFileSystemControl\n"); FsRtlExitFileSystem(); } return status; }
NTSTATUS DokanDispatchFlush( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; PVOID buffer; NTSTATUS status = STATUS_INVALID_PARAMETER; PDokanFCB fcb; PDokanCCB ccb; PDokanVCB vcb; PEVENT_CONTEXT eventContext; ULONG eventLength; PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanFlush\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); status = STATUS_SUCCESS; __leave; } vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_SUCCESS; __leave; } DDbgPrint(" FileName:%wZ\n", &fileObject->FileName); ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } eventContext->Context = ccb->UserContext; DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); // copy file name to be flushed eventContext->Flush.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Flush.FileName, fcb->FileName.Buffer, fcb->FileName.Length); CcUninitializeCacheMap(fileObject, NULL, NULL); //fileObject->Flags &= FO_CLEANUP_COMPLETE; // register this IRP to waiting IRP list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext); } __finally { // if status is not pending, must complete current IRPs if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); } else { DDbgPrint(" STATUS_PENDING\n"); } DDbgPrint("<== DokanFlush\n"); FsRtlExitFileSystem(); } return status; }
BOOLEAN Ext2FastIoWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject) { PEXT2_FCB Fcb = NULL; BOOLEAN Status = FALSE; BOOLEAN Locked = FALSE; Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL) return FALSE; __try { FsRtlEnterFileSystem(); ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsVcbReadOnly(Fcb->Vcb)) { __leave; } if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) { __leave; } Locked = TRUE; if (IsWritingToEof(*FileOffset) || Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length || Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) { Status = FALSE; __leave; } if (Locked) { ExReleaseResourceLite(Fcb->Header.Resource); Locked = FALSE; } Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); if (Status) { if (IoStatus) Length = (ULONG)IoStatus->Information; } } __finally { if (Locked) { ExReleaseResourceLite(Fcb->Header.Resource); } FsRtlExitFileSystem(); } DEBUG(DL_IO, ("Ext2FastIoWrite: %wZ Offset: %I64xh Length: %xh Key: %xh Status=%d\n", &Fcb->Mcb->ShortName, FileOffset->QuadPart, Length, LockKey, Status)); return Status; }
VOID NTAPI NpCancelDataQueueIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PNP_DATA_QUEUE DataQueue; PNP_DATA_QUEUE_ENTRY DataEntry; LIST_ENTRY DeferredList; PSECURITY_CLIENT_CONTEXT ClientSecurityContext; BOOLEAN CompleteWrites, FirstEntry; if (DeviceObject) IoReleaseCancelSpinLock(Irp->CancelIrql); InitializeListHead(&DeferredList); DataQueue = Irp->Tail.Overlay.DriverContext[2]; ClientSecurityContext = NULL; if (DeviceObject) { FsRtlEnterFileSystem(); NpAcquireExclusiveVcb(); } DataEntry = Irp->Tail.Overlay.DriverContext[3]; if (DataEntry) { if (DataEntry->QueueEntry.Blink == &DataQueue->Queue) { DataQueue->ByteOffset = 0; FirstEntry = TRUE; } else { FirstEntry = FALSE; } RemoveEntryList(&DataEntry->QueueEntry); ClientSecurityContext = DataEntry->ClientSecurityContext; CompleteWrites = TRUE; if (DataQueue->QueueState != WriteEntries || DataQueue->QuotaUsed < DataQueue->Quota || !DataEntry->QuotaInEntry) { CompleteWrites = FALSE; } DataQueue->BytesInQueue -= DataEntry->DataSize; DataQueue->QuotaUsed -= DataEntry->QuotaInEntry; --DataQueue->EntriesInQueue; if (IsListEmpty(&DataQueue->Queue)) { DataQueue->QueueState = Empty; ASSERT(DataQueue->BytesInQueue == 0); ASSERT(DataQueue->EntriesInQueue == 0); ASSERT(DataQueue->QuotaUsed == 0); } else { if (FirstEntry) { NpGetNextRealDataQueueEntry(DataQueue, &DeferredList); } if (CompleteWrites) { NpCompleteStalledWrites(DataQueue, &DeferredList); } } } if (DeviceObject) { NpReleaseVcb(); FsRtlExitFileSystem(); } if (DataEntry) ExFreePool(DataEntry); NpFreeClientSecurityContext(ClientSecurityContext); Irp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); NpCompleteDeferredIrps(&DeferredList); }
NTSTATUS DokanDispatchQueryInformation( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS status = STATUS_NOT_IMPLEMENTED; PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; PDokanCCB ccb; PDokanFCB fcb; PDokanVCB vcb; ULONG info = 0; ULONG eventLength; PEVENT_CONTEXT eventContext; //PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanQueryInformation\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; DDbgPrint(" FileInfoClass %d\n", irpSp->Parameters.QueryFile.FileInformationClass); DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); status = STATUS_INVALID_PARAMETER; __leave; } DokanPrintFileName(fileObject); /* if (fileObject->FsContext2 == NULL && fileObject->FileName.Length == 0) { // volume open? status = STATUS_SUCCESS; __leave; }*/ vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_INVALID_PARAMETER; __leave; } ccb = (PDokanCCB)fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); switch (irpSp->Parameters.QueryFile.FileInformationClass) { case FileBasicInformation: DDbgPrint(" FileBasicInformation\n"); break; case FileInternalInformation: DDbgPrint(" FileInternalInformation\n"); break; case FileEaInformation: DDbgPrint(" FileEaInformation\n"); break; case FileStandardInformation: DDbgPrint(" FileStandardInformation\n"); break; case FileAllInformation: DDbgPrint(" FileAllInformation\n"); break; case FileAlternateNameInformation: DDbgPrint(" FileAlternateNameInformation\n"); break; case FileAttributeTagInformation: DDbgPrint(" FileAttributeTagInformation\n"); break; case FileCompressionInformation: DDbgPrint(" FileCompressionInformation\n"); break; case FileNameInformation: { PFILE_NAME_INFORMATION nameInfo; DDbgPrint(" FileNameInformation\n"); if (irpSp->Parameters.QueryFile.Length < sizeof(FILE_NAME_INFORMATION) + fcb->FileName.Length) { status = STATUS_INSUFFICIENT_RESOURCES; } else { nameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(nameInfo != NULL); nameInfo->FileNameLength = fcb->FileName.Length; RtlCopyMemory(nameInfo->FileName, fcb->FileName.Buffer, fcb->FileName.Length); info = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + fcb->FileName.Length; status = STATUS_SUCCESS; } __leave; } break; case FileNetworkOpenInformation: DDbgPrint(" FileNetworkOpenInformation\n"); break; case FilePositionInformation: { PFILE_POSITION_INFORMATION posInfo; DDbgPrint(" FilePositionInformation\n"); if (irpSp->Parameters.QueryFile.Length < sizeof(FILE_POSITION_INFORMATION)) { status = STATUS_INFO_LENGTH_MISMATCH; } else { posInfo = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(posInfo != NULL); RtlZeroMemory(posInfo, sizeof(FILE_POSITION_INFORMATION)); if (fileObject->CurrentByteOffset.QuadPart < 0) { status = STATUS_INVALID_PARAMETER; } else { // set the current file offset posInfo->CurrentByteOffset = fileObject->CurrentByteOffset; info = sizeof(FILE_POSITION_INFORMATION); status = STATUS_SUCCESS; } } __leave; } break; case FileStreamInformation: DDbgPrint(" FileStreamInformation\n"); break; default: DDbgPrint(" unknown type:%d\n", irpSp->Parameters.QueryFile.FileInformationClass); break; } // if it is not treadted in swich case // calculate the length of EVENT_CONTEXT // sum of it's size and file name length eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } eventContext->Context = ccb->UserContext; //DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); eventContext->File.FileInformationClass = irpSp->Parameters.QueryFile.FileInformationClass; // bytes length which is able to be returned eventContext->File.BufferLength = irpSp->Parameters.QueryFile.Length; // copy file name to EventContext from FCB eventContext->File.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->File.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // register this IRP to pending IPR list status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); } DDbgPrint("<== DokanQueryInformation\n"); FsRtlExitFileSystem(); } return status; }
NTSTATUS DokanDispatchWrite( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; NTSTATUS status =STATUS_INVALID_PARAMETER; PEVENT_CONTEXT eventContext; ULONG eventLength; PDokanCCB ccb; PDokanFCB fcb; PDokanVCB vcb; PVOID buffer; ULONG bufferLength; //PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanWrite"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject == NULL"); status = STATUS_INVALID_PARAMETER; __leave; } vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_INVALID_PARAMETER; __leave; } DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); ccb = fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); if (fcb->Flags & DOKAN_FILE_DIRECTORY) { status = STATUS_INVALID_PARAMETER; __leave; } if (irpSp->Parameters.Write.Length == 0) { status = STATUS_SUCCESS; __leave; } if (Irp->MdlAddress) { DDbgPrint(" use MdlAddress"); buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); } else { DDbgPrint(" use UserBuffer"); buffer = Irp->UserBuffer; } if (buffer == NULL) { DDbgPrint(" buffer == NULL"); status = STATUS_INVALID_PARAMETER; __leave; } // the length of EventContext is sum of length to write and length of file name eventLength = sizeof(EVENT_CONTEXT) + irpSp->Parameters.Write.Length + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); // no more memory! if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } eventContext->Context = ccb->UserContext; //DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); // When the length is bigger than usual event notitfication buffer, // saves pointer in DiverContext to copy EventContext after allocating // more bigger memory. Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = eventContext; if (Irp->Flags & IRP_PAGING_IO) { DDbgPrint(" Paging IO"); eventContext->FileFlags |= DOKAN_PAGING_IO; } if (fileObject->Flags & FO_SYNCHRONOUS_IO) { DDbgPrint(" Synchronous IO"); eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO; } // offset of file to write eventContext->Write.ByteOffset = irpSp->Parameters.Write.ByteOffset; if (irpSp->Parameters.Write.ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE && irpSp->Parameters.Write.ByteOffset.HighPart == -1) { eventContext->FileFlags |= DOKAN_WRITE_TO_END_OF_FILE; DDbgPrint(" WriteOffset = end of file"); } if ((fileObject->Flags & FO_SYNCHRONOUS_IO) && ((irpSp->Parameters.Write.ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION) && (irpSp->Parameters.Write.ByteOffset.HighPart == -1))) { // NOTE: // http://msdn.microsoft.com/en-us/library/ms795960.aspx // Do not check IrpSp->Parameters.Write.ByteOffset.QuadPart == 0 // Probably the document is wrong. eventContext->Write.ByteOffset.QuadPart = fileObject->CurrentByteOffset.QuadPart; } // the size of buffer to write eventContext->Write.BufferLength = irpSp->Parameters.Write.Length; // the offset from the begining of structure // the contents to write will be copyed to this offset eventContext->Write.BufferOffset = FIELD_OFFSET(EVENT_CONTEXT, Write.FileName[0]) + fcb->FileName.Length + sizeof(WCHAR); // adds last null char // copies the content to write to EventContext RtlCopyMemory((PCHAR)eventContext + eventContext->Write.BufferOffset, buffer, irpSp->Parameters.Write.Length); // copies file name eventContext->Write.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Write.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // When eventlength is less than event notification buffer, // returns it to user-mode using pending event. if (eventLength <= EVENT_CONTEXT_MAX_SIZE) { DDbgPrint(" Offset %d:%d, Length %d\n", irpSp->Parameters.Write.ByteOffset.HighPart, irpSp->Parameters.Write.ByteOffset.LowPart, irpSp->Parameters.Write.Length); // EventContext is no longer needed, clear it Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0; // register this IRP to IRP waiting list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); // Resuests bigger memory // eventContext will be freed later using Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] } else { // the length at lest file name can be stored ULONG requestContextLength = max(sizeof(EVENT_CONTEXT), eventContext->Write.BufferOffset); PEVENT_CONTEXT requestContext = AllocateEventContext(vcb->Dcb, Irp, requestContextLength, ccb); // no more memory! if (requestContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0; DokanFreeEventContext(eventContext); __leave; } DDbgPrint(" Offset %d:%d, Length %d (request)\n", irpSp->Parameters.Write.ByteOffset.HighPart, irpSp->Parameters.Write.ByteOffset.LowPart, irpSp->Parameters.Write.Length); // copies from begining of EventContext to the end of file name RtlCopyMemory(requestContext, eventContext, eventContext->Write.BufferOffset); // puts actual size of RequestContext requestContext->Length = requestContextLength; // requsts enough size to copy EventContext requestContext->Write.RequestLength = eventLength; // regiters this IRP to IRP wainting list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, requestContext, 0); } } __finally { // if status of IRP is not pending, must complete current IRP if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); } else { DDbgPrint(" STATUS_PENDING"); } DDbgPrint("<== DokanWrite"); FsRtlExitFileSystem(); } return status; }
NTSTATUS DokanDispatchSetInformation( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS status = STATUS_NOT_IMPLEMENTED; PIO_STACK_LOCATION irpSp; PVOID buffer; PFILE_OBJECT fileObject; PDokanCCB ccb; PDokanFCB fcb; PDokanVCB vcb; ULONG eventLength; PFILE_OBJECT targetFileObject; PEVENT_CONTEXT eventContext; //PAGED_CODE(); vcb = DeviceObject->DeviceExtension; __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanSetInformationn\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); status = STATUS_INVALID_PARAMETER; __leave; } if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_INVALID_PARAMETER; __leave; } ccb = (PDokanCCB)fileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); buffer = Irp->AssociatedIrp.SystemBuffer; switch (irpSp->Parameters.SetFile.FileInformationClass) { case FileAllocationInformation: DDbgPrint(" FileAllocationInformation %lld\n", ((PFILE_ALLOCATION_INFORMATION)buffer)->AllocationSize.QuadPart); break; case FileBasicInformation: DDbgPrint(" FileBasicInformation\n"); break; case FileDispositionInformation: DDbgPrint(" FileDispositionInformation\n"); break; case FileEndOfFileInformation: DDbgPrint(" FileEndOfFileInformation %lld\n", ((PFILE_END_OF_FILE_INFORMATION)buffer)->EndOfFile.QuadPart); break; case FileLinkInformation: DDbgPrint(" FileLinkInformation\n"); break; case FilePositionInformation: { PFILE_POSITION_INFORMATION posInfo; posInfo = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(posInfo != NULL); DDbgPrint(" FilePositionInformation %lld\n", posInfo->CurrentByteOffset.QuadPart); fileObject->CurrentByteOffset = posInfo->CurrentByteOffset; status = STATUS_SUCCESS; __leave; } break; case FileRenameInformation: DDbgPrint(" FileRenameInformation\n"); break; case FileValidDataLengthInformation: DDbgPrint(" FileValidDataLengthInformation\n"); break; default: DDbgPrint(" unknown type:%d\n", irpSp->Parameters.SetFile.FileInformationClass); break; } // // when this IRP is not handled in swich case // // calcurate the size of EVENT_CONTEXT // it is sum of file name length and size of FileInformation eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length + irpSp->Parameters.SetFile.Length; targetFileObject = irpSp->Parameters.SetFile.FileObject; if (targetFileObject) { DDbgPrint(" FileObject Specified %wZ\n", &(targetFileObject->FileName)); eventLength += targetFileObject->FileName.Length; } eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } eventContext->Context = ccb->UserContext; eventContext->SetFile.FileInformationClass = irpSp->Parameters.SetFile.FileInformationClass; // the size of FileInformation eventContext->SetFile.BufferLength = irpSp->Parameters.SetFile.Length; // the offset from begining of structure to fill FileInfo eventContext->SetFile.BufferOffset = FIELD_OFFSET(EVENT_CONTEXT, SetFile.FileName[0]) + fcb->FileName.Length + sizeof(WCHAR); // the last null char // copy FileInformation RtlCopyMemory((PCHAR)eventContext + eventContext->SetFile.BufferOffset, Irp->AssociatedIrp.SystemBuffer, irpSp->Parameters.SetFile.Length); if (irpSp->Parameters.SetFile.FileInformationClass == FileRenameInformation || irpSp->Parameters.SetFile.FileInformationClass == FileLinkInformation) { // We need to hanle FileRenameInformation separetly because the structure of FILE_RENAME_INFORMATION // has HANDLE type field, which size is different in 32 bit and 64 bit environment. // This cases problems when driver is 64 bit and user mode library is 32 bit. PFILE_RENAME_INFORMATION renameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer; PDOKAN_RENAME_INFORMATION renameContext = (PDOKAN_RENAME_INFORMATION)((PCHAR)eventContext + eventContext->SetFile.BufferOffset); // This code assumes FILE_RENAME_INFORMATION and FILE_LINK_INFORMATION have // the same typse and fields. ASSERT(sizeof(FILE_RENAME_INFORMATION) == sizeof(FILE_LINK_INFORMATION)); renameContext->ReplaceIfExists = renameInfo->ReplaceIfExists; renameContext->FileNameLength = renameInfo->FileNameLength; RtlCopyMemory(renameContext->FileName, renameInfo->FileName, renameInfo->FileNameLength); if (targetFileObject != NULL) { // if Parameters.SetFile.FileObject is specified, replase FILE_RENAME_INFO's file name by // FileObject's file name. The buffer size is already adjusted. DDbgPrint(" renameContext->FileNameLength %d\n", renameContext->FileNameLength); DDbgPrint(" renameContext->FileName %ws\n", renameContext->FileName); RtlZeroMemory(renameContext->FileName, renameContext->FileNameLength); RtlCopyMemory(renameContext->FileName, targetFileObject->FileName.Buffer, targetFileObject->FileName.Length); renameContext->FileNameLength = targetFileObject->FileName.Length; } } // copy the file name eventContext->SetFile.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->SetFile.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // register this IRP to waiting IRP list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); } DDbgPrint("<== DokanSetInformation\n"); FsRtlExitFileSystem(); } return status; }
NTSTATUS FatFsdQueryVolumeInformation ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine implements the Fsd part of the NtQueryVolumeInformation API call. Arguments: VolumeDeviceObject - Supplies the volume device object where the file being queried exists. Irp - Supplies the Irp being processed. Return Value: NTSTATUS - The FSD status for the Irp. --*/ { NTSTATUS Status; PIRP_CONTEXT IrpContext = NULL; BOOLEAN TopLevel; DebugTrace(+1, Dbg, "FatFsdQueryVolumeInformation\n", 0); // // Call the common query routine, with blocking allowed if synchronous // FsRtlEnterFileSystem(); TopLevel = FatIsIrpTopLevel( Irp ); try { IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) ); Status = FatCommonQueryVolumeInfo( IrpContext, Irp ); } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) { // // We had some trouble trying to perform the requested // operation, so we'll abort the I/O request with // the error status that we get back from the // execption code // Status = FatProcessException( IrpContext, Irp, GetExceptionCode() ); } if (TopLevel) { IoSetTopLevelIrp( NULL ); } FsRtlExitFileSystem(); // // And return to our caller // DebugTrace(-1, Dbg, "FatFsdQueryVolumeInformation -> %08lx\n", Status); UNREFERENCED_PARAMETER( VolumeDeviceObject ); return Status; }
BOOLEAN Ext2FastIoQueryBasicInfo ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject) { PEXT2_FCB Fcb = NULL; BOOLEAN Status = FALSE; BOOLEAN FcbMainResourceAcquired = FALSE; __try { FsRtlEnterFileSystem(); __try { if (IsExt2FsDevice(DeviceObject)) { IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); #if EXT2_DEBUG DEBUG(DL_INF, ( "Ext2FastIoQueryBasicInfo: %s %s %wZ\n", Ext2GetCurrentProcessName(), "FASTIO_QUERY_BASIC_INFO", &Fcb->Mcb->FullName )); #endif if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) { if (!ExAcquireResourceSharedLite( &Fcb->MainResource, Wait)) { __leave; } FcbMainResourceAcquired = TRUE; } RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION)); /* typedef struct _FILE_BASIC_INFORMATION { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; ULONG FileAttributes; } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; */ if (IsRoot(Fcb)) { Buffer->CreationTime = Buffer->LastAccessTime = Buffer->LastWriteTime = Buffer->ChangeTime = Ext2NtTime(0); } else { Buffer->CreationTime = Fcb->Mcb->CreationTime; Buffer->LastAccessTime = Fcb->Mcb->LastAccessTime; Buffer->LastWriteTime = Fcb->Mcb->LastWriteTime; Buffer->ChangeTime = Fcb->Mcb->ChangeTime; } Buffer->FileAttributes = Fcb->Mcb->FileAttr; if (Buffer->FileAttributes == 0) { Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL; } IoStatus->Information = sizeof(FILE_BASIC_INFORMATION); IoStatus->Status = STATUS_SUCCESS; Status = TRUE; } __except (EXCEPTION_EXECUTE_HANDLER) { IoStatus->Status = GetExceptionCode(); } } __finally { if (FcbMainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } FsRtlExitFileSystem(); } #if EXT2_DEBUG if (Status == FALSE) { DEBUG(DL_ERR, ("Ext2FastIoQueryBasicInfo: %s %s Status: FALSE ***\n", Ext2GetCurrentProcessName(), "FASTIO_QUERY_BASIC_INFO")); } else if (IoStatus->Status != STATUS_SUCCESS) { DEBUG(DL_ERR, ( "Ext2FastIoQueryBasicInfo: %s %s Status: %#x ***\n", Ext2FastIoQueryBasicInfo, "FASTIO_QUERY_BASIC_INFO", IoStatus->Status )); } #endif return Status; }
NTSTATUS DokanDispatchDirectoryControl( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS status = STATUS_NOT_IMPLEMENTED; PFILE_OBJECT fileObject; PIO_STACK_LOCATION irpSp; PDokanVCB vcb; //PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanDirectoryControl\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject is NULL\n"); status = STATUS_INVALID_PARAMETER; __leave; } vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB || !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { status = STATUS_INVALID_PARAMETER; __leave; } DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DokanPrintFileName(fileObject); if (irpSp->MinorFunction == IRP_MN_QUERY_DIRECTORY) { status = DokanQueryDirectory(DeviceObject, Irp); } else if( irpSp->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY) { status = DokanNotifyChangeDirectory(DeviceObject, Irp); } else { DDbgPrint(" invalid minor function\n"); status = STATUS_INVALID_PARAMETER; } } __finally { if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } DokanPrintNTStatus(status); DDbgPrint("<== DokanDirectoryControl\n"); FsRtlExitFileSystem(); } return status; }
BOOLEAN CdFastQueryStdInfo ( __in PFILE_OBJECT FileObject, __in BOOLEAN Wait, __out PFILE_STANDARD_INFORMATION Buffer, __out PIO_STATUS_BLOCK IoStatus, __in PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This routine is for the fast query call for standard file information. Arguments: FileObject - Supplies the file object used in this operation Wait - Indicates if we are allowed to wait for the information Buffer - Supplies the output buffer to receive the basic information IoStatus - Receives the final status of the operation Return Value: BOOLEAN - TRUE if the operation succeeded and FALSE if the caller needs to take the long route. --*/ { BOOLEAN Result = FALSE; TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PAGED_CODE(); UNREFERENCED_PARAMETER( DeviceObject ); ASSERT_FILE_OBJECT( FileObject ); FsRtlEnterFileSystem(); // // Decode the file object to find the type of open and the data // structures. // TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); // // We only support this request on initialized user file or directory objects. // if ((TypeOfOpen != UserFileOpen) && ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ))) { FsRtlExitFileSystem(); return FALSE; } // // Acquire the file shared to access the Fcb. // if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) { FsRtlExitFileSystem(); return FALSE; } // // Use a try-finally to facilitate cleanup. // try { // // Only deal with 'good' Fcb's. // if (CdVerifyFcbOperation( NULL, Fcb )) { // // Check whether this is a directory. // if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { Buffer->AllocationSize.QuadPart = Buffer->EndOfFile.QuadPart = 0; Buffer->Directory = TRUE; } else { Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; Buffer->Directory = FALSE; } Buffer->NumberOfLinks = 1; Buffer->DeletePending = FALSE; // // Update the IoStatus block with the size of this data. // IoStatus->Status = STATUS_SUCCESS; IoStatus->Information = sizeof( FILE_STANDARD_INFORMATION ); Result = TRUE; } } finally { ExReleaseResourceLite( Fcb->Resource ); FsRtlExitFileSystem(); } return Result; }