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

📄 floppy.c

📁 The flpydisk sample is a floppy driver that resides in the directory \NtddkSrcStorageFdcFlpydsk. It
💻 C
📖 第 1 页 / 共 5 页
字号:
            // The thread must know which diskette to operate on, but the
            // request list only passes the IRP.  So we'll stick a pointer
            // to the diskette extension in Type3InputBuffer, which is
            // a field that isn't used for floppy ioctls.
            //

            //
            // Add the request to the queue, and wake up the thread to
            // process it.
            //

//            irpSp->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)
//                disketteExtension;

            FloppyDump(
                FLOPIRPPATH,
                ("Floppy: Enqueing  up IRP: %p\n",Irp)
                );

            ntStatus = FlQueueIrpToThread(Irp, disketteExtension);

            break;

        case IOCTL_DISK_GET_MEDIA_TYPES:
        case IOCTL_STORAGE_GET_MEDIA_TYPES: {

            FloppyDump(
                FLOPSHOW,
                ("Floppy: IOCTL_DISK_GET_MEDIA_TYPES called\n")
                );

            lowestDriveMediaType = DriveMediaLimits[
                disketteExtension->DriveType].LowestDriveMediaType;
            highestDriveMediaType = DriveMediaLimits[
                disketteExtension->DriveType].HighestDriveMediaType;

            outputBufferLength =
                irpSp->Parameters.DeviceIoControl.OutputBufferLength;

            //
            // Make sure that the input buffer has enough room to return
            // at least one descriptions of a supported media type.
            //

            if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) ) ) {

                FloppyDump(
                    FLOPDBGP,
                    ("Floppy: invalid GET_MEDIA_TYPES buffer size\n")
                    );

                ntStatus = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            //
            // Assume success, although we might modify it to a buffer
            // overflow warning below (if the buffer isn't big enough
            // to hold ALL of the media descriptions).
            //

            ntStatus = STATUS_SUCCESS;

            if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) *
                ( highestDriveMediaType - lowestDriveMediaType + 1 ) ) ) {

                //
                // The buffer is too small for all of the descriptions;
                // calculate what CAN fit in the buffer.
                //

                FloppyDump(
                    FLOPDBGP,
                    ("Floppy: GET_MEDIA_TYPES buffer size too small\n")
                    );

                ntStatus = STATUS_BUFFER_OVERFLOW;

                highestDriveMediaType =
                    (DRIVE_MEDIA_TYPE)( ( lowestDriveMediaType - 1 ) +
                    ( outputBufferLength /
                    sizeof( DISK_GEOMETRY ) ) );
            }

            outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;

            for (
                i = (UCHAR)lowestDriveMediaType;
                i <= (UCHAR)highestDriveMediaType;
                i++ ) {

                outputBuffer->MediaType = DriveMediaConstants[i].MediaType;
                outputBuffer->Cylinders.LowPart =
                    DriveMediaConstants[i].MaximumTrack + 1;
                outputBuffer->Cylinders.HighPart = 0;
                outputBuffer->TracksPerCylinder =
                    DriveMediaConstants[i].NumberOfHeads;
                outputBuffer->SectorsPerTrack =
                    DriveMediaConstants[i].SectorsPerTrack;
                outputBuffer->BytesPerSector =
                    DriveMediaConstants[i].BytesPerSector;
                FloppyDump(
                    FLOPSHOW,
                    ("Floppy: media types supported [%d]\n"
                     "------- Cylinders low:  0x%x\n"
                     "------- Cylinders high: 0x%x\n"
                     "------- Track/Cyl:      0x%x\n"
                     "------- Sectors/Track:  0x%x\n"
                     "------- Bytes/Sector:   0x%x\n"
                     "------- Media Type:       %d\n",
                     i,
                     outputBuffer->Cylinders.LowPart,
                     outputBuffer->Cylinders.HighPart,
                     outputBuffer->TracksPerCylinder,
                     outputBuffer->SectorsPerTrack,
                     outputBuffer->BytesPerSector,
                     outputBuffer->MediaType)
                     );
                outputBuffer++;

                Irp->IoStatus.Information += sizeof( DISK_GEOMETRY );
            }

            break;
        }

        case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: {

            if (IsNEC_98) {
                PMOUNTDEV_SUGGESTED_LINK_NAME   suggestedName;
                WCHAR                           driveLetterNameBuffer[10];
                RTL_QUERY_REGISTRY_TABLE        queryTable[2];
                PWSTR                           valueName;
                UNICODE_STRING                  driveLetterName;

                FloppyDump(FLOPDBGP,("FLOPPY: IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME to device %#08lx"
                            " through irp %#08lx\n", 
                            DeviceObject, Irp));

                if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {

                    ntStatus = STATUS_NOT_FOUND;
                    break;
                }

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

                    ntStatus = STATUS_INVALID_PARAMETER;
                    break;
                }

                valueName = ExAllocatePool(PagedPool, sizeof(WCHAR) * 64);

                if (!valueName) {
                    ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                    break;
                }

                RtlZeroMemory( valueName, sizeof(WCHAR) * 64 );
                RtlCopyMemory( valueName, 
                               disketteExtension->DeviceName.Buffer, 
                               disketteExtension->DeviceName.Length );

                driveLetterName.Buffer = driveLetterNameBuffer;
                driveLetterName.MaximumLength = 20;
                driveLetterName.Length = 0;

                RtlZeroMemory(queryTable, 2*sizeof(RTL_QUERY_REGISTRY_TABLE));
                queryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
                                      RTL_QUERY_REGISTRY_DIRECT;
                queryTable[0].Name = valueName;
                queryTable[0].EntryContext = &driveLetterName;

                ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                                                L"\\Registry\\Machine\\System\\DISK",
                                                queryTable, NULL, NULL);

                if (!NT_SUCCESS(ntStatus)) {
                    ExFreePool(valueName);
                    break;
                }

                if (driveLetterName.Length != 4 ||
                    driveLetterName.Buffer[0] < 'A' ||
                    driveLetterName.Buffer[0] > 'Z' ||
                    driveLetterName.Buffer[1] != ':') {

                    ntStatus = STATUS_NOT_FOUND;
                    ExFreePool(valueName);
                    break;
                }

                suggestedName = Irp->AssociatedIrp.SystemBuffer;
                suggestedName->UseOnlyIfThereAreNoOtherLinks = TRUE;
                suggestedName->NameLength = 28;

                Irp->IoStatus.Information =
                        FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME, Name) + 28;

                if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
                    Irp->IoStatus.Information) {

                    Irp->IoStatus.Information =
                            sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
                    ntStatus = STATUS_BUFFER_OVERFLOW;
                    ExFreePool(valueName);
                    break;
                }

                RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE,
                                       L"\\Registry\\Machine\\System\\DISK",
                                       valueName);

                ExFreePool(valueName);

                RtlCopyMemory(suggestedName->Name, L"\\DosDevices\\", 24);
                suggestedName->Name[12] = driveLetterName.Buffer[0];
                suggestedName->Name[13] = ':';

                break;
            } // (IsNEC_98)

            // Pass this to the default.
        }

       case IOCTL_DISK_SENSE_DEVICE: {

            if (IsNEC_98) {
                FloppyDump(
                    FLOPDBGP,
                    ("Floppy: SENSE_DEVISE_STATUS \n")
                    );

                //
                // Make sure that we got all the necessary IOCTL read write parameters.
                //

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

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

                    ntStatus = STATUS_INVALID_PARAMETER;
                    break;
                }


//                irpSp->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)
//                    disketteExtension;

                FloppyDump(
                    FLOPIRPPATH,
                    ("Floppy: Enqueing  up IRP: %p\n",Irp)
                    );


                ntStatus = FlQueueIrpToThread(Irp, disketteExtension);

                break;
            } // (IsNEC_98)
        }

        default: {

            //
            // We pass down IOCTL's because ACPI uses this as a communications
            // method. ACPI *should* have used a PNP Interface mechanism, but
            // it's too late now.
            //
#if 0
            FloppyDump(
                FLOPDBGP,
                ("Floppy: invalid device request %x\n",
                 irpSp->Parameters.DeviceIoControl.IoControlCode)
                );

            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
            break;
#endif
            IoSkipCurrentIrpStackLocation( Irp );
            ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
            return ntStatus;
        }
    }

    if ( ntStatus != STATUS_PENDING ) {

        Irp->IoStatus.Status = ntStatus;
        if (!NT_SUCCESS( ntStatus ) &&
            IoIsErrorUserInduced( ntStatus )) {

            IoSetHardErrorOrVerifyDevice( Irp, DeviceObject );

        }
        IoCompleteRequest( Irp, IO_NO_INCREMENT );
    }

    return ntStatus;
}

