
In a msg on <Mar 19 18:28>, to All, John Lobraico writes:

 JL> Does anybody have any code snippets that will show me how to hook 
 JL> any interrupt in the protected mode interupt table. I'll be doing 
 JL> this as a Vxd so protection shouldn't be a problem. 

Just like real mode, protected mode interrupts are handled through a table of
vectors.  Unlike real mode, however, this table can be anywhere in memory.  Use
the SIDT instruction to get the 48-bit base and limit into memory.  From there
you can do one of two things.  Either you can search the GDT and LDT for a
selector which matches the base and limit, or you can create a new selector
since VxDs run in ring 0.  Once you've done that, you can access the contents of
the IDT.  Now here's the tricky part.  The IDT is a table of gates, one for each
interrupt, up to a maximum of 256 interrupts.  Unlike the GDT, the first entry
in the IDT is used and is valid (for interrupt 0, of course).  Each gate entry
is eight bytes long and may be one of three possible kinds of descriptors:  task
gate, interrupt gate, or trap gate.  The descriptors are as follows:

Task Gate:


 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 <- bit

+-----------------------------------------------+
|                    RESERVED                   |  6
+-----------------------------------------------+
| P| DPL | 0  0  1  0  1|      RESERVED         |  4
+-----------------------------------------------+
|             TSS SEGMENT SELECTOR              |  2
+-----------------------------------------------+
|                    RESERVED                   |  0  <- byte
+-----------------------------------------------+


Interrupt Gate:


 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0

+-----------------------------------------------+
|                 OFFSET 31..16                 |  6
+-----------------------------------------------+
| P| DPL | 0  1  1  1  0| 0  0  0|   RESERVED   |  4
+-----------------------------------------------+
|                SEGMENT SELECTOR               |  2
+-----------------------------------------------+  
|                 OFFSET 15..0                  |  0
+-----------------------------------------------+


Trap Gate:


 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0

+-----------------------------------------------+
|                 OFFSET 31..16                 |  6
+-----------------------------------------------+
| P| DPL | 0  1  1  1  1| 0  0  0|   RESERVED   |  4
+-----------------------------------------------+
|                SEGMENT SELECTOR               |  2
+-----------------------------------------------+
|                 OFFSET 15..0                  |  0
+-----------------------------------------------+


DPL      = descriptor privilege level
OFFSET   = offset to procedure entry point 
P        = segment present bit
RESERVED = do not use -- reserved by Intel
SELECTOR = segment selector for destination code segment

To reroute an interrupt vector to your own routine, you'd just have to multiply
the interrupt number by eight and place the appropriate gate structure at that
location (relative to the start of the IDT).  Be warned, though, that whatever
selector you load into the structure must still exist whenever the interrupt is
triggered or you will suffer difficult-to-trace system crashes.

Interrupt gates and trap gates are just like any other gate, but task gates are
a bit more complex, referring to the base of a TSS descriptor instead of
pointing to interrupt handler code.  

The part I'm not so sure about is how one would actually "chain" through to the
original handler.  You can't just JMP through a gate in the IDT since there'd be
no way to address it, AFAIK.  However, you could copy the original gate to the
GDT or to an LDT and jump via that instead.  If it's a task gate, I'm sure that
will work; if it's a trap or interrupt gate, I'm not as sure since I've never
tried it and my documents don't seem to say whether or not JMPing via a task
gate is legal.  If you go that route, let me know -- I'm curious now.
