创建设备实例
#include<ntddk.h>
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName; //设备名称
UNICODE_STRING ustrSymLinkName; //符号链接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
DbgPrint("Unload!");
}
NTSTATUS FirstDriverRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
KdPrint(("Welcome to FirstDriverRoutinen"));
NTSTATUS status = STATUS_SUCCESS;
// 完成IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
DbgPrint("Leave FirstDriverRoutinen");
return status;
}
NTSTATUS DriverCreateDevice(PDRIVER_OBJECT pDriverObj)
{
//创建变量
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
//1.创建设备名称
UNICODE_STRING devName;
RtlInitUnicodeString(&devName, L"\\Device\\MyFirstDevice");
//2.创建设备
status = IoCreateDevice(pDriverObj,
sizeof(DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&pDevObj);
if (!NT_SUCCESS(status))
{
DbgPrint("Create Device Failed!");
return status;
}
pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;
//3.创建符号链接
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName, L"\\??\\FirstDriver");
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink(&symLinkName, &devName);
//4.删除设备
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
return status;
}
return STATUS_SUCCESS;
}
//入口点
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING reg_path)
{
//创建变量
NTSTATUS status;
DbgPrint("Hello World");
//消息循环
pDriverObj->MajorFunction[IRP_MJ_CREATE] = FirstDriverRoutine;
pDriverObj->MajorFunction[IRP_MJ_CLOSE] = FirstDriverRoutine;
pDriverObj->MajorFunction[IRP_MJ_WRITE] = FirstDriverRoutine;
pDriverObj->MajorFunction[IRP_MJ_READ] = FirstDriverRoutine;
pDriverObj->DriverUnload = DriverUnload;
//创建驱动设备对象
status = DriverCreateDevice(pDriverObj);//函数封装
//卸载
DbgPrint(L"See you Again!");
return status;
}
解释:
1.extern "C"的用处是让C++可以和其他语言混合使用
2.驱动程序虽然有了设备名称,但这种设备只在内核态可见,对于应用程序是不可见的
因此,驱动需要暴露一个符号链接,指向真正的设备名
3.在驱动程序中,定义设备对象名称需要以L"\\Device\\"开头
4.定义符号链接的名称需要以L"\\dosDevices\\"开头,或者以L"\\??\\"开头也可以
5.NT_SUCCESS()宏,测试返回的NTSTATUS值
6.NTSTATUS是一个有符号 的长整数。并且分为四个域。最高2位Sev域,描述的是这个NTSTATUS的严重性(Severity):
00 成功(Success)
01 信息(Informational)
10 警告(Warning)
11 错误(Error)
00和01应该都表示成功的状态,10和11都表示错误状态。
7.RtlInitUnicodeString() 函对一个Unicode字符串初始化
8.Rtl_Constant_String() 初始化Unicode字符串的宏 只能在串定义的时候使用
9.驱动程序创建设备对象一共有三种读写方式,分别是缓冲区读写、直接方式读写和其他方式读写。
这三种方式对应的设备对象的Flags子域分别是DO_BUFFERED_IO、DO_DIRECT_IO和0。
创建好设备IoCreateDevice后,需要设置DO_BUFFERED_IO, pDevObj->Flags |= DO_BUFFERED_IO
10. |= 意思为:按位或后赋值
^= 意思为:按位异或后赋值
&= 意思为:按位与后赋值
11.PDEVICE_EXTENSION pDevExt; //自定义结构的指针
12.pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
//将设备的扩展结构转为自定义结构类型,将指针赋于pDevExt
13.pDevExt->pDevice = pDevObj; //修改自定义结构成员
14。
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName; //设备名称
UNICODE_STRING ustrSymLinkName; //符号链接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName; //设备名称
UNICODE_STRING ustrSymLinkName; //符号链接名
} DEVICE_EXTENSION;
typedef struct _DEVICE_EXTENSION *PDEVICE_EXTENSION;
关于DeviceExtension的使用
https://blog.csdn.net/trustnature/article/details/7927813 *****
https://blog.csdn.net/ccx_john/article/details/6331254 ****
https://blog.csdn.net/qq_37232329/article/details/109837833 ***
https://blog.csdn.net/qq125096885/article/details/47313007
http://www.myexceptions.net/embedded-driver/330718.html