How the handle of DeviceIoControl() is transferred& translated in kernel?

Hi All,

As everyone knows when we invoke DeviceIoControl() in user mode, we
passed a handle as first parameter. Can someone provide some information
about how this handle is transferred in kernel mode? Especially I eager
to know the difference between the handle get from KsCreatePin() and the
one got from user mode. And how I can get the handle again in the
KsPropertyHandler() (I’ve hooked this routine).

From following stack trace, I can see the handle(2c8) is kept as first
parameter until nt!IopXxxControlFile().

Any comment will be highly appreciated!

eec3a670 ee2c0190 85010980 00000003 eec7c098 ks!KsPropertyHandler (FPO:
WARNING: Stack unwind information not available. Following frames may be
eec3a710 eec7e1d8 85010980 00000003 eec7c098 AudSight+0x5190
eec3a764 f73efdfe 85124160 85010980 804ee171
sysaudio!CPinInstance::PinDispatchIoControl+0x115 (FPO: [Non-Fpo])
eec3a770 804ee171 85124160 85010980 806be2cc
ks!DispatchDeviceIoControl+0x25 (FPO: [2,0,0])
eec3a780 805674d2 85010ac8 857d8198 85010980 nt!IopfCallDriver+0x31
(FPO: [0,0,1])
eec3a794 805681f6 85124160 85010980 857d8198
nt!IopSynchronousServiceTail+0x5e (FPO: [Non-Fpo])
eec3a830 80561288 000002c8 00000108 00000000 nt!IopXxxControlFile+0x5a6
(FPO: [Non-Fpo])
eec3a864 805333c4 000002c8 00000108 00000000
nt!NtDeviceIoControlFile+0x28 (FPO: [Non-Fpo])
eec3a864 7ffe0304 000002c8 00000108 00000000 nt!KiSystemService+0xc9
(FPO: [0,0] TrapFrame @ eec3a894)
0022f514 77f75b1d 77e755d6 000002c8 00000108
SharedUserData!SystemCallStub+0x4 (FPO: [0,0,0])

Best Regards,

How can I use windbg to find virtual address of my physical device
address ?

!ptov does not show the virtual address