/************************************************************************
* 文件名称:Driver.cpp
* 作 者:严琳
* 完成日期:2011-2
*************************************************************************/
#pragma once
#ifdef _cplusplus
extern "C"//C++包含C的头文件
{
#endif
#include <NTDDK.h>
#ifdef _cplusplus
}
#endif
#include "Driver.h"
//代码段
#define PAGEDCODE code_seg("PAGE")//定义分页标记
#define LOCKDCODE 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]))
#define MAX_FILE_LENGTH 2048//模拟文件最大长度
//自定义一个结构体
typedef struct _DEVICE_EXTENSION{
PDEVICE_OBJECT pDevice;//从IO管理器中传进来的驱动对象
UNICODE_STRING ustrDeviceName;//设备名
UNICODE_STRING ustrSymLinkName;//符号连接名
PUCHAR buffer;//缓冲区
ULONG file_length;//模拟文件长度,必须小于MAX_FILE_LENGTH
}DEVICE_EXTENSION,*pDEVICE_EXTENSION;
//各种函数声明
NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);//初始化设备对象
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);//驱动程序的卸载操作
NTSTATUS HelloDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);//对读IRP进行处理
NTSTATUS HelloDeviceIOControl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);//IO控制函数
#pragma INITCODE 指明此函数加载到intt内存区域中,成功卸载后即可退出内存
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)//又是一个C
函数
{
NTSTATUS status;
KdPrint(("Enter DriverEntry./n"));//用于调试
//注册其他驱动调用函数入口
pDriverObject->DriverUnload = HelloDDKUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloDeviceIOControl;
status = CreateDevice(pDriverObject);//创建驱动设备对象
//容错性判断
if(!NT_SUCCESS(status))
{
KdPrint(("CreateDevice Error!/n"));
}
else
{
KdPrint(("CreateDevice Success!/n"));
}
KdPrint(("Leave DriverEntry./n"));//用于调试
return status;
}
/*****************************************************
*函数名称:CreateDevice
*功能描述:初始化设备对象
*参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
*返回值:返回初始化状态
******************************************************/
#pragma INITCODE
NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
pDEVICE_EXTENSION pDevExt;
UNICODE_STRING devName;//创建设备名称
RtlInitUnicodeString(&devName,L"//Device//MyDevice");//构造一个Unicode字符串,用于储存设备对象的名称
/*****************************
*NTSTATUS IoCreateDevice //用于创建常规的设备对象
*(
*IN PDRIVER_OBJECT DriverObject,//一个指向调用该函数的驱动程序对象
*IN ULONG DeviceExtensionSize,//指定驱动程序为设备扩展对象而定义的结构体的大小
*IN PUNICODE_STRING DeviceName OPTIONAL,//(可选的参数)指向一个以零结尾的包含Unicode字符串的缓冲区,那是这
个设备的名称,该字符串必须是一个完整的设备路径名.
*IN DEVICE_TYPE DeviceType,//指定一个由一个系统定义的FILE_DEVICE_XXX常量,表明了这个设备的类型
*IN ULONG DeviceCharacteristics,//提供有关驱动程序的设备其他信息
*IN BOOLEAN Exclusive,//如果指定设备是独占的,大部分驱动程序设置这个值为FALSE,如果不是独占的话设置为TRUE
*OUT PDEVICE_OBJECT *DeviceObject//用来接收DEVICE_OBJECT结构体的指针
*);
******************************/
status = IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&(UNICODE_STRING)
devName,FILE_DEVICE_UNKNOWN,0,TRUE,&pDevObj);//设备的创建
pDevExt->file_length = 0;//设置模拟文件大小
//创建符号链接
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName,L"//??//HelloDDK");//给应用层的符号链接,指向真正的设备
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink(&symLinkName,&devName);//将两个名称链接
//判断是否创建成功,若不成功则删除
if(!NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
return status;
}
return STATUS_SUCCESS;
}
/*****************************************************
*函数名称:HelloDDKUnload
*功能描述:负责驱动程序的卸载
*参数列表:
pDriverObject:驱动对象
*返回值:返回状态
******************************************************/
#pragma PAGEDCODE
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
KdPrint(("Enter DriverUnload./n"));//用于调试
pNextObj = pDriverObject->DeviceObject;//有驱动对象得到设备对象
while(pNextObj != NULL)
{
pDEVICE_EXTENSION pDevExt = (pDEVICE_EXTENSION)pNextObj -> DeviceExtension;
if(pDevExt->buffer)
{
ExFreePool(pDevExt->buffer);//释放指针
pDevExt->buffer = NULL;
}
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;//获得设备对象的符号链接
IoDeleteSymbolicLink(&pLinkName);//删除设备对象的符号链接
pNextObj = pNextObj->NextDevice;
IoDeleteDevice(pDevExt->pDevice);//卸载
}
}
/*****************************************************
*函数名称:HelloDispatchRoutine
*功能描述:对读IRP进行处理
*参数列表:
pDvObj:功能设备对象
pIrp:从IO请求包
*返回值:返回状态
******************************************************/
#pragma PAGEDCODE
NTSTATUS HelloDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
{
KdPrint(("Enter HelloDispatchRoutin./n"));//用于调试
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);//得到堆栈单元
//建立一个字符串数组与IRP类型对应起来
static char* irpname[] =
{
"IRP_MJ_CREATE",
"IRP_MJ_CREATE_NAMED_PIPE",
"IRP_MJ_CLOSE",
"IRP_MJ_READ",
"IRP_MJ_WRITE",
"IRP_MJ_QUERY_INFORMATION",
"IRP_MJ_SET_INFORMATION",
"IRP_MJ_QUERY_EA",
"IRP_MJ_SET_EA",
"IRP_MJ_FLUSH_BUFFERS",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION",
"IRP_MJ_DIRECTORY_CONTROL",
"IRP_MJ_FILE_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CONTROL",
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
"IRP_MJ_SHUTDOWN",
"IRP_MJ_LOCK_CONTROL",
"IRP_MJ_CLEANUP",
"IRP_MJ_CREATE_MAILSLOT",
"IRP_MJ_QUERY_SECURITY",
"IRP_MJ_SET_SECURITY",
"IRP_MJ_POWER",
"IRP_MJ_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CHANGE",
"IRP_MJ_QUERY_QUOTA",
"IRP_MJ_SET_QUOTA",
"IRP_MJ_PNP",
};
UCHAR type = stack->MajorFunction;
//判断是否存在此IRP
if(type >= arraysize(irpname))
{
KdPrint(("-Unknown IRP,major type %X./n",type));
}
else
{
KdPrint(("/t%s/n",irpname[type]));
}
NTSTATUS status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status;//设置IRP的状态为成功
pIrp->IoStatus.Information = 0;//设置操作字节数为0
IoCompleteRequest(pIrp,IO_NO_INCREMENT);//指示完成此irp
KdPrint(("Leave HelloDispatchRoutin./n"));//用于调试
return status;//返回成功
}
/*****************************************************
*函数名称: HelloDeviceIOControl
*功能描述:IO控制函数
*参数列表:
pDvObj:功能设备对象
pIrp:从IO请求包
*返回值:返回状态
******************************************************/
#pragma PAGEDCODE
NTSTATUS HelloDeviceIOControl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
KdPrint(("Enter HelloDeviceIOControl./n"));//用于调试
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);//得到堆栈单元
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;//得到输入缓冲区大小
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;//得到输出缓冲区大小
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;//得到IOCTL码
ULONG info = 0;
switch(code)
{
case WRITE_PORT:
{
KdPrint(("WRITE_PORT./n"));
PULONG InputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer;//得到缓冲区中的数据
ULONG port = (ULONG)(*InputBuffer);
InputBuffer++;
UCHAR method = (UCHAR)(*InputBuffer);
InputBuffer++;
ULONG value = (ULONG)(*InputBuffer);
PULONG OutputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer;//操作输出缓冲区
if(method == 1)//8位
{
WRITE_PORT_UCHAR((PUCHAR)port,(UCHAR)value);
}
else if(method == 2)//16位
{
WRITE_PORT_USHORT((PUSHORT)port,(USHORT)value);
}
else if(method == 4)//32位
{
WRITE_PORT_ULONG((PULONG)port,(ULONG)value);
}
KdPrint(("WRITE Port %02xH : %02xH/n",port,value));
info = 0;//设置实际操作输出缓冲区的大小
break;
}
case READ_PORT:
{
KdPrint(("READ_PORT./n"));
PULONG InputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer;//得到缓冲区中的数据
ULONG port = (ULONG)(*InputBuffer);
InputBuffer++;
UCHAR method = (UCHAR)(*InputBuffer);
PULONG OutputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer;//操作输出缓冲区
if(method == 1)//8位
{
*OutputBuffer = READ_PORT_UCHAR((PUCHAR)port);
}
else if(method == 2)//16位
{
*OutputBuffer = READ_PORT_USHORT((PUSHORT)port);
}
else if(method == 4)//32位
{
*OutputBuffer = READ_PORT_ULONG((PULONG)port);
}
KdPrint(("ReadPort %02xH/n",port,(*OutputBuffer)));
info = 4;//设置实际操作输出缓冲区大小
break;
}
default:
status = STATUS_INVALID_VARIANT;
}
pIrp->IoStatus.Status = status;//设置IRP的状态
pIrp->IoStatus.Information = info;//设置操作字节数
IoCompleteRequest(pIrp,IO_NO_INCREMENT);//指示完成此irp
KdPrint(("Leave HelloDeviceIOControl./n"));//用于调试
return status;
}