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

📄 charsample.c

📁 一个简单的wdm驱动开发实例,可以大概看开发流程作为入门
💻 C
📖 第 1 页 / 共 2 页
字号:
// CharSample.c
//
// Generated by C DriverWizard 3.1.0 (Build 1722)
// Requires DDK Only
// File created on 1/23/2009
//

#include "pch.h"
#include "..\intrface.h"
#ifdef CHARSAMPLE_WMI_TRACE
#include "CharSample.tmh"
#endif

// global data
CHARSAMPLE_DATA g_Data;

///////////////////////////////////////////////////////////////////////////////////////////////////
//  DriverEntry 
//      Installable driver initialization entry point.
//      This entry point is called directly by the I/O system.
//
//  Arguments:
//      IN  DriverObject
//              pointer to the driver object
//
//      IN  RegistryPath
//              pointer to a unicode string representing the path,
//              to driver-specific key in the registry.
//
//  Return Value:
//      Status
//
NTSTATUS DriverEntry(
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PUNICODE_STRING RegistryPath
    )
{
    NTSTATUS    status;

    CharSampleDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"++");
    CharSampleDebugPrint(DBG_INIT, DBG_INFO, "Compiled at %s on %s", __TIME__, __DATE__);

#ifdef DBG
//    DbgBreakPoint();
#endif

#ifdef CHARSAMPLE_WMI_TRACE 
    WPP_INIT_TRACING(DriverObject, RegistryPath);
#endif

    status = STATUS_SUCCESS;

    RtlZeroMemory(&g_Data, sizeof(CHARSAMPLE_DATA));

    // save registry path for wmi
    g_Data.RegistryPath.Length = RegistryPath->Length;
    g_Data.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
    g_Data.RegistryPath.Buffer = (PWCHAR)ExAllocatePoolWithTag(
                                            PagedPool,
                                            g_Data.RegistryPath.MaximumLength,
                                            CHARSAMPLE_POOL_TAG
                                            );

    if (g_Data.RegistryPath.Buffer == NULL)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        CharSampleDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__": Failed to allocate memory for RegistryPath");

        return status;
    }

    RtlCopyUnicodeString(&g_Data.RegistryPath, RegistryPath);

    // detect current operating system
    if (IoIsWdmVersionAvailable(1, 0x30))
    {
        g_Data.WdmVersion = 0x0130;
    }
    else if (IoIsWdmVersionAvailable(1, 0x20))
    {
        g_Data.WdmVersion = 0x0120;
    }
    else if (IoIsWdmVersionAvailable(1, 0x10))
    {
        g_Data.WdmVersion = 0x0110;
    }
    else if (IoIsWdmVersionAvailable(1, 0x05))
    {
        g_Data.WdmVersion = 0x0105;
    }
    else
    {
        g_Data.WdmVersion = 0x0100;
    }

    // setup our dispatch function table in the driver object
    DriverObject->MajorFunction[IRP_MJ_PNP] = CharSamplePnpDispatch;
    DriverObject->MajorFunction[IRP_MJ_POWER] = CharSamplePowerDispatch;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = CharSampleCreateDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = CharSampleCloseDispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CharSampleDeviceIoControlDispatch;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CharSampleSystemControlDispatch;

    DriverObject->DriverExtension->AddDevice = CharSampleAddDevice;
    DriverObject->DriverUnload = CharSampleUnload;

    CharSampleDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"--. STATUS %x", status);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSampleAddDevice 
