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

📄 floppy.c

📁 The sfloppy sample is a super floppy driver that resides in the directory \NtddkSrcStoragesfloppy. I
💻 C
📖 第 1 页 / 共 5 页
字号:

Arguments:

    DriverObject - Pointer to driver object created by system.

Return Value:

    NTSTATUS

--*/

{
    CLASS_INIT_DATA InitializationData;

    //
    // Zero InitData
    //

    RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA));

    //
    // Set sizes
    //

    InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
    InitializationData.FdoData.DeviceExtensionSize =
        sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA);

    InitializationData.FdoData.DeviceType = FILE_DEVICE_DISK;
    InitializationData.FdoData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE;

    //
    // Set entry points
    //

    InitializationData.FdoData.ClassInitDevice = ScsiFlopInitDevice;
    InitializationData.FdoData.ClassStartDevice = ScsiFlopStartDevice;
    InitializationData.FdoData.ClassStopDevice = ScsiFlopStopDevice;
    InitializationData.FdoData.ClassRemoveDevice = ScsiFlopRemoveDevice;

    InitializationData.FdoData.ClassReadWriteVerification = ScsiFlopReadWriteVerification;
    InitializationData.FdoData.ClassDeviceControl = ScsiFlopDeviceControl;

    InitializationData.FdoData.ClassShutdownFlush = NULL;
    InitializationData.FdoData.ClassCreateClose = NULL;
    InitializationData.FdoData.ClassError = ScsiFlopProcessError;
    InitializationData.ClassStartIo = NULL;

    InitializationData.ClassAddDevice = ScsiFlopAddDevice;
    InitializationData.ClassUnload = ScsiFlopUnload;
    //
    // Call the class init routine
    //

    return ClassInitialize( DriverObject, RegistryPath, &InitializationData);


} // end DriverEntry()

VOID
ScsiFlopUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{
    PAGED_CODE();
    UNREFERENCED_PARAMETER(DriverObject);
    return;
}


NTSTATUS
ScsiFlopAddDevice (
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT Pdo
    )
/*++

Routine Description:

    This routine creates and initializes a new FDO for the corresponding
    PDO.  It may perform property queries on the FDO but cannot do any
    media access operations.

Arguments:

    DriverObject - Scsiscan class driver object.

    Pdo - the physical device object we are being added to

Return Value:

    status

--*/
{

    PCONFIGURATION_INFORMATION configurationInformation;

    NTSTATUS status;
    ULONG floppyCount = IoGetConfigurationInformation()->FloppyCount;

    //
    // Get the number of disks already initialized.
    //

    status = CreateFlopDeviceObject(DriverObject, Pdo, floppyCount);

    if (NT_SUCCESS(status)) {

        //
        // Increment system floppy device count.
        //

        IoGetConfigurationInformation()->FloppyCount++;
    }

    return status;
}



NTSTATUS
CreateFlopDeviceObject(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT Pdo,
    IN ULONG DeviceCount
    )

/*++

Routine Description:

    This routine creates an object for the device and then calls the
    SCSI port driver for media capacity and sector size.

Arguments:

    DriverObject - Pointer to driver object created by system.
    PortDeviceObject - to connect to SCSI port driver.
    DeviceCount - Number of previously installed Floppys.
    AdapterDescriptor - Pointer to structure returned by SCSI port
                        driver describing adapter capabilites (and limitations).
    DeviceDescriptor - Pointer to configuration information for this device.

Return Value:

--*/
{
    NTSTATUS        status;
    PDEVICE_OBJECT  deviceObject;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;

    PDISK_DATA  diskData;
    PVOID       senseData;

    BOOLEAN freeDevice = TRUE;


    DebugPrint((3,"CreateFlopDeviceObject: Enter routine\n"));

    //
    // Try to claim the device.
    //

    status = ClassClaimDevice(Pdo,FALSE);

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

    DeviceCount--;

    do {
        UCHAR           name[256];

        //
        // Create device object for this device.
        //

        DeviceCount++;

        sprintf(name, "\\Device\\Floppy%d", DeviceCount);

        status = ClassCreateDeviceObject(DriverObject,
                                         name,
                                         Pdo,
                                         TRUE,
                                         &deviceObject);

    } while ((status == STATUS_OBJECT_NAME_COLLISION) ||
             (status == STATUS_OBJECT_NAME_EXISTS));

    if (!NT_SUCCESS(status)) {
        DebugPrint((1,"CreateFlopDeviceObjects: Can not create device\n"));
        goto CreateFlopDeviceObjectExit;
    }

    //
    // Indicate that IRPs should include MDLs.
    //

    deviceObject->Flags |= DO_DIRECT_IO;

    fdoExtension = deviceObject->DeviceExtension;

    //
    // Back pointer to device object.
    //

    fdoExtension->CommonExtension.DeviceObject = deviceObject;

    //
    // This is the physical device.
    //

    fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension;

    //
    // Reset the drive type.
    //

    diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
    diskData->DriveType = DRIVE_TYPE_NONE;
    diskData->IsDMF = FALSE;
    // diskData->EnableDMF = TRUE;

    //
    // Initialize lock count to zero. The lock count is used to
    // disable the ejection mechanism when media is mounted.
    //

    fdoExtension->LockCount = 0;

    //
    // Save system floppy number
    //

    fdoExtension->DeviceNumber = DeviceCount;

    //
    // Set the alignment requirements for the device based on the
    // host adapter requirements
    //

    if (Pdo->AlignmentRequirement > deviceObject->AlignmentRequirement) {
        deviceObject->AlignmentRequirement = Pdo->AlignmentRequirement;
    }

    //
    // Clear the SrbFlags and disable synchronous transfers
    //

    fdoExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;

    //
    // Finally, attach to the PDO
    //

    fdoExtension->LowerPdo = Pdo;

    fdoExtension->CommonExtension.LowerDeviceObject =
        IoAttachDeviceToDeviceStack(deviceObject, Pdo);

    if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) {

        status = STATUS_UNSUCCESSFUL;
        goto CreateFlopDeviceObjectExit;
    }

    deviceObject->StackSize++;

    //
    // The device is initialized properly - mark it as such.
    //

    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    return STATUS_SUCCESS;

