第一个入门WDM驱动

HelloWDM.h

#pragma once

#ifdef __cplusplus
extern "C"
{
#endif
#include <ntddk.h>
#ifdef __cplusplus
};
#endif

#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")

#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

typedef struct _DEVICE_EXTERNSION{
    PDEVICE_OBJECT fdo;
    PDEVICE_OBJECT NextStackDevice;
    UNICODE_STRING ustrDeviceName; //设备名称
    UNICODE_STRING ustrSymLinkName; //符号链接名
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;

//函数声明
NTSTATUS HelloWDMAddDevice(
    IN PDRIVER_OBJECT pDriverObject,
    IN PDEVICE_OBJECT PhySicalDeviceObject);
NTSTATUS HelloWDMPnp(
    IN PDEVICE_OBJECT fdo,
    IN PIRP pIrp);
VOID HelloWDMUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS HelloWDMDispatchRoutine(
    IN PDEVICE_OBJECT fdo,
    IN PIRP pIrp);
extern "C" NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING pRegistryPath);

HelloWDM.cpp

#include "HelloWDM.h"

/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
      pDriverObject:从I/O管理器中传进来的驱动对象
      pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
#pragma INITCODE
extern "C" NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING pRegistryPath)
{
    KdPrint(("Enter DriverEntry\n"));

    pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
    pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = 
    pDriverObject->MajorFunction[IRP_MJ_CREATE] =
    pDriverObject->MajorFunction[IRP_MJ_READ] = 
    pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
    pDriverObject->DriverUnload = HelloWDMUnload;

    KdPrint(("Leave DriverEntry\n"));
    return STATUS_SUCCESS;
}


