⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adddevice.txt

📁 ADDRIVER 源代码! 注释! 新手入门
💻 TXT
字号:
//DriverObject参数指向一个驱动程序对象,就是你在DriverEntry例程中初始化的那个驱动程序对象。
//pdo参数指向设备堆栈底部的物理设备对象。

NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
{



//调用IoCreateDevice创建设备对象,并建立一个私有的设备扩展对象。

PDEVICE_OBJECT fdo;
NTSTATUS status = IoCreateDevice(DriverObject,//就是AddDevice的第一个参数。该参数用于在驱动
                                               //程序和新设备对象之间建立连接,这样I/O管理器
                                                //就可以向设备发送指定的IRP。

				 sizeof(DEVICE_EXTENSION),//设备扩展结构的大小。I/O管理器自
                                                          //动分配这个内存,并把设备对象中的
                                                          //DeviceExtension指针指向这块内存。

				 NULL,       //它可以是命名该设备对象的UNICODE_STRING串的地址
				 FILE_DEVICE_UNKNOWN,//设备类型
				 FILE_DEVICE_SECURE_OPEN,//设备对象提供Characteristics标志
				 FALSE,               //指出设备是否是排斥的
				 &fdo);  //是存放设备对象指针的地址,IoCreateDevice函数使用该
                                           //变量保存刚创建设备对象的地址




NTSTATUS status = IoCreateDevice(...);    //如果IoCreateDevice由于某种原因失败,则它返回一个错
                                          //误代码,不改变fdo中的值。如果IoCreateDevice函数返回
                                          //成功代码,那么它同时也设置了fdo指针。然后我们进行到
                                         //下一步,初始化设备扩展,做与创建新设备对象相关的其它
                                        //工作,如果在这之后又发现了错误,那么在返回前应先释放刚
                                          //创建的设备对象并返回状态码
if (!NT_SUCCESS(status))
  return status;
...
if (<some other error discovered>)
{
  IoDeleteDevice(fdo);
  return status;
}


//如果我们使用设备名COM1,那么最终收到该IRP的将是\Device\Serial0的驱动程序。

//用户模式程序可以调用DefineDosDevice创建一个符号连接,如下例:

BOOL okay = DefineDosDevice(DDD_RAW_TARGET_PATH, "barf", "\\Device\\SECTEST_0");
 



//如果你需要在WDM驱动程序中创建一个符号连接,可以调用IoCreateSymbolicLink函数:

IoCreateSymbolicLink(linkname, targname);//linkname是要创建的符号连接名,targname是要连接的名字。
 //设备命名  方法一使用带有硬编码性质的名称
UNICODE_STRING devname;
RtlInitUnicodeString(&devname, L"\\Device\\Simple0");
IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devname, ...);

//方法二 串操作函数动态地合成一个名字
UNICODE_STRING devname;
static LONG lastindex = -1;/从私有设备类型得出的实例号应该是一个静态变量。

LONG devindex = InterlockedIncrement(&lastindex);
WCHAR name[32];
_snwprintf(name, arraysize(name), L"\\Device\\SIMPLE%2.2d", devindex);
RtlInitUnicodeString(&devname, name);
IoCreateDevice(...);
//定义设备扩展
typedef struct _DEVICE_EXTENSION {				<--1
  PDEVICE_OBJECT DeviceObject;					<--2
  PDEVICE_OBJECT LowerDeviceObject;				<--3
  PDEVICE_OBJECT Pdo;						<--4
  UNICODE_STRING ifname;					<--5
  IO_REMOVE_LOCK RemoveLock;					<--6
  DEVSTATE devstate;						<--7
  DEVSTATE prevstate;
  DEVICE_POWER_STATE devpower;
  SYSTEM_POWER_STATE syspower;
  DEVICE_CAPABILITIES devcaps;					<--8
  ...
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
//初始化设备扩展
  PDEVICE_OBJECT fdo;
  IoCreateDevice(..., sizeof(DEVICE_EXTENSION), ..., &fdo);
  PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
  pdx->DeviceObject = fdo;
  pdx->Pdo = pdo;
  IoInitializeRemoveLock(&pdx->RemoveLock, ...);
  pdx->devstate = STOPPED;
  pdx->devpower = PowerDeviceD0;
  pdx->syspower = PowerSystemWorking;
 IoRegisterDeviceInterface(..., &pdx->ifname);
  pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(...);


//初始化默认的DPC对象
IoCreateDevice(...);
  IoInitializeDpcRequest(fdo, DpcForIsr);
//设置缓冲区对齐掩码方法一
PVOID address = ...;
SIZE_T ar = fdo->AlignmentRequirement;
address = (PVOID) ((SIZE_T) address & ~ar);
 
//方法二 
PVOID address = ...;
SIZE_T ar = fdo->AlignmentRequirement;
address = (PVOID) (((SIZE_T) address + ar) & ~ar);


//设置初始电源状态
POWER_STATE state;
state.DeviceState = PowerDeviceD0;
PoSetPowerState(fdo, DevicePowerState, state);

//建立设备堆
PDEVICE_OBJECT fdo;
  IoCreateDevice(..., &fdo);
  pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
}

//清除DO_DEVICE_INITIALIZING标志
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
当这个标志设置时,I/O管理器将拒绝任何打开该设备句柄的请求或向该设备对象
上附着其它设备对象的请求。在驱动程序完成初始化后,必须清除这个标志。




//注册设备接口
#include <initguid.h>							<--1
#include "guids.h"							<--2
...
NTSTATUS AddDevice(...)
{
  ...//IoRegisterDeviceInterface的第一个参数必须是设备PDO的地址。
//第二个参数指出与接口关联的GUID,第三个参数指出额外的接口细分类名。
//只有Microsoft的代码才使用名称细分类方案。第四个参数是一个UNICODE_STRING串的地址,
//该串用于接收设备对象的符号连接名。
  IoRegisterDeviceInterface(pdo, &GUID_SIMPLE, NULL, &pdx->ifname);	<--3
  ...
}

























}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -