INF: How to Prevent a Warm Boot in Real Mode

ID Number: Q81887

6.00 6.00a 6.00ax

MS-DOS

Summary:

The simultaneous pressing of the CTRL, ALT, and DEL keys

(CTRL+ALT+DEL) causes the computer to restart. This article

demonstrates one method of preventing this from occurring.

More Information:

Every time a key is pressed, the following sequence of events take

place:

1. The interrupt 09H handler reads a 1-byte scan code from the

keyboard controller.

2. The interrupt 09H handler calls interrupt 15H with AH=4FH (the

keyboard intercept service) on PC/AT and PS/2 machines.

3. Control is returned to interrupt 09H. If the CTRL+ALT+DEL key

sequence, or any other special key sequence, is detected, the

appropriate handler is invoked.

4. If no special cases have occurred, the 1-byte code is translated

into a 2-byte code (using internal tables) and placed in a

circular keyboard buffer. This buffer may now be accessed by user

applications through interrupt 16H calls.

The sample code below takes advantage of the second event by hooking

the keyboard interrupt service. When the new handler is called, if the

scan code in the AL register is that of the DEL key, check to see if

the CTRL and ALT keys are being pressed. This is done by checking the

ROM BIOS keyboard-status byte located at 0040:0017H. Bits 2 and 3 of

this byte will be set if the CTRL and an ALT keys are being pressed,

respectively.

If a CTRL+ALT+DEL key sequence is detected by the handler, the handler

resets the carry flag, which consumes the DEL. This causes the

interrupt 09H handler to see only the CTRL and ALT key sequence, thus

preventing the reboot from occurring.

Note that MS-DOS and/or other applications may hook the keyboard

intercept service first. If this occurs, the interrupt 15H service may

not be called each time a key is pressed. Also, this program will not

work properly with EMM386 earlier than version 4.44.

Sample Code

-----------

/* Compile options needed: None

*/

#include <dos.h>

#include <conio.h>

#include <stdio.h>

#define LOBYTE(x) ((unsigned char)((unsigned) x & 0x00FF) )

#define HIBYTE(x) ((unsigned char)(((unsigned) x & 0xFF00) >> 8 ))

#define BITSET(x, n) ((((unsigned char) x >> n) & 1) == 1 ? 1 : 0)

#define ESC 0x1B /* scan code for ESC */

#define DEL 0x53 /* scan code for DEL */

#define INT15 0x15 /* Interrupt to intercept */

#define KBD_INT_BIT 4 /* Int 15H Service 4FH support bit */

#define ESB_OFFSET 5 /* Environment status byte offset */

#define KBD_STATUS_PTR 0x00400017 /* Address of shift-state byte */

#define KEYBRD_INTERCEPT 0x4F /* Keyboard intercept subfunction */

/* NewInt15 will point to the new interrupt 15H handler */

void (_interrupt _far _cdecl *NewInt15)(

unsigned _es, unsigned _ds, unsigned _di,

unsigned _si, unsigned _bp, unsigned _sp,

unsigned _bx, unsigned _dx, unsigned _cx,

unsigned _ax, unsigned _ip, unsigned _cs,

unsigned _flags );

/* OldInt15 will point to the original interrupt 15H handler */

void (_interrupt _far _cdecl *OldInt15)(void);

/****************************************************************

void _interrupt _far _cdecl Int15(unsigned _es,unsigned ds,...)

This function hooks service 4FH, and checks for the

CTRL+ALT+DEL key combination. If detected, the system

reboot is prevented by consuming the DEL and exiting the

interrupt handler. Otherwise, call the default handler.

****************************************************************/

void _interrupt _far _cdecl Int15(unsigned _es,unsigned _ds,

unsigned _di,unsigned _si, unsigned _bp,

unsigned _sp,unsigned _bx, unsigned _dx,

unsigned _cx,unsigned _ax, unsigned _ip,

unsigned _cs,unsigned _flags )

{

unsigned char far *ptr=(unsigned char far *) KBD_STATUS_PTR;

if(HIBYTE(_ax)==KEYBRD_INTERCEPT) /* Was this a call to us? */

{

if(LOBYTE(_ax)==DEL) /* Was DEL key pressed? */

{

if(BITSET(*ptr,2)&&BITSET(*ptr,3)) /* CTRL and ALT pressed? */

{

_flags ^= 1; /* Consume DEL */

}

}

else

{

_chain_intr( OldInt15 ); /* Call default handler */

}

}

else

{

_chain_intr( OldInt15 ); /* Call default handler */

}

}

/************************************************************

int Supports_Int154F(void)

Detects whether the ROM BIOS keyboard intercept function

is supported.

RETURNS: TRUE if interrupt 15H service 4FH is supported,

FALSE if not.

**************************************************************/

int Supports_Int154F(void)

{

union REGS inregs,outregs;

struct SREGS segregs;

unsigned char far *config_flags;

/* Set up to get system environment information */

inregs.h.ah = 0xC0; /* Get system environment function */

/* Execute interrupt */

int86x( INT15, &inregs, &outregs, &segregs );

/* Get the configuration flags */

config_flags = (unsigned char far *) (((long)segregs.es << 16) |

((long) outregs.x.bx+ESB_OFFSET) );

/* Does this system support keyboard intercept function? */

return ( BITSET(*config_flags, KBD_INT_BIT) );

}

/***************************************

***************************************

**** MAIN PROGRAM BEGINS HERE ****

***************************************

***************************************/

void main(void)

{

unsigned ch;

if(Supports_Int154F()) /* program must support int 15 service */

{

OldInt15 = _dos_getvect( INT15 ); /* Save original handler */

NewInt15 = Int15; /* Get pointer to new handler */

_dos_setvect( INT15, NewInt15 ); /* Hook interrupt 15H */

printf("** WARM BOOT now disabled..."

"press Escape Key to Exit **\n");

ch = getch(); /* Initialize character buffer */

/**********************************

** LOOP UNTIL ESCAPE IS PRESSED **

**********************************/

while ( LOBYTE(ch) != ESC )

{

ch = getch();

}

_dos_setvect(INT15,OldInt15); /* Restore original handler */

}

else

{

printf("This machine does not support interrupt "

"15H service 4FH\n");

}

}

Additional reference words: trap reset 6.00 6.00a 6.00ax 2.00 2.01

2.50 2.51