CreateFlopDeviceObjectExit:

    if (deviceObject != NULL) {
        IoDeleteDevice(deviceObject);
    }

    return status;

} // end CreateFlopDeviceObject()


NTSTATUS
ScsiFlopInitDevice(
    IN PDEVICE_OBJECT Fdo
    )
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
    PDISK_DATA diskData = commonExtension->DriverData;

    PVOID senseData = NULL;
    ULONG timeOut;
    BOOLEAN srbListInitialized = FALSE;

    NTSTATUS status = STATUS_SUCCESS;

    //
    // Allocate request sense buffer.
    //

    senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

    if (senseData == NULL) {

        //
        // The buffer cannot be allocated.
        //

        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    //
    // Set the sense data pointer in the device extension.
    //

    fdoExtension->SenseData = senseData;

    //
    // Build the lookaside list for srb's for this device.
    //

    ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION)fdoExtension,
                                    SFLOPPY_SRB_LIST_SIZE);

    srbListInitialized = TRUE;

    //
    // Register for media change notification
    //
    ClassInitializeMediaChangeDetection(fdoExtension,
                                        "SFloppy");

    //
    // Set timeout value in seconds.
    //

    timeOut = ClassQueryTimeOutRegistryValue(Fdo);
    if (timeOut) {
        fdoExtension->TimeOutValue = timeOut;
    } else {
        fdoExtension->TimeOutValue = SCSI_FLOPPY_TIMEOUT;
    }

    //
    // Floppies are not partitionable so starting offset is 0.
    //

    fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)0;

#if 0
    if (!IsFloppyDevice(Fdo) ||
        !(Fdo->Characteristics & FILE_REMOVABLE_MEDIA) ||
        (fdoExtension->DeviceDescriptor->DeviceType != DIRECT_ACCESS_DEVICE)) {

        ExFreePool(senseData);
        status = STATUS_NO_SUCH_DEVICE;
        return status;
    }
#endif

    RtlZeroMemory(&(fdoExtension->DiskGeometry),
                  sizeof(DISK_GEOMETRY));

    //
    // Determine the media type if possible. Set the current media type to
    // Unknown so that determine media type will check the media.
    //

    fdoExtension->DiskGeometry.MediaType = Unknown;

#if 0
    {
        PUCHAR vendorId;
        UCHAR vendorString[6] = {'I','N','S','I','T','E'};

        vendorId = (PUCHAR)fdoExtension->DeviceDescriptor +
                           fdoExtension->DeviceDescriptor->VendorIdOffset;
        if (!SFlopStringCmp(vendorId,vendorString,6)) {
            diskData->EnableDMF = FALSE;
        }
    }
#endif

    //
    // Register interfaces for this device.
    //

    {
        UNICODE_STRING interfaceName;

        RtlInitUnicodeString(&interfaceName, NULL);

        status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
                                           (LPGUID) &FloppyClassGuid,
                                           NULL,
                                           &interfaceName);

        if(NT_SUCCESS(status)) {
            diskData->FloppyInterfaceString = interfaceName;
        } else {
            RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL);
            DebugPrint((1, "ScsiFlopStartDevice: Unable to register device "
                           "interface for fdo %#p [%#08lx]\n",
                        Fdo, status));
        }
    }

    return (STATUS_SUCCESS);
}

NTSTATUS
ScsiFlopStartDevice(
    IN PDEVICE_OBJECT Fdo
    )
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;

    PIRP        irp;
    IO_STATUS_BLOCK ioStatus;

    SCSI_ADDRESS    scsiAddress;

    WCHAR   ntNameBuffer[256];
    UNICODE_STRING  ntUnicodeString;

    WCHAR   arcNameBuffer[256];
    UNICODE_STRING  arcUnicodeString;

    KEVENT event;

    NTSTATUS status = STATUS_SUCCESS;

    KeInitializeEvent(&event,SynchronizationEvent,FALSE);

    DetermineMediaType(Fdo); // ignore unsuccessful here

    //
    // Create a symbolic link from the disk name to the corresponding
    // ARC name, to be used if we're booting off the disk.  This will
    // fail if it's not system initialization time; that's fine.  The
    // ARC name looks something like \ArcName\scsi(0)Flop(0)fdisk(0).
    // In order to get the address, we need to send a IOCTL_SCSI_GET_ADDRESS...
    //

    irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS,
                                        Fdo,
                                        NULL,
                                        0,
                                        &scsiAddress,
                                        sizeof(scsiAddress),
                                        FALSE,
                                        &event,
                                        &ioStatus);

    if (irp == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp);

    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatus.Status;
    }

    swprintf(arcNameBuffer,
             L"\\ArcName\\scsi(%d)disk(%d)fdisk(%d)",
             scsiAddress.PortNumber,

⌨️ 快捷键说明

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