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

📄 floppy.c

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

Copyright (C) Microsoft Corporation, 1991 - 1999

Module Name:

    floppy.c

Abstract:

    This is the NEC PD756 (aka AT, aka ISA, aka ix86) and Intel 82077
    (aka MIPS) floppy diskette driver for NT.

Environment:

    Kernel mode only.

--*/

//
// Include files.
//

#include "stdio.h"

#include "ntddk.h"                       // various NT definitions
#include "ntdddisk.h"                    // disk device driver I/O control codes
#include "ntddfdc.h"                     // fdc I/O control codes and parameters
#include "initguid.h"
#include "mountdev.h"
#include "acpiioct.h"

#include <flo_data.h>                    // this driver's data declarations


//
// This is the actual definition of FloppyDebugLevel.
// Note that it is only defined if this is a "debug"
// build.
//
#if DBG
extern ULONG FloppyDebugLevel = 0;
#endif

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,DriverEntry)

#pragma alloc_text(PAGE,FloppyAddDevice)
#pragma alloc_text(PAGE,FloppyPnp)
#pragma alloc_text(PAGE,FloppyPower)
#pragma alloc_text(PAGE,FlConfigCallBack)
#pragma alloc_text(PAGE,FlInitializeControllerHardware)
#pragma alloc_text(PAGE,FlInterpretError)
#pragma alloc_text(PAGE,FlDatarateSpecifyConfigure)
#pragma alloc_text(PAGE,FlRecalibrateDrive)
#pragma alloc_text(PAGE,FlDetermineMediaType)
#pragma alloc_text(PAGE,FlCheckBootSector)
#pragma alloc_text(PAGE,FlConsolidateMediaTypeWithBootSector)
#pragma alloc_text(PAGE,FlIssueCommand)
#pragma alloc_text(PAGE,FlReadWriteTrack)
#pragma alloc_text(PAGE,FlReadWrite)
#pragma alloc_text(PAGE,FlFormat)
#pragma alloc_text(PAGE,FlFinishOperation)
#pragma alloc_text(PAGE,FlStartDrive)
#pragma alloc_text(PAGE,FloppyThread)
#pragma alloc_text(PAGE,FlAllocateIoBuffer)
#pragma alloc_text(PAGE,FlFreeIoBuffer)
#pragma alloc_text(PAGE,FloppyCreateClose)
#pragma alloc_text(PAGE,FloppyDeviceControl)
#pragma alloc_text(PAGE,FloppyReadWrite)
#pragma alloc_text(PAGE,FlCheckFormatParameters)
#pragma alloc_text(PAGE,FlFdcDeviceIo)
#pragma alloc_text(PAGE,FlHdbit)
#endif

#ifdef POOL_TAGGING
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'polF')
#endif

// #define KEEP_COUNTERS 1

#ifdef KEEP_COUNTERS
ULONG FloppyUsedSeek   = 0;
ULONG FloppyNoSeek     = 0;
#endif

//
// Used for paging the driver.
//

ULONG PagingReferenceCount = 0;
PFAST_MUTEX PagingMutex = NULL;


NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    This routine is the driver's entry point, called by the I/O system
    to load the driver.  The driver's entry points are initialized and
    a mutex to control paging is initialized.

    In DBG mode, this routine also examines the registry for special
    debug parameters.

Arguments:

    DriverObject - a pointer to the object that represents this device
                   driver.

    RegistryPath - a pointer to this driver's key in the Services tree.

Return Value:

    STATUS_SUCCESS unless we can't allocate a mutex.

--*/

