Bugcheck CF name is the second longest one (doesn’t fit in this post title):
TERMINAL_SERVER_DRIVER_MADE_INCORRECT_MEMORY_REFERENCE (cf)
Arguments:
Arg1: a020b1d4, memory referenced
Arg2: 00000000, value 0 = read operation, 1 = write operation
Arg3: a020b1d4, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 00000000, Mm internal code.
A driver has been incorrectly ported to Terminal Server. It is referencing session space addresses from the system process context. Probably from queueing an item to a system worker thread. The broken driver's name is displayed on the screen.
Although bugcheck explanation mentions only system process context it can also happen in an arbitrary process context. Recall that kernel space address mapping is usually considered as persistent where virtual-to-physical mapping doesn’t change between switching threads that belong to different processes. However there is so called session space in multi-user terminal services environments where different users can use different display drivers, for example:
- MS RDP users - RDPDD.DLL
- Citrix ICA users - VDTW30.DLL
- Vista users - TSDDD.DLL
- Console user - Some H/W related video driver like ATI or NVIDIA
These drivers are not committed at the same time persistently since OS boot although their module addresses might remain fixed. Therefore when a new user session is created the appropriate display driver corresponding to terminal services protocol is loaded and mapped to the so called session space starting from A0000000 (x86) or FFFFF90000000000 (x64) after win32k.sys address range (on first usage) and then committed to physical memory by proper PTE entries in process page tables. During thread switch, if the new process context belongs to a different session with a different display driver, the current display driver is decommitted by clearing its PTEs and the new driver is committed by setting its proper PTE entries.
Therefore in the system process context like worker threads virtual addresses corresponding to display driver code and data might be unknown. This can also happen in an arbitrary process context if we access the code that belongs to a display driver that doesn’t correspond to the current session protocol. This can be illustrated with the following example where TSDD can be either RDP or ICA display driver.
In the list of loaded modules we can see that ATI and TSDD drivers are loaded:
0: kd> lm
start end module name
...
...
...
77d30000 77d9f000 RPCRT4 (deferred)
77e10000 77e6f000 USER32 (deferred)
77f40000 77f7c000 GDI32 (deferred)
77f80000 77ffc000 ntdll (pdb symbols)
78000000 78045000 MSVCRT (deferred)
7c2d0000 7c335000 ADVAPI32 (deferred)
7c340000 7c34f000 Secur32 (deferred)
7c570000 7c624000 KERNEL32 (deferred)
7cc30000 7cc70000 winsrv (deferred)
80062000 80076f80 hal (deferred)
80400000 805a2940 nt (pdb symbols)
a0000000 a0190ce0 win32k (pdb symbols)
a0191000 a01e8000 ati2drad (deferred)
a01f0000 a0296000 tsdd (no symbols)
b4a60000 b4a72320 naveng (deferred)
b4a73000 b4b44c40 navex15 (deferred)
…
…
…
The bugcheck happens in 3rd-partyApp process context running inside some terminal session:
PROCESS_NAME: 3rd-partyApp.exe
TRAP_FRAME: b475f84c -- (.trap 0xffffffffb475f84c)
ErrCode = 00000000
eax=a020b1d4 ebx=00000000 ecx=04e0443b edx=ffffffff esi=a21b6778 edi=a201b018
eip=a020b1d4 esp=b475f8c0 ebp=b475f900 iopl=3 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00013246
TSDD+0×1b1d4:
a020b1d4 ?? ???
Examining display driver virtual address shows that it is unknown (PTE is NULL):
0: kd> !pte a020b1d4
A020B1D4 - PDE at C0300A00 PTE at C028082C
contains 14AB6863 contains 00000000
pfn 14ab6 –DA–KWV not valid
ATI display driver address is unknown too:
0: kd> !pte a0191000
A0191000 - PDE at C0300A00 PTE at C0280644
contains 3E301863 contains 00000000
pfn 3e301 –DA–KWV not valid
Let’s switch to another terminal session :
PROCESS 87540a60 SessionId: 45 Cid: 3954 Peb: 7ffdf000 ParentCid: 0164
DirBase: 2473d000 ObjectTable: 889b2c48 TableSize: 182.
Image: csrss.exe
0: kd> .process /r /p 87540a60
Implicit process is now 87540a60
Loading User Symbols
................
Now TSDD display driver address is valid:
0: kd> !pte a020b1d4
A020B1D4 - PDE at C0300A00 PTE at C028082C
contains 5D2C2863 contains 20985863
pfn 5d2c2 –DA–KWV pfn 20985 –DA–KWV
but ATI driver address is not. It is unknown and this is expected because no real display hardware is used:
0: kd> !pte a0191000
A0191000 - PDE at C0300A00 PTE at C0280644
contains 5D2C2863 contains 00000000
pfn 5d2c2 –DA–KWV not valid
Let’s switch to session 0 where display is “physical”:
PROCESS 8898a5e0 SessionId: 0 Cid: 0180 Peb: 7ffdf000 ParentCid: 0164
DirBase: 14c58000 ObjectTable: 8898b948 TableSize: 1322.
Image: csrss.exe
0: kd> .process /r /p 8898a5e0
Implicit process is now 8898a5e0
Loading User Symbols
..............
TSDD driver address is unknown and this is expected too because we no longer use terminal services protocol:
0: kd> !pte a020b1d4
A020B1D4 - PDE at C0300A00 PTE at C028082C
contains 14AB6863 contains 00000000
pfn 14ab6 –DA–KWV not valid
However ATI display driver addresses are not unknown (not NULL) and their 2 selected pages are either in transition or in a page file:
0: kd> !pte a0191000
A0191000 - PDE at C0300A00 PTE at C0280644
contains 14AB6863 contains 156DD882
pfn 14ab6 –DA–KWV not valid
Transition: 156dd
Protect: 4
0: kd> !pte a0198000
A0198000 - PDE at C0300A00 PTE at C0280660
contains 14AB6863 contains 000B9060
pfn 14ab6 –DA–KWV not valid
PageFile 0
Offset b9
Protect: 3
- Dmitry Vostokov @ DumpAnalysis.org -