驱动程序由于有较强的模式约束,加上不易调试,往往让学习者望而却步,在这里我将学习驱动的一点心得与大家共享。
为了探寻过滤驱动和驱动之间的关系,我写了一个小小的示例驱动,《Windows 2000/XP WDM设备驱动程序开发》一书所配套的源代码中的CharSample_DDK,及DDK所带的KbFilter驱动改造成一个过滤驱动。驱动源代码放到了我的资源中,有需要的用户可以去下载。
CharSample_DDK完成将一个数据转换成一个大写如将1转换成一,为功能驱动
CharFilter完成将一串数据转换成大写,如 123转换成一二三等。为过滤驱动
CharFilter主要功能是将一串数字一个个的传给功能驱动CharSample_DDK主要代码如下。
一、驱动创建过程信息抓图
二、驱动卸载过程信息抓图
三、读取数据过程信息抓图
四、信息处理过程主要实现代码
NTSTATUS CharFilter_Control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status; PIO_STACK_LOCATION irpStack, irpnextStack; ULONG in, out; PVOID *inputbuf, *outputbuf; CHAR ins[16], outs[16]; DbgPrint(__FUNCTION__);
RtlZeroMemory(ins, sizeof(CHAR) * 16); RtlZeroMemory(outs, sizeof(CHAR) * 16); irpStack = IoGetCurrentIrpStackLocation(Irp); in = irpStack->Parameters.DeviceIoControl.InputBufferLength; out = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
inputbuf = Irp->AssociatedIrp.SystemBuffer; outputbuf = Irp->AssociatedIrp.SystemBuffer;
strncpy((PCHAR)ins, (PCHAR)inputbuf, in);
irpnextStack = IoGetNextIrpStackLocation(Irp); DbgPrint("%s irpstack = %p, irpnext = %p", __FUNCTION__, irpStack, irpnextStack); status = STATUS_SUCCESS; switch(irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_800: while(in > 0) { KEVENT event;
strncpy((PCHAR)inputbuf, (PCHAR)&ins[in-1], 1); irpnextStack = IoGetNextIrpStackLocation(Irp); RtlCopyMemory(irpnextStack, irpStack, sizeof(IO_STACK_LOCATION)); DbgPrint("%s irpstack = %p, irpnext = %p", __FUNCTION__, irpStack, irpnextStack); DbgPrint("%s times in = %d out = %d", __FUNCTION__, in, out); KeInitializeEvent(&event,NotificationEvent , FALSE); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) CharCompletionRoutine, &event, TRUE, TRUE, TRUE); // No need for Cancel DbgPrint("begin call IoCallDriver %s", __FUNCTION__); status = IoCallDriver(((PDEVICE_EXTENSION) DeviceObject->DeviceExtension)->TopOfStack, Irp); DbgPrint("end call IoCallDriver %s", __FUNCTION__); if (STATUS_PENDING == status) { DbgPrint("%s status pending ", __FUNCTION__); KeWaitForSingleObject( &event, Executive, // Waiting for reason of a driver KernelMode, // Waiting in kernel mode FALSE, // No allert NULL); // No timeout } KeClearEvent(&event);
strncpy((PCHAR)&outs[(in-1)*2], (PCHAR)inputbuf, 2); in --; } strcpy((PCHAR)outputbuf, (PCHAR)outs); break; /* default:*/
} Irp->IoStatus.Status = status; Irp->IoStatus.Information = out; IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Leave %s", __FUNCTION__); return status; }
//完成例程,在功能驱动CharSample_DDK转换成完成后,执行下面的完成例程。
NTSTATUS CharCompletionRoutine(PDEVICE_OBJECT device, PIRP Irp, PVOID context) { NTSTATUS status; PKEVENT event;
event = (PKEVENT) context; DbgPrint(__FUNCTION__); status = STATUS_MORE_PROCESSING_REQUIRED; KeSetEvent(event, 0, FALSE); return status; }