驱动开发:派遣函数与设备对象

驱动中的默认派遣函数,通过IRP_MJ_MAXIMUM_FUNCTION得到所有的派遣函数,并初始化为DriverDefaultHandle默认派遣,以及驱动中创建设备对象的基础知识总结。

初始化默认派遣函数: 通过IRP_MJ_MAXIMUM_FUNCTION得到所有的派遣函数,并初始化为DriverDefaultHandle默认派遣。

#include <ntifs.h>

// 默认派遣函数
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
  NTSTATUS status = STATUS_SUCCESS;
  pIrp->IoStatus.Status = status;
  pIrp->IoStatus.Information = 0;
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);

  return status;
}

VOID UnDriver(PDRIVER_OBJECT Driver)
{
  DbgPrint(("Uninstall Driver Is OK \n"));
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
  DbgPrint("Enter DriverEntry\n");

  NTSTATUS status = STATUS_SUCCESS;
  Driver->DriverUnload = UnDriver;

  // 将所有的派遣函数统一初始化
  for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
  {
    Driver->MajorFunction[i] = DriverDefaultHandle;
  }

  return status;
}

驱动中创建设备对象: 想要在应用层与内核层进行直接通信必须要创建设备并增加符号连接实现通信.

#include <ntifs.h>

// 驱动卸载时执行
VOID UnDriver(PDRIVER_OBJECT pDriver)
{
  PDEVICE_OBJECT pDev;         // 用来取得要删除设备对象
  UNICODE_STRING SymLinkName;  // 局部变量symLinkName

  // 卸载掉所有设备
  pDev = pDriver->DeviceObject;

  // 调用IoDeleteDevice用于删除设备
  IoDeleteDevice(pDev);
  
  // 删除服务号链接

  // 初始化字符串将symLinkName定义成需要删除的符号链接名称
  RtlInitUnicodeString(&SymLinkName, "\\??\\My_Driver");

  // 调用IoDeleteSymbolicLink删除符号链接
  IoDeleteSymbolicLink(&SymLinkName);
  
  DbgPrint("删除设备与符号链接成功...");
}

// 创建设备对象
NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
  NTSTATUS Status;               // 接收驱动程序的返回状态
  PDEVICE_OBJECT pDevObj;        // 用于返回创建设备
  UNICODE_STRING DriverName;     // 用于存放设备的名称
  UNICODE_STRING SymLinkName;    // 用于存放符号链接名称

  // 将DrvierName填充为\\Device\\My_Device
  RtlInitUnicodeString(&DriverName, "\\Device\\My_Device");

  // 使用命令IoCreateDevice用来创建设备 并将创建后的状态保存在status
  Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
  if (!NT_SUCCESS(Status))
  {
    // 调用IoCreateDevice成功与失败都会返回参数,将返回参数给Status用于判断
    // STATUS_INSUFFICIENT_RESOURCES   资源不足
    if (Status == STATUS_OBJECT_NAME_COLLISION)
    {
      DbgPrint("对象名冲突...");
      return STATUS_SUCCESS;
    }
    if (Status == STATUS_OBJECT_NAME_EXISTS)
    {
      DbgPrint("指定对象名存在...");
      return STATUS_SUCCESS;
    }
    if (Status == STATUS_INSUFFICIENT_RESOURCES)
    {
      DbgPrint("资源不足...");
      return STATUS_SUCCESS;
    }
    DbgPrint("创建失败.");
    return STATUS_SUCCESS;
  }

  // 设备Flags标识为有没有do_buffered_io位标识
  pDevObj->Flags |= DO_BUFFERED_IO;

  // 对symLinkName初始化字串为 "\\??\\My_Device"
  RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Device");
  
  // 创建设备链接,驱动程序虽然有设备名称,但是这种设备名只能在内核态可见
  // 而对于应用程序是不可见的,因此驱动需要要暴露一个符号链接,该链接指向真正的设备名称
  // 调用命令IoCreateSymbolicLink用于创建符号链接
  Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);

  // 如果status不等于0就执行
  if (!NT_SUCCESS(Status))
  {
    // 调用命令IoDeleteDevice删除当前pDevObj设备
    IoDeleteDevice(pDevObj);
    DbgPrint("删除设备成功...");
    return Status;
  }
  else
  {
    DbgPrint("创建符号链接成功...");
  }
  return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
  // 创建设备对象
  CreateDriverObject(pDriver);

  DbgPrint("驱动已加载...");
  pDriver->DriverUnload = UnDriver;
  return STATUS_SUCCESS;
}
posted @ 2019-09-14 12:21  lyshark  阅读(1637)  评论(0编辑  收藏  举报

loading... | loading...
博客园 - 开发者的网上家园