//      The PnP manager new device callback
//
//  Arguments:
//      IN  DeviceObject
//              pointer to a device object.
//
//      IN  PhysicalDeviceObject
//              pointer to a device object created by the
//              underlying bus driver.
//
//  Return Value:
//      Status
//
NTSTATUS CharSampleAddDevice(
    IN PDRIVER_OBJECT   DriverObject,
    IN PDEVICE_OBJECT   PhysicalDeviceObject
    )
{
    NTSTATUS                            status;
    PDEVICE_OBJECT                      deviceObject;
    PCHARSAMPLE_DEVICE_EXTENSION   deviceExtension;

    CharSampleDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"++: PDO %p", PhysicalDeviceObject);

    // Create our function device object.
    status = IoCreateDevice(
                DriverObject,
                sizeof (CHARSAMPLE_DEVICE_EXTENSION),
                NULL,                    // no name
                FILE_DEVICE_UNKNOWN,
                FILE_DEVICE_SECURE_OPEN, // Do not use if binary intended for 9x
                FALSE,
                &deviceObject
                );

    if (!NT_SUCCESS(status)) 
    {
        CharSampleDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__"--. IoCreateDevice STATUS %x", status);

        return status;
    }

    CharSampleDebugPrint(DBG_INIT, DBG_INFO, __FUNCTION__": Created FDO %p", deviceObject);

    // Initialize the device extension.
    deviceExtension = (PCHARSAMPLE_DEVICE_EXTENSION)deviceObject->DeviceExtension;

    // Zero the memory
    RtlZeroMemory(deviceExtension, sizeof(CHARSAMPLE_DEVICE_EXTENSION));

    // save the PDO pointer
    deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;

    // save our device object
    deviceExtension->DeviceObject = deviceObject;

    // set RemoveCount to 1. Transition to zero
    // means IRP_MN_REMOVE_DEVICE was received
    deviceExtension->RemoveCount = 1;

    // Initialize Remove event
    KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent, FALSE);

    // initialize io lock
    CharSampleInitializeIoLock(&deviceExtension->IoLock, deviceObject);

    deviceExtension->PnpState = PnpStateNotStarted;
    deviceExtension->PreviousPnpState = PnpStateNotStarted;

    // Initialize the device object flags

    // All WDM drivers are supposed to set this flag.  Devices
    // requiring a large amount of current at statup set the 
    // DO_POWER_INRUSH flag instead.  These flags are mutually
    // exclusive.
    if (PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) 
    {
        deviceObject->Flags |= DO_POWER_PAGABLE;
    }

    // This flag sets the buffering method for reads and writes
    // to METHOD_DIRECT.  IOCTLs are handled by IO control codes
    // independent of the value of this flag.
    deviceObject->Flags |= DO_DIRECT_IO;

    // Attach our device to the device stack and get the device object to 
    // which we send down IRPs to.
    deviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(
                                            deviceObject,
                                            PhysicalDeviceObject
                                            );

    if (deviceExtension->LowerDeviceObject == NULL) 
    {
        CharSampleDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__"--. IoAttachDeviceToDeviceStack failed");

        IoDeleteDevice(deviceObject);
        return STATUS_DEVICE_REMOVED;
    }

    // Initialize our device's interface
    status = IoRegisterDeviceInterface (
                PhysicalDeviceObject,
                (LPGUID)&GUID_DEVINTERFACE_CHARSAMPLE,
                NULL,
                &deviceExtension->InterfaceName
                );

    if (!NT_SUCCESS(status)) 
    {
        CharSampleDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__"--. IoRegisterDeviceInterface STATUS %x", status);

        IoDetachDevice(deviceExtension->LowerDeviceObject);
        IoDeleteDevice(deviceObject);
        return status;
    }

    // increment device instance count
    ++g_Data.InstanceCount;

    // We are all done, so we need to clear the
    // DO_DEVICE_INITIALIZING flag.  This must be our
    // last action in AddDevice
    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    CharSampleDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"--. CharSampleAddDevice--. STATUS %x", status);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSampleStartDevice
