
From jeffrey@carlyle.com Mon May  3 19:22:39 1999
From: jeffrey@carlyle.com (Jeffrey Carlyle)
Newsgroups: comp.os.msdos.programmer,alt.msdos.programmer,comp.answers,alt.answers,news.answers
Subject: comp.os.msdos.programmer FAQ part 2/5
Supersedes: <msdos-programmer-faq/part2_919862829@rtfm.mit.edu>
Followup-To: comp.os.msdos.programmer
Date: 23 Apr 1999 13:34:15 GMT
Organization: Jeffrey Carlyle World Domination
Lines: 864
Sender: jeffrey@carlyle.com (Jeffrey Carlyle)
Approved: news-answers-request@MIT.Edu
Expires: 27 May 1999 13:32:46 GMT
Message-ID: <msdos-programmer-faq/part2_924874366@rtfm.mit.edu>
References: <msdos-programmer-faq/part1_924874366@rtfm.mit.edu>
Reply-To: jeffrey@carlyle.com (Jeffrey Carlyle)
NNTP-Posting-Host: penguin-lust.mit.edu
Summary: Frequently asked questions by DOS programmers with tested answers.
X-Last-Updated: 1999/01/05
Originator: faqserv@penguin-lust.MIT.EDU
Path: news.nic.utwente.nl!news.cs.utwente.nl!newshunter!cosy.sbg.ac.at!newsmaster-01.vbs.at!news.datacomm.ch!newsfeed-zh.ip-plus.net!news.ip-plus.net!News.Amsterdam.UnisourceCS!masternews.telia.net!news.algonet.se!algonet!news.maxwell.syr.edu!newsfeed.enteract.com!cde.net!sipb-server-1.mit.edu!sipb-server-2.mit.edu!senator-bedfellow.mit.edu!faqserv
Xref: news.nic.utwente.nl comp.os.msdos.programmer:80557 alt.msdos.programmer:38292 comp.answers:32020 alt.answers:37088 news.answers:72408

Archive-name: msdos-programmer-faq/part2
Comp-os-msdos-programmer-archive-name: dos-faq-pt2.txt
Posting-frequency: 56 days
Last-modified: 05 Jan 99


------------------------------

Subject: comp.os.msdos.programmer FAQ
Date: Sun, 03 Jan 99 17:46:33 CST
 
 comp.os.msdos.programmer FAQ Version 1999.01

 This is the Frequently Asked Questions list for the newsgroup
 comp.os.msdos.programmer. This message is part 2 of 5 parts.
 
 Copyright  1999  by  Jeffrey Carlyle. All rights  reserved.  This
 article  is not in the public domain, but it may be redistributed
 so  long as this notice, the acknowledgments, and the information
 on obtaining the latest copy of this list are retained and no fee
 is  charged. The code fragments may be used freely; credit to the
 FAQ would be polite. This FAQ is not to be included in any static
 archive (e.g. CD-ROM or book); however, a pointer to the FAQ  may
 be included.
 

------------------------------

Subject: Table of Contents
Date: Sun, 03 Jan 99 17:46:33 CST
 
=============================
TABLE OF CONTENTS
=============================
 
Part 1: <first file>
  Section 1.  General FAQ and Newsgroup Information
    <Q:01.01> - Is MS-DOS dead?
    <Q:01.02> - What is this article for?
    <Q:01.03> - Who has contributed to this article?
    <Q:01.04> - How can I search this article for a particular topic?
    <Q:01.05> - Are the answers guaranteed to be correct and complete?
    <Q:01.06> - What is comp.os.msdos.programmer about?
    <Q:01.07> - Is comp.os.msdos.programmer just for C programmers?
    <Q:01.08> - What is comp.sys.ibm.pc.programmer?
    <Q:01.09> - Is  comp.os.msdos.programmer available as a  mailing list?
    <Q:01.10> - What's this "netiquette"?
    <Q:01.11> - How can I learn more about Usenet?
    <Q:01.12> - What other technical newsgroups should I know about?
    <Q:01.13> - Where are FAQ lists archived?
    <Q:01.14> - Where can I get the latest copy of this FAQ list?
  Section 2.  General Reference
    <Q:02.01> - Are there any good on-line references for PC hardware
                components?
    <Q:02.02> - Are there any good on-line references for PC interrupts?
    <Q:02.03> - What and where is "Ralf Brown's interrupt list"?
    <Q:02.04> - Where can I find lex, yacc, and language grammars?
    <Q:02.05> - What's the best book to learn programming?
    <Q:02.06> - Why won't my code work?
    <Q:02.07> - Are there any good sources of example code?
    <Q:02.08> - What and where is "SNIPPETS"?
    <Q:02.09> - Is the source code MS-DOS available?
    <Q:02.10> - What are my alternatives for MS-DOS compatible OSes?
    <Q:02.11> - What and where is "FreeDOS?"
    <Q:02.12> - What and where is "Caldera DR-DOS"?
