简单的IO驱动学习笔记

/************************************************************************
* 文件名称: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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值