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

📄 floppy.c

📁 The flpydisk sample is a floppy driver that resides in the directory \NtddkSrcStorageFdcFlpydsk. It
💻 C
📖 第 1 页 / 共 5 页
字号:
    IN OUT  PDISKETTE_EXTENSION DisketteExtension
    )

/*++

Routine Description:

    This routine queues the given irp to be serviced by the controller's
    thread.  If the thread is down then this routine creates the thread.

Arguments:

    Irp             - Supplies the IRP to queue to the controller's thread.

    ControllerData  - Supplies the controller data.

Return Value:

    May return an error if PsCreateSystemThread fails.
    Otherwise returns STATUS_PENDING and marks the IRP pending.

--*/

{
    KIRQL       oldIrql;
    NTSTATUS    status;
    HANDLE      threadHandle;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );


    //
    // Verify if the system is powering down. If so we fail
    // the irps.
    //
    ExAcquireFastMutex(&DisketteExtension->PowerDownMutex);
    if (DisketteExtension->PoweringDown == TRUE) {
       ExReleaseFastMutex(&DisketteExtension->PowerDownMutex);
       FloppyDump( FLOPDBGP, 
                  ("Queue IRP: Bailing out since power irp is waiting.\n"));

       Irp->IoStatus.Status = STATUS_POWER_STATE_INVALID;
       Irp->IoStatus.Information = 0;
       return STATUS_POWER_STATE_INVALID;
    } 
    ExReleaseFastMutex(&DisketteExtension->PowerDownMutex);
    FloppyDump( FLOPSHOW, ("Queue IRP: No power irp waiting.\n"));

    ExAcquireFastMutex(&DisketteExtension->ThreadReferenceMutex);

    if (++(DisketteExtension->ThreadReferenceCount) == 0) {
       OBJECT_ATTRIBUTES ObjAttributes;

        DisketteExtension->ThreadReferenceCount++;

        FloppyResetDriverPaging();

        //
        //  Create the thread.
        //
        ASSERT(DisketteExtension->FloppyThread == NULL);
        InitializeObjectAttributes(&ObjAttributes, NULL,
                                   OBJ_KERNEL_HANDLE,
                                   NULL,
                                   NULL);

        status = PsCreateSystemThread(&threadHandle,
                                      (ACCESS_MASK) 0L,
                                      &ObjAttributes,
                                      (HANDLE) 0L,
                                      NULL,
                                      FloppyThread,
                                      DisketteExtension);

        if (!NT_SUCCESS(status)) {
            DisketteExtension->ThreadReferenceCount = -1;

            FloppyPageEntireDriver();

            ExReleaseFastMutex(&DisketteExtension->ThreadReferenceMutex);
            return status;
        }

        status = ObReferenceObjectByHandle( threadHandle,
                                            SYNCHRONIZE,
                                            NULL,
                                            KernelMode,
                                            &DisketteExtension->FloppyThread,
                                            NULL );

        ASSERT(NT_SUCCESS(status));

        ZwClose(threadHandle);

        ExReleaseFastMutex(&DisketteExtension->ThreadReferenceMutex);

        if (!NT_SUCCESS(status)) {
            return status;
        }

    } else {
        ExReleaseFastMutex(&DisketteExtension->ThreadReferenceMutex);
    }

    IoMarkIrpPending(Irp);

    ExInterlockedInsertTailList(
        &DisketteExtension->ListEntry,
        &Irp->Tail.Overlay.ListEntry,
        &DisketteExtension->ListSpinLock );

    KeReleaseSemaphore(
        &DisketteExtension->RequestSemaphore,
        (KPRIORITY) 0,
        1,
        FALSE );

    return STATUS_PENDING;
}

NTSTATUS
FloppyCreateClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine is called only rarely by the I/O system; it's mainly
    for layered drivers to call.  All it does is complete the IRP
    successfully.

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:

    Always returns STATUS_SUCCESS, since this is a null operation.

--*/

{
    UNREFERENCED_PARAMETER( DeviceObject );

    FloppyDump(
        FLOPSHOW,
        ("FloppyCreateClose...\n")
        );

    //
    // Null operation.  Do not give an I/O boost since
    // no I/O was actually done.  IoStatus.Information should be
    // FILE_OPENED for an open; it's undefined for a close.
    //

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = FILE_OPENED;

    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    return STATUS_SUCCESS;
}

NTSTATUS
FloppyDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine is called by the I/O system to perform a device I/O
    control function.

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:

    STATUS_SUCCESS or STATUS_PENDING if recognized I/O control code,
    STATUS_INVALID_DEVICE_REQUEST otherwise.

--*/

