首先使用QuickSys向导一个驱动框架hellodrv,然后在DeviceControl例程里写入以下代码:
NTSTATUS
HellodrvDispatchDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS ntStatus;
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PVOID lpInOutBuffer;
ULONG nInBufferSize, nOutBufferSize, dwIoControlCode;
UCHAR uBuffer[256]={0};
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Get the pointer to the input/output buffer and it's length
//
lpInOutBuffer = Irp->AssociatedIrp.SystemBuffer;
nInBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
nOutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
dprintf("[HelloDrv] IRP_MJ_DEVICE_CONTROL/n");
dwIoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch (dwIoControlCode)
{
case IOCTL_HELLODRV_HELLO:
{
__try
{
strncpy(uBuffer,lpInOutBuffer,256);
dprintf(uBuffer);
{
int iLen=strlen("Hi! I Got it!");
strncpy(lpInOutBuffer,"Hi! I Got it!",nOutBufferSize);
Irp->IoStatus.Information=iLen;
}
}
__except(1)
{
dprintf("Excpetion during strncpy");
}
break;
}
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
dprintf("[HelloDrv] unknown IRP_MJ_DEVICE_CONTROL/n");
break;
}
//
// DON'T get cute and try to use the status field of
// the irp in the return status. That IRP IS GONE as
// soon as you call IoCompleteRequest.
//
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// We never have pending operation so always return the status code.
//
return ntStatus;
}
编译生成一个sys后,使用Driver Testter测试它。
装载驱动:设置好参数后点Load按钮完成驱动装载.
进行IO测试,在这里可以通过Driver Tester程序传递最长256字节数据给驱动。
点Content按钮,设置参数,可以在左边使用16进制设置数据包值,比如某种特别的包结构内容,也可以使用右边的ASIIC视图输入字符,我在这里只敲了个了字符串"can you see it?"
参数设置好后,点IoControl按钮
可以看到驱动已收到了我们的数据,再看看驱动返回的数据,按Content按钮
我们也以收到驱动返回的数据,后面的那个t?是因为驱动返回的数据没有我们输入的长,所以没有被覆盖掉。
卸载驱动:最后点击Unload按钮,卸载驱动同时删除服务,不会在系统留下干什么痕迹,我不喜欢什么东东都在注册表写东东,自所不欲,勿所于人!这一点我很明白,所以在停止Driver的Kernel类型服务后,我就将服务删除。
一个小问题:
就是输入输出缓冲最大只支持256字节,为什么只支持这么小的数据Buffer,因为我只是要写一个小的驱动来研究系统,而不是要搞大数据量的东东,而且在对驱动进行一次DeviceIoControl也不宜用过大的数据,特别是在Buffered方式时IO管理器会把数据copy到内核态空间,此前IO管理器会分配一块内存,在驱动处理完后IO管理器再将数据从内核心态空间copy回ring3的Buffer里,这样会使效率所低,会占用很多我们很宝贵的内存啊!所以我建议的做法是驱动只完成很小的动作,比如要dump什么数据,驱动一次只负责dump一块出来,由Ring3程序进行多次DeviceIoControl请求来完成大量数据的dump操作,这样的效率也许会高一些,也就是驱动只完成一些"原子操作",而应用逻辑由Ring3程序进行包装实现。
Driver Logical Tester不是一个Debug工具,更不能防止BSOD出现,它所能做的是在你已经对你的驱动Debug后,对驱动的输入输出做一些逻辑测试,所以我给它起的名称叫Driver Logical Tester,也许没有什么大不了,但对我来说很有用,呵呵!
程序介绍:
关于DeviceID,ControlCode和Method不要问我是什么意思,怎么取值!!!具体的取值也根据你自己定义的来设置,界面里的Notes已经说明了它们的关系。需要这个小东东的朋友可以到http://kruglinski.ys168.com/下载。