首页
社区
课程
招聘
东拼西凑认识WDM驱动程序
发表于: 2008-1-3 22:01 5119

东拼西凑认识WDM驱动程序

2008-1-3 22:01
5119
原文引自:
711K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3y4G2k6r3g2H3M7X3!0B7k6h3y4@1i4K6u0W2j5$3!0E0i4K6u0r3d9@1u0Q4x3V1k6K6P5i4y4@1k6h3#2Q4x3V1k6i4c8p5#2Q4y4h3k6p5M7X3W2$3k6i4u0Q4y4h3k6V1k6i4k6W2L8r3!0H3L8h3g2F1N6q4)9J5k6h3q4K6M7s2R3`.
部分注释来自:
Programming the Microsoft Windows Driver Model.pdf
建立你自己的WDM驱动:
所需重要的数据结构:DEVICE_EXTENSION!
    typedef struct tagDEVICE_EXTENSION {
        PDEVICE_OBJECT DeviceObject;       // device object this driver creates
        PDEVICE_OBJECT NextDeviceObject;   // next-layered device object in this
                                           // device stack
        DEVICE_CAPABILITIES pdc;           // device capability
        IO_REMOVE_LOCK RemoveLock;         // removal control locking structure
        LONG handles;                      // # open handles
        PVOID DataBuffer;                  // Internal Buffer for Read/Write I/O
        UNICODE_STRING Device_Description; // Device Description
        SYSTEM_POWER_STATE SysPwrState;    // Current System Power State
        DEVICE_POWER_STATE DevPwrState;    // Current Device Power State
        PIRP PowerIrp;                     // Current Handling Power-Related IRP
    } DEVICE_EXTENSION, *PDEVICE_EXTENSION;


对上图的一些解释:
1.对于 WDM 驱动程序的DriverEntry 例程,其主要工作是把各种函数指针填入驱动程序对象。这些指针为操作系统指明了驱动程序容器中各种子例程的位置。
2.需要对 IRP排队的驱动程序一般都有一个StartIo例程。执行 DMA传输的驱动程序应有一个 AdapterControl 例程。大部分能生成硬件中断的设备,其驱动程序都有一个中断服务例程(ISR)和一个推迟过程调用(DPC)例程。驱动程序一般都有几个支持不同类型IRP的派遣函数,其中三个派遣函数(DispatchPnp,DispatchPower,DispatchWmi)是必须的。所以,WDM 驱动程序开发者的一个任务就是为这个容器选择所需要的例程。
DriverEntry 注册所有的例程:
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
RtlInitUnicodeString(
&Global_sz_Drv_RegInfo,
RegistryPath->Buffer);

// Initialize function pointers

DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = AddDevice;

DriverObject->MajorFunction[IRP_MJ_CREATE] = PsdoDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PsdoDispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = PsdoDispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = PsdoDispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PsdoDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = PsdoDispatchPower;
DriverObject->MajorFunction[IRP_MJ_PNP] = PsdoDispatchPnP;

return STATUS_SUCCESS;
}