Part 2: <this file>
  Section 3.  Compile and Link
    <Q:03.01> - What the heck is "DGROUP > 64K"?
    <Q:03.02> - How  do I fix "automatic data segment exceeds 64K" or "stack
                plus data exceed 64K"?
    <Q:03.03> - Will Borland C code and Microsoft C code link together?
    <Q:03.04> - Why  did  my program bomb  at run time with "floating point
                formats not linked" or "floating point not loaded"?
    <Q:03.05> - How can I change the stack size in Borland's C compilers?
    <Q:03.06> - What's the format of an .OBJ file?
    <Q:03.07> - What's the format of an .EXE header?
    <Q:03.08> - What's  the difference between .COM and .EXE formats?
    <Q:03.09> - How do I create a .COM file?
    <Q:03.10> - Where is EXE2BIN located?
    <Q:03.11> - What does this message mean: "A20 already enabled so test
                is meaning less?"
  Section 4.  Keyboard
    <Q:04.01> - How can I read a character without echoing it to the screen,
                and without waiting for the user to press the Enter key?
    <Q:04.02> - How can I find out whether a character has been typed, without
                waiting for one?
    <Q:04.03> - How can I disable Ctrl-C/Ctrl-Break and/or Ctrl-Alt-Del?
    <Q:04.04> - How can I disable the print screen function?
    <Q:04.05> - How  can  my  program turn NumLock (CapsLock, ScrollLock)
                on or off?
    <Q:04.06> - How can I speed up the keyboard's auto-repeat?
    <Q:04.07> - What is the SysRq key for?
    <Q:04.08> - How can my program tell what kind of keyboard is on the
                system?
    <Q:04.09> - How can I tell if input, output, or stderr has been redirected?
    <Q:04.10> - How can I increase the size of the keyboard buffer?
    <Q:04.11> - How can I stuff characters into the keyboard buffer?
Part 3: <third file>
  Section 5.  Disks and files
    <Q:05.01> - What drive was the PC booted from?
    <Q:05.02> - How can I boot from drive B:?
    <Q:05.03> - Which real and virtual disk drives are valid?
    <Q:05.04> - How can I make my single floppy drive both A: and B:?
    <Q:05.05> - How can I disable access to a drive?
    <Q:05.06> - How can a batch file test existence of a directory?
    <Q:05.07> - Why won't my C program open a file with a path?
    <Q:05.08> - How can I redirect printer output to a file?
    <Q:05.09> - How can I redirect the output of a batch file?
    <Q:05.10> - How can I redirect stderr?
    <Q:05.11> - How can my program open more files than DOS's limit of 20?
    <Q:05.12> - How can I read, create, change, or delete the volume label?
    <Q:05.13> - How can I get the disk serial number?
    <Q:05.14> - What's the format of .OBJ, .EXE, .COM files?
    <Q:05.15> - How can I flush the software disk cache?
    <Q:05.16> - How can I see if a drive is a RAM drive?
  Section 6.  Serial ports (COM ports)
    <Q:06.01> - How do I set my machine up to use COM3 and COM4?
    <Q:06.02> - How do I find the I/O address of a COM port?
    <Q:06.03> - But aren't the COM ports always at I/O addresses 3F8, 2F8,
                3E8, and 2E8?
    <Q:06.04> - How do I configure a COM port and  use  it  to transmit data?
Part 4: <fourth file>
  Section 7.  Other hardware questions and problems
    <Q:07.01> - Which 80x86 CPU is running my program?
    <Q:07.02> - How can a C program send control codes  to  my printer?
    <Q:07.03> - How can I redirect printer output to a file?
    <Q:07.04> - Which video adapter is installed?
    <Q:07.05> - How do I switch to 43- or 50-line mode?
    <Q:07.06> - How can I find the Microsoft mouse position and button status?
    <Q:07.07> - How can I access a specific address in the PC's memory?
    <Q:07.08> - How can I read or write my PC's CMOS memory?
    <Q:07.09> - How can I access memory beyond 640K?
    <Q:07.10> - How can I use the protected mode?
    <Q:07.11> - How can I tell if my program is running on a
                PS/2-style machine.
    <Q:07.12> - Is there a 80x87 math unit installed?
  Section 8.  Other software questions and problems
    <Q:08.01> - How can a program reboot my PC?
    <Q:08.02> - How can I time events with finer resolution than the system
                clock's 55 ms (about 18 ticks a second)?
    <Q:08.03> - How can I find the error level of the previous program?
    <Q:08.04> - How can a program set DOS environment variables?
    <Q:08.05> - How can I change the switch character to - from /?
    <Q:08.06> - How can I write a TSR (terminate-stay-resident utility)?
    <Q:08.07> - Why does my interrupt function behave strangely?
    <Q:08.08> - How can I write a device driver?
    <Q:08.09> - What can I use to manage versions of software?
    <Q:08.10> - What's this "null pointer assignment" after my C
                program executes?
    <Q:08.11> - How can a batch file tell whether it's being run in a DOS box
                under Windows?
    <Q:08.12> - How can my program tell if it's running under Windows?
    <Q:08.13> - How can a program tell whether ANSI.SYS is installed?
    <Q:08.14> - How do I copyright software that I write?