NTSTATUS
FloppyPnp(
    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:

--*/

{
    PIO_STACK_LOCATION irpSp;
    PDISKETTE_EXTENSION disketteExtension;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    ULONG i;

    FloppyDump( FLOPSHOW, ("FloppyPnp:\n") );

    //
    //  Lock down the driver if it is not already locked.
    //
    FloppyResetDriverPaging();


    disketteExtension = DeviceObject->DeviceExtension;

    irpSp = IoGetCurrentIrpStackLocation( Irp );

    if ( disketteExtension->IsRemoved ) {

        //
        // Since the device is stopped, but we don't hold IRPs,
        // this is a surprise removal. Just fail it.
        //
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = STATUS_DELETE_PENDING;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return STATUS_DELETE_PENDING;
    }

    switch ( irpSp->MinorFunction ) {

    case IRP_MN_START_DEVICE:

        ntStatus = FloppyStartDevice( DeviceObject, Irp );
        break;

    case IRP_MN_QUERY_STOP_DEVICE:
    case IRP_MN_QUERY_REMOVE_DEVICE:

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

        if ( !disketteExtension->IsStarted ) {
            //
            // If we aren't started, we'll just pass the irp down.
            //
            IoSkipCurrentIrpStackLocation (Irp);
            ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );

            return ntStatus;
        }

        //
        //  Hold all new requests.
        //
        ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
        disketteExtension->HoldNewRequests = TRUE;
        ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));

        //
        //  Queue this irp to the floppy thread, this will shutdown the
        //  floppy thread without waiting for the typical 3 second motor
        //  timeout.
        //
        ntStatus = FlQueueIrpToThread( Irp, disketteExtension );

        //
        //  Wait for the floppy thread to finish.  This could take a few hundred
        //  milliseconds if the motor needs to be shut down.
        //
        if ( ntStatus == STATUS_PENDING ) {

⌨️ 快捷键说明

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