对上图的一些解释:
1.WDM驱动程序的 DriverEntry 例程应完成对这个驱动程序对象的初始化并返回。
2.PnP管理器按照设备驱动程序的要求构造了设备对象堆栈,PnP管理器自动把新硬件匹配到正确的 WDM 驱动程序上,并调用该驱动程序的 AddDevice 例程,再由AddDevice 例程做所有必要的初始化工作。
3.在 WDM 驱动程序模型中,每个硬件设备至少有两个驱动程序。
a.其中一个驱动程序我们称为功能(function)驱动程序,通常它就是你认为的那个硬件设备驱动程序。它了解使硬件工作的所有细节,负责初始化 I/O 操作,有责任处理 I/O 操作完成时所带来的中断事件,有责任为用户提供一种设备适合的控制方式。
b.另一个驱动程序我们称为总线(bus)驱动程序。它负责管理硬件与计算机的连接。
c.有些设备有两个以上的驱动程序。我们使用术语过滤器驱动程序(filter driver)来描述它们。某些过滤器驱动程序,仅仅是在功能驱动程序执行I/O 操作时进行监视。
AddDevice 创建一个设备对象并把它连接到已存在的设备堆栈中。
    NTSTATUS
    AddDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PhysicalDeviceObject
    )
    {
        ULONG DeviceExtensionSize;
        PDEVICE_EXTENSION p_DVCEXT;
        PDEVICE_OBJECT ptr_PDO;
        NTSTATUS status;

        RtlInitUnicodeString(
            &Global_sz_DeviceName, L"");
        //Get DEVICE_EXTENSION required memory space
        DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
        //Create Device Object
        status = IoCreateDevice(
            DriverObject,
            DeviceExtensionSize,
            &Global_sz_DeviceName,
            FILE_DEVICE_UNKNOWN,
            FILE_DEVICE_SECURE_OPEN,
            FALSE,
            &ptr_PDO
            );

        if (NT_SUCCESS(status)) {
            ptr_PDO->Flags &= ~DO_DEVICE_INITIALIZING;
            ptr_PDO->Flags |= DO_BUFFERED_IO;  //For Buffered I/O
            //ptr_PDO->Flags |= DO_DIRECT_IO;  //For Direct I/O
            p_DVCEXT = ptr_PDO->DeviceExtension;
            p_DVCEXT->DeviceObject = ptr_PDO;
            RtlInitUnicodeString(
            //Other initialization tasks go here
            //Store next-layered device object
            //Attach device object to device stack
            p_DVCEXT->NextDeviceObject =
                IoAttachDeviceToDeviceStack(ptr_PDO, PhysicalDeviceObject);
        }

        return status;
    }

通常,你将使用CreateFile/fopen函数连接底层设备,Win32子系统发送IRP_MJ_CREATE,
并向驱动程序请求连接目标设备。
    NTSTATUS
    PsdoDispatchCreate(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
    {
        PIO_STACK_LOCATION p_IO_STK;
        PDEVICE_EXTENSION p_DVCEXT;
        NTSTATUS status;

        p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
        p_DVCEXT = DeviceObject->DeviceExtension;
        status = IoAcquireRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
        if (NT_SUCCESS(status)) {
            CompleteRequest(Irp, STATUS_SUCCESS, 0);
            return STATUS_SUCCESS;
        } else {
            IoReleaseRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
            CompleteRequest(Irp, status, 0);
            return status;
        }
    }
如何支持IRP_MJ_CLOSE:

你将使用CloseFile/flose函数连接底层设备,Win32子系统发送IRP_MJ_CREATE,
并向驱动程序请求关闭目标设备。
    NTSTATUS
    PsdoDispatchClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
    {
        PIO_STACK_LOCATION p_IO_STK;
        PDEVICE_EXTENSION p_DVCEXT;

        p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
        p_DVCEXT = DeviceObject->DeviceExtension;
        IoReleaseRemoveLock(&p_DVCEXT->RemoveLock,
        p_IO_STK->FileObject);
        CompleteRequest(Irp, STATUS_SUCCESS, 0);
        return STATUS_SUCCESS;
    }

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
  • 2.JPG (42.47kb,191次下载)
  • 1.jpg (32.72kb,188次下载)
  • 3.JPG (49.83kb,189次下载)
  • 4.JPG (56.38kb,189次下载)
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 223
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
到是很形象.
不过是不是楼主贴出来得不全呀!!!
有几个历程我怎么没发现。如果对入门教程得话,个人认为这个复杂了点,并且注释偏少。^_^
2008-1-4 01:22
0
雪    币: 248
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
很好的教程,LZ,应该还有吧,一起贴出来,支持!
2008-1-5 14:56
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
还有接着的么?
2008-1-5 18:01
0
游客
登录 | 注册 方可回帖
返回