⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floppy.c

📁 The flpydisk sample is a floppy driver that resides in the directory \NtddkSrcStorageFdcFlpydsk. It
💻 C
📖 第 1 页 / 共 5 页
字号:
            ASSERT(disketteExtension->FloppyThread != NULL);

            KeWaitForSingleObject( disketteExtension->FloppyThread,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   NULL );
 
            //
            // Very unlikely, but it did happen once. So make
            // sure FloppyThread is not NULL.
            //
            if (disketteExtension->FloppyThread != NULL) {
               ObDereferenceObject( disketteExtension->FloppyThread );
            }

            disketteExtension->FloppyThread = NULL;

            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation( Irp );
            ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
        
        } else {
            //
            // We failed to either start the thread or get a pointer to the
            // thread object.  Either way veto the Query.
            //
            ntStatus = STATUS_UNSUCCESSFUL;
            Irp->IoStatus.Status = ntStatus;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
        }
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:
    case IRP_MN_CANCEL_REMOVE_DEVICE:

        if ( irpSp->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE ) {
            FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_CANCEL_STOP_DEVICE - Irp: %p\n", Irp) );
        } else {
            FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_CANCEL_REMOVE_DEVICE - Irp: %p\n", Irp) );
        }

        if ( !disketteExtension->IsStarted ) {

            //
            // Nothing to do, just pass the irp down:
            // no need to start the device
            //
            // Set Status to SUCCESS before passing the irp down
            //
            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation (Irp);
            ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
            
        } else  {
            
            KEVENT doneEvent;

            //
            // Set the status to STATUS_SUCCESS
            //
            Irp->IoStatus.Status = STATUS_SUCCESS;
            
            //
            // We need to wait for the lower drivers to do their job.
            //
            IoCopyCurrentIrpStackLocationToNext (Irp);
        
            //
            // Clear the event: it will be set in the completion
            // routine.
            //
            KeInitializeEvent( &doneEvent, 
                               SynchronizationEvent, 
                               FALSE);
        
            IoSetCompletionRoutine( Irp,
                                    FloppyPnpComplete,
                                    &doneEvent,
                                    TRUE, TRUE, TRUE );

            ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
        
            if ( ntStatus == STATUS_PENDING ) {

                KeWaitForSingleObject( &doneEvent,
                                       Executive,
                                       KernelMode,
                                       FALSE,
                                       NULL );

                ntStatus = Irp->IoStatus.Status;
            }
        
            ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
            disketteExtension->HoldNewRequests = FALSE;
            ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));

            //
            // Process the queued requests
            //
            FloppyProcessQueuedRequests( disketteExtension );

            //
            // We must now complete the IRP, since we stopped it in the
            // completetion routine with MORE_PROCESSING_REQUIRED.
            //
            Irp->IoStatus.Status = ntStatus;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
        }
        break;

    case IRP_MN_STOP_DEVICE:

        FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_STOP_DEVICE - Irp: %p\n", Irp) );

        disketteExtension->IsStarted = FALSE;

        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation( Irp );
        ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );

        break;

    case IRP_MN_REMOVE_DEVICE:

        FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_REMOVE_DEVICE - Irp: %p\n", Irp) );

        //
        // We need to mark the fact that we don't hold requests first, since
        // we asserted earlier that we are holding requests only if
        // we're not removed.
        //
        ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
        disketteExtension->HoldNewRequests = FALSE;
        ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));

        disketteExtension->IsStarted = FALSE;
        disketteExtension->IsRemoved = TRUE;

        //
        // Here we either have completed all the requests in a personal
        // queue when IRP_MN_QUERY_REMOVE was received, or will have to 
        // fail all of them if this is a surprise removal.
        // Note that fdoData->IsRemoved is TRUE, so pSD_ProcessQueuedRequests
        // will simply flush the queue, completing each IRP with
        // STATUS_DELETE_PENDING
        //
        FloppyProcessQueuedRequests( disketteExtension );

        //
        //  Forward this Irp to the underlying PDO
        //
        IoSkipCurrentIrpStackLocation( Irp );
        Irp->IoStatus.Status = STATUS_SUCCESS;
        ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );

        //
        //  Send notification that we are going away.
        //
        if ( disketteExtension->InterfaceString.Buffer != NULL ) {

            IoSetDeviceInterfaceState( &disketteExtension->InterfaceString,
                                       FALSE);

            RtlFreeUnicodeString( &disketteExtension->InterfaceString );
            RtlInitUnicodeString( &disketteExtension->InterfaceString, NULL );
        }

        RtlFreeUnicodeString( &disketteExtension->DeviceName );
        RtlInitUnicodeString( &disketteExtension->DeviceName, NULL );

        if ( disketteExtension->ArcName.Length != 0 ) {

            IoDeassignArcName( &disketteExtension->ArcName );
            RtlFreeUnicodeString( &disketteExtension->ArcName );
            RtlInitUnicodeString( &disketteExtension->ArcName, NULL );
        }

        //
        //  Detatch from the undelying device.
        //
        IoDetachDevice( disketteExtension->TargetObject );

        //
        //  And delete the device.
        //
        IoDeleteDevice( DeviceObject );

        IoGetConfigurationInformation()->FloppyCount--;

        break;

    default:
        FloppyDump( FLOPPNP, ("FloppyPnp: Unsupported PNP Request %x - Irp: %p\n",irpSp->MinorFunction, Irp) );
        IoSkipCurrentIrpStackLocation( Irp );
        ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
    }

    //
    //  Page out the driver if it is not busy elsewhere.
    //
    FloppyPageEntireDriver();

    return ntStatus;
}