{
    NTSTATUS ntStatus = STATUS_SUCCESS;

#if DBG
    //
    // We use this to query into the registry as to whether we
    // should break at driver entry.
    //
    RTL_QUERY_REGISTRY_TABLE paramTable[3];
    ULONG zero = 0;
    ULONG one = 1;
    ULONG debugLevel = 0;
    ULONG shouldBreak = 0;
    ULONG notConfigurable = 0;
    PWCHAR path;
    ULONG pathLength;

    //
    // Since the registry path parameter is a "counted" UNICODE string, it
    // might not be zero terminated.  For a very short time allocate memory
    // to hold the registry path zero terminated so that we can use it to
    // delve into the registry.
    //
    // NOTE NOTE!!!! This is not an architected way of breaking into
    // a driver.  It happens to work for this driver because the author
    // likes to do things this way.
    //
    pathLength = RegistryPath->Length + sizeof(WCHAR);

    if ( path = ExAllocatePool(PagedPool, pathLength) ) {

        RtlZeroMemory( &paramTable[0], sizeof(paramTable) );
        RtlZeroMemory( path, pathLength);
        RtlMoveMemory( path, RegistryPath->Buffer, RegistryPath->Length );

        paramTable[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
        paramTable[0].Name          = L"BreakOnEntry";
        paramTable[0].EntryContext  = &shouldBreak;
        paramTable[0].DefaultType   = REG_DWORD;
        paramTable[0].DefaultData   = &zero;
        paramTable[0].DefaultLength = sizeof(ULONG);

        paramTable[1].Flags         = RTL_QUERY_REGISTRY_DIRECT;
        paramTable[1].Name          = L"DebugLevel";
        paramTable[1].EntryContext  = &debugLevel;
        paramTable[1].DefaultType   = REG_DWORD;
        paramTable[1].DefaultData   = &zero;
        paramTable[1].DefaultLength = sizeof(ULONG);

        if (!NT_SUCCESS(RtlQueryRegistryValues(
                            RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
                            path,
                            &paramTable[0],
                            NULL,
                            NULL))) {

            shouldBreak = 0;
            debugLevel = 0;

        }

        ExFreePool( path );
    }

    FloppyDebugLevel = debugLevel;

    if ( shouldBreak ) {

        DbgBreakPoint();
    }

#endif

    FloppyDump(FLOPSHOW, ("Floppy: DriverEntry\n") );

    //
    // Initialize the driver object with this driver's entry points.
    //
    DriverObject->MajorFunction[IRP_MJ_CREATE]         = FloppyCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = FloppyCreateClose;
    DriverObject->MajorFunction[IRP_MJ_READ]           = FloppyReadWrite;
    DriverObject->MajorFunction[IRP_MJ_WRITE]          = FloppyReadWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FloppyDeviceControl;
    DriverObject->MajorFunction[IRP_MJ_PNP]            = FloppyPnp;
    DriverObject->MajorFunction[IRP_MJ_POWER]          = FloppyPower;

    DriverObject->DriverUnload = FloppyUnload;

    DriverObject->DriverExtension->AddDevice = FloppyAddDevice;

    //
    //  Allocate and initialize a mutex for paging the driver.
    //
    PagingMutex = ExAllocatePool( NonPagedPool, sizeof(FAST_MUTEX) );

    if ( PagingMutex == NULL ) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    ExInitializeFastMutex(PagingMutex);

    //
    //  Now page out the driver and wait for a call to FloppyAddDevice.
    //
    MmPageEntireDriver(DriverEntry);

    DriveMediaLimits =
        (IsNEC_98 ? (PDRIVE_MEDIA_LIMITS)&_DriveMediaLimits_NEC98[0] : &_DriveMediaLimits[0]);

    DriveMediaConstants =
        (IsNEC_98 ? (PDRIVE_MEDIA_CONSTANTS)&_DriveMediaConstants_NEC98[0] : &_DriveMediaConstants[0]);

    return ntStatus;
}

VOID
FloppyUnload(
    IN PDRIVER_OBJECT DriverObject
    )
/*++

Routine Description:

    Unload the driver from the system.  The paging mutex is freed before
    final unload.

Arguments:

    DriverObject - a pointer to the object that represents this device
                   driver.

Return Value:
    
    none

--*/

{
    FloppyDump( FLOPSHOW, ("FloppyUnload:\n"));

    //
    //  The device object(s) should all be gone by now.
    //
    ASSERT( DriverObject->DeviceObject == NULL );

    //
    //  Free the paging mutex that was allocated in DriverEntry.
    //
    ExFreePool( PagingMutex );

    return;
}

NTSTATUS
FloppyAddDevice(
    IN      PDRIVER_OBJECT DriverObject,
    IN OUT  PDEVICE_OBJECT PhysicalDeviceObject
    )
/*++

Routine Description:

    This routine is the driver's pnp add device entry point.  It is
    called by the pnp manager to initialize the driver.

    Add device creates and initializes a device object for this FDO and 
    attaches to the underlying PDO.

Arguments:

    DriverObject - a pointer to the object that represents this device
    driver.
    PhysicalDeviceObject - a pointer to the underlying PDO to which this
    new device will attach.

Return Value:

    If we successfully create a device object, STATUS_SUCCESS is
    returned.  Otherwise, return the appropriate error code.

--*/

{
    NTSTATUS            ntStatus;
    PDEVICE_OBJECT      deviceObject;
    PDISKETTE_EXTENSION disketteExtension;
    FDC_INFO            fdcInfo;
    UCHAR               arcNameBuffer[256];
    STRING              arcNameString;
    WCHAR               deviceNameBuffer[20];
    UNICODE_STRING      deviceName;


    ntStatus = STATUS_SUCCESS;

    FloppyDump( FLOPSHOW, ("FloppyAddDevice:  CreateDeviceObject\n"));

    //
    //  Get some device information from the underlying PDO.
    //
    fdcInfo.BufferCount = 0;
    fdcInfo.BufferSize = 0;

    ntStatus = FlFdcDeviceIo( PhysicalDeviceObject,
                              IOCTL_DISK_INTERNAL_GET_FDC_INFO,
                              &fdcInfo );

    if ( NT_SUCCESS(ntStatus) ) {

        USHORT i = 0;

        //
        //  Create a device.  We will use the first available device name for 
        //  this device.
        //
        do {

            swprintf( deviceNameBuffer, L"\\Device\\Floppy%d", i++ );
            RtlInitUnicodeString( &deviceName, deviceNameBuffer );
            ntStatus = IoCreateDevice( DriverObject,
                                       sizeof( DISKETTE_EXTENSION ),
                                       &deviceName,
                                       FILE_DEVICE_DISK,
                                       (FILE_REMOVABLE_MEDIA | 
                                        FILE_FLOPPY_DISKETTE |
                                        FILE_DEVICE_SECURE_OPEN),
                                       FALSE,
                                       &deviceObject );

        } while ( ntStatus == STATUS_OBJECT_NAME_COLLISION );

        if ( NT_SUCCESS(ntStatus) ) {

            disketteExtension = (PDISKETTE_EXTENSION)deviceObject->DeviceExtension;

            //
            //  Save the device name.
            //
            FloppyDump( FLOPSHOW | FLOPPNP,
                        ("FloppyAddDevice - Device Object Name - %S\n", deviceNameBuffer) );

            disketteExtension->DeviceName.Buffer = ExAllocatePool( PagedPool, deviceName.Length );
            if ( disketteExtension->DeviceName.Buffer == NULL ) {

                IoDeleteDevice( deviceObject );
                return STATUS_INSUFFICIENT_RESOURCES;
            }
            disketteExtension->DeviceName.Length = 0;
            disketteExtension->DeviceName.MaximumLength = deviceName.Length;
            RtlCopyUnicodeString( &disketteExtension->DeviceName, &deviceName );

            IoGetConfigurationInformation()->FloppyCount++;

            //
            // 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
            // if it's not system initialization time; that's fine.  The ARC
            // name looks something like \ArcName\multi(0)disk(0)rdisk(0).
            //
            sprintf( arcNameBuffer,
                     "%s(%d)disk(%d)fdisk(%d)",
                     "\\ArcName\\multi",
                     fdcInfo.BusNumber,
                     fdcInfo.ControllerNumber,
                     fdcInfo.PeripheralNumber );

            RtlInitString( &arcNameString, arcNameBuffer );

            ntStatus = RtlAnsiStringToUnicodeString( &disketteExtension->ArcName,
                                                     &arcNameString,
                                                     TRUE );

            if ( NT_SUCCESS( ntStatus ) ) {

⌨️ 快捷键说明

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