Part 5: <fifth file>
  Section 9.  Downloading
    <Q:09.01> - What are SimTel, Garbo, and Wustl?
    <Q:09.02> - Can I get archives on CD-ROM?
    <Q:09.03> - Where do I find program <mumble>?
  Section 10. Vendors and products
    <Q:10.01> - How can I contact Borland?
    <Q:10.02> - How can I contact Microsoft?
    <Q:10.03> - What's the current version of UNZIP?
    <Q:10.04> - What is the phone number for a vendor's BBS?
    <Q:10.05> - What is the current version of DJGPP?
    <Q:10.06> - What and where is DJGPP?
    <Q:10.07> - Are there any good shareware/freeware compilers?
    <Q:10.08> - Is the source code to MS-DOS available?
    <Q:10.09> - What is a vendor's web site address?


------------------------------

Subject: Section 3.  Compile and link
Date: Mon, 04 Jan 99 10:47:18 CST

 The Compile and Link section contains information issues involving compiling
 and linking of MS-DOS code.


------------------------------

Subject: <Q:03.01> - What the heck is "DGROUP > 64K"?
Date: Sun, 03 Aug 97 19:48:24 CST

 This question explains the problem; the next question gives
 some remedies.
 
 DGROUP  is  a  link-time group of data  segments,  and  the
 compiler  typically generates code that expects  DS  to  be
 pointing  to DGROUP. (Exception:  Borland's huge model  has
 no DGROUP.)
 
 Here's what goes into DGROUP:
 - Tiny  models (all pointers near): DGROUP  holds  the
   entire program.
  
 - Small and medium models (data pointers near): DGROUP
   holds all  globals and static variables including string
   literal data, plus the stack and the heap.
  
 - Large,  compact, and huge models in Microsoft  (data
   pointers far): DGROUP holds only initialized globals and
   static variables including string literal data, plus the
   stack and the near heap.
  
 - Large  and compact models in Borland (data  pointers
   far): DGROUP holds initialized and uninitialized globals and
   static variables including string literal data, but not the
   stack or heap.
  
 - Huge model in Borland (data pointers far): there is no
   DGROUP, so the 64K limit doesn't apply.
 
 In  all  of  the above, which is to say all six  models  in
 Microsoft  C  and  all  but huge in Borland  C,  DGROUP  is
 limited  to  64K including string literal data  (which  are
 treated  as  static data).  This limitation is due  to  the
 Intel CPU's segmented architecture.
 
 For  more information, see topics like "memory models"  and
 "memory  management" in the index of your compiler  manual.
 Also for an extended general discussion of memory usage  in
 Borland C programs, of which much applies to any C compiler
 in DOS see TI738.asc, downloadable as part of:
 
 <ftp://ftp.simtel.net/pub/simtelnet/msdos/turbo_c/bchelp10.zip>
 <ftp://garbo.uwasa.fi/pc/c-lang/bchelp10.zip>

------------------------------

Subject: <Q:03.02> - How do I fix "automatic data segment
      exceeds 64K" or "stack plus data exceed 64K"?
 
 These  messages  are a variation of "DGROUP  >  64K".   For
 causes, please see the preceding question.
 
 If you get this error in tiny model, your program is simply
 too  big and you must use a different memory model.  If you
 get  this  link  error  in models small,  compact,  medium,
 large,  or Microsoft's huge, there are some things you  can
 do.  (This error can't occur in Borland's huge model.)
 
 If  you  have one or two big global arrays, simply  declare
 them  far.  The  compiler  takes  this  to  mean  that  any
 references to them will use 32-bit pointers, so they'll  be
 in separate segments and no longer part of DGROUP.
 
 Or  you can use the /Gt[number] option with Microsoft or  -
 Ff[=size]   with  Borland  C++  2.0  and  up.   This   will
 automatically put variables above a certain size into their
 own segments outside of DGROUP.
 
 Yet  another  option  is to change  global  arrays  to  far
 pointers.  Then at the beginning of your program,  allocate
 them   from   the   far  heap  (_fmalloc()  in   Microsoft,
 farmalloc() in Borland).
 
 Finally,  you  can  change  to  huge  model  (with  Borland
 compilers,  not Microsoft).  Borland's H model  still  uses
 far  pointers by default, but "sets aside the [64K]  limit"
 and  has  no  DGROUP  group,  according  to  the  BC++  2.0
 Programmer's Guide.  Microsoft's H model does use huge data
 pointers  by default but retains DGROUP and its 64K  limit,
 so  switching to the huge model doesn't buy you anything if
 you have DGROUP problems.
 

