Loading...
墨滴

我只想

2021/07/01  阅读:33  主题:极简黑

Windows驱动开发入门(wdm)

Windows驱动开发入门(wdm)

对于想学习Windows驱动开发的同学,都苦于没有一个可运行例子。今天gogo就给大家讲解下《Windows驱动开发详解》中wdm驱动开发,文末会给出wdm例子。

准备

编写windows驱动需要安装DDK(Driver Development Kit)WDK 包含对应的驱动

https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk

选择对应版本的WDK,这里我使用的是vs2013安装完WDK后顶端会出现DRIVER

开始

  • 新建项目选择Windows Driver-〉Empty WDM Driver 最后点确定
  • 生成以下两个子项目 MyDriver1是写驱动代码的地方, MyDriver1 Package是打包的地方编译这个项目可以把生成文件放到一起。

代码

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

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

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

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

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

NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp);
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp);

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
  • HelloWDM.cpp 一定要用.cpp结尾
#include "HelloWDM.h"

#pragma INITCODE
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
 KdPrint(("Entry 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;
}

#pragma PAGECODE
NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
{
 PAGED_CODE();

 KdPrint(("Enter HelloWDMAddDevice\n"));

 NTSTATUS status;
 PDEVICE_OBJECT fdo;
 UNICODE_STRING devName;
 RtlInitUnicodeString(&devName, L"\\Device\\MyWDMDevice");
 status = IoCreateDevice(DriverObject, 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;
 pdx->NextStatckDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
 UNICODE_STRING symLinkName;
 RtlInitUnicodeString(&symLinkName, L"\\DosDevices\\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;
}

#pragma PAGEDCODE
NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
 PAGED_CODE();

 KdPrint(("Enter HelloWDMPnp\n"));

 NTSTATUS status = STATUS_SUCCESS;
 PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
 static NTSTATUS(*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =
 {
  DefaultPnpHandler,
  DefaultPnpHandler,
  HandleRemoveDevice,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
  DefaultPnpHandler,
 };

 ULONG fcn = stack->MinorFunction;
 if (fcn >= arraysize(fcntab))
 {
  status = DefaultPnpHandler(pdx, Irp);
  return status;
 }

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

 return status;
}

#pragma PAGEDCODE
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
{
 PAGED_CODE();
 KdPrint(("Enter DefaultPnpHandler\n"));
 IoSkipCurrentIrpStackLocation(Irp);
 KdPrint(("Leave DefaultPnpHandler\n"));
 return IoCallDriver(pdx->NextStatckDevice, Irp);
}

#pragma PAGEDCODE
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
 PAGED_CODE();
 KdPrint(("Enter HandlerRemoveDevice\n"));

 Irp->IoStatus.Status = STATUS_SUCCESS;
 NTSTATUS status = DefaultPnpHandler(pdx, Irp);
 IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);

 if (pdx->NextStatckDevice)
  IoDetachDevice(pdx->NextStatckDevice);

 IoDeleteDevice(pdx->fdo);
 KdPrint(("Leave HandlerRemoveDevice\n"));

 return status;
}

#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;
 IoCompleteRequest(Irp, IO_NO_INCREMENT);
 KdPrint(("Leave HelloWdmDispatchRoutine\n"));

 return STATUS_SUCCESS;
}

#pragma PAGEDCODE
void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
{
 PAGED_CODE();
 KdPrint(("Enter HelloWDMUnload\n"));
 KdPrint(("Leave HelloWDMUnload\n"));
}
  • MyDriver1.inf
;--------- Version Section ---------------------------------------------------
[Version]
Signature="$CHICAGO$";
Provider=Zhangfan_Device
DriverVer=06/29/2021,15.16.19.288
; 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}
CatalogFile=HelloWDM.cat
 
 
;--------- 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]
MyDriver1.sys = 1,,
 
;--------- 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,,MyDriver1.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\MyDriver1.sys
 
[YouMark_NT_AddReg]
HKLM, "System\CurrentControlSet\Services\HelloWDM\Parameters",\
"BreakOnEntry", 0x00010001, 0
 
 
; --------- Files (common) -------------
 
[YouMark_Files_Driver]
MyDriver1.sys
 
;--------- Strings Section ---------------------------------------------------
 
[Strings]
ProviderName="Zhangfan."
MfgName="Zhangfan Soft"
DeviceDesc="Hello World WDM!"
DeviceClassName="Zhangfan_Device"
SvcDesc="Zhangfan"

编译

  • 如下图调整编译选项, 将警告视为错误-〉改为“否(/WX-)”
  • 编译生成 不出意外编译后可生成如下文件

安装

使用EzDriverInstaller.exe软件加载驱动,这里要在win7 32位系统上加载,对于64位系统要求强制签名需要编译64位驱动并签名才能加载成功。

在File选项中Open打开驱动的inf文件,然后点Add New Device就行

安装后

代码获取

所有代码和工具都放在gitee,读者可自行获取。https://gitee.com/luoweichui/hello-wdm.git

结束

欢迎关注公众号zzktkj_8888,更多精彩内容。

- END -

我只想

2021/07/01  阅读:33  主题:极简黑

作者介绍

我只想