• 最简单的WDM驱动


    一、代码部分

    //HelloWDM.h

    #pragma once

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

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

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

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

    typedef struct _DEVICE_EXTENSION
    {
     PDEVICE_OBJECT fdo;
     PDEVICE_OBJECT pNextStackDevice;
     UNICODE_STRING ustrDevName;
     UNICODE_STRING ustrLinkName;
    }DEVICE_EXTENSION, *PDEVICE_EXTENSION;

    NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT pDriverObject, IN PDEVICE_OBJECT pdo);
    NTSTATUS HelloWDMDefaultPnp(IN PDEVICE_OBJECT fdo, IN PIRP pIrp);
    NTSTATUS HelloWDMDefaultDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP pIrp);
    VOID HelloWDMUnload(IN PDRIVER_OBJECT pDriverObject);
    NTSTATUS RemovableDevice(IN PDEVICE_EXTENSION pdx, IN PIRP pIrp);
    NTSTATUS HandlerPnp(IN PDEVICE_EXTENSION pdx, IN PIRP pIrp);

    //HelloWDM.cpp

    #include "HelloWDM.h"

    #pragma INITCODE
    extern "C" DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegisterPath)
    {
     KdPrint(("DriverEntry:Enter\n"));

     pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
     pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMDefaultPnp;
     pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloWDMDefaultDispatchRoutine;
     pDriverObject->MajorFunction[IRP_MJ_READ] = HelloWDMDefaultDispatchRoutine;
     pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDefaultDispatchRoutine;
     pDriverObject->DriverUnload = HelloWDMUnload;

     KdPrint(("DriverEntry:Leave\n"));

     return STATUS_SUCCESS;
    }

    #pragma PAGEDCODE
    NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT pDriverObject, IN PDEVICE_OBJECT pdo)
    {
     PAGED_CODE();
     KdPrint(("HelloWDMAddDevice:Enter\n"));
     PDEVICE_OBJECT fdo;
     NTSTATUS status;
     UNICODE_STRING devName;
     UNICODE_STRING linkName;
     PDEVICE_EXTENSION pdx;
     
     //创建设备
     RtlInitUnicodeString(&devName, L"\\Device\\MyHelloWDM");
     status = IoCreateDevice(pDriverObject,
           sizeof(DEVICE_EXTENSION),
           &devName,
           FILE_DEVICE_UNKNOWN,
           0,
           FALSE,
           &fdo);
     if(!NT_SUCCESS(status))
     {
      return status;
     }
     //创建符号链接
     RtlInitUnicodeString(&linkName, L"\\??\\HelloWDM");
     status = IoCreateSymbolicLink(&linkName, &devName);
     if(!NT_SUCCESS(status))
     {
      IoDeleteDevice(fdo);
      return status;
     }
     //设备扩展
     pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
     pdx->fdo = fdo;
     pdx->ustrDevName = devName;
     pdx->ustrLinkName = linkName;
     //挂接到设备栈
     pdx->pNextStackDevice = IoAttachDeviceToDeviceStack(fdo, pdo);
     if(pdx->pNextStackDevice == NULL)
     {
      IoDeleteSymbolicLink(&pdx->ustrLinkName);
      IoDeleteDevice(fdo);
      return STATUS_UNSUCCESSFUL;
     }
     //设备标志
     fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
     fdo->Flags &= ~DO_DEVICE_INITIALIZING;

     KdPrint(("HelloWDMAddDevice:Leave\n"));
     return status;
    }

    #pragma PAGEDCODE
    VOID HelloWDMUnload(IN PDRIVER_OBJECT pDriverObject)
    {
     PAGED_CODE();
     //此卸载例程不做任何事情,交由IRP_MN_REMOVABLE_DEVICE处理
     KdPrint(("HelloWDMUnload:Enter\n"));
     KdPrint(("HelloWDMUnload:Leave\n"));
    }

    #pragma PAGEDCODE
    NTSTATUS HelloWDMDefaultDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP pIrp)
    {
     PAGED_CODE();
     //本层驱动直接处理irp
     KdPrint(("HelloWDMDefaultDispatchRoutine:Enter\n"));

     pIrp->IoStatus.Status = STATUS_SUCCESS;
     pIrp->IoStatus.Information = 0;
     IoCompleteRequest(pIrp, IO_NO_INCREMENT);

     KdPrint(("HelloWDMDefaultDispatchRoutine:Leave\n"));
     return STATUS_SUCCESS;
    }

    #pragma PAGEDCODE
    NTSTATUS HelloWDMDefaultPnp(IN PDEVICE_OBJECT fdo, IN PIRP pIrp)
    {
     PAGED_CODE();
     KdPrint(("HelloWDMDefaultPnp:Enter\n"));
     NTSTATUS status;
     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
     ULONG fcn;

     NTSTATUS (*fcntab[])(PDEVICE_EXTENSION, PIRP) =
     {
      HandlerPnp,
      HandlerPnp,
      RemovableDevice,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,

      HandlerPnp,

      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
      HandlerPnp,
     };
     fcn = stack->MinorFunction;
     if(fcn >= arrarysize(fcntab))
     {
      status = HandlerPnp(pdx, pIrp);
      KdPrint(("HelloWDMDefaultPnp:Leave\n"));
      return status;
     }
     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]));

     status = (*fcntab[fcn])(pdx, pIrp);

     KdPrint(("HelloWDMDefaultPnp:Leave\n"));
     return status;
    }

    #pragma PAGEDCODE
    NTSTATUS HandlerPnp(IN PDEVICE_EXTENSION pdx, IN PIRP pIrp)
    {
     //交由下层处理IRP
     PAGED_CODE();
     NTSTATUS status = STATUS_SUCCESS;
     KdPrint(("HandlerPnp:Enter\n"));

     IoSkipCurrentIrpStackLocation(pIrp);
     status = IoCallDriver(pdx->pNextStackDevice, pIrp);

     KdPrint(("HandlerPnp:Leave\n"));
     return status;
    }

    #pragma PAGEDCODE
    NTSTATUS RemovableDevice(IN PDEVICE_EXTENSION pdx, IN PIRP pIrp)
    {
     PAGED_CODE();
     KdPrint(("RemovableDevice:Enter\n"));
     NTSTATUS status = STATUS_SUCCESS;
     //交由下层处理irp
     status = HandlerPnp(pdx, pIrp);
     //解除挂载
     if(pdx->pNextStackDevice)
     {
      IoDetachDevice(pdx->pNextStackDevice);
     }
     //删除符号链接
     IoDeleteSymbolicLink(&pdx->ustrLinkName);
     //删除设备
     IoDeleteDevice(pdx->fdo);

     KdPrint(("RemovableDevice:Leave\n"));
     return status;
    }

    二、编译(用DDK编译)

    1、sources文件内容:

    !IF 0

    Copyright (C) Microsoft Corporation, 1997 - 1999

    Module Name:

        sources.

    !ENDIF

    TARGETNAME=HelloWDM
    TARGETPATH=obj
    TARGETTYPE=DRIVER
    DRIVERTYPE=WDM
    SOURCES=HelloWDM.cpp

    TARGETLIBS= $(DDK_LIB_PATH)\ntstrsafe.lib

    2、makefile文件内容:

    !IF 0

    Copyright (C) Microsoft Corporation, 1997 - 1998

    Module Name:

        makefile.

    !ENDIF

    #
    # DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
    # file to this component.  This file merely indirects to the real make file
    # that is shared by all the components of Windows NT
    #

    #
    # if building in a DDK environment
    #
    !IF defined(DDK_TARGET_OS)

    #
    # ensure that said build environment is at least Windows XP
    # 0x500 == Windows 2000
    # 0x501 == Windows XP
    # 0x502 == Windows .NET
    #
    !    IF defined(_NT_TARGET_VERSION) && $(_NT_TARGET_VERSION)>=0x501
    !        INCLUDE $(NTMAKEENV)\makefile.def
    !    ELSE
    !        message BUILDMSG: Warning : The sample "$(MAKEDIR)" is not valid for the current OS target.
    !    ENDIF

    !ELSE

    #
    # not a DDK environment, probably RAZZLE, so build
    #
    !    INCLUDE $(NTMAKEENV)\makefile.def

    !ENDIF

     3、编译方法:将源码、sources、makefile文件放在同一目录,执行下面命令即可

    build -c

    三、安装驱动

    1、编写info文件

    ;; The Win2K DDK documentation contains an excellent INF reference.

    ;--------- Version Section ---------------------------------------------------

    [Version]
    Signature="$CHICAGO$"
    Provider=Zhangfan_Device
    DriverVer=11/1/2007,3.0.0.3

    ; If device fits one of the standard classes, use the name and GUID here,
    ; otherwise create your own device class and GUID as this example shows.

    Class=ZhangfanDevice
    ClassGUID={EF2962F0-0D55-4bff-B8AA-2221EE8A79B0}


    ;--------- SourceDiskNames and SourceDiskFiles Section -----------------------

    ; These sections identify source disks and files for installation. They are
    ; shown here as an example, but commented out.

    [SourceDisksNames]
    1 = "HelloWDM",Disk1,,

    [SourceDisksFiles]
    HelloWDM.sys = 1,MyDriver_Check,

    ;--------- ClassInstall/ClassInstall32 Section -------------------------------

    ; Not necessary if using a standard class

    ; 9X Style
    [ClassInstall]
    Addreg=Class_AddReg

    ; NT Style
    [ClassInstall32]
    Addreg=Class_AddReg

    [Class_AddReg]
    HKR,,,,%DeviceClassName%
    HKR,,Icon,,"-5"

    ;--------- DestinationDirs Section -------------------------------------------

    [DestinationDirs]
    YouMark_Files_Driver = 10,System32\Drivers

    ;--------- Manufacturer and Models Sections ----------------------------------

    [Manufacturer]
    %MfgName%=Mfg0

    [Mfg0]

    ; PCI hardware Ids use the form
    ; PCI\VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd
    ;改成你自己的ID
    %DeviceDesc%=YouMark_DDI, PCI\VEN_9999&DEV_9999

    ;---------- DDInstall Sections -----------------------------------------------
    ; --------- Windows 9X -----------------

    ; Experimentation has shown that DDInstall root names greater than 19 characters
    ; cause problems in Windows 98

    [YouMark_DDI]
    CopyFiles=YouMark_Files_Driver
    AddReg=YouMark_9X_AddReg

    [YouMark_9X_AddReg]
    HKR,,DevLoader,,*ntkern
    HKR,,NTMPDriver,,HelloWDM.sys
    HKR, "Parameters", "BreakOnEntry", 0x00010001, 0

    ; --------- Windows NT -----------------

    [YouMark_DDI.NT]
    CopyFiles=YouMark_Files_Driver
    AddReg=YouMark_NT_AddReg

    [YouMark_DDI.NT.Services]
    Addservice = HelloWDM, 0x00000002, YouMark_AddService

    [YouMark_AddService]
    DisplayName = %SvcDesc%
    ServiceType = 1 ; SERVICE_KERNEL_DRIVER
    StartType = 3 ; SERVICE_DEMAND_START
    ErrorControl = 1 ; SERVICE_ERROR_NORMAL
    ServiceBinary = %10%\System32\Drivers\HelloWDM.sys

    [YouMark_NT_AddReg]
    HKLM, "System\CurrentControlSet\Services\HelloWDM\Parameters",\
    "BreakOnEntry", 0x00010001, 0


    ; --------- Files (common) -------------

    [YouMark_Files_Driver]
    HelloWDM.sys

    ;--------- Strings Section ---------------------------------------------------

    [Strings]
    ProviderName="Zhangfan."
    MfgName="Zhangfan Soft"
    DeviceDesc="Hello World WDM!"
    DeviceClassName="Zhangfan_Device"
    SvcDesc="Zhangfan"

    2、两种驱动安装方法

    (1)用工具安装,如DriverStdio提供的EzDriverInstall

    (2)"开始"->"控制面板"->"添加新硬件"->手工方式。。。

  • 相关阅读:
    剖析虚幻渲染体系(12) 移动端专题Part 1(UE移动端渲染分析)
    剖析虚幻渲染体系(13) RHI补充篇:现代图形API之奥义与指南
    剖析虚幻渲染体系(12) 移动端专题Part 3(渲染优化)
    浏览器无环境调试
    RPC调用获取参数值
    vscode插件
    前端异常收集和处理
    互联网名词集锦
    今日思考20211104
    备忘项目进展萃取
  • 原文地址:https://www.cnblogs.com/spinsoft/p/2563375.html
Copyright © 2020-2023  润新知