------------------------------

Subject: <Q:03.03> - Will Borland C code and Microsoft C
      code link together?

 Typically  someone who owns compiler A  and  is  trying  to
 write  code  to  link with a third-party library  that  was
 compiled under compiler B asks this question.
 
 The  answer to the question is, Not in general.   Here  are
 some of the reasons:
  
 - "Helper" functions (undocumented functions for stack
   checking, floating-point arithmetic, and operations on
   longs) differ between the two compilers.
  
 - Extended dictionaries are not compatible between the 2
   formats. However, the basic structure of both MS and Borland
   OBJ formats is based on the OMF format so specifying that
   the linker ignore the extended dictionary records (/NOE for
   LINK, -e for TLINK) will disable this little hassle.
  
 - The compilers may embed instructions in the object code
   that  tell  the linker to look for their  own  run-time
   libraries.  You can use the linker option that says  to
   ignore such instructions: /n in TLINK, /NOD in the Microsoft
   linker (the one that comes with the C compiler, not the one
   that  used to come with DOS).  But getting around  this
   problem will very likely just reveal other problems, like
   different helper functions, that have no easy solution.
 
 Those problems will generate link-time errors.  Others  may
 not show up until run time:
  
 - Borland's compact, large, and huge models don't assume
   DS=SS, but Microsoft's do.  The -Fs option on the Borland
   compiler, or one of the /A options on Microsoft, should take
   care of this problem-once you know that's what's going on.
  
 - Check conventions for ordering and packing structure
   members, and for alignment of various types on byte, word,
   paragraph, or other boundaries.  Again, you can generally
   adjust your code to match if you know what conventions were
   used in compiling the "foreign" libraries.
     
 - Check the obvious and make sure that your code was
   compiled under the same memory model as the code you're
   trying to link with. (That's necessary, but no guarantee.
   Microsoft and Borland don't use exactly the same conventions
   for segments and groups, particularly in the larger memory
   models.)
 
 That  said, there are some circumstances where you can link
 hybrids.  Your best chance of success comes if you  compile
 in large model with the compiler switch that says to reload
 DS  on  entry  to each function, avoid longs  and  floating
 point,  use only 16-bit pointers, suppress stack  checking,
 and specify all libraries used in the link.
 

------------------------------

Subject: <Q:03.04> - Why did my program bomb at run time
      with "floating point formats not linked" or "floating
      point not loaded"?
 
 These messages look similar but have very different causes.
 
 "Floating  point  not  loaded" is  Microsoft  C's  run-time
 message  when  the code requires a numeric coprocessor  but
 your  computer doesn't have one installed.  If the  program
 is  yours,  relink  it using the xLIBCE or  xLIBCA  library
 (where x is the memory model).
 
 "Floating  point formats not linked" is a Borland  run-time
 error  (Borland  C  or  C++, Turbo C  or  C++).   Borland's
 compilers  try  to be smart and not link in  the  floating-
 point (f-p) library unless you need it.  Alas, they all get
 the  decision  wrong.  One common case is where  you  don't
 call  any  f-p  functions, but you have  %f  or  other  f-p
 formats in scanf() or printf() calls.  The cure is to  call
 an f-p function, or at least force one to be present in the
 link.
 
 To do that, define this function somewhere in a source file
 but don't call it:
 
   static void forcefloat(float *p)
   {
     float f = *p;
     forcefloat(&f);
   }
 
 It  doesn't have to be in the module with the main program,
 as  long as it's in a module that will be included  in  the
 link.
 
 If  you  have Borland C++ 3.0, the README file documents  a
 slightly less ugly work-around.  Insert these statements in
 your program:
 
   extern unsigned _floatconvert;
   #pragma extref _floatconvert


------------------------------

Subject: <Q:03.05> - How can I change the stack size in
     Borland's C compilers?

 
 In  Turbo  C, Turbo C++, and Borland C++, you may not  find
 "stack  size" in the index but the global variable  _stklen
 should  be  there. The manual will instruct you  to  put  a
 statement like
 
   extern unsigned _stklen = 54321U;
 
 in your code, outside of any function.  You must assign the
 value  right  in  the extern statement; it  won't  work  to
 assign  a  value at run time.  The linker may  give  you  a
 duplicate symbol warning, which you can ignore.
 
 
 If you are using the Borland PowerPack for DOS _stklen does
 not  change  the stack size. To change the stack  size  you
 must  use STACKSIZE in your .DEF file. HEAPSIZE can be used
 to change the size of your program's heap.
 

------------------------------