{
    PIO_STACK_LOCATION irpSp;
    PDISKETTE_EXTENSION disketteExtension;
    PDISK_GEOMETRY outputBuffer;
    NTSTATUS ntStatus;
    ULONG outputBufferLength;
    UCHAR i;
    DRIVE_MEDIA_TYPE lowestDriveMediaType;
    DRIVE_MEDIA_TYPE highestDriveMediaType;
    ULONG formatExParametersSize;
    PFORMAT_EX_PARAMETERS formatExParameters;

    FloppyDump( FLOPSHOW, ("FloppyDeviceControl...\n") );

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

    //
    // We need to check if we are currently holding requests.
    //
    ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
    if ( disketteExtension->HoldNewRequests ) {

        //
        // Queue request only if this is not an ACPI exec method.  There is
        // a nasty recursion with ACPI and fdc/flpy that requires that these
        // requests get through in order to avoid a deadlock.
        //
        if ( irpSp->Parameters.DeviceIoControl.IoControlCode != IOCTL_ACPI_ASYNC_EVAL_METHOD ) {

            ntStatus = FloppyQueueRequest( disketteExtension, Irp );
            
            ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));
            return ntStatus;
        }
    }
    ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));

    //
    //  If the device has been removed we will just fail this request outright.
    //
    if ( disketteExtension->IsRemoved ) {

        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_DELETE_PENDING;
        IoCompleteRequest( Irp, IO_NO_INCREMENT );
        return STATUS_DELETE_PENDING;
    }

    //
    // If the device hasn't been started we will let the IOCTL through. This
    // is another hack for ACPI.
    //
    if (!disketteExtension->IsStarted) {

        IoSkipCurrentIrpStackLocation( Irp );
        return IoCallDriver( disketteExtension->TargetObject, Irp );
    }

    switch( irpSp->Parameters.DeviceIoControl.IoControlCode ) {

        case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: {

            PMOUNTDEV_NAME mountName;

            FloppyDump( FLOPSHOW, ("FloppyDeviceControl: IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n") );
            ASSERT(disketteExtension->DeviceName.Buffer);

            if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(MOUNTDEV_NAME) ) {

                ntStatus = STATUS_INVALID_PARAMETER;
                break;
            }

            mountName = Irp->AssociatedIrp.SystemBuffer;
            mountName->NameLength = disketteExtension->DeviceName.Length;

            if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(USHORT) + mountName->NameLength) {

                ntStatus = STATUS_BUFFER_OVERFLOW;
                Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
                break;
            }

            RtlCopyMemory( mountName->Name, disketteExtension->DeviceName.Buffer,
                           mountName->NameLength);

            ntStatus = STATUS_SUCCESS;
            Irp->IoStatus.Information = sizeof(USHORT) + mountName->NameLength;
            break;
            }

        case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: {

            PMOUNTDEV_UNIQUE_ID uniqueId;

            FloppyDump( FLOPSHOW, ("FloppyDeviceControl: IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n") );

            if ( !disketteExtension->InterfaceString.Buffer ||
                 irpSp->Parameters.DeviceIoControl.OutputBufferLength <
                  sizeof(MOUNTDEV_UNIQUE_ID)) {

                ntStatus = STATUS_INVALID_PARAMETER;
                break;
            }

            uniqueId = Irp->AssociatedIrp.SystemBuffer;
            uniqueId->UniqueIdLength =
                    disketteExtension->InterfaceString.Length;

            if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(USHORT) + uniqueId->UniqueIdLength) {

                ntStatus = STATUS_BUFFER_OVERFLOW;
                Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
                break;
            }

            RtlCopyMemory( uniqueId->UniqueId,
                           disketteExtension->InterfaceString.Buffer,
                           uniqueId->UniqueIdLength );

            ntStatus = STATUS_SUCCESS;
            Irp->IoStatus.Information = sizeof(USHORT) +
                                        uniqueId->UniqueIdLength;
            break;
            }

        case IOCTL_DISK_FORMAT_TRACKS:
        case IOCTL_DISK_FORMAT_TRACKS_EX:

            //
            // Make sure that we got all the necessary format parameters.
            //

            if ( irpSp->Parameters.DeviceIoControl.InputBufferLength <
                sizeof( FORMAT_PARAMETERS ) ) {

                FloppyDump(
                    FLOPDBGP,
                    ("Floppy: invalid FORMAT buffer length\n")
                    );

                ntStatus = STATUS_INVALID_PARAMETER;
                break;
            }

            //
            // Make sure the parameters we got are reasonable.
            //

            if ( !FlCheckFormatParameters(
                disketteExtension,
                (PFORMAT_PARAMETERS) Irp->AssociatedIrp.SystemBuffer ) ) {

                FloppyDump(
                    FLOPDBGP,
                    ("Floppy: invalid FORMAT parameters\n")
                    );

                ntStatus = STATUS_INVALID_PARAMETER;
                break;
            }

            //
            // If this is an EX request then make a couple of extra checks
            //

            if (irpSp->Parameters.DeviceIoControl.IoControlCode ==
                IOCTL_DISK_FORMAT_TRACKS_EX) {

                if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
                    sizeof(FORMAT_EX_PARAMETERS)) {

                    ntStatus = STATUS_INVALID_PARAMETER;
                    break;
                }

                formatExParameters = (PFORMAT_EX_PARAMETERS)
                                     Irp->AssociatedIrp.SystemBuffer;
                formatExParametersSize =
                        FIELD_OFFSET(FORMAT_EX_PARAMETERS, SectorNumber) +
                        formatExParameters->SectorsPerTrack*sizeof(USHORT);

                if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
                    formatExParametersSize ||
                    formatExParameters->FormatGapLength >= 0x100 ||
                    formatExParameters->SectorsPerTrack >= 0x100) {

                    ntStatus = STATUS_INVALID_PARAMETER;
                    break;
                }
            }

            //
            // Fall through to queue the request.
            //

        case IOCTL_DISK_CHECK_VERIFY:
        case IOCTL_STORAGE_CHECK_VERIFY:
        case IOCTL_DISK_GET_DRIVE_GEOMETRY:
        case IOCTL_DISK_IS_WRITABLE:

            //

⌨️ 快捷键说明

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