//      Start device handler, sets up resources
//
//  Arguments:
//      IN  DeviceExtension
//              our device extension
//
//      IN  Irp
//              pointer to the Start IRP
//
//  Return Value:
//      NT status code
//
NTSTATUS CharSampleStartDevice(
    IN  PCHARSAMPLE_DEVICE_EXTENSION    DeviceExtension,
    IN  PIRP                            Irp
    )
{
    NTSTATUS                        status = STATUS_SUCCESS;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR resource;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceTrans;
    PCM_PARTIAL_RESOURCE_LIST       partialResourceList;
    PCM_PARTIAL_RESOURCE_LIST       partialResourceListTranslated;
    PIO_STACK_LOCATION              irpStack;
    POWER_STATE                     powerState;
    ULONG                           ii;

    CharSampleDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);

    // Get our current IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    // Do whatever initialization needed when starting the device:
    // gather information about it,  update the registry, etc.
    // At this point, the lower level drivers completed the IRP
    if ((irpStack->Parameters.StartDevice.AllocatedResources != NULL) &&
        (irpStack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)) 
    {
        // Parameters.StartDevice.AllocatedResources points to a
        // CM_RESOURCE_LIST describing the hardware resources that
        // the PnP Manager assigned to the device. This list contains
        // the resources in raw form. Use the raw resources to program
        // the device.

        partialResourceList =
            &irpStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;

        resource = &partialResourceList->PartialDescriptors[0];

        // Parameters.StartDevice.AllocatedResourcesTranslated points
        // to a CM_RESOURCE_LIST describing the hardware resources that
        // the PnP Manager assigned to the device. This list contains
        // the resources in translated form. Use the translated resources
        // to connect the interrupt vector, map I/O space, and map memory.

        partialResourceListTranslated =
            &irpStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;

        resourceTrans = &partialResourceListTranslated->PartialDescriptors[0];

        // search the resources
        for (ii = 0;
             ii < partialResourceList->Count;
             ++ii, ++resource, ++resourceTrans) 
        {

            switch (resource->Type) 
            {
            case CmResourceTypePort:
                CharSampleDebugPrint(DBG_PNP, DBG_INFO,  "Resource Type Port");
                CharSampleDebugPrint(DBG_PNP, DBG_INFO, "Port.Start %I64x", resource->u.Port.Start.QuadPart);
                CharSampleDebugPrint(DBG_PNP, DBG_INFO, "Port.Length %x", resource->u.Port.Length);
                break;
            case CmResourceTypeMemory:
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Resource Type Memory");
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Memory.Start %I64x", resource->u.Memory.Start.QuadPart);
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Memory.Length %x", resource->u.Memory.Length);
                break;
            case CmResourceTypeInterrupt:
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Resource Type Interrupt");
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Level %x", resourceTrans->u.Interrupt.Level);
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Vector %x", resourceTrans->u.Interrupt.Vector);
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Affinity %x\n", resourceTrans->u.Interrupt.Affinity);
                break;
            default:
                CharSampleDebugPrint(DBG_PNP, DBG_TRACE, "Unknown Resource Type %x", resourceTrans->Type);
                break;
            }
        }
    }

    //*****************************************************************
    //*****************************************************************
    // TODO: check that all required resources have been allocated
    //*****************************************************************
    //*****************************************************************
    //*****************************************************************
    //*****************************************************************
    // TODO: allocate and initialize dma and shared memory resources
    //*****************************************************************
    //*****************************************************************


    //*****************************************************************
    //*****************************************************************
    // TODO: Reset and initialize your hardware
    //*****************************************************************
    //*****************************************************************

    //*****************************************************************
    //*****************************************************************
    // TODO: enable interrupts
    //*****************************************************************
    //*****************************************************************

    CharSampleDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSampleFreeResources
//      This routine returns all the resources acquired during
//      device startup.  Here we disconnect from any interrupt, 
//      unmap any I/O ports that are mapped in StartDevice, and 
//      disable any device interfaces or symbolic links.  
//      Before disconnecting an interrupt, be sure the device can
//      no longer generate interrupts.
//
//  Arguments:
//      IN  DeviceExtension
//              our device extension
//
//  Return Value:
//      NT status code
//
NTSTATUS CharSampleFreeResources(
    IN  PCHARSAMPLE_DEVICE_EXTENSION DeviceExtension
    )
{
    NTSTATUS    status;

    CharSampleDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++");

    CharSampleDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--");

    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSampleCreateDispatch
//      Dispatch routine for IRP_MJ_CREATE requests.
//
//  Arguments:
//      IN  DeviceObject
//              pointer to the device object for our device
//
//      IN  Irp
//              the create IRP
//
//  Return Value:
//      NT status code.
//
NTSTATUS CharSampleCreateDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    PCHARSAMPLE_DEVICE_EXTENSION    deviceExtension;
    NTSTATUS                status;

    CharSampleDebugPrint(DBG_CREATECLOSE, DBG_TRACE, __FUNCTION__": IRP %p", Irp);

    deviceExtension = (PCHARSAMPLE_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if (!CharSampleAcquireRemoveLock(deviceExtension))
    {
        status = STATUS_NO_SUCH_DEVICE;

⌨️ 快捷键说明

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