IRP(IO请求包)用于win32和驱动程序通讯,NT内核有一个组件叫做IO管理器。IO管理器负责IRP的分发,驱动程序里创建好设备并且创建好符号链接后,Win32就可以加载驱动了。而要让一个驱动可以处理IRP,必需给驱动添加IRP处理例程。
添加的方法就是再DriverEntry里面对驱动对象DriverObject操作。该参数是一个指针,指向驱动对象,驱动对象内部有一个MajorFunction数组,该数组的类型是
NTSTATUS (*PDRIVER_DISPATCH) (IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) 。这是一个函数指针,指向每个IRP对于的处理例程。最后就是为所有需要处理的IRP实现对应的例程。
#ifndef _IRP_H_ #define _IRP_H_ /*device type*/ /*0-32767 reserved for M$ */ #define FILE_DEVICE_IRP 0x00008011 /*IRP*/ /*0-2047 reserved for M$*/ #define IRP_IOCTL_INDEX 0x810 #define IOCTL_IRP_1 CTL_CODE(FILE_DEVICE_IRP, \ IRP_IOCTL_INDEX, \ METHOD_BUFFERED, \ FILE_ANY_ACCESS) #define IOCTL_IRP_2 CTL_CODE(FILE_DEVICE_IRP, \ IRP_IOCTL_INDEX+1,\ METHOD_BUFFERED, \ FILE_ANY_ACCESS) #define IOCTL_IRP_3 CTL_CODE(FILE_DEVICE_IRP, \ IRP_IOCTL_INDEX+2,\ METHOD_BUFFERED, \ FILE_ANY_ACCESS) #endif /*_IRP_H_*/
#include <ntddk.h> #include "irp.h" /* function declares */ NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp); VOID DriverUnload(PDRIVER_OBJECT DriverObject); /* DriverEntry */ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { UNICODE_STRING DeviceNameUnicodeString; UNICODE_STRING DeviceLinkUnicodeString; NTSTATUS ntStatus; PDEVICE_OBJECT DeviceObject = NULL; DbgPrint ("Entering DriverEntry"); RtlInitUnicodeString (&DeviceNameUnicodeString, L"\\Device\\irp"); // Create an EXCLUSIVE device object (only 1 thread at a time // can make requests to this device). ntStatus = IoCreateDevice (DriverObject, 0, &DeviceNameUnicodeString, FILE_DEVICE_IRP, 0, TRUE, &DeviceObject); if (NT_SUCCESS(ntStatus)) { // Create dispatch points for device control, create, close. DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl; DriverObject->DriverUnload = DriverUnload; // Create a symbolic link, e.g. a name that a Win32 app can specify // to open the device. RtlInitUnicodeString (&DeviceLinkUnicodeString, L"\\DosDevices\\irp"); ntStatus = IoCreateSymbolicLink (&DeviceLinkUnicodeString, &DeviceNameUnicodeString); if (!NT_SUCCESS(ntStatus)) { // Symbolic link creation failed- note this & then delete the // device object (it's useless if a Win32 app can't get at it). DbgPrint ("ERROR: IoCreateSymbolicLink failed"); IoDeleteDevice (DeviceObject); } } else { DbgPrint ("ERROR: IoCreateDevice failed"); } DbgPrint ("Leaving DriverEntry"); return ntStatus; } /*DriverUnload*/ VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNICODE_STRING DeviceLinkUnicodeString; NTSTATUS ntStatus; DbgPrint ("Entering DriverUnload"); RtlInitUnicodeString (&DeviceLinkUnicodeString, L"\\DosDevices\\irp"); ntStatus = IoDeleteSymbolicLink (&DeviceLinkUnicodeString); if (NT_SUCCESS(ntStatus)) { IoDeleteDevice (DriverObject->DeviceObject); } else { DbgPrint ("ERROR: IoDeleteSymbolicLink"); } DbgPrint ("Leaving DriverUnload"); } /* DispatchCreate */ NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { DbgPrint("CreateFile called"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } /* DispatchClose */ NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { DbgPrint("CloseHandle called"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } /*DispatchDeviceControl*/ NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { PIO_STACK_LOCATION irpStack; NTSTATUS ntStatus; ULONG IoControlCodes; irpStack=IoGetCurrentIrpStackLocation(Irp); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoControlCodes=irpStack->Parameters.DeviceIoControl.IoControlCode; switch (IoControlCodes) { case IOCTL_IRP_1: DbgPrint("irp1\n"); break; case IOCTL_IRP_2: DbgPrint("irp2\n"); break; case IOCTL_IRP_3: DbgPrint("irp3\n"); break; default: ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } ntStatus=Irp->IoStatus.Status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return ntStatus; }
/*win32产生IRP*/ HANDLE hDriver= CreateFile("\\\\.\\irp", GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); ... CloseHandle(hDriver); ... DeviceIoControl(hDriver, IOCTL_IRP_1, NULL, 0, // no input buffer NULL, 0, // output buffer &junk, // # bytes returned (LPOVERLAPPED) NULL) ; // synchronous I/O