26.08.2013 Views

366.7 KB - Evernote

366.7 KB - Evernote

366.7 KB - Evernote

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

A detailed explanation of how this is achieved can be found in [1] in the section titled APC<br />

Environments. I did not revise this material for Windows Vista, however, all the APC control variables<br />

described there are still present and used in the rest of the Vista APC implementation. Below is a<br />

summary of the Environments section<br />

Windows maintains the state of APCs waiting to execute in the _KAPC_STATE data structure, shown<br />

below (output from the WinDbg dt command):<br />

kd> dt nt!_KAPC_STATE<br />

+0x000 ApcListHead : [2] _LIST_ENTRY<br />

+0x010 Process : Ptr32 _KPROCESS<br />

+0x014 KernelApcInProgress : UChar<br />

+0x015 KernelApcPending : UChar<br />

+0x016 UserApcPending : Uchar<br />

The main kernel data structure _KTHREAD has two members of type _KAPC_STATE, named<br />

ApcState and SavedApcState, which are called APC environments. ApcState is the environment for<br />

APCs targeted at the current thread context: regardless of whether the thread is attached to its own<br />

process, or another one, this member contains APCs for the current process context and therefore<br />

deliverable ones. SavedApcState stores APCs for the context which is not current and that must wait.<br />

For instance, if the thread is attached to a process other than its owner and there are APCs for the<br />

owner process, they go into SavedApcState and have to wait until the thread detaches from the other<br />

process.<br />

From the explanation above, we can understand that when a thread attaches itself to another<br />

process, ApcState is copied into SavedApcState and re-initialized. When the thread detaches itself,<br />

ApcState is restored from SavedApcState, which is then emptied. Also, we can see that the kernel<br />

components responsible for dispatching APCs, always look into ApcState for delivarable ones.<br />

The _KTHREAD structure also stores an array of 2 pointers called ApcStatePointer, whose members<br />

hold the addresses of ApcState and SavedApcState (that is, they point inside _KTHREAD itself). The<br />

kernel updates these pointers so that the first one always points to the APC environment for the<br />

thread owning process and the second one points to the environment for an eventual process the<br />

thread is attached to.<br />

For instance, if the thread is not attached to another process, the Environment for the owning process<br />

is also currently active, therefore it is stored into ApcState and ApcStatePointer[0] holds the address<br />

of ApcState.<br />

Finally, _KTHREAD.ApcStateIndex stores the index of the pointer to ApcState, i. e. the active<br />

environment. Thus, if the thread is attached to another process, the owning process environment is<br />

into SavedApcState, ApsStatePointer[0] points to SavedApcState, because it always points to the<br />

owning process environment. In turn, ApcStatePointer[1] points to ApcState, because it always points<br />

to the attached process environment. Finally, ApcStateIndex is set to 1, because it is<br />

ApcStatePointer[1] which is pointing to the active environment.<br />

When we schedule an APC, we can specify that we want to add it to the environment for the owning<br />

process (i. e. the one pointed by ApcStatePointer[0]), to the secondary one (ApcStatePointer[1]) or to<br />

whichever environment is currently active (i. e. the one at ApcState, no matter what).<br />

APC Types<br />

APCs come in three kinds.<br />

5

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!