
              Correction / addition to Prasad's "Undocumented NT"

   From: dan_ps@my-deja.com
   Reply to: dan_ps@my-deja.com
   Date: Sun, 23 Apr 2000 10:03:30 GMT
   Organization: Deja.com - Before you buy.
   Newsgroups:
          comp.os.ms-windows.programmer.nt.kernel-mode
   Followup to: newsgroup


  Recently , I had a chanche to borrow "Undocumented NT" by Mr Prasad
Dabak from one of my friends and read it. While reading the chapters
regarding builidng your own interrupt handlers or callgates under NT ,
I found that the book glosses over very important topics such as IDT
in SMP enviroments , and a complete wrong presentation of what structure
a interrupt handler is supposed to build on the stack to ensure shamless
OS functionality. Mr's Prasad  choice is a straigtforward pushad ,
folowed by setting the FS segment to the ring0 PCR selector. This way
to build a trap frame for a interrupt is still used in Windows 95 ,
but in Windows NT , the layout of a correct Trap Frame is a little bit
more complex.
        The correct layout for a Trap Frame is the folowing: (note that
it consitis from two parts , a stack frame wich is built by the CPU
according to mode in wich was the CPU when the exception or software
interrupt was generated , and a Context Capure frame who has to be built
by the exception handler itself )

struc   KeTrapFrame

.DebugEBP       resd    1       ; 00
.DebugEIP       resd    1       ; 04
.DebugArgMark   resd    1       ; 08
.DebugPointer   resd    1       ; 0C
.TempCS         resd    1       ; 10
.TempEsp        resd    1       ; 14

.DR0            resd    1       ; 18
.DR1            resd    1       ; 1C
.DR2            resd    1       ; 20
.DR3            resd    1       ; 24
.DR6            resd    1       ; 28
.DR7            resd    1       ; 2C
.GS             resw    1       ; 30
                resw    1       ; 32
.ES             resw    1       ; 34
                resw    1       ; 36
.DS             resw    1       ; 38
                resw    1       ; 3A
.EDX            resd    1       ; 3C
.ECX            resd    1       ; 40
.EAX            resd    1       ; 44
.PreviousMode   resd    1       ; 48
.ExceptionList  resd    1       ; 4C
.FS             resw    1       ; 50
                resw    1       ; 52
.EDI            resd    1       ; 54
.ESI            resd    1       ; 58
.EBX            resd    1       ; 5C
.EBP            resd    1       ; 60
.Error          resd    1       ; 64
.EIP            resd    1       ; 68
.CS             resw    1       ; 6C
                resw    1       ; 6E
.EFLAGS         resd    1       ; 70
.ESP            resd    1       ; 74
.SS             resw    1       ; 78
                resw    1       ; 7A
.ES_V86         resw    1       ; 7C
                resw    1       ; 7E
.DS_V86         resw    1       ; 80
                resw    1       ; 82
.FS_V86         resw    1       ; 84
                resw    1       ; 86
.GS_V86         resw    1       ; 88
endstruc

        Note that this is the complete layout of a TrapFrame structure.
Depending in what mode the CPU was when the exception occured , it may
break earlier than .GS_V86. Also , it seems that fields above .DR0 are
required only to debug builds. The declaration is for NASM , a free X86
assembler  , but this shouldnt have  any kind of importance.

       Now why one should build the correct layout for this stack
frame ? The  answer is that for shamlees operation of OS , a interrupt
handler HAS to poke into interrupted thread's KTHREAD strucure a
pointer to current TrapFrame existing on stack. This pointer will be
later used by several ntoskrnl API's to gain access to interrupted
thread;s acccess registers , or to gain information about the
interrupted thread's ring3 stack location , or simply to capture all
this information and package it into the form of a CONTEXT structure.
Since ntoskrnl assumes the above layout for a stack frame , using any
other  structure size or layout can lead to unforeseen consequences.

        Other things wich one may want to do when building a stack
frame are : (assumes that the handler already set the FS register to
kernel PCR selector )

        1. Save old Exception List head , and patch -1 to FS:0 ( thus
overriding any potentialy pre-existing SEH handlers.

        2. Determine whatever the interrupted thread was runing in
ring0 or in ring3 and save this information in PreviousMode field of
The Trap frame. This is also important , since many internal API's will
check the Provious mode , acting  differently in each case. (check CS
image on stack for this )

        3. Get a pointer to the top of KeTrapFrame , and patch it into
KTHREAD structure, at KTHREAD->TrapFrame. if ya want the layout of
TrapFrame , there are multiple places where one can get it , but Im
willing to post it here on request.

        4. In the case that the hardware stack built by CPU does not
contain an error code , fake one ( generaly , aborts always push an
error code on stack , some exceptions do , and traps never push an
error code by deafult. Suplimentary information can be found in intel
arch. reference manual .

        5. Optionaly enable the interrupts trough a STI . NT uses
usualy interrupt gates , so the CPU will clear IF upon entering an
exception handler. Note that in the case handling the interrupt or
exception trough a trap gate , IF will not be automaticly cleared.

        If you are interesting in the code wich can actualy build such
a structure on  the stack , use a kernel debugger and Break on Int
0x2E , and single step the code .

        As last words , I want to ensure Mr Prasad  of my respect , and
the thing that the only reason for this posting is my feeling that all
holes must be covered , for the sake of all NT driver writing comunity.

        Later , Dan







Sent via Deja.com http://www.deja.com/
Before you buy.
