Today I had occasion to debug a problem with some IRP handling code in my driver. In the particular debugger session I found myself in, I wanted to examine some of the Irp parameters, found in the current stack location. Unfortunately I had only a pointer to the Irp in this code, and therefore needed to figure out how to find the stack location pointer using the debugger. Fun!
The function that does this in code is IoGetCurrentIrpStackLocation, which I decided to disassemble. The first part of the function basically just checks the StackCount and CurrentLocation members of the Irp to make sure that everything is ok. (This fires an assert if it doesn’t check out.) Then near the bottom of the function, we find
drv!IoGetCurrentIrpStackLocation+0x42 [source language="removed"][/source]: 23318 9dc43ea2 8b4d08 mov ecx,dword ptr [ebp+8] 23318 9dc43ea5 8b4160 mov eax,dword ptr [ecx+60h] 23319 9dc43ea8 8be5 mov esp,ebp 23319 9dc43eaa 5d pop ebp 23319 9dc43eab c20400 ret 4
So first this moves the Irp pointer into ecx, and then goes to offset 60 within that structure (which happens to be outside the range of the documented structure), and puts the pointer there into eax for return to the caller. So I try that in my debugger and compare with the output of the !irp command.
kd> !irp 9f104f68 Irp is active with 1 stacks 1 is current (= 0x9f104fd8) No Mdl: System buffer=9f08cbf0: Thread 88e05558: Irp stack trace. cmd flg cl Device File Completion-Context >[ e, 0] 5 1 88dcbd18 88e05ab8 00000000-00000000 pending FileSystemFSLX Args: 0000040c 00000000 94000004 00000000 kd> dd 9f104f68+60 L1 9f104fc8 9f104fd8 kd> db 9f104fd8 9f104fd8 0e 00 05 01 0c 04 00 00-00 00 00 00 04 00 00 94 ................ 9f104fe8 00 00 00 00 18 bd dc 88-b8 5a e0 88 00 00 00 00 .........Z...... 9f104ff8 00 00 00 00 15 15 15 15-?? ?? ?? ?? ?? ?? ?? ?? ........????????
At this point, I now realized that this structure that I needed to look at really doesn’t provide anything that’s not already provided in the !irp output. The Args output of that command correspond to the members of the IO_STACK_LOCATION.Parameters union. In this case, I am looking at a device control Irp, so these parameters are OutputBufferLength (40c), InputBufferLength (0), IoControlCode (94000004), and Type3InputBuffer (0).
So I guess the bottom line of this post is that !irp is cool and does just what you need it to, I just had to poke around a little bit before I realized it.