一个驱动程序的源代码Driver.cpp,接上篇

来源:互联网 发布:大数据行业研究报告 编辑:程序博客网 时间:2024/04/30 18:02

/***************************
*文件名称:Driver.cpp
***************************/

#include <Driver.h>

#pragma INITCODE

extern "C" NTSTATUS DriverEntry(IN PDERIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
{
 NTSTATUS status;
 KdPrint(("Enter DriverEntry/n"));
 //注册其他的驱动调用函数入口
 pDriverObject->DriverUnload=HelloDDKUnload;
 pDriverObject->MajorFunction[IRP_MJ_CREATE]=HelloDDKDispatchRoutine;
 pDriverObject->MajorFunction[IRP_MJ_CLOSE]=HelloDDKDispatchRoutine;
 pDriverObject->MajorFunction[IRP_MJ_WRITE]=HelloDDKDispatchRoutine;
 pDriverObject->MajorFunction[IRP_MJ_READ]=HelloDDKDispatchRoutine;

 //创建驱动设备对象
 status=CreateDevice(pDriverObject);

 KdPrint(("DriverEntry end/n"));
 return status;

}

/*************************
*函数名:CreateDevice
功能描述:初始化设备对象
*************************/

#pragma INITCODE
NTSTATUS CreateDevice( IN PDRIVER_OBJECT pDriverObject)
{
 NTSTATUS status;
 PDEVICE_OBJECT pDevObj;
    PDEVICE_EXTENSION pDevExt;

 //创建设备名称
 UNICODE_STRING devName;
 RtlInitUnicodeString(&devName,L"//Device//MyDDKDevice");
 
 //创建设备
    status=IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&(UNICODE_STRING)devName,FILE_DEVICE_UNKNOWN,0,TRUE,&pDevObj);
 if(!NT_SUCCESS(status))
  return status;

 pDevObj->Flags |=DO_BUFFERED_IO;
 pDevExt=(PDEVICE_EXTENSION)pDevObj->DeviceExtension;
 pDevExt->pDevice=pDevObj;
 pDevExt->ustrDeviceName=devName;

 //创建符号链接
 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
*功能描述:负责驱动程序的卸载操作
************************************/

#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;

  //删除符号链接
  UNICODE_STRING pLinkName=pDevExt->ustrSymLinkName;
  IoDeleteSymbolicLink(&pLinkName);
  pNextObj=pNextObj->NextDevice;
  IoDeleteDevice(pDevExt->pDevice);
 }
}

/*************************************
*函数名:HelloDDKDispatchRoutine
*功能描述:对读IRP进行处理
************************************/

#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
{
 KdPrint(("Enter HelloDDKDispatchRoutine/n"));
 NTSTATUS status=STATUS_SUCCESS;
 //完成IRP
 pIrp->IoStatus.Status=status;
 pIrp->IoStatus.Information=0;
 IoCompleteRequest(pIrp,IO_NO_INCREMENT);
 KdPrint(("Leave HelloDDKDispatchRoutine/n"));
 return status;
}

 

#pragma INITCODE,指明此函数是加载到INIT内存域中,即成功卸载后,可以退出内存。

extern "C" NTSTATUS DriverEntry(IN PDERIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
这句代码标志DriverEntry函数的开始,extern "C"修饰,这样在编译时会编译成_DriverEntry@8的符号,否则就会出现链接错误。

KdPrint(("Enter DriverEntry/n"))这句代码中的KdPrint其实是个宏,在调试版本中会被DbgPrint代替,而在发行版本中,则不执行任何操作。

接着看下CreateDevice函数

UNICODE_STRING devName;
 RtlInitUnicodeString(&devName,L"//Device//MyDDKDevice");
这两句代码用于构造一个Unicode字符串,此字符串用来存储设备对象的名称。

status=IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&(UNICODE_STRING)devName,FILE_DEVICE_UNKNOWN,0,TRUE,&pDevObj);
这句代码是用IoCreateDevice函数创建一个设备对象。

pDevObj->Flags |=DO_BUFFERED_IO,这句代码表明此种设备为BUFFERED_IO设备。设备对内存的操作分为两种,BUFFERED_IO和DO_DIRECT_IO。

pDevExt=(PDEVICE_EXTENSION)pDevObj->DeviceExtension;
 pDevExt->pDevice=pDevObj;
 pDevExt->ustrDeviceName=devName;

上述代码用来填写设备的扩展结构体。

UNICODE_STRING symLinkName;
 RtlInitUnicodeString(&symLinkName,L"//??//HelloDDK");
 pDevExt->ustrSymLinkName=symLinkName;
 status=IoCreateSymbolicLink(&symLinkName,&devName);

上述代码创建符号链接。虽然驱动程序有了设备名称,但是这种设备名称只能在内核态中可见,而对于应用程序是不可见的。因此,驱动需要一个符号链接,该链接指向真正的设备名称。

卸载驱动例程HelloDDKUnload

pNextObj=pDriverObject->DeviceObject,由驱动对象得到设备对象

UNICODE_STRING pLinkName=pDevExt->ustrSymLinkName;
  IoDeleteSymbolicLink(&pLinkName);

这两句代码用于删除符号链接

pNextObj=pNextObj->NextDevice;
  IoDeleteDevice(pDevExt->pDevice);

这两句遍历设备对象并删除。

 

默认派遣例程HelloDDKDispatchRoutine

pIrp->IoStatus.Status=status;

设置IRP的状态为成功
 pIrp->IoStatus.Information=0;

设置操作的字节数为0
 IoCompleteRequest(pIrp,IO_NO_INCREMENT);

指示完成此IRP

原创粉丝点击