How to Prevent a Warm Boot in Real Mode

Last reviewed: July 17, 1997
Article ID: Q81887
6.00 6.00a 6.00ax 7.00 | 1.00 1.50
MS-DOS                 | WINDOWS
kbprg

The information in this article applies to:

  • Microsoft C for MS-DOS, versions 6.0, 6.0a, and 6.0ax
  • Microsoft C/C++ for MS-DOS, version 7.0
  • Microsoft Visual C++ for Windows, versions 1.0 and 1.5

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: kbinf trap reset 6.00 6.00a 6.00ax 7.00 1.00
1.50
KBCategory: kbprg
KBSubcategory: CLngIss
Keywords : kb16bitonly


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 17, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.