[转载]IRP 乱杂谈
文章作者:JIURL <BR><BR>IRP 乱杂谈 <BR><BR>作者: JIURL <BR>主页: [url]http://jiurl.yeah.net[/url] <BR>--------------------------------------------------------------------------------<BR>IRP 是 I/O request packet 的缩写,即 I/O 请求包。驱动与驱动之间通过 IRP 进行通信。而使用驱动的应用层调用的 CreatFile,ReadFile,WriteFile,DeviceIoControl 等函数,说到底也是使用 IRP 和驱动进行通信。<BR><BR>一个 IRP 由两部分组成。首先是头部或者叫包的固定部分,是一个 IRP 结构。紧跟在这个头部之后的是 I/O stack locations ,这是一个 IO_STACK_LOCATION 结构的数组,这个数组中元素的个数是根据情况而定的,由 IoAllocateIrp( IN CCHAR StackSize , IN BOOLEAN ChargeQuota ) 时的参数 StackSize 决定。而 StackSize 通常由 IRP 发往的目标 DEVICE_OBJECT 的 +30 char StackSize 决定。而这个 StackSize 是由设备对象连入所在的设备栈时,根据在设备栈中位置决定的。我们先看看 IRP 结构和 IO_STACK_LOCATION 结构的定义。<BR><BR>IRP 结构定义如下<BR><BR>struct _IRP (sizeof=112)<BR>+00 int16 Type<BR>+02 uint16 Size<BR>+04 struct _MDL *MdlAddress<BR>+08 uint32 Flags<BR>+0c union __unnamed14 AssociatedIrp<BR>+0c struct _IRP *MasterIrp<BR>+0c int32 IrpCount<BR>+0c void *SystemBuffer<BR>+10 struct _LIST_ENTRY ThreadListEntry<BR>+10 struct _LIST_ENTRY *Flink<BR>+14 struct _LIST_ENTRY *Blink<BR>+18 struct _IO_STATUS_BLOCK IoStatus<BR>+18 int32 Status<BR>+18 void *Pointer<BR>+1c uint32 Information<BR>+20 char RequestorMode<BR>+21 byte PendingReturned<BR>+22 char StackCount<BR>+23 char CurrentLocation<BR>+24 byte Cancel<BR>+25 byte CancelIrql<BR>+26 char ApcEnvironment<BR>+27 byte AllocationFlags<BR>+28 struct _IO_STATUS_BLOCK *UserIosb<BR>+2c struct _KEVENT *UserEvent<BR>+30 union __unnamed15 Overlay<BR>+30 struct __unnamed16 AsynchronousParameters<BR>+30 function *UserApcRoutine<BR>+34 void *UserApcContext<BR>+30 union _LARGE_INTEGER AllocationSize<BR>+30 uint32 LowPart<BR>+34 int32 HighPart<BR>+30 struct __unnamed3 u<BR>+30 uint32 LowPart<BR>+34 int32 HighPart<BR>+30 int64 QuadPart<BR>+38 function *CancelRoutine<BR>+3c void *UserBuffer<BR>+40 union __unnamed17 Tail<BR>+40 struct __unnamed18 Overlay<BR>+40 struct _KDEVICE_QUEUE_ENTRY DeviceQueueEntry<BR>+40 struct _LIST_ENTRY DeviceListEntry<BR>+40 struct _LIST_ENTRY *Flink<BR>+44 struct _LIST_ENTRY *Blink<BR>+48 uint32 SortKey<BR>+4c byte Inserted<BR>+40 void *DriverContext[4]<BR>+50 struct _ETHREAD *Thread<BR>+54 char *AuxiliaryBuffer<BR>+58 struct _LIST_ENTRY ListEntry<BR>+58 struct _LIST_ENTRY *Flink<BR>+5c struct _LIST_ENTRY *Blink<BR>+60 struct _IO_STACK_LOCATION *CurrentStackLocation<BR>+60 uint32 PacketType<BR>+64 struct _FILE_OBJECT *OriginalFileObject<BR>+40 struct _KAPC Apc<BR>+40 int16 Type<BR>+42 int16 Size<BR>+44 uint32 Spare0<BR>+48 struct _KTHREAD *Thread<BR>+4c struct _LIST_ENTRY ApcListEntry<BR>+4c struct _LIST_ENTRY *Flink<BR>+50 struct _LIST_ENTRY *Blink<BR>+54 function *KernelRoutine<BR>+58 function *RundownRoutine<BR>+5c function *NormalRoutine<BR>+60 void *NormalContext<BR>+64 void *SystemArgument1<BR>+68 void *SystemArgument2<BR>+6c char ApcStateIndex<BR>+6d char ApcMode<BR>+6e byte Inserted<BR>+40 void *CompletionKey<BR><BR>IO_STACK_LOCATION 结构定义如下<BR><BR>struct _IO_STACK_LOCATION (sizeof=36)<BR>+00 byte MajorFunction<BR>+01 byte MinorFunction<BR>+02 byte Flags<BR>+03 byte Control<BR>+04 union __unnamed19 Parameters<BR>+04 struct __unnamed20 Create<BR>+04 struct _IO_SECURITY_CONTEXT *SecurityContext<BR>+08 uint32 Options<BR>+0c uint16 FileAttributes<BR>+0e uint16 ShareAccess<BR>+10 uint32 EaLength<BR>+04 struct __unnamed21 CreatePipe<BR>+04 struct _IO_SECURITY_CONTEXT *SecurityContext<BR>+08 uint32 Options<BR>+0c uint16 Reserved<BR>+0e uint16 ShareAccess<BR>+10 struct _NAMED_PIPE_CREATE_PARAMETERS *Parameters<BR>+04 struct __unnamed22 CreateMailslot<BR>+04 struct _IO_SECURITY_CONTEXT *SecurityContext<BR>+08 uint32 Options<BR>+0c uint16 Reserved<BR>+0e uint16 ShareAccess<BR>+10 struct _MAILSLOT_CREATE_PARAMETERS *Parameters<BR>+04 struct __unnamed23 Read<BR>+04 uint32 Length<BR>+08 uint32 Key<BR>+0c union _LARGE_INTEGER ByteOffset<BR>+0c uint32 LowPart<BR>+10 int32 HighPart<BR>+0c struct __unnamed3 u<BR>+0c uint32 LowPart<BR>+10 int32 HighPart<BR>+0c int64 QuadPart<BR>+04 struct __unnamed23 Write<BR>+04 uint32 Length<BR>+08 uint32 Key<BR>+0c union _LARGE_INTEGER ByteOffset<BR>+0c uint32 LowPart<BR>+10 int32 HighPart<BR>+0c struct __unnamed3 u<BR>+0c uint32 LowPart<BR>+10 int32 HighPart<BR>+0c int64 QuadPart<BR>+04 struct __unnamed24 QueryDirectory<BR>+04 uint32 Length<BR>+08 struct _STRING *FileName<BR>+0c int32 FileInformationClass<BR>+10 uint32 FileIndex<BR>+04 struct __unnamed25 NotifyDirectory<BR>+04 uint32 Length<BR>+08 uint32 CompletionFilter<BR>+04 struct __unnamed26 QueryFile<BR>+04 uint32 Length<BR>+08 int32 FileInformationClass<BR>+04 struct __unnamed27 SetFile<BR>+04 uint32 Length<BR>+08 int32 FileInformationClass<BR>+0c struct _FILE_OBJECT *FileObject<BR>+10 byte ReplaceIfExists<BR>+11 byte AdvanceOnly<BR>+10 uint32 ClusterCount<BR>+10 void *DeleteHandle<BR>+04 struct __unnamed28 QueryEa<BR>+04 uint32 Length<BR>+08 void *EaList<BR>+0c uint32 EaListLength<BR>+10 uint32 EaIndex<BR>+04 struct __unnamed29 SetEa<BR>+04 uint32 Length<BR>+04 struct __unnamed30 QueryVolume<BR>+04 uint32 Length<BR>+08 int32 FsInformationClass<BR>+04 struct __unnamed30 SetVolume<BR>+04 uint32 Length<BR>+08 int32 FsInformationClass<BR>+04 struct __unnamed31 FileSystemControl<BR>+04 uint32 OutputBufferLength<BR>+08 uint32 InputBufferLength<BR>+0c uint32 FsControlCode<BR>+10 void *Type3InputBuffer<BR>+04 struct __unnamed32 LockControl<BR>+04 union _LARGE_INTEGER *Length<BR>+08 uint32 Key<BR>+0c union _LARGE_INTEGER ByteOffset<BR>+0c uint32 LowPart<BR>+10 int32 HighPart<BR>+0c struct __unnamed3 u<BR>+0c uint32 LowPart<BR>+10 int32 HighPart<BR>+0c int64 QuadPart<BR>+04 struct __unnamed33 DeviceIoControl<BR>+04 uint32 OutputBufferLength<BR>+08 uint32 InputBufferLength<BR>+0c uint32 IoControlCode<BR>+10 void *Type3InputBuffer<BR>+04 struct __unnamed34 QuerySecurity<BR>+04 uint32 SecurityInformation<BR>+08 uint32 Length<BR>+04 struct __unnamed35 SetSecurity<BR>+04 uint32 SecurityInformation<BR>+08 void *SecurityDescriptor<BR>+04 struct __unnamed36 MountVolume<BR>+04 struct _VPB *Vpb<BR>+08 struct _DEVICE_OBJECT *DeviceObject<BR>+04 struct __unnamed36 VerifyVolume<BR>+04 struct _VPB *Vpb<BR>+08 struct _DEVICE_OBJECT *DeviceObject<BR>+04 struct __unnamed37 Scsi<BR>+04 *Srb<BR>+04 struct __unnamed38 QueryQuota<BR>+04 uint32 Length<BR>+08 void *StartSid<BR>+0c struct _FILE_GET_QUOTA_INFORMATION *SidList<BR>+10 uint32 SidListLength<BR>+04 struct __unnamed29 SetQuota<BR>+04 uint32 Length<BR>+04 struct __unnamed39 QueryDeviceRelations<BR>+04 int32 Type<BR>+04 struct __unnamed40 QueryInterface<BR>+04 struct _GUID *InterfaceType<BR>+08 uint16 Size<BR>+0a uint16 Version<BR>+0c struct _INTERFACE *Interface<BR>+10 void *InterfaceSpecificData<BR>+04 struct __unnamed41 DeviceCapabilities<BR>+04 struct _DEVICE_CAPABILITIES *Capabilities<BR>+04 struct __unnamed42 FilterResourceRequirements<BR>+04 struct _IO_RESOURCE_REQUIREMENTS_LIST *IoResourceRequirementList<BR>+04 struct __unnamed51 ReadWriteConfig<BR>+04 uint32 WhichSpace<BR>+08 void *Buffer<BR>+0c uint32 Offset<BR>+10 uint32 Length<BR>+04 struct __unnamed52 SetLock<BR>+04 byte Lock<BR>+04 struct __unnamed53 QueryId<BR>+04 int32 IdType<BR>+04 struct __unnamed54 QueryDeviceText<BR>+04 int32 DeviceTextType<BR>+08 uint32 LocaleId<BR>+04 struct __unnamed55 UsageNotification<BR>+04 byte InPath<BR>+05 byte Reserved[3]<BR>+08 int32 Type<BR>+04 struct __unnamed56 WaitWake<BR>+04 int32 PowerState<BR>+04 struct __unnamed57 PowerSequence<BR>+04 struct _POWER_SEQUENCE *PowerSequence<BR>+04 struct __unnamed58 Power<BR>+04 uint32 SystemContext<BR>+08 int32 Type<BR>+0c union _POWER_STATE State<BR>+0c int32 SystemState<BR>+0c int32 DeviceState<BR>+10 int32 ShutdownType<BR>+04 struct __unnamed59 StartDevice<BR>+04 struct _CM_RESOURCE_LIST *AllocatedResources<BR>+08 struct _CM_RESOURCE_LIST *AllocatedResourcesTranslated<BR>+04 struct __unnamed60 WMI<BR>+04 uint32 ProviderId<BR>+08 void *DataPath<BR>+0c uint32 BufferSize<BR>+10 void *Buffer<BR>+04 struct __unnamed61 Others<BR>+04 void *Argument1<BR>+08 void *Argument2<BR>+0c void *Argument3<BR>+10 void *Argument4<BR>+14 struct _DEVICE_OBJECT *DeviceObject<BR>+18 struct _FILE_OBJECT *FileObject<BR>+1c function *CompletionRoutine<BR>+20 void *Context<BR><BR>IO_STACK_LOCATION 结构的大小是固定的,+04 到 +14 之间的16个字节是个公用体。<BR><BR>我们大略的看一个例子,或许能让你对 IO_STACK_LOCATION 有点概念<BR><BR>一个驱动程序的应用层程序,调用 DeviceIoControl ,让驱动程序完成一个任务。DeviceIoControl 中会申请一个Irp,初始化它,然后用这个 Irp,调用 IoCallDriver 发往设备栈的最高层。<BR><BR>IoCallDriver 会根据Irp中的当前 IO_STACK_LOCATION 中的 +00 byte MajorFunction,调用发往设备对象所属驱动中的相应函数。<BR><BR>我们看看被传入到设备栈最高层的 irp,<BR><BR>kd> !irp fe403968<BR>Irp is active with 6 stacks 6 is current (= 0xfe403a8c)<BR>No Mdl System buffer = fe3d6068 Thread fe427960: Irp stack trace. <BR>cmd flg cl Device File Completion-Context<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>>[ e, 0] 0 0 fe4f5df0 fe426688 00000000-00000000 <BR>\\Driver\\Kbdclass<BR>Args: 00000000 00000004 000b0008 00000000<BR><BR>WinDbg 的 !irp 命令,会显示一个 Irp 的 IO_STACK_LOCATION 数组的一些格式化信息<BR><BR>可以看到传入的这个 Irp,它的最后一个 IO_STACK_LOCATION 是当前的 IO_STACK_LOCATION,里面有传入的一些参数。<BR><BR>>[ e, 0] 0 0 fe4f5df0 fe426688 00000000-00000000 <BR>\\Driver\\Kbdclass<BR>Args: 00000000 00000004 000b0008 00000000<BR><BR>kd> !strct io_stack_location fe403a8c<BR>struct _IO_STACK_LOCATION (sizeof=36)<BR>+00 byte MajorFunction = 0e .<BR>+01 byte MinorFunction = 00 .<BR>+02 byte Flags = 00 .<BR>+03 byte Control = 00 .<BR>+04 union __unnamed19 Parameters<BR>+04 struct __unnamed33 DeviceIoControl<BR>+04 uint32 OutputBufferLength = 00000000<BR>+08 uint32 InputBufferLength = 00000004<BR>+0c uint32 IoControlCode = 000b0008<BR>+10 void *Type3InputBuffer = 00000000<BR>+14 struct _DEVICE_OBJECT *DeviceObject = FE4F5DF0<BR>+18 struct _FILE_OBJECT *FileObject = FE426688<BR>+1c function *CompletionRoutine = 00000000<BR>+20 void *Context = 00000000<BR><BR>这些就是当前 IO_STACK_LOCATION,里面有参数什么的,这样本层驱动就可以根据 IRP 和当前的 IO_STACK_LOCATION 中的内容,知道该干些什么。本例中,本层驱动根据这个 Irp 做了些处理,发现还需要下层驱动做更多处理,就设置了下一层驱动要使用的 IO_STACK_LOCATION ,然后调用 IoCallDriver ,把这个 Irp 发到了下一层。<BR><BR>在下一层的处理程序中,我们看看收到的 Irp<BR><BR>kd> !irp fe403968<BR>Irp is active with 6 stacks 5 is current (= 0xfe403a68)<BR>No Mdl System buffer = fe3d6068 Thread fe427960: Irp stack trace. <BR>cmd flg cl Device File Completion-Context<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000 00000000<BR>>[ f, 0] 0 0 fe4f5020 fe426688 00000000-00000000 <BR>\\Driver\\i8042prt<BR>Args: 00000000 00000004 000b0008 00000000<BR>[ e, 0] 0 0 fe4f5df0 fe426688 00000000-00000000 <BR>\\Driver\\Kbdclass<BR>Args: 00000000 00000004 000b0008 00000000<BR><BR>我们看到了 Irp 的当前 IO_STACK_LOCATION 变成了倒数第二个 IO_STACK_LOCATION ,里面是上一层驱动中设置的参数,告诉这一层驱动要干什么。本例中,本层驱动读写端口,操作硬件,完成了相应的功能。<BR><BR>IoCallDriver<BR><BR>首先我们看看对了解 IRP 最重要的一个函数,也是使用 IRP 进行驱动间通信所使用的函数,IoCallDriver。这个函数并不大,也不复杂,我们将详细的看看它的汇编代码。<BR><BR>NTSTATUS <BR>IoCallDriver(<BR>IN PDEVICE_OBJECT DeviceObject,<BR>IN OUT PIRP Irp<BR>);<BR>Irp 是发往设备对象的。参数 DeviceObject 指明设备目标设备对象。<BR><BR>nt!IoCallDriver:<BR>80421417 8b542408 mov edx,[esp+0x8]<BR>/* [esp+0x8] 为 IN OUT PIRP Irp */<BR>8042141b 8b4c2404 mov ecx,[esp+0x4]<BR>/* [esp+0x4] 为 IN PDEVICE_OBJECT DeviceObject */<BR>8042141f e82ae1ffff call nt!IofCallDriver (8041f54e)<BR>80421424 c20800 ret 0x8<BR><BR>nt!IofCallDriver:<BR>8041f54e ff25d01a4780 jmp dword ptr [nt!pIofCallDriver (80471ad0)]<BR><BR>nt!IopfCallDriver:<BR>8041f516 56 push esi<BR>8041f517 8bf2 mov esi,edx<BR>/* edx 为 IN OUT PIRP Irp */<BR>8041f519 57 push edi<BR>8041f51a 8bf9 mov edi,ecx<BR>/* ecx 为 IN PDEVICE_OBJECT DeviceObject */<BR>8041f51c fe4e23 dec byte ptr [esi+0x23]<BR>/* esi 为 IN OUT PIRP Irp */<BR>/* struct _IRP (sizeof=112) */<BR>/* +23 char CurrentLocation */<BR>8041f51f 8a4623 mov al,[esi+0x23]<BR>8041f522 33c9 xor ecx,ecx<BR>8041f524 3ac1 cmp al,cl<BR>8041f526 7f0b jg nt!IopfCallDriver+0x1d (8041f533)<BR>/* 如果 Irp->CurrentLocation 大于0,就跳 */<BR>8041f528 51 push ecx<BR>8041f529 51 push ecx<BR>8041f52a 51 push ecx<BR>8041f52b 56 push esi<BR>8041f52c 6a35 push 0x35<BR>8041f52e e8e1c90000 call nt!KeBugCheckEx (8042bf14)<BR>8041f533 8b4660 mov eax,[esi+0x60]<BR>/* esi 为 IN OUT PIRP Irp */<BR>/* struct _IRP (sizeof=112) */<BR>/* +60 struct _IO_STACK_LOCATION *CurrentStackLocation */<BR>8041f536 56 push esi<BR>/* esi 为 IN OUT PIRP Irp */<BR>8041f537 83e824 sub eax,0x24<BR>/* eax 为 Irp->CurrentStackLocation */<BR>/* 0x24 为 sizeof(IO_STACK_LOCATION) */<BR>8041f53a 57 push edi<BR>/* edi 为 IN PDEVICE_OBJECT DeviceObject */<BR>8041f53b 894660 mov [esi+0x60],eax<BR>/* [esi+0x60] 为 Irp->CurrentStackLocation */<BR>8041f53e 897814 mov [eax+0x14],edi<BR>/* eax 为新的当前 IO_STACK_LOCATION */<BR>/* struct _IO_STACK_LOCATION (sizeof=36) */<BR>/* +14 struct _DEVICE_OBJECT *DeviceObject */<BR>/* edi 为 IN PDEVICE_OBJECT DeviceObject */<BR>8041f541 8b4f08 mov ecx,[edi+0x8]<BR>/* edi 为 IN PDEVICE_OBJECT DeviceObject */<BR>/* struct _DEVICE_OBJECT (sizeof=184) */<BR>/* +08 struct _DRIVER_OBJECT *DriverObject */<BR>8041f544 0fb600 movzx eax,byte ptr [eax]<BR>/* eax 为新的当前 IO_STACK_LOCATION */<BR>/* struct _IO_STACK_LOCATION (sizeof=36) */<BR>/* +00 byte MajorFunction */<BR>8041f547 ff548138 call dword ptr [ecx+eax*4+0x38]<BR>/* ecx 为 DeviceObject->DriverObject */<BR>/* struct _DRIVER_OBJECT (sizeof=168) */<BR>/* +38 function *MajorFunction[28] */<BR>/* eax 为 Irp->CurrentStackLocation->MajorFunction */<BR>/* [ecx+eax*4+0x38] 为 */<BR>/* DeviceObject->DriverObject.MajorFunction[Irp->CurrentStackLocation->MajorFunction] */<BR>8041f54b 5f pop edi<BR>8041f54c 5e pop esi<BR>8041f54d c3 ret<BR><BR>IoCallDriver 将参数 Irp 的 +23 char CurrentLocation 减1,然后检查这时的 CurrentLocation 是否大于0。如果不大于0,将蓝屏。接着将参数 Irp 的 +60 struct _IO_STACK_LOCATION *CurrentStackLocation 减 0x24 。这里原来是一个 IO_STACK_LOCATION 的地址,0x24是一个 IO_STACK_LOCATION 结构的大小。这样减 0x24 就等于把 +60 struct _IO_STACK_LOCATION *CurrentStackLocation 指向了前一个 IO_STACK_LOCATION。然后将新的 CurrentStackLocation 的 +14 struct _DEVICE_OBJECT *DeviceObject 赋值为传入的参数 DeviceObject 。从传入的参数 DeviceObject 中获得该 DeviceObject 的 DriverObject,调用该 DriverObject 的新的 CurrentStackLocation 的 +00 byte MajorFunction 相应的 MajorFunction ,用传入的两个参数 IN PDEVICE_OBJECT DeviceObject,IN OUT PIRP Irp 做参数。<BR><BR>简单的说,把 Irp 的 CurrentLocation 减1,CurrentStackLocation 指向前一个(地址更小处) 的IO_STACK_LOCATION。然后根据现在的 CurrentStackLocation 所指的 IO_STACK_LOCATION 结构中 MajorFunction 的值,调用 DeviceObject 所属的驱动的 DriverObject 中 MajorFunction[28] 相应的函数。<BR><BR>DriverObject 中的 MajorFunction[28],是在 DriverEntry 中初始化的。<BR><BR>Irp 的产生<BR><BR>Irp 说到底是由 IoAllocateIrp 产生的。IoBuildDeviceIoControlRequest 这样产生 Irp 的函数,也是调用 <BR>IoAllocateIrp 实现的。一个驱动可能需要另一层的驱动完成什么功能,而直接使用 IoBuildDeviceIoControlRequest 这样函数产生 Irp,并用这个 Irp 和其他驱动通信。更多的 Irp 是应用层,使用 ReadFile,WriteFile,DeviceIoControl 等这样的 api,来产生的。这些 api 最终也会调用 IoAllocateIrp 产生一个 Irp,然后初始化这个 Irp,发给驱动,驱动会根据 Irp ,完成相应的任务。<BR><BR>Irp 操作的一些函数<BR><BR>操作Irp的一些函数,很简单,只是一些宏。了解这些函数的具体的操作,有助于对 Irp 的了解。<BR>下面的内容来自 ntddk.h<BR><BR>IoGetCurrentIrpStackLocation<BR><BR>#define IoGetCurrentIrpStackLocation( Irp ) ( (Irp)->Tail.Overlay.CurrentStackLocation )<BR><BR>IoSkipCurrentIrpStackLocation<BR><BR>#define IoSkipCurrentIrpStackLocation( Irp ) \\<BR>(Irp)->CurrentLocation++; \\<BR>(Irp)->Tail.Overlay.CurrentStackLocation++;<BR><BR>IoGetNextIrpStackLocation<BR><BR>#define IoGetNextIrpStackLocation( Irp ) (\\<BR>(Irp)->Tail.Overlay.CurrentStackLocation - 1 )<BR><BR>IoCopyCurrentIrpStackLocationToNext<BR><BR>#define IoCopyCurrentIrpStackLocationToNext( Irp ) { \\<BR>PIO_STACK_LOCATION irpSp; \\<BR>PIO_STACK_LOCATION nextIrpSp; \\<BR>irpSp = IoGetCurrentIrpStackLocation( (Irp) ); \\<BR>nextIrpSp = IoGetNextIrpStackLocation( (Irp) ); \\<BR>RtlCopyMemory( nextIrpSp, irpSp, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); \\<BR>nextIrpSp->Control = 0; }<BR><BR>IoMarkIrpPending<BR><BR>#define IoMarkIrpPending( Irp ) ( \\<BR>IoGetCurrentIrpStackLocation( (Irp) )->Control |= SL_PENDING_RETURNED )<BR><BR>Irp 的释放<BR><BR>使用 IoFreeIrp 释放一个 Irp<BR><BR>Irp 的结束<BR><BR>使用 IoCompleteRequest 结束一个 Irp,这个是了解如何使用 Irp 通信中,除了 IoCallDriver 外,第二重要的函数,这个函数又大又复杂,牵涉到其他的一些机制,对自己,还是下不了这个毒手,所以就不说了,用一用也就有个大概的概念。页:
[1]