标签:
原文:http://blog.csdn.net/caperingrabbit/article/details/5285288
配置好了开发环境之后,下面就要通过具体的程序来了解驱动的开发了。下面我们以一个WDM驱动的框架来实现Windows驱动程序的HelloWorld。
作为一个驱动程序,首先应该写的是它的入口函数,这点跟MFC的WinMain或者C++中的Main函数一样,驱动的入口函数使用DriverEntry。在入口函数中主要实现的功能是一些分发例程的注册以及其他的需要初始化的事务。
DriverEntry的原型是NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath),IN、OUT这只是一个宏,用来表示参数的输入输出类型,并无实质意义,也不占空间。pDriverObject是我们所要创建的驱动对象,pRegistryPath是驱动程序在注册表中的地址。至于它们的类型,PDRIVER_OBJECT是驱动开发中一个重要的数据结构,这是驱动对象,具体的我们以后再讨论,而PUNICODE_STRING则是一个宽字符的指针,在内核开发中,一般使用的字符串都是宽字符,即Unicode string。 下面是一个范例:
- extern"C"
- NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
- IN PUNICODE_STRING pRegistryPath
- )
- {
- KdPrint(("Hello!welcome to the driver entry!/n"));
-
- for(ULONG i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
- {
- pDriverObject->MajorFunction[i] = DispatchRoutine;
- }
-
-
-
- pDriverObject->DriverExtension->AddDevice = MyDeviceAdd;
- pDriverObject->DriverUnload = DriverUnload;
- pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchRoutine;
-
- return STATUS_SUCCESS;
- }
完成了入口函数之后,接下来就要实现上面注册的分发例程的功能函数了。作为一个WDM驱动程序,首先需要创建设备对象,这个任务就交给AddDevice例程,通过上面的注册,实现部分放在MyDeviceAdd。
- NTSTATUS MyDeviceAdd(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PhysicalDeviceObject)
- {
- PAGED_CODE();
- KdPrint(("Enter MyDrivers/n"));
-
- NTSTATUS status;
- PDEVICE_OBJECT fdo;
- UNICODE_STRING devName;
- RtlInitUnicodeString(&devName,L"//Device//MyDevice");
-
- status = IoCreateDevice(
- DriverObject,
- sizeof(DEVICE_EXTENSION),
- &(UNICODE_STRING)devName,
- FILE_DEVICE_UNKNOWN,
- 0,
- FALSE,
- &fdo);
- if( !NT_SUCCESS(status))
- return status;
-
- PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
-
- pdx->fdo = fdo;
-
- pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
- UNICODE_STRING symLinkName;
- RtlInitUnicodeString(&symLinkName,L"//DosDevices//MyDriver");
-
- pdx->ustrDeviceName = devName;
- pdx->ustrSymLinkName = symLinkName;
- status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);
-
- if( !NT_SUCCESS(status))
- {
- IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
- status = IoCreateSymbolicLink(&symLinkName,&devName);
- if( !NT_SUCCESS(status))
- {
- return status;
- }
- }
-
- fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
- fdo->Flags &= ~DO_DEVICE_INITIALIZING;
-
- KdPrint(("LeaveMyDrivers/n"));
- return STATUS_SUCCESS;
- }
生成了设备对象之后,接下来就要处理发向设备的各种请求了。这里就用一个通用的处理例程来示范一下。其实这个处理函数只是将这些请求转交给真实的设备而已,没有实际的功能。
- NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
- IN PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMDispatchRoutine/n"));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest( Irp, IO_NO_INCREMENT );
- KdPrint(("Leave HelloWDMDispatchRoutine/n"));
- return STATUS_SUCCESS;
- }
- 执行完所有的请求之后,在最后卸载驱动。对于WDM驱动,标准的程序其实卸载例程没什么实质内容,一般都是有Pnp里边的RemoveDevice来处理的,这里只是一个演示,演示一下这个例程的功能和内容。
- VOID DriverUnload(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 );
- }
- }
这样,一个驱动的主要部分就完成了。接下来完成一些细碎的工作,编译一下,一个驱动就出现了。
头文件
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- #include <wdm.h>
- #ifdef __cplusplus
- }
- #endif
-
- typedef struct _DEVICE_EXTENSION
- {
- PDEVICE_OBJECT fdo;
- PDEVICE_OBJECT NextStackDevice;
- UNICODE_STRING ustrDeviceName;
- UNICODE_STRING ustrSymLinkName;
- } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
-
- #define PAGEDCODE code_seg("PAGE")
- #define LOCKEDCODE code_seg()
- #define INITCODE code_seg("INIT")
-
- #define PAGEDDATA data_seg("PAGE")
- #define LOCKEDDATA data_seg()
- #define INITDATA data_seg("INIT")
-
- #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
-
- NTSTATUS MyDeviceAdd(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PhysicalDeviceObject);
- NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT fdo,
- IN PIRP Irp);
- void DriverUnload(IN PDRIVER_OBJECT DriverObject);
-
- extern "C"
- NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath);
新建一个文本文件,内容如下:
- #
- # DO NOT EDIT THIS FILE!!! Edit ./sources. If you want to add a new source
- # file to this component. This file merely indirects to the real make file
- # that is shared by all the driver components of the Windows NT DDK
- #
-
- !INCLUDE $(NTMAKEENV)/makefile.def
重命名文件,改为Makefile,后缀没有。然后重新建立一个文本文件,写入如下内容:
- TARGETNAME=HellOWORLD
- TARGETTYPE=DRIVER
- DRIVERTYPE=WDM
- TARGETPATH=OBJ
-
- INCLUDES=$(BASEDIR)/inc;/
- $(BASEDIR)/inc/ddk;/
-
- SOURCES=MyDrivers.cpp/
保存,更改文件名为Sources,后缀没有,这样进入DDK的编译环境,已编译,一个后缀为.sys的驱动文件就出现了。
好了,一个简单的驱动就诞生了。
http://blog.csdn.net/chence19871/article/details/50697439
第二讲:我的第一个驱动
标签:
原文地址:http://www.cnblogs.com/findumars/p/5636488.html