NTSTATUS
FloppyStartDevice(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    NTSTATUS ntStatus;
    NTSTATUS pnpStatus;
    KEVENT doneEvent;
    FDC_INFO fdcInfo;

    CONFIGURATION_TYPE Dc = DiskController;
    CONFIGURATION_TYPE Fp = FloppyDiskPeripheral;

    PDISKETTE_EXTENSION disketteExtension = (PDISKETTE_EXTENSION)DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );

    FloppyDump( FLOPSHOW,("FloppyStartDevice: Irp: %p\n", Irp) );
    FloppyDump( FLOPSHOW, ("  AllocatedResources = %08x\n",irpSp->Parameters.StartDevice.AllocatedResources));
    FloppyDump( FLOPSHOW, ("  AllocatedResourcesTranslated = %08x\n",irpSp->Parameters.StartDevice.AllocatedResourcesTranslated));

    //
    // First we must pass this Irp on to the PDO.
    //
    KeInitializeEvent( &doneEvent, NotificationEvent, FALSE );

    IoCopyCurrentIrpStackLocationToNext( Irp );

    IoSetCompletionRoutine( Irp,
                            FloppyPnpComplete,
                            &doneEvent,
                            TRUE, TRUE, TRUE );

    ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );

    if ( ntStatus == STATUS_PENDING ) {

        ntStatus = KeWaitForSingleObject( &doneEvent,
                                          Executive,
                                          KernelMode,
                                          FALSE,
                                          NULL );

        ASSERT( ntStatus == STATUS_SUCCESS );

        ntStatus = Irp->IoStatus.Status;
    }

    fdcInfo.BufferCount = 0;
    fdcInfo.BufferSize = 0;

    ntStatus = FlFdcDeviceIo( disketteExtension->TargetObject,
                              IOCTL_DISK_INTERNAL_GET_FDC_INFO,
                              &fdcInfo );

    if ( NT_SUCCESS(ntStatus) ) {

        disketteExtension->MaxTransferSize = fdcInfo.MaxTransferSize;

        if ( (fdcInfo.AcpiBios) &&
             (fdcInfo.AcpiFdiSupported) ) {

            ntStatus = FlAcpiConfigureFloppy( disketteExtension, &fdcInfo );

            if ( disketteExtension->DriveType == DRIVE_TYPE_2880 ) {

                disketteExtension->PerpendicularMode |= 1 << fdcInfo.PeripheralNumber;
            }

        } else {

            INTERFACE_TYPE InterfaceType;
    
            if ( disketteExtension->DriveType == DRIVE_TYPE_2880 ) {

                disketteExtension->PerpendicularMode |= 1 << fdcInfo.PeripheralNumber;
            }

            //
            // Query the registry till we find the correct interface type,
            // since we do not know what type of interface we are on.
            //
            for ( InterfaceType = 0;
                  InterfaceType < MaximumInterfaceType;
                  InterfaceType++ ) {
    
                fdcInfo.BusType = InterfaceType;
                ntStatus = IoQueryDeviceDescription( &fdcInfo.BusType,
                                                     &fdcInfo.BusNumber,
                                                     &Dc,
                                                     &fdcInfo.ControllerNumber,
                                                     &Fp,
                                                     &fdcInfo.PeripheralNumber,
                                                     FlConfigCallBack,
                                                     disketteExtension );
    
                if (NT_SUCCESS(ntStatus)) {
                   //
                   // We found the interface we are on.
                   //
                   FloppyDump(FLOPSHOW,
                              ("Interface Type is %x\n", InterfaceType));
                   break;
                }
            }
        }

        if ( NT_SUCCESS(ntStatus) ) {

            if (IsNEC_98) {
                disketteExtension->DeviceUnit = (UCHAR)fdcInfo.UnitNumber;
                disketteExtension->DriveOnValue = (UCHAR)fdcInfo.UnitNumber;
            } else { // (IsNEC_98)
                disketteExtension->DeviceUnit = (UCHAR)fdcInfo.PeripheralNumber;
                disketteExtension->DriveOnValue =
                    (UCHAR)(fdcInfo.PeripheralNumber | ( DRVCTL_DRIVE_0 << fdcInfo.PeripheralNumber ));
            } // (IsNEC_98)

            pnpStatus = IoRegisterDeviceInterface( disketteExtension->UnderlyingPDO,
                                                   (LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID,
                                                   NULL,
                                                   &disketteExtension->InterfaceString );

            if ( NT_SUCCESS(pnpStatus) ) {

                pnpStatus = IoSetDeviceInterfaceState( &disketteExtension->InterfaceString,
                                                   TRUE );
            }

            disketteExtension->IsStarted = TRUE;

            ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
            disketteExtension->HoldNewRequests = FALSE;
            ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));

            FloppyProcessQueuedRequests( disketteExtension );
        }
    }

    Irp->IoStatus.Status = ntStatus;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    return ntStatus;
}

NTSTATUS
FloppyPnpComplete (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
/*++
Routine Description:
    A completion routine for use when calling the lower device objects to
    which our bus (FDO) is attached.

--*/
{

    KeSetEvent ((PKEVENT) Context, 1, FALSE);
    // No special priority
    // No Wait

    return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
}

NTSTATUS
FloppyPower(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

Arguments:

    DeviceObject - a pointer to the object that represents the device
    that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

--*/
{
    PDISKETTE_EXTENSION disketteExtension;
    NTSTATUS ntStatus = Irp->IoStatus.Status;
    PIO_STACK_LOCATION irpSp;
    POWER_STATE_TY

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -