参考张帆的windows驱动开发技术详解,自学中。。。
#pragma once
#ifndef __HELLODDK__HH
#define __HELLODDK__HH
//包含ntddk.h文件,使用c标准的方式编译
#ifdef __cplusplus
extern "C"
{
#endif
#include <ntddk.h>
#ifdef __cplusplus
};
#endif
//定义分页标记,非分页标记和初始化内存块,
//在windows驱动程序的开发中,所有程序的函数和变量都有指明被加载到分页内存还是非分页内存
//DriverEntry函数需要放在INIT标志的内存中
//关于区别后续解释
#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_EXTENSION
{
PDEVICE_OBJECT pDevice; //设备结构体指针
UNICODE_STRING usDeviceName;//设备名称
UNICODE_STRING usSymLinkName;//符号连接名
}DEVICE_EXTENSION,*pDEVICE_EXTENSION;
NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject); //创建设备
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject);//卸载设备
NTSTATUS HelloDDKDispatchRoutine(IN PDRIVER_OBJECT pDriverObject,IN PIRP pIrp);//通用的设备例程函数
#endif
#include "MyDDKHello.h"
/*
DriverEntry:驱动程序的入口函数
功能:初始化驱动程序,申请硬件资源,创建内核对象
参数:
IN pDriverObject 从I/O管理器中传进来的驱动对象
IN pRegisterPath 驱动程序在注册表中的路径
返回:返回初始化驱动的状态
*/
//#include <wdm.h>
#pragma INITCODE
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegisterPath)
{
NTSTATUS status;
DbgPrint("Into DriverEntry..."); //相当于TRACRE()
//向I/O管理器注册驱动回调函数
pDriverObject->MajorFunction[IRP_MJ_CREATE] =
pDriverObject->MajorFunction[IRP_MJ_CLOSE] =
pDriverObject->MajorFunction[IRP_MJ_WRITE] =
pDriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)HelloDDKDispatchRoutine;
pDriverObject->DriverUnload = HelloDDKUnload;
status = CreateDevice(pDriverObject);
DbgPrint("DriverEntry End...");
return status;
}
/*
CreateDevice:初始化设备对象
参数:pDriverObject 从I/O管理器传进来的驱动对象
返回:返回创建设备的初始化状态
*/
#pragma INITCODE
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_OBJECT pDeviceObject;
//设备的扩展结构体,其他的驱动程序的函数中,可以很方便的得到此结构体,进而得到设备的自定义信息
pDEVICE_EXTENSION pDevExt;
//创建设备名
UNICODE_STRING usDevName;
RtlInitUnicodeString(&usDevName,L"\\Device\\MyDDKDevice"); //初始化UNICODE_STRING类型的变量,使用后不需要释放
//创建设备
status = IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&usDevName,
FILE_DEVICE_UNKNOWN,//此种设备为独占设备,设备只能被一个应用程序所使用
0, //
TRUE,//
&pDeviceObject);
if (!NT_SUCCESS(status))
{
return status;
}
pDeviceObject->Flags |= DO_BUFFERED_IO; //设备对内存的操作分类:DO_BUFFERED_IO DO_DIRECT_IO ,详解后说明
pDevExt = (pDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
pDevExt->pDevice = pDeviceObject;
pDevExt->usDeviceName = usDevName;
//创建符号连接
UNICODE_STRING usSymLinkName;
RtlInitUnicodeString(&usSymLinkName,L"\\??\\MySymbLinkNameHelloDDK");
pDevExt->usSymLinkName = usSymLinkName;
//对于应用程序,设备名称是不可见的,只能使用符号连接名称,该连接指向真正的设备名称
status = IoCreateSymbolicLink(&usSymLinkName,&usDevName);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pDeviceObject); //删除设备对象
return status;
}
return STATUS_SUCCESS;
}
/*
HelloDDKUnload:负责驱动程序的卸载操作
参数: pDriverObject :驱动程序对象
*/
/*
此历程遍历系统中所有的此类设备对象。第一个设备对象的地址存在于驱动对象的DeviceObject域中,
每个设备对象的NextDevice域记录着下一个设备对象的地址,这样就形成了一个链表。
卸载驱动函数的主要目的就是遍历此链表,获得设备名称和符号链接名称,并执行删除操作。
*/
#pragma PAGEDCODE
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_OBJECT pDevNext;
DbgPrint("into HelloDDKUnload");
pDevNext = pDriverObject->DeviceObject;
while (pDevNext != NULL)
{
pDEVICE_EXTENSION pDevExt = (pDEVICE_EXTENSION)pDevNext->DeviceExtension;
//删除符号链接
UNICODE_STRING usLinkName = pDevExt->usSymLinkName;
IoDeleteSymbolicLink(&usLinkName);
pDevNext = pDevNext->NextDevice;
IoDeleteDevice(pDevNext); //删除设备
}
}
/*
HelloDDKDispatchRoutine:默认派遣函数
参数:
pDriverObject:功能设备对象
pIrp:从I/O请求包
返回值:返回处理的状态
*/
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutine(IN PDRIVER_OBJECT pDriverObject,IN PIRP pIrp)
{
DbgPrint("in to HelloDDKDispatchRoutine");
NTSTATUS status = STATUS_SUCCESS;
//完成IRP
pIrp->IoStatus .Status= status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp,
IO_NO_INCREMENT//后续详解
);
DbgPrint("end HelloDDKDispatchRoutine");
return status;
}