/************************************************************************
* 函数名称:HelloWDMAddDevice
* 功能描述:添加新设备
* 参数列表:
      DriverObject:从I/O管理器中传进来的驱动对象
      PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象
* 返回 值:返回添加新设备状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloWDMAddDevice(
    IN PDRIVER_OBJECT pDriverObject,
    IN PDEVICE_OBJECT PhySicalDeviceObject)
{
    PAGED_CODE();//只在Check版本中有效
    KdPrint(("Enter HelloWDMAddDevice\n"));

    NTSTATUS status;
    PDEVICE_OBJECT fdo;
    UNICODE_STRING devName;
    RtlInitUnicodeString(&devName, L"\\Device\\MyWDMDevice");
    
    status = IoCreateDevice(
        pDriverObject,
        sizeof(DEVICE_EXTENSION),
        &(UNICODE_STRING)devName,
        FILE_DEVICE_UNKNOWN,
        0, FALSE,
        &fdo);
    if(!NT_SUCCESS(status))
        return status;

    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
    pdx->fdo = fdo;
    //将此fdo(功能设备对象)挂载在设备堆栈上,并将返回值(下层堆栈的位置),记录在设备扩展结构中
    pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhySicalDeviceObject);
    UNICODE_STRING symLinkName;
    RtlInitUnicodeString(&symLinkName, L"\\??\\HelloWDM");
    pdx->ustrDeviceName = devName;
    pdx->ustrSymLinkName = symLinkName;

    status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName, &(UNICODE_STRING)devName);
    if(!NT_SUCCESS(status))
    {
        IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
        status = IoCreateSymbolicLink(&symLinkName, &devName);
        if(!NT_SUCCESS(status))
            return status;
    }

    fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
    fdo->Flags &= ~DO_DEVICE_INITIALIZING;

    KdPrint(("Leave HelloWDMAddDevice\n"));
    return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:DefaultPnpHandler
* 功能描述:对PNP IRP进行缺省处理
* 参数列表:
      pdx:设备对象的扩展
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/ 
#pragma PAGEDCODE
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
{
    PAGED_CODE();
    KdPrint(("Enter DefaultPnpHandler\n"));
    //略过当前堆栈
    IoSkipCurrentIrpStackLocation(Irp);
    KdPrint(("Leave DefaultPnpHandler\n"));
    //用下层堆栈的驱动设备对象处理此IRP
    return IoCallDriver(pdx->NextStackDevice, Irp);
}

/************************************************************************
* 函数名称:HandleRemoveDevice
* 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理
* 参数列表:
      pdx:设备对象的扩展
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
    PAGED_CODE();
    KdPrint(("Enter HandleRemoveDevice\n"));

    Irp->IoStatus.Status = STATUS_SUCCESS;
    NTSTATUS status = DefaultPnpHandler(pdx, Irp);
    //删除符号链接
    IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);

    //从车陂堆栈中卸载此设备对象
    if (pdx->NextStackDevice)
        IoDetachDevice(pdx->NextStackDevice);
    
    //删除设备对象fdo:
    IoDeleteDevice(pdx->fdo);
    KdPrint(("Leave HandleRemoveDevice\n"));
    return status;
}

/************************************************************************
* 函数名称:HelloWDMPnp
* 功能描述:对即插即用IRP进行处理
* 参数列表:
      fdo:功能设备对象
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloWDMPnp(
    IN PDEVICE_OBJECT fdo,
    IN PIRP pIrp)
{
    PAGED_CODE();//确保该例程运行在低于APC_LEVEL的中断优先级的级别上

    KdPrint(("Enter HelloWDMPnp\n"));
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
    //得到当前IRP的堆栈
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
    static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) = 
    {                    
        DefaultPnpHandler,        // IRP_MN_START_DEVICE
        DefaultPnpHandler,        // IRP_MN_QUERY_REMOVE_DEVICE
        HandleRemoveDevice,        // IRP_MN_REMOVE_DEVICE
        DefaultPnpHandler,        // IRP_MN_CANCEL_REMOVE_DEVICE
        DefaultPnpHandler,        // IRP_MN_STOP_DEVICE
        DefaultPnpHandler,        // IRP_MN_QUERY_STOP_DEVICE
        DefaultPnpHandler,        // IRP_MN_CANCEL_STOP_DEVICE
        DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_RELATIONS
        DefaultPnpHandler,        // IRP_MN_QUERY_INTERFACE
        DefaultPnpHandler,        // IRP_MN_QUERY_CAPABILITIES
        DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCES
        DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
        DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_TEXT
        DefaultPnpHandler,        // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
        DefaultPnpHandler,        // 
        DefaultPnpHandler,        // IRP_MN_READ_CONFIG
        DefaultPnpHandler,        // IRP_MN_WRITE_CONFIG
        DefaultPnpHandler,        // IRP_MN_EJECT
        DefaultPnpHandler,        // IRP_MN_SET_LOCK
        DefaultPnpHandler,        // IRP_MN_QUERY_ID
        DefaultPnpHandler,        // IRP_MN_QUERY_PNP_DEVICE_STATE
        DefaultPnpHandler,        // IRP_MN_QUERY_BUS_INFORMATION
        DefaultPnpHandler,        // IRP_MN_DEVICE_USAGE_NOTIFICATION
        DefaultPnpHandler,        // IRP_MN_SURPRISE_REMOVAL
    };

    ULONG fcn = stack->MinorFunction;
    if (fcn >= arraysize(fcntab))
    {    // unknown function
        status = DefaultPnpHandler(pdx, pIrp); // some function we don't know about
        return status;
    }    // unknown function

#if DBG
    static char* fcnname[] = 
    {
        "IRP_MN_START_DEVICE",
        "IRP_MN_QUERY_REMOVE_DEVICE",
        "IRP_MN_REMOVE_DEVICE",
        "IRP_MN_CANCEL_REMOVE_DEVICE",
        "IRP_MN_STOP_DEVICE",
        "IRP_MN_QUERY_STOP_DEVICE",
        "IRP_MN_CANCEL_STOP_DEVICE",
        "IRP_MN_QUERY_DEVICE_RELATIONS",
        "IRP_MN_QUERY_INTERFACE",
        "IRP_MN_QUERY_CAPABILITIES",
        "IRP_MN_QUERY_RESOURCES",
        "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
        "IRP_MN_QUERY_DEVICE_TEXT",
        "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
        "",
        "IRP_MN_READ_CONFIG",
        "IRP_MN_WRITE_CONFIG",
        "IRP_MN_EJECT",
        "IRP_MN_SET_LOCK",
        "IRP_MN_QUERY_ID",
        "IRP_MN_QUERY_PNP_DEVICE_STATE",
        "IRP_MN_QUERY_BUS_INFORMATION",
        "IRP_MN_DEVICE_USAGE_NOTIFICATION",
        "IRP_MN_SURPRISE_REMOVAL",
    };

    KdPrint(("PNP Request (%s)\n", fcnname[fcn]));
#endif // DBG

    status = (*fcntab[fcn])(pdx, pIrp);
    KdPrint(("Leave HelloWDMPnp\n"));
    return status;
}

/************************************************************************
* 函数名称:HelloWDMDispatchRoutine
* 功能描述:对缺省IRP进行处理
* 参数列表:
      fdo:功能设备对象
      Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
                                 IN PIRP Irp)
{
    PAGED_CODE();
    KdPrint(("Enter HelloWDMDispatchRoutine\n"));
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;    // no bytes xfered
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    KdPrint(("Leave HelloWDMDispatchRoutine\n"));
    return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:HelloWDMUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:
      DriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
{
    PAGED_CODE();
    KdPrint(("Enter HelloWDMUnload\n"));
    KdPrint(("Leave HelloWDMUnload\n"));
}
原文地址:https://www.cnblogs.com/qintangtao/p/2986913.html