NTSTATUS FatCommonPnp ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for doing PnP operations called by both the fsd and fsp threads Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PVOLUME_DEVICE_OBJECT OurDeviceObject; PVCB Vcb; // // Force everything to wait. // SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); // // Get the current Irp stack location. // IrpSp = IoGetCurrentIrpStackLocation( Irp ); // // Find our Vcb. This is tricky since we have no file object in the Irp. // OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject; // // Take the global lock to synchronise against volume teardown. // FatAcquireExclusiveGlobal( IrpContext ); // // Make sure this device object really is big enough to be a volume device // object. If it isn't, we need to get out before we try to reference some // field that takes us past the end of an ordinary device object. // if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) || NodeType( &OurDeviceObject->Vcb ) != FAT_NTC_VCB) { // // We were called with something we don't understand. // FatReleaseGlobal( IrpContext ); Status = STATUS_INVALID_PARAMETER; FatCompleteRequest( IrpContext, Irp, Status ); return Status; } #if __NDAS_FAT__ if (OurDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY) SetFlag( IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT ); #endif Vcb = &OurDeviceObject->Vcb; // // Case on the minor code. // #if __NDAS_FAT_SECONDARY__ if ( ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Secondary && ( ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode == NETDISK_SECONDARY || ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY ) ) { PSECONDARY Secondary = ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Secondary; Status = STATUS_SUCCESS; Secondary_Reference( Secondary ); switch ( IrpSp->MinorFunction ) { case IRP_MN_QUERY_REMOVE_DEVICE: { DebugTrace2( 0, Dbg, ("FatCommonPnp: IRP_MN_QUERY_REMOVE_DEVICE NetdiskEnableMode = %d\n", ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) ); ExAcquireFastMutex( &Secondary->FastMutex ); if (!Secondary->TryCloseActive) { Secondary->TryCloseActive = TRUE; ExReleaseFastMutex( &Secondary->FastMutex ); Secondary_Reference( Secondary ); //FatDebugTraceLevel |= DEBUG_TRACE_CLOSE; SecondaryTryClose( IrpContext, Secondary ); //FatDebugTraceLevel &= ~DEBUG_TRACE_CLOSE; } else { ExReleaseFastMutex( &Secondary->FastMutex ); } if (Vcb->SecondaryOpenFileCount) { LARGE_INTEGER interval; // Wait all files closed interval.QuadPart = (1 * HZ); //delay 1 seconds KeDelayExecutionThread(KernelMode, FALSE, &interval); } #if 0 if (Vcb->SecondaryOpenFileCount) { LONG ccbCount; PLIST_ENTRY ccbListEntry; PVOID restartKey; PFCB fcb; ExAcquireFastMutex( &Secondary->RecoveryCcbQMutex ); for (ccbCount = 0, ccbListEntry = Secondary->RecoveryCcbQueue.Flink; ccbListEntry != &Secondary->RecoveryCcbQueue; ccbListEntry = ccbListEntry->Flink, ccbCount++); ExReleaseFastMutex( &Secondary->RecoveryCcbQMutex ); ASSERT( !IsListEmpty(&Secondary->RecoveryCcbQueue) ); ASSERT( ccbCount == Vcb->SecondaryOpenFileCount ); DebugTrace2( 0, Dbg, ("IRP_MN_QUERY_REMOVE_DEVICE: Vcb->SecondaryCloseCount = %d, Vcb->CloseCount = %d, ccbCount = %d\n", Vcb->SecondaryOpenFileCount, Vcb->OpenCount, ccbCount) ); restartKey = NULL; fcb = NdFatGetNextFcbTableEntry( &Secondary->VolDo->Vcb, &restartKey ); ASSERT( fcb != NULL || !IsListEmpty(&Secondary->DeletedFcbQueue) ); Status = STATUS_UNSUCCESSFUL; } #endif break; } case IRP_MN_REMOVE_DEVICE: { PVOID restartKey; PFCB fcb; DebugTrace2( 0, Dbg, ("FatCommonPnp: IRP_MN_REMOVE_DEVICE NetdiskEnableMode = %d\n", ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) ); #if 0 restartKey = NULL; fcb = NdFatGetNextFcbTableEntry( &Secondary->VolDo->Vcb, &restartKey ); ASSERT( fcb == NULL && IsListEmpty(&Secondary->DeletedFcbQueue) ); #endif if (Vcb->SecondaryOpenFileCount) { ASSERT( NDFAT_BUG ); Status = STATUS_UNSUCCESSFUL; } break; } default: { DebugTrace2( 0, Dbg, ("FatCommonPnp: IrpSp-MinorFunction = %d NetdiskEnableMode = %d\n", IrpSp->MinorFunction, ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) ); if (IrpSp->MinorFunction != IRP_MN_QUERY_DEVICE_RELATIONS) { if (IrpSp->FileObject && IS_SECONDARY_FILEOBJECT(IrpSp->FileObject)) { ASSERT( FALSE ); } } Status = STATUS_SUCCESS; break; } } Secondary_Dereference( Secondary ); if (!NT_SUCCESS(Status)) { FatCompleteRequest( NULL, Irp, Status ); return Status; } } #endif switch ( IrpSp->MinorFunction ) { case IRP_MN_QUERY_REMOVE_DEVICE: Status = FatPnpQueryRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_SURPRISE_REMOVAL: Status = FatPnpSurpriseRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_REMOVE_DEVICE: Status = FatPnpRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_CANCEL_REMOVE_DEVICE: Status = FatPnpCancelRemove( IrpContext, Irp, Vcb ); break; default: FatReleaseGlobal( IrpContext ); // // Just pass the IRP on. As we do not need to be in the // way on return, ellide ourselves out of the stack. // IoSkipCurrentIrpStackLocation( Irp ); Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); // // Cleanup our Irp Context. The driver has completed the Irp. // FatCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); break; } return Status; }
NTSTATUS FatCommonPnp ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for doing PnP operations called by both the fsd and fsp threads Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PVOLUME_DEVICE_OBJECT OurDeviceObject; PVCB Vcb; // // Get the current Irp stack location. // IrpSp = IoGetCurrentIrpStackLocation( Irp ); // // Find our Vcb. This is tricky since we have no file object in the Irp. // OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject; // // Make sure this device object really is big enough to be a volume device // object. If it isn't, we need to get out before we try to reference some // field that takes us past the end of an ordinary device object. // if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) || NodeType( &OurDeviceObject->Vcb ) != FAT_NTC_VCB) { // // We were called with something we don't understand. // Status = STATUS_INVALID_PARAMETER; FatCompleteRequest( IrpContext, Irp, Status ); return Status; } // // Force everything to wait. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); Vcb = &OurDeviceObject->Vcb; // // Case on the minor code. // switch ( IrpSp->MinorFunction ) { case IRP_MN_QUERY_REMOVE_DEVICE: Status = FatPnpQueryRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_SURPRISE_REMOVAL: Status = FatPnpSurpriseRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_REMOVE_DEVICE: Status = FatPnpRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_CANCEL_REMOVE_DEVICE: Status = FatPnpCancelRemove( IrpContext, Irp, Vcb ); break; default: // // Just pass the IRP on. As we do not need to be in the // way on return, ellide ourselves out of the stack. // IoSkipCurrentIrpStackLocation( Irp ); Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); // // Cleanup our Irp Context. The driver has completed the Irp. // FatCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); break; } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FatCommonPnp ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for doing PnP operations called by both the fsd and fsp threads Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PVOLUME_DEVICE_OBJECT OurDeviceObject; PVCB Vcb; PAGED_CODE(); // // Force everything to wait. // SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); // // Get the current Irp stack location. // IrpSp = IoGetCurrentIrpStackLocation( Irp ); // // Find our Vcb. This is tricky since we have no file object in the Irp. // OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject; // // Take the global lock to synchronise against volume teardown. // #pragma prefast( push ) #pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" ) #pragma prefast( disable: 28193, "this will always wait" ) FatAcquireExclusiveGlobal( IrpContext ); #pragma prefast( pop ) // // Make sure this device object really is big enough to be a volume device // object. If it isn't, we need to get out before we try to reference some // field that takes us past the end of an ordinary device object. // #pragma prefast( suppress: 28175, "touching Size is ok for a filesystem" ) if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) || NodeType( &OurDeviceObject->Vcb ) != FAT_NTC_VCB) { // // We were called with something we don't understand. // FatReleaseGlobal( IrpContext ); Status = STATUS_INVALID_PARAMETER; FatCompleteRequest( IrpContext, Irp, Status ); return Status; } Vcb = &OurDeviceObject->Vcb; // // Case on the minor code. // switch ( IrpSp->MinorFunction ) { case IRP_MN_QUERY_REMOVE_DEVICE: Status = FatPnpQueryRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_SURPRISE_REMOVAL: Status = FatPnpSurpriseRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_REMOVE_DEVICE: Status = FatPnpRemove( IrpContext, Irp, Vcb ); break; case IRP_MN_CANCEL_REMOVE_DEVICE: Status = FatPnpCancelRemove( IrpContext, Irp, Vcb ); break; default: FatReleaseGlobal( IrpContext ); // // Just pass the IRP on. As we do not need to be in the // way on return, ellide ourselves out of the stack. // IoSkipCurrentIrpStackLocation( Irp ); Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); // // Cleanup our Irp Context. The driver has completed the Irp. // FatCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); break; } return Status; }