Subject: <Q:03.06> - What's the format of an .OBJ file?
Date: Wed, 11 Jan 95 15:34:00 CDT

 Information  about the base .OBJ format  can  be  found  in
 Intel's  document  number  #121748-001,  {8086  Relocatable
 Object Module Formats} (not verified).
 
 Both  Microsoft and Borland have extended the .OBJ  format,
 as   has   IBM  for  OS/2;  and  according  to  the  MS-DOS
 encyclopedia, Microsoft doesn't actually use all the listed
 formats.

 Microsoft-specific .OBJ formats:
  - The .OBJ format document in a text file format is downloadable as:
      <ftp://ftp.microsoft.com/softlib/mslfiles/ss0288.exe>

  - A  45-page  article can be found in  the  {MS-DOS Encyclopedia},
    ISBN 1-55615-049-0, now out of print.
     
  - "Microsoft Object Module Format (OMF)" Specification, 22 Nov 1991,
    was published by the Microsoft Languages Group (not verified).
  
 Borland-specific .OBJ formats:
  - Open Architecture Handbook. The Borland Developer's Technical
    Guide, 1991, no ISBN.  Chapter 2, "Object file contents", (pages 27-50)
    covers  the comment records sent to the object file by Borland C++
    version 3.0 and other Borland compilers. The comment records mostly
    contain information for the Borland debugger (not verified).
     
 A "tutorial on the .OBJ format" comes with the VAL experimental linker,
 downloadable as <ftp://garbo.uwasa.fi/pc/assembler/linker.zoo>.


------------------------------

