Dec 282017
 
Docs on hooking 0x2F interrupt properly in Windows.
File WIN2F.ZIP from The Programmer’s Corner in
Category Tutorials + Patches
Docs on hooking 0x2F interrupt properly in Windows.
File Name File Size Zip Size Zip Type
WIN2F.TXT 7954 1542 deflated

Download File WIN2F.ZIP Here

Contents of the WIN2F.TXT file


How to hook int 2F properly.

It is necessary to use the equivalent of _chain_intr when
hooking int 2F. In other words, unless you are processing
a broadcast you should leave all registers, stack, and
stack pointer EXACTLY as they were at entry to your
interrupt handler.

Note: The DDK has assembler code like:
(See \samples\eatpages\vxdstub.asm)

cmp ax,1605h
jnz around1
.
. Do 1605h processing
.
around1:
jmp DWORD PTR [oldint]

It is probably wiser to push and pop the flags register so
that the next interrupt handler in the chain sees EXACTLY
the same environment (as if the previous interrupt handler
didn't exist.) This is one of those cases where doing the
"right" thing is unnecessary but wise.


Also note: Unlike a "standard" C/C++ function, an interrupt
function will modify its parameters (the registers!). In
other words, bp ... ax are NOT local to the function.

//
// N.B. The following two code fragments are pseudo code
// and will not compile
//

-----------------------------------------------------------
The following pseudo code will cause mysterious system crashes


void interrupt
int_2F_handler_bad(
unsigned bp,
unsigned di,
unsigned si,
unsigned ds,
unsigned es,
unsigned dx,
unsigned cx,
unsigned bx,
unsigned ax)
{
// Save all registers here
_asm pushf
_asm push bp
.
.
_asm push ax
_asm sti // Re-enable interrupts


// See pg. 573 in Microsoft Device Driver Adaptation Guide
switch(ax)
{
case 0x1605:
// It's a Windows initialization notification.
if(di == 0x030A)
{
// Windows 3.1
} /* if(di == 0x030A) */
else
{
// Windows not 3.1
} /* else/if(di == 0x030A) */

// If your device driver can't run in Windows
cx = 1; // Set to non 0 to indicate we can't run

// If your device driver can run in Windows
cx = 0; // Set to 0 to indicate we can run

// Call the old interrupt handler here
// See comments about pushf above.
_asm pushf
// Make sure that this is a FAR call!
_asm call DWORD PTR int_2f_old

//
// Do what you gotta do; such as free memory or
// return to real mode. Make sure you get
// out of V86 mode if you are in it.
//
.
.
.
return;

case 0x1606:
// It's a Windows termination notification.

//
// Do what you gotta do to restore your environment
// to make it compatible with MSDOS
//
.
.
.


break;

default:
break;
} /* switch(ax) */


//
// Pass through here and we call the old
// interrupt handler.
// Even though we restore all the registers,
// system failure will still occur.
//

// Restore registers
_asm pop ax
.
.
_asm pop bp

// The popf/pushf pair isn't necessary since we pushed
// the flags onto the stack above. You absolutely need
// to push the flags onto the stack before calling the
/ old interrupt handler because the old interrupt handler
// is going to do an iret which pops three words off the stack
_asm popf
_asm pushf
int_2F_old();


} /* int_2F_handler_bad( */

-----------------------------------------------------------
The following pseudo code should work correctly


void interrupt
int_2F_handler_good(
unsigned bp,
unsigned di,
unsigned si,
unsigned ds,
unsigned es,
unsigned dx,
unsigned cx,
unsigned bx,
unsigned ax)
{
_asm sti // Re-enable interrupts


// See pg. 573 in Microsoft Device Driver Adaptation Guide
switch(ax)
{
case 0x1605:
// It's a Windows initialization notification.
if(di == 0x030A)
{
// Windows 3.1
} /* if(di == 0x030A) */
else
{
// Windows not 3.1
} /* else/if(di == 0x030A) */

// If your device driver can't run in Windows
cx = 1; // Set to non 0 to indicate we can't run

// If your device driver can run in Windows
cx = 0; // Set to 0 to indicate we can run

// Call the old interrupt handler here
// See comments about pushf above.
_asm pushf
// Make sure that this is a FAR call!
_asm call DWORD PTR int_2f_old

//
// Do what you gotta do; such as free memory or
// return to real mode. Make sure you get
// out of V86 mode if you are in it.
//
.
.
.

return;

case 0x1606:
// It's a Windows termination notification.

// Call the old interrupt handler here
// See comments about pushf above.
_asm pushf
// Make sure that this is a FAR call!
call DWORD PTR int_2f_old

//
// Do what you gotta do to restore your environment
// to make it compatible with MSDOS
//
.
.
.

break;

default:
break;
} /* switch(ax) */


//
// Pass through here and we chain interrupts
//
_chain_intr(int_2F_old);
} /* int_2F_handler_good( */




Ralph Shnelvar
Information, Inc.






 December 28, 2017  Add comments

Leave a Reply