最简单的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)"开始"->"控制面板"->"添加新硬件"->手工方式。。。

原文地址:https://www.cnblogs.com/spinsoft/p/2563375.html