Subject: <Q:03.07> - What's the format of an .EXE header?

 See PC Magazine 30 June 1992 (XI: 12) pages 349-350 for the
 old  and  new  formats.  For a more detailed  layout,  look
 under  INT  21  AH=4B  in Ralf Brown's interrupt  list  <Q:
 2.03>.   That list includes extensions for Borland's  TLINK
 and Borland debugger info.
 
 Among the books that detail formats of executable files are
 {DOS  Programmer's Reference: 2d Edition} by Terry  Dettman
 and  Jim  Kyle,  ISBN 0-88022-458-4; and {Microsoft  MS-DOS
 Programmer's Reference}, ISBN 1-55615-329-5.
 

------------------------------

Subject: <Q:03.08> - What's the difference between .COM and .EXE formats?
Date: Sun, 03 Jan 99 20:49:03 CST
 
 To oversimplify: a .COM file is a direct image of core, and
 a .EXE file will undergo some further relocation when it is
 run  (and so it begins with a relocation header).   A  .COM
 file  is  limited to 64K for all segments combined,  but  a
 .EXE  file  can have as many segments as your  linker  will
 handle and be as large as RAM can take.
 
 The actual file extension doesn't matter.  DOS knows that a
 file  being loaded is in .EXE format if its first two bytes
 are MZ or ZM; otherwise it is assumed to be in .COM format.
 For instance, DR-DOS 6.0's COMMAND.COM is in .EXE format as
 is COMMAND.COM in recent versions of MS-DOS.


------------------------------

Subject: <Q:03.09> - How do I create a .COM file?
Date: Fri, 13 Jan 95 15:34:00 CDT
 
 There  are  two steps to creating a .COM file. First,  your
 program must not have a stack. In C, you must compile  your
 program with the TINY memory model. Second, use EXE2BIN  or
 a  similar program to convert an EXE file to a COM file. To
 find  EXE2BIN  see  subject: <Q: 3.10>  "Where  is  EXE2BIN
 located?"
 

------------------------------

Subject: <Q:03.10> - Where is EXE2BIN located?
Date: Fri, 07 Jul 95 15:34:00 CDT

 EXE2BIN was formerly shipped with MS-DOS. If you are  still
 using  DOS 5.0 or earlier you can find EXE2BIN in your  DOS
 directory.  Users  of  DOS  6.x  need  to  get  the  MS-DOS
 Supplemental Disks. These disks are available  via  FTP  at
 ftp.microsoft.com.
 
 <ftp://ftp.microsoft.com/peropsys/msdos/public/supplmnt>
 

------------------------------

Subject: <Q:03.11> - What does this message mean: "A20
      already enabled so test is meaning less?"
 
 The  DPMIINST  program  included  with  older  versions  of
 Borland C++ and Turbo C++ compilers generates this message.
 Before running DPMIINST you must clean boot your computer.
 

------------------------------

Subject: Section 4.  Keyboard
Date: Mon, 04 Jan 99 10:48:15 CST

 The keyboards sections coontains information about how to access the
 keyboard.


------------------------------

Subject: <Q:04.01> - How can I read a character without
      echoing it to the screen, and without waiting for the
      user to press the Enter key?
 
 The  C  compilers from Microsoft and Borland offer  getch()
 (or  getche()  to  echo the character);  Turbo  Pascal  has
 ReadKey.
 
 In  other programming languages, execute INT 21 AH=8; AL is
 returned  with the character from standard input  (possibly
 redirected).   If  you don't want to allow redirection,  or
 you  want to capture Ctrl-C and other special keys, use INT
 16  AH=10;  this will return the scan code in AH and  ASCII
 code  (if  possible)  in  AL, but  AL=E0  with  AH  nonzero
 indicates that one of the gray "extended" keys was pressed.
 (If  your  BIOS doesn't support the extended keyboard,  use
 INT 16 AH=0 not 10.)
 

------------------------------

Subject: <Q:04.02> - How can I find out whether a character
      has been typed, without waiting for one?

 In  Turbo  Pascal, use KeyPressed.  Both  Microsoft  C  and
 Turbo C offer the kbhit() function.  All of these tell  you
 whether  a  key  has  been pressed.  If  no  key  has  been
 pressed, they return that information to your program.   If
 a  keystroke  is waiting, they tell your program  that  but
 leave the key in the input buffer.
 
 You  can  use the BIOS call, INT 16 AH=01 or 11,  to  check
 whether  an actual keystroke is waiting; or the  DOS  call,
 INT  21 AH=0B, to check for a keystroke from stdin (subject
 to  redirection).   See  Ralf Brown's  interrupt  list <Q:02.03>.
 

------------------------------

Subject: <Q:04.03> - How can I disable Ctrl-C/Ctrl-Break and/or Ctrl-Alt-Del?

 Several utilities are downloadable from:
   <ftp://ftp.simtel.net/pub/simtelnet/msdos/keyboard/>
 
 In that directory, cadel.zip contains  a  TSR (with source code)
 to disable those keys. Also, keykill.arc  contains two utilities:
 keykill.com lets you disable up to three keys of your choice, and
 deboot.com changes the boot key to leftShift-Alt-Del. C programmers
 who simply want to make sure that the user can't Ctrl-Break out
 of their program can use the ANSI-standard  signal() function; the
 Borland compilers also offer ctrlbrk() for handling Ctrl-Break.
 However, if your program uses normal DOS input such as getch(), ^C
 will appear on the screen when the user presses Ctrl-C or Ctrl-Break.
 You can avoid the  ^C  echo for Ctrl-C by using _bios_keybrd() in MSC
 or bioskey() in BC++; however, Ctrl-Break will still terminate
 the program.
 
 An  alternative approach involves programming  input  at  a
 lower  level.  You  can  use  INT  21  AH=7,  which  allows
 redirection  but  doesn't  echo  the  ^C  (or   any   other
 character, for that matter); or use INT 16 AH=0 or  10;  or
 hook  INT  9  to discard Ctrl-C and Ctrl-Break  before  the
 regular BIOS keyboard handler sees them; etc., etc.
 
 You   should  be  aware  that  Ctrl-C  and  Ctrl-Break  are
 processed  quite differently internally.  Ctrl-Break,  like
 all  keystrokes, is processed by the BIOS code at INT 9  as
 soon as the user presses the keys, even if earlier keys are
 still in the keyboard buffer: by default the handler at INT
 1B is called.  Ctrl-C is not special to the BIOS, nor is it
 special  to  DOS  functions 6 and 7; it is special  to  DOS
 functions 1 and 8 when at the head of the keyboard  buffer.
 You  will  need  to make sure BREAK is OFF to  prevent  DOS
 polling   the   keyboard  for  Ctrl-C  during  non-keyboard
 operations.
 
 Some  good general references are {Advanced MS-DOS} by  Ray
 Duncan,   ISBN  1-55615-157-8;  {8088  Assembler   Language
 Programming: The IBM PC}, ISBN 0-672-22024-5, by  Willen  &
 Krantz; and {COMPUTE!'s Mapping the IBM PC}, ISBN 0-942386-
 92-2.
 

------------------------------

Subject: <Q:04.04> - How can I disable the print screen function?
 
 There  are  really  two print screen  functions:  1)  print
 current screen snapshot, triggered by PrintScreen or Shift-
 PrtSc  or  Shift-gray*, and 2) turn  on  continuous  screen
 echo, started and stopped by Ctrl-P or Ctrl-PrtSc.
 
 1) Screen snapshot to printer:
 
 The  BIOS uses INT 5 for this.  Fortunately, you don't need
 to mess with that interrupt handler.  The standard handler,
 in  BIOS versions dated December 1982 or later, uses a byte
 at  0040:0100  (= 0000:0500) to determine whether  a  print
 screen  is  currently  in progress.   If  it  is,  pressing
 PrintScreen  again  is ignored.  So to disable  the  screen
 snapshot,  all  you have to do is write a 1 to  that  byte.
 When the user presses PrintScreen, the BIOS will think that
 a  print screen is already in progress and will ignore  the
 user's  keypress.  You can re-enable PrintScreen by zeroing
 the same byte.
 
 Here's some simple code:
   
   void prtsc_allow(int allow) /* 0=disable, nonzero=enable */
   {
     unsigned char far* flag = (unsigned char far*)0x00400100UL;
     *flag = (unsigned char)!allow;
   }
 
 2) Continuous echo of screen to printer:
 
 If   ANSI.SYS  is  loaded,  you  can  easily  disable   the
 continuous  echo  of  screen to printer  (Ctrl-P  or  Ctrl-
 PrtSc).  Just redefine the keys by "printing" strings  like
 these  to the screen (BASIC print, C printf(), Pascal Write
 statements,  or  ECHO command in batch files),  where  <27>
 stands for the Escape character, ASCII 27:
   
   <27>[0;114;"Ctrl-PrtSc disabled"p
   <27>[16;"^P"p
 
 If  you  haven't installed ANSI.SYS, I can't offer an  easy
 way to disable the echo-screen-to-printer function.
 
 Actually,  you might not need to disable Ctrl-P  and  Ctrl-
 PrtSc.   If  your  only  concern is  not  locking  up  your
 machine,  when  you  see the "Abort, Retry,  Ignore,  Fail"
 prompt  just press Ctrl-P again and then press  I.   As  an
 alternative,  install one of the many print  spoolers  that
 intercept printer-status queries and always return "Printer
 ready".
 

------------------------------

Subject: <Q:04.05> - How can my program turn NumLock (CapsLock, ScrollLock)
      on or off?
 
 First,  if you just don't want NumLock turned on  when  you
 reboot,  check  your system's setups.  (Press a special key
 like Del at boot time, or run  the  setup  program supplied
 with your system.) Many systems may have an option in setup
 to turn NumLock off  at  boot time.
 
 You  need  to twiddle bit 5, 6, or 4 of location 0040:0017.
 The   code  example  below  demonstrates  changing  NumLock
 status:  lck() turns on a lock state, and unlck() turns  it
 off.
 
   /* The  status  lights on some keyboards may not reflect  the
    * change.   If  yours  is one, call INT 16 AH=2,  "get  shift
    * status", and that may update them.  It will certainly do no
    * harm.)
    */
 
    #define NUM_LOCK  (1 << 5)
    #define CAPS_LOCK (1 << 6)
    #define SCRL_LOCK (1 << 4)
  
    void lck(int shiftype)
    {
      char far* kbdstatus = (char far*)0x00400017UL;
      *kbdstatus |= (char)shiftype;
    }
    void unlck(int shiftype)
    {
      char far* kbdstatus = (char far*)0x00400017UL;
      *kbdstatus &= ~(char)shiftype;
    }
    

------------------------------

Subject: <Q:04.06> - How can I speed up the keyboard's auto-repeat?
Date: Sun, 03 Aug 97 19:53:45 CST
 
 The  keyboard speed has two components: delay (before a key
 that  you  hold  down starts repeating) and typematic  rate
 (the  speed  once  the  key starts repeating).   Most  BIOS
 versions  since  1986  let software change  the  delay  and
 typematic rate by calling INT 16 AH=3, "set typematic  rate
 and  delay"; see Ralf Brown's interrupt list <Q:02.03>.  If
 you have DOS 4.0 or later, you can use the MODE CON command
 that you'll find in your DOS manual.
 
 On  83-key  keyboards (mostly XTs), the delay and typematic
 rate can't easily be changed.  According to PC Magazine  15
 Jan  1991 (x: 1) page 409, to adjust the typematic rate you
 need  "a  memory-resident program which simply  '[watches]'
 the  keyboard to see if you're holding down  a  key  .  and
 after a certain time [starts] stuffing extra copies of  the
 held-down key into the buffer."  No source code is given in
 that  issue;  but  the QUICKEYS utility  that  PC  Magazine
 published   in  1986  does  this  sort  of  watching   (not
 verified); source and object code are downloadable in:
   <ftp://ftp.simtel.net/pub/simtelnet/msdos/pcmag/vol5n05.zip>
 

------------------------------

Subject: <Q:04.07> - What is the SysRq key for?
 
 There  is  no standard use for the key.  The BIOS  keyboard
 routines  in INT 16 simply ignore it; therefore so  do  the
 DOS  input  routines  in INT 21 as  well  as  the  keyboard
 routines in libraries supplied with high-level languages.
 
 When  you  press  or  release a key, the keyboard  triggers
 hardware line IRQ1, and the CPU calls INT 9.  INT  9  reads
 the  scan code from the keyboard and the shift states  from
 the BIOS data area.
 
 What  happens  next  depends  on  whether  your  PC's  BIOS
 supports  an enhanced keyboard (101 or 102 keys).   If  so,
 INT  9  calls INT 15 AH=4F to translate the scan code.   If
 the translated scan code is 54 hex (for the SysRq key) then
 INT 9 calls INT 15 AH=85 and doesn't put the keystroke into
 the  keyboard buffer.  The default handler of that function
 does  nothing and simply returns.  (If your PC has an older
 BIOS  that doesn't support the extended keyboards,  INT  15
 AH=4F  is not called.  Early ATs have 84-key keyboards,  so
 their BIOS calls INT 15 AH=85 but not 4F.)
 
 Thus  your  program  is  free to  use  SysRq  for  its  own
 purposes,  but at the cost of some programming.  You  could
 hook  INT 9, but it's probably easier to hook INT 15 AH=85,
 which is called when SysRq is pressed or released.
 

------------------------------

Subject: <Q:04.08> - How can my program tell what kind of keyboard is on
      the system?
 
 Ralf  Brown's Interrupt List <Q: 2.03> includes MEMORY.LST,
 a detailed breakdown by Robin Walker of the contents of the
 BIOS  system block that starts at 0040:0000.  Bit 4 of byte
 0040:0096 is "1=enhanced keyboard installed".  Here is a  C
 code example to test the keyboard type:
 
   char far *kbd_stat_byte3 = (char far *)0x00400096UL;
   if (0x10 & *kbd_stat_byte3)
   {
     /* 101- or 102- keyboard is installed */
   }
   else
   {
     /* Not installed */
   }
 
 PC  Magazine 15 Jan 1991 (x: 1) suggests on page  412  that
 "for  some  clones [the above test] is not foolproof".   If
 you  use this method in your program you should provide the
 user  some way to override this test, or at least some  way
 to  tell  your  program to assume a non-enhanced  keyboard.
 The  article  suggests a different approach to  determining
 the type of keyboard.
 

------------------------------

Subject: <Q:04.09> - How can I tell if input, output, or stderr has
      been redirected?
Date: Sun, 03 Aug 97 20:00:44 CST

 Normally, input and output are associated with the  console
 (i.e., with the keyboard and the screen, respectively).  If
 either is not, you know that it has been redirected.   Some
 source code to check this is available at the usual archive
 sites.
 
 If   you   program  in  Turbo  Pascal,  you'll  want   this
 downloadable collection of Turbo Pascal units:
   <ftp://ftp.simtel.net/pub/simtelnet/msdos/turbopas/>
   <ftp://garbo.uwasa.fi/pc/ts/>
 
 (The filenames are of the format tspaVV??.zip where the VV is
 the current version and ?? is 70, 60, 55, 50, or 40 for Turbo
 Pascal 7.0, 6.0, 5.5, 5.0, or 4.0 respectively.)  Source code
 is not included.  Also see  the downloadable  Frequently  Asked
 Questions  files  by  Timo Salmi:
   <ftp://ftp.simtel.net/pub/simtelnet/msdos/info/tsfaqp**.zip>
   <ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip>
 
 (Where ?? is the current version of the file.)
 
 If  you  program  in C, use isatty() if your implementation
 has  it.  Otherwise, try the following file, which includes
 source code:
   <ftp://ftp.simtel.net/pub/simtelnet/msdos/sysutil/is_con10.zip>
 
 Good  references for the principles are PC Magazine 16  Apr
 1991  (x: 7) page 374; Ray Duncan's {Advanced MS-DOS}, ISBN
 1-55615-157-8, or Ralf Brown's interrupt list  (<Q:02.03>)
 for  INT 21 AX=4400; and Terry Dettman and Jim Kyle's  {DOS
 Programmer's  Reference: 2d edition},  ISBN  0-88022-458-4,
 pages 602-603.
 

------------------------------

Subject: <Q:04.10> - How can I increase the size of the keyboard buffer?
Date: Fri, 07 Jul 95 15:34:00 CDT

 Microsoft has its own keyboard extender available on the MS-DOS
 supplemental disks for MS-DOS 6.22 which can be found at:
   <ftp://ftp.microsoft.com/peropsys/msdos/public/supplmnt/sup622.exe>
 
 
 Stan Brown, the former list maintainet, tested only one of the
 many available device drivers that do this, namely BUF160, which
 extends the keyboard  buffer to  160  characters. It performed
 flawlessly for two years with MS-DOS 5 and Windows 3.1. It's
 downloadable as:
   <ftp://ftp.simtel.net/pub/simtelnet/msdos/keyboard/buf160_6.zip>
   <ftp://garbo.uwasa.fi/pc/keyboard/buf160_6.zip>


------------------------------

Subject: <Q:04.11> - How can I stuff characters into the keyboard buffer?

 If your computer has an enhanced keyboard (see <Q: 4.08>  -
 "How  can my program tell what kind of keyboard is  on  the
 system?"), put the scan code in CH and the ASCII  character
 in  CL, then execute INT 16 AH=5. The return in AL is 0 for
 success or 1 for buffer full.


------------------------------

Subject: End of Part 2

 This is the end of part 2 of The comp.os.msdos.programmer FAQ Version 1999.01.
 
 This text is copyright 1999 by Jeffrey Carlyle. All rights reserved. Please
 see the top of this article for additional copyright information.

// Jeffrey Coleman Carlyle <jeffrey@carlyle.com> <www.jeffrey.carlyle.com>
// Computer Engineering major at the University of Evansville in Indiana.
// Bowling Green, Kentucky, USA; Creator of Windows Restart 98 and
// StratoSetup; comp.os.msdos.programmer FAQ maintainer; Ruler or Earth!


