zoukankan      html  css  js  c++  java
  • 第一个入门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"));
    }
  • 相关阅读:
    【心情】12月22日
    【心情】12月12日
    【心情】12月8日
    【转载】信息学竞赛知识地图
    SharePoint 2013 工作流之年假审批Designer配置篇
    SharePoint 2013 状态机工作流之扩展自定义状态
    SharePoint 2013 状态机工作流之UpdateItemActivity
    SharePoint 2013 状态机工作流之日常报销示例
    SharePoint 2013 对二进制大型对象(BLOB)进行爬网
    SharePoint 2013 图文开发系列之应用程序页
  • 原文地址:https://www.cnblogs.com/qintangtao/p/2986913.html
Copyright © 2011-2022 走看看