home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1997 December / Internet_Info_CD-ROM_Walnut_Creek_December_1997.iso / faqs / alt / msdos / programmer / comp.os.msdos.programmer_FAQ_part_4_5 < prev    next >
Internet Message Format  |  1997-10-01  |  40KB

  1. Path: senator-bedfellow.mit.edu!faqserv
  2. From: jeffrey@carlyle.com (Jeffrey Carlyle)
  3. Newsgroups: comp.os.msdos.programmer,alt.msdos.programmer,comp.answers,alt.answers,news.answers
  4. Subject: comp.os.msdos.programmer FAQ part 4/5
  5. Supersedes: <msdos-programmer-faq/part4_873193441@rtfm.mit.edu>
  6. Followup-To: comp.os.msdos.programmer
  7. Date: 30 Sep 1997 09:50:07 GMT
  8. Organization: The COMP-FAQ Project
  9. Lines: 1154
  10. Sender: jeffrey@carlyle.com (Jeffrey Carlyle)
  11. Approved: news-answers-request@MIT.Edu
  12. Expires: 3 Nov 1997 09:49:05 GMT
  13. Message-ID: <msdos-programmer-faq/part4_875612945@rtfm.mit.edu>
  14. References: <msdos-programmer-faq/part1_875612945@rtfm.mit.edu>
  15. Reply-To: jeffrey@carlyle.com (Jeffrey Carlyle)
  16. NNTP-Posting-Host: penguin-lust.mit.edu
  17. Summary: Frequently asked questions by DOS programmers with tested answers.
  18. X-Last-Updated: 1997/08/04
  19. Originator: faqserv@penguin-lust.MIT.EDU
  20. Xref: senator-bedfellow.mit.edu comp.os.msdos.programmer:92883 alt.msdos.programmer:39080 comp.answers:28271 alt.answers:29278 news.answers:113416
  21.  
  22. Archive-name: msdos-programmer-faq/part4
  23. Comp-os-msdos-programmer-archive-name: dos-faq-pt4.txt
  24. Posting-frequency: 28 days
  25. Last-modified: 04 Aug 97
  26.  
  27. ------------------------------
  28.  
  29. Subject: comp.os.msdos.programmer FAQ part 4/5
  30.  
  31.  
  32.  For more information about this FAQ list please see Part 1.
  33.  
  34.  
  35.  FAQ        updates       can       be       found        at
  36.  <http://www.premiernet.net/~carlyle>.
  37.  
  38.  
  39.  This  is  part 4 of the frequently asked question list  for
  40.  the newsgroup comp.os.msdos.programmer.
  41.  
  42. Part 4:
  43.   Section 7.  Other hardware questions and problems
  44.   Section 8.  Other software questions and problems
  45.  
  46. ------------------------------
  47.  
  48. Subject: comp.os.msdos.programmer FAQ
  49.  
  50.  
  51.  Comp.os.msdos.programmer FAQ Version 1997.08
  52.  
  53.  
  54.  Copyright  1997  by Jeffrey Carlyle. All  rights  reserved.
  55.  This  article is not in the public domain, but  it  may  be
  56.  redistributed  so long as this notice, the acknowledgments,
  57.  and  the  information on obtaining the latest copy of  this
  58.  list are retained and no fee is charged. The code fragments
  59.  may be used freely; credit to the FAQ would be polite. This
  60.  FAQ  is not to be included in any static archive (e.g.  CD-
  61.  ROM  or  book);  however,  a pointer  to  the  FAQ  may  be
  62.  included.
  63.  
  64. =============================
  65. TABLE OF CONTENTS
  66. =============================
  67. Part 1:
  68.   Section 1.  General FAQ and Newsgroup Information
  69.   Section 2.  General Reference
  70. Part 2:
  71.   Section 3.  Compile and Link
  72.   Section 4.  Keyboard
  73. Part 3:
  74.   Section 5.  Disks and files
  75.   Section 6.  Serial ports (COM ports)
  76. Part 4:
  77.   Section 7.  Other hardware questions and problems
  78.   Section 8.  Other software questions and problems
  79. Part 5:
  80.   Section 9.  Downloading
  81.   Section 10. Vendors and products
  82.  
  83. ------------------------------
  84.  
  85. Subject: Section 7. Other hardware questions and problems
  86.  
  87. <Q: 7.01> - Which 80x86 CPU is running my program?
  88. <Q: 7.02>  -  How can a C program send control codes  to  my
  89.      printer?
  90. <Q: 7.03> - How can I redirect printer output to a file?
  91. <Q: 7.04> - Which video adapter is installed?
  92. <Q: 7.05> - How do I switch to 43- or 50-line mode?
  93. <Q: 7.06> - How can I find the Microsoft mouse position  and
  94.      button status?
  95. <Q: 7.07>  - How can I access a specific address in the PC's
  96.      memory?
  97. <Q: 7.08> - How can I read or write my PC's CMOS memory?
  98. <Q: 7.09> - How can I access memory beyond 640K?
  99. <Q: 7.10> - How can I use the protected mode?
  100. <Q: 7.11>  -  How can I tell if my program is running  on  a
  101.      PS/2-style machine.
  102. <Q: 7.12> - Is there a 80x87 math unit installed?
  103.  
  104. ------------------------------
  105.  
  106. Subject: <Q: 7.01> - Which 80x86 CPU is running my program?
  107. Date: Sun, 03 Aug 97 20:32:26 CST
  108.  
  109.  
  110.  SNIPPETS  (see <Q: 2.08>) contains C-callable x86  assembly
  111.  language   code  for  determining  the  type  of   CPU   in
  112.  CPUCHECK.ASM.
  113.  
  114.  
  115. ------------------------------
  116.  
  117. Subject: <Q: 7.02> - How can a C program send control codes
  118.      to my printer?
  119.  
  120.  
  121.  If  you just fprintf(stdprn, ...), C will translate some of
  122.  your  control codes.  The way around this is to reopen  the
  123.  printer in binary mode:
  124.  
  125.   prn = fopen("PRN", "wb");
  126.  
  127.  You  must use a different file handle because stdprn  isn't
  128.  an  lvalue. By the way, in DOS 5.0 a colon must not  follow
  129.  PRN or LPT1.
  130.  
  131.  
  132.  There's one special case, Ctrl-Z (ASCII 26), the DOS end-of-
  133.  file  character.  If you try to send an ASCII  26  to  your
  134.  printer,  DOS simply ignores it.  To get around  this,  you
  135.  need  to  reset  the printer from "cooked" to  "raw"  mode.
  136.  Microsoft  C  users must use INT 21 AH=44, "get/set  device
  137.  information".  Turbo C and Borland C++ users can use  ioctl
  138.  to accomplish the same thing:
  139.  
  140.   ioctl(fileno(prn), 1, ioctl(fileno(prn),0) & 0xFF |  0x20,
  141.   0);
  142.  
  143.  An  alternative  approach is simply to  write  the  printer
  144.  output  into a disk file, then copy the file to the printer
  145.  with the /B switch.
  146.  
  147.  
  148.  A  third  approach is to bypass DOS functions entirely  and
  149.  use  the  BIOS printer functions at INT 17.   If  you  also
  150.  fprintf(stdprn,...) in the same program, you'll need to use
  151.  fflush()  to  synchronize fprintf()'s buffered output  with
  152.  the BIOS's unbuffered.
  153.  
  154.  
  155.  By  the  way,  if you've opened the printer in binary  mode
  156.  from  a  C  program,  remember that outgoing  \n  won't  be
  157.  translated to carriage return/line feed.  Depending on your
  158.  printer, you may need to send explicit \n\r sequences.
  159.  
  160.  
  161. ------------------------------
  162.  
  163. Subject: <Q: 7.03> - How can I redirect printer output to a
  164.      file?
  165.  
  166.  
  167.  Please see <Q: 5.08> "How can I redirect printer output  to
  168.  a file?"
  169.  
  170.  
  171. ------------------------------
  172.  
  173. Subject: <Q: 7.04> - Which video adapter is installed?
  174.  
  175.  
  176.  The  technique below should work if your BIOS  is  not  too
  177.  old.   It uses three functions from INT 10, the BIOS  video
  178.  interrupt.   (If you're using a Borland language,  you  may
  179.  not  have  to  do this the hard way.  Look for  a  function
  180.  called DetectGraph or something similar.)
  181.  
  182.  
  183.  Set  AX=1200, BL=32 and call INT 10.  If AL returns 12, you
  184.  have  a  VGA.   If not, set AH=12, BL=10 and  call  INT  10
  185.  again.   If  BL  returns  0,1,2,3, you  have  an  EGA  with
  186.  64,128,192,256K memory.  If not, set AH=0F and call INT  10
  187.  a  third  time.   If  AL is 7, you have  an  MDA  (original
  188.  monochrome adapter) or Hercules; if not, you have a CGA.
  189.  
  190.  
  191.  This  worked  when tested with a VGA, but I  had  no  other
  192.  adapter types to test it with.
  193.  
  194.  
  195. ------------------------------
  196.  
  197. Subject: <Q: 7.05> - How do I switch to 43- or 50-line mode?
  198.  
  199.  
  200.  The  following file contains .COM utilities and .ASM source
  201.  code:
  202.  
  203.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/vidmode.zi
  204.  p>
  205.  
  206. ------------------------------
  207.  
  208. Subject: <Q: 7.06> - How can I find the Microsoft mouse
  209.      position and button status?
  210. Date: Sun, 03 Aug 97 20:35:38 CST
  211.  
  212.  
  213.  Use  INT 33 AX=3, described in Ralf Brown's interrupt  list
  214.  <Q: 2.03>.
  215.  
  216.  
  217.  The  Windows  manual  says  that  the  Logitech  mouse   is
  218.  compatible  with the Microsoft one, so the  interrupt  will
  219.  probably work the same.
  220.  
  221.  
  222.  Also, many files are downloadable from
  223.  
  224.      <ftp://ftp.simtel.net/pub/simtelnet/msdos/mouse>
  225.  
  226. ------------------------------
  227.  
  228. Subject: <Q: 7.07> - How can I access a specific address in
  229.      the PC's memory?
  230.  
  231.  
  232.  First check the library that came with your compiler.  Many
  233.  vendors  have some variant of peek and poke functions.  For
  234.  example:
  235.  
  236.   
  237.   -    In Turbo Pascal, use the pseudo-arrays Mem, MemW, and
  238.      MemL.  Be sure you use the correct array for the size of
  239.      data you want to access: byte, word, or double word.
  240.      
  241.   
  242.   -     In  Turbo  C/Borland C, and in  recent  versions  of
  243.      Microsoft C, use MK_FP; in older versions of Microsoft C,
  244.      use FP_OFF and FP_SEG. (Caution:  Turbo C and Turbo C++ also
  245.      have FP_OFF and FP_SEG macros, but they can't be used to
  246.      construct a pointer.)  Be sure to pick the right data type:
  247.      probably "unsigned char far *" if you're planning to access
  248.      bytes and "unsigned short far *" for words.  (The "far"
  249.      isn't needed if your memory model uses 32-bit data pointers,
  250.      but including it does no harm.)
  251.      
  252.  
  253.  By  the way, it's not useful to talk about "portable"  ways
  254.  to  do  this.   Any operation that is tied  to  a  specific
  255.  memory  address  is not likely to work on another  kind  of
  256.  machine.
  257.  
  258.  
  259. ------------------------------
  260.  
  261. Subject: <Q: 7.08> - How can I read or write my PC's CMOS
  262.      memory?
  263. Date: Sun, 03 Aug 97 20:35:57 CST
  264.  
  265.  
  266.  There  are  a  great many public-domain utilities  that  do
  267.  this.    The   following  files  can  be  downloaded   from
  268.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/sysutl/>:
  269.  
  270.   cmos14.zip      5965  920817  Saves/restores CMOS  to/from
  271.   file
  272.   cmoser11.zip  28323  910721  386/286 enhanced  CMOS  setup
  273.   program
  274.   cmosram.zip   76096  920214  Save AT/386/486 CMOS data  to
  275.   file and restore
  276.   rom2.zip      15692  900131  Save AT and 386 CMOS data  to
  277.   file and restore
  278.   setup21.zip   18172  880613  Setup program which  modifies
  279.   CMOS RAM
  280.   viewcmos.zip  11068  900225  Display contents of  AT  CMOS
  281.   RAM, w/C source
  282.  
  283.  A  program to check and display CMOS memory (but not  write
  284.  to it) is downloadable as part of:
  285.  
  286.  <ftp://garbo.uwasa.fi/pc/ts/tsutle22.zip>
  287.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/sysutl/tsutle22.z
  288.  ip>
  289.  
  290.  Good reports of CMOS299.ZIP have been posted:
  291.  
  292.  <ftp://cantva.canterbury.ac.nz/pub/pc/cmos299.zip>
  293.  
  294.  Of  the  above,  my only experience is with CMOSRAM,  which
  295.  seems  to work fine.  It contains an excellent (and  witty)
  296.  .DOC  file  that explains the hardware involved  and  gives
  297.  specific   recommendations  for  preventing   disaster   or
  298.  recovering from it.  It's $5 shareware.
  299.  
  300.  
  301.  Robert Jourdain's {Programmer's Problem Solver for the  IBM
  302.  PC,  XT,  and  AT}  has code for accessing  the  CMOS  RAM,
  303.  according to an article posted in this newsgroup.
  304.  
  305.  
  306. ------------------------------
  307.  
  308. Subject: <Q: 7.09> - How can I access memory beyond 640K?
  309. Date: Sun, 03 Aug 97 14:24:56 CST
  310.  
  311.  
  312.  PC  Magazine 29 June 1993 (xii: 12) pages 302-304 carry  an
  313.  article, "How DOS Programs Can Use Over 1MB of RAM".
  314.  
  315.  
  316.  See also <Q: 7.10> - How can I use the protected mode?
  317.  
  318.  
  319. ------------------------------
  320.  
  321. Subject: <Q: 7.10> - How can I use the protected mode?
  322. Date: Sun, 03 Aug 97 20:43:48 CST
  323.  
  324.  
  325.  DJ Delorie has produced DJGPP, a protected mode programming
  326.  environment which supports a port of the GNU C/C++/Ada. For
  327.  more informat see "<Q: 10.06> - What and where is DJGPP?"
  328.  
  329.  
  330.  If you are using Borland C++ Version 4.xx, you can purchase
  331.  the  Borland  PowerPack for DOS Version 1.00. This  package
  332.  includes  Borland  C++  4.02 Service  Update,  16-bit  DPMI
  333.  libraries   and   extenders,  32-bit  DPMI  libraries   and
  334.  extenders, TurboVision 2.0 (16-bit DOS, 16-bit DPMI, 32-bit
  335.  DPMI),  SuperVGA BGI Drivers (16-bit DOS, 16-bit DPMI,  32-
  336.  bit DPMI).
  337.  
  338.  
  339.  There  are  more  extenders  out  there.  One  notable  DOS
  340.  extender is Adam Seychell's DOS32. It can be found at:
  341.  
  342.  
  343.  <ftp://ftp.cdrom.com/.24/demos/code/pmode/dos32b35.zip>
  344.  
  345.  
  346. ------------------------------
  347.  
  348. Subject: <Q: 7.11> - How can I tell if my program is running
  349.      on a PS/2-style machine.
  350.  
  351.  
  352.  Use  INT 15 AX=C0, described in Ralf Brown's interrupt list
  353.  <Q: 2.03>.
  354.  
  355.  
  356. ------------------------------
  357.  
  358. Subject: <Q: 7.12> - Is there a 80x87 math unit installed?
  359.  
  360.  
  361.  SNIPPETS (see <Q: 2.08>) contains C-callable assembly  code
  362.  to determine presence of coprocessor in NDPCHECK.ASM.
  363.  
  364.  
  365. ------------------------------
  366.  
  367. Subject: Section 8. Other software questions and problems
  368.  
  369. <Q: 8.01> - How can a program reboot my PC?
  370. <Q: 8.02> - How can I time events with finer resolution than
  371.      the system clock's 55 ms (about 18 ticks a second)?
  372. <Q: 8.03>  -  How can I find the error level of the previous
  373.      program?
  374. <Q: 8.04> - How can a program set DOS environment variables?
  375. <Q: 8.05>  - How can I change the switch character to - from
  376.      /?
  377. <Q: 8.06>  -  How can I write a TSR (terminate-stay-resident
  378.      utility)?
  379. <Q: 8.07> - Why does my interrupt function behave strangely?
  380. <Q: 8.08> - How can I write a device driver?
  381. <Q: 8.09> - What can I use to manage versions of software?
  382. <Q: 8.10> - What's this "null pointer assignment" after my C
  383.      program executes?
  384. <Q: 8.11> - How can a batch file tell whether it's being run
  385.      in a DOS box under Windows?
  386. <Q: 8.12>  -  How can my program tell if it's running  under
  387.      Windows?
  388. <Q: 8.13>  -  How  can  a program tell whether  ANSI.SYS  is
  389.      installed?
  390. <Q: 8.14> - How do I copyright software that I write?
  391.  
  392. ------------------------------
  393.  
  394. Subject: <Q: 8.01> - How can a program reboot my PC?
  395. Date: Tue, 7 Mar 95 12:00:00 CDT
  396.  
  397.  
  398.  You  can generate a "cold" boot or a "warm" boot.   A  cold
  399.  boot  is the same as turning the power off and on;  a  warm
  400.  boot  is  the  same as Ctrl-Alt-Del and skips the  power-on
  401.  self 'test.
  402.  
  403.  
  404.  For  a  warm boot, store the hex value 1234 in the word  at
  405.  0040:0072. For a cold boot, store 0 in that word.  Then, if
  406.  you  want  to live dangerously, jump to address  FFFF:0000.
  407.  Here's C code to do it:
  408.  
  409.   /* WARNING:  data loss possible */
  410.   void bootme(int want_warm)  /* arg 0 = cold boot, 1 = warm
  411.   */
  412.   {
  413.           void      (far*      boot)(void)      =      (void
  414.   (far*)(void))0xFFFF0000UL;
  415.     unsigned far* type = (unsigned far*)0x00400072UL;
  416.     *type = (want_warm ? 0x1234 : 0);
  417.     (*boot)( );
  418.   }
  419.  
  420.  What's  wrong with that method?  It will boot  right  away,
  421.  without closing files, flushing disk caches, etc.   If  you
  422.  boot without flushing a write-behind disk cache (if one  is
  423.  running),  you could lose data or trash the file allocation
  424.  table in your hard drive.
  425.  
  426.  
  427.  There  are two methods of signaling the cache to flush  its
  428.  buffers:
  429.  
  430.  
  431.  (1)   Simulate  a  keyboard Ctrl-Alt-Del in  the  keystroke
  432.    translation function of the BIOS (INT 15 AH=4F;  but  see
  433.    notes below)
  434.    
  435.  
  436.  (2)  Issue a disk reset (DOS function 0D).  Most disk-cache
  437.    programs hook one or both of those interrupts, so if you use
  438.    both methods you'll probably be safe.
  439.    
  440.  
  441.  When user code simulates a Ctrl-Alt-Del, one or more of the
  442.  programs that have hooked INT 15 AH=4F can ask that the key
  443.  be  ignored  by  clearing  the carry  flag.   For  example,
  444.  HyperDisk does this when it has started but not finished  a
  445.  cache flush.  So if the carry flag comes back cleared,  the
  446.  boot code has to wait a couple of clock ticks and then  try
  447.  again.  (None of this matters on older machines whose  BIOS
  448.  can't support 101- or 102-key keyboards; see the discussion
  449.  of INT 21 AH=4F in "307. What is the SysRq key for?")
  450.  
  451.  
  452.  C  code  that  tries to signal the disk cache (if  any)  to
  453.  flush is given below.  Turbo Pascal code by Timo Salmi that
  454.  does more or less the same job may be found at question  49
  455.  (as   of   this  writing)  in  the  Turbo  Pascal  FAQ   in
  456.  comp.lang.pascal, and is downloadable as file  FAQPAS2.TXT,
  457.  which is part of:
  458.  
  459.  <ftp://garbo.uwasa.fi/pc/ts/tsfaqp*.zip>
  460.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/info/tsfaqp*.zip>
  461.  
  462.  Here's C code that reboots after trying to signal the  disk
  463.  cache:
  464.  
  465.   #include <dos.h>
  466.   
  467.   void bootme(int want_warm)  /* arg 0 = cold boot, 1 = warm
  468.   */
  469.   {
  470.     union REGS reg;
  471.          void      (far*     boot)(void)        =      (void
  472.   (far*)(void))0xFFFF0000UL;    unsigned far* boottype     =
  473.   (unsigned far*)0x00400072UL;
  474.     char     far* shiftstate  = (char far*)0x00400017UL;
  475.     unsigned      ticks;
  476.     int           time_to_waste;
  477.   
  478.     /* Simulate reception of Ctrl-Alt-Del: */
  479.     for (;;)
  480.     {
  481.       *shiftstate |= 0x0C;    /* turn on Ctrl & Alt */
  482.       reg.h.ah = 0x4F;        /* see notes below */
  483.       reg.h.al = 0x53;        /* 0x53 = Del's scan code */
  484.        reg.x.cflag = 1;        /* sentinel for ignoring  key
  485.   */
  486.        int86(0x15, ®, ®);
  487.   
  488.       /* If carry flag is still set, we've finished. */
  489.        if (reg.x.cflag)
  490.         break;
  491.   
  492.       /* Else waste some time before trying again: */
  493.        reg.h.ah = 0;
  494.       int86(0x1A, ®, ®);/* system time into CX:DX */
  495.       ticks = reg.x.dx;
  496.       for (time_to_waste = 3;  time_to_waste > 0;  ) {
  497.         reg.h.ah = 0;
  498.         int86(0x1A, ®, ®);
  499.         if (ticks != reg.x.dx)
  500.           ticks = reg.x.dx , --time_to_waste;
  501.       }
  502.     }
  503.   
  504.     /* Issue a DOS disk reset request: */
  505.     reg.h.ah = 0x0D;
  506.     int86(0x21, ®, ®);
  507.     /* Set boot type and boot: */
  508.     *boottype = (want_warm ? 0x1234 : 0);
  509.     (*boot)( );
  510.   }
  511.  
  512.  Reader  Timo Salmi reported (26 July 1993) that the INT  15
  513.  AH=4F  call  may  not  work on older PCs  (below  AT,  XT2,
  514.  XT286),  according  to  Ralf Brown's  interrupt  list  (<Q:
  515.  2.03>).
  516.  
  517.  
  518.  Reader  Roger  Fulton reported (1 July 1993)  that  INT  15
  519.  AH=4F  hangs  even  a  modern PC "ONLY when  ANSI.SYS  [is]
  520.  loaded  high  using EMM386.EXE.  (Other things loaded  high
  521.  with   EMM386.EXE  were  OK;  ANSI.SYS  loaded  high   with
  522.  QEMM386.SYS  was  OK; ANSI.SYS loaded low  with  EMM386.EXE
  523.  installed was OK.)"  His solution was to use only the  disk
  524.  reset,  INT 21 AH=0D, which does flush SMARTDRV, then  wait
  525.  five  seconds in hopes that any other disk-caching software
  526.  would have time to flush its queue.
  527.  
  528.  
  529.  Reader Per Bergland reported (10 Sep 1993) that the jump to
  530.  FFFF:0000  will not work in Windows or other protected-mode
  531.  programs. (For example, when the above reboot code ran in a
  532.  DOS  session under Windows, a box with "waiting for  system
  533.  shutdown"  appeared.  The PC hung and had to  be  reset  by
  534.  cycling power.)  His solution, which does a cold boot not a
  535.  warm  boot,  is  to  pulse  pin  0  of  the  8042  keyboard
  536.  controller, which is connected to the CPU's "reset" line.
  537.  
  538.  
  539.  He  has  tested the following code on various Compaqs,  and
  540.  expects  it will work for any AT-class machine; he cautions
  541.  that  you  must  first flush the disk  cache  as  indicated
  542.  above.
  543.  
  544.   cli
  545.   
  546.   @@WaitOutReady:  ;  Busy-wait until  8042  ready  for  new
  547.   command
  548.   in al,64h         ; read 8042 status byte
  549.   test al,00000010b ; this bit indicates input buffer full
  550.   jnz @@WaitOutReady
  551.   mov al,0FEh       ; Pulse "reset" = 8042 pin 0
  552.   out 64h,al
  553.   ; The PC will reboot now
  554.  
  555. ------------------------------
  556.  
  557. Subject: <Q: 8.02> - How can I time events with finer
  558.      resolution than the system clock's 55 ms (about 18
  559.      ticks a second)?
  560. Date: Sun, 03 Aug 97 20:47:02 CST
  561.  
  562.  
  563.  The  PC  Timing FAQ / Application Note, maintained by  Kris
  564.  Heidenstrom     (kheidenstrom@actrix.gen.nz),      contains
  565.  information  relating  to  timing  with  PC  hardware   and
  566.  software. It can be found on SimTel:
  567.  
  568.  
  569.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/info/pctim*.zip>
  570.  
  571.  
  572.  The  following  files, among others, are downloadable  from
  573.  SimTel:
  574.  
  575.  
  576.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/sysutl>:
  577.  
  578.   
  579.   atim.zip       4783  881126  Precision program timing  for
  580.   AT
  581.   
  582.  
  583.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/c>
  584.  
  585.   millisec.zip   37734  911205  MSC/asm src for  millisecond
  586.   timing
  587.   mschrt3.zip    53708  910605  High-res timer  toolbox  for
  588.   MSC 5.1
  589.   msec_12.zip    8484  920320  High-def timer v1.2 (C,ASM)
  590.   ztimer11.zip  77625  920428  Microsecond timer for C, C++,
  591.   ASM
  592.  
  593.  For   Turbo  Pascal  users,  source  and  object  code  are
  594.  downloadable as:
  595.  
  596.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/turbopas/bonus507
  597.  .zip>
  598.  <ftp://garbo.uwasa.fi/pc/turbopas/bonus507.zip>
  599.  
  600.  
  601.  
  602.  
  603.  Also   see   "Q:  How  is  millisecond  timing  done?"   in
  604.  FAQPAS.TXT, downloadable as part of:
  605.  
  606.  <ftp://garbo.uwasa.fi/pc/ts/tsfaqp*.zip>
  607.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/info/tsfaqp*.zip>
  608.  
  609. ------------------------------
  610.  
  611. Subject: <Q: 8.03> - How can I find the error level of the
  612.      previous program?
  613. Date: Sun, 03 Aug 97 20:47:59 CST
  614.  
  615.  
  616.  First,  which previous program are you talking  about?   If
  617.  your  current  program  ran another  one,  when  the  child
  618.  program  ends its error level is available to  the  program
  619.  that  spawned it.  Most high-level languages provide a  way
  620.  to   do   this;   for  instance,  in  Turbo   Pascal   it's
  621.  Lo(DosExitCode) and the high byte gives the  way  in  which
  622.  the  child terminated.  In Microsoft C, the exit code of  a
  623.  synchronous child process is the return value of the spawn-
  624.  type function that creates the process.
  625.  
  626.  
  627.  If  your  language doesn't have a function  to  return  the
  628.  error  code  of a child process, you can use INT  21  AH=4D
  629.  (get  return  code).  By the way, this will  tell  you  the
  630.  child's  exit  code and the manner of its  ending  (normal,
  631.  Ctrl-C, critical error, or TSR).
  632.  
  633.  
  634.  It's much trickier if the current program wants to get  the
  635.  error  level  of  the program that ran and finished  before
  636.  this  one  started.  G.A. Theall has published  source  and
  637.  compiled code to do this; the code is downloadable as:
  638.  
  639.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/batchutil/errlvl1
  640.  3.zip>
  641.  
  642.  (The  code  uses undocumented features in DOS  3.3  through
  643.  5.0.  In the .DOC file Theall says that the values returned
  644.  under 4DOS or other replacements won't be right.)
  645.  
  646.  
  647. ------------------------------
  648.  
  649. Subject: <Q: 8.04> - How can a program set DOS environment
  650.      variables?
  651. Date: Sun, 03 Aug 97 20:52:18 CST
  652.  
  653.  
  654.  Program  functions  that  read or write  "the  environment"
  655.  typically access only the program's copy of it.  What  this
  656.  Q  really  wants to do is to modify the active environment,
  657.  the one that is affected by SET commands in batch files  or
  658.  at the DOS prompt.  You need to do some programming to find
  659.  the active environment, and that depends on the version  of
  660.  DOS.
  661.  
  662.  
  663.  A  fairly  well-written article in PC Magazine 28 Nov  1989
  664.  (viii:20),  pages 309-314, explains how to find the  active
  665.  environment, and includes Pascal source code.  The  article
  666.  hints  at  how  to  change  the environment,  and  suggests
  667.  creating   paths   longer  than  128  characters   as   one
  668.  application.
  669.  
  670.  
  671.  Now  as  for  downloadable  source  code,  there  are  many
  672.  possibilities.
  673.  
  674.  
  675.  I looked at some of these, and liked this file the best:
  676.  
  677.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/envutil/rbsetnv1.
  678.  zip>
  679.  <ftp://garbo.uwasa.fi/pc/envutil/rbsetnv1.zip>
  680.  
  681.  It  includes  some utilities to manipulate the environment,
  682.  with source code in C.  A newer program from PC Magazine 22
  683.  Dec 1992 (XI: 22) is:
  684.  
  685.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/batchutl/string25
  686.  .zip>
  687.  <ftp://garbo.uwasa.fi/pc/pcmagvol/vol11n22.zip>
  688.  
  689.  You  can  also  use  a  call to INT  2E,  Pass  Command  to
  690.  Interpreter for Execution; see Ralf Brown's interrupt  list
  691.  <Q: 2.03> for details and cautions.
  692.  
  693.  
  694. ------------------------------
  695.  
  696. Subject: <Q: 8.05> - How can I change the switch character
  697.      to - from /?
  698.  
  699.  
  700.  Under  DOS 5.0 and above you can not.  INT 21 AX=3700,  get
  701.  switch  character, always returns a '/' (hex 2F).  But  the
  702.  DOS  commands  don't even call that function:  they  simply
  703.  hard  code '/' as the switch character.
  704.  
  705.  
  706.  Some  history:  DOS  used  to let  you  change  the  switch
  707.  character  by using SWITCHAR= in CONFIG.SYS or  by  calling
  708.  DOS  function 3701.  DOS commands and other programs called
  709.  DOS function 3700 to find out the switch character.  If you
  710.  changed the switch character to '-' (the usual choice), you
  711.  could  then type "dir c:/c700 -p" rather than "dir  c:\c700
  712.  /p".   Under  DOS 4.0, the DOS commands ignored the  switch
  713.  character  but  functions 3700 and 3701  still  worked  and
  714.  could be used by other programs.  Under DOS 5.0, even those
  715.  functions  no  longer work, though all DOS functions  still
  716.  accept '/' or '\' in file specs.
  717.  
  718.  
  719.  You can reactivate the functions to get and set switchar by
  720.  using  programs  like SLASH.ZIP or the  sample  TSR  called
  721.  SWITCHAR in amisl091.zip (see <Q: 8.06> "How can I write  a
  722.  TSR  (terminate-stay-resident  utility)?").   DOS  commands
  723.  will  still use the slash, but non-DOS programs  that  call
  724.  DOS  function 3700 will use your desired switch  character.
  725.  (DOS  replacements like 4DOS may honor the switch character
  726.  for internal commands.)
  727.  
  728.  
  729.  Some  readers may wonder why this is even an issue.  Making
  730.  '-'  the  switch  character frees up  the  front  slash  to
  731.  separate  names in the path part of a file spec.   This  is
  732.  easier  for  the ten-fingered to type, and  it's  one  less
  733.  difference to remember for commuters between DOS and  Unix.
  734.  The  switch character is the only issue, since all the  INT
  735.  21 functions accept '/' or '\' to separate directory names.
  736.  
  737.  
  738. ------------------------------
  739.  
  740. Subject: <Q: 8.06> - How can I write a TSR (terminate-stay-
  741.      resident utility)?
  742. Date: Sun, 03 Aug 97 21:03:10 CST
  743.  
  744.  
  745.  There are books, and there's code to download.
  746.  
  747.  
  748.  First, the books:
  749.  
  750.  
  751.  -     Ray  Duncan's  {Advanced MS-DOS}, ISBN 1-55615-157-8,
  752.    gives   a   brief  checklist  intended  for   experienced
  753.    programmers.  The ISBN is for the second edition, through
  754.    DOS  4;  but  check to see whether the DOS 6  version  is
  755.    available yet.
  756.    
  757.  
  758.  -     {DOS 5: A Developer's Guide} by Al Williams, ISBN  1-
  759.    55851-177-6, goes into a little more detail, 90 pages worth!
  760.    
  761.  
  762.  -     Pascal  programmers might look at {The  Ultimate  DOS
  763.    Programmer's Manual} by John Mueller and Wallace Wang, ISBN
  764.    0-8306-3534-3, for an extended example in mixed Pascal and
  765.    assembler.
  766.    
  767.  
  768.  -    For a pure assembler treatment, check Steven Holzner's
  769.    {Advanced Assembly Language}, ISBN 0-13-663014-6.  He has a
  770.    book  with the same title out from Brady Press, but  it's
  771.    about half as long as this one.
  772.    
  773.  
  774.  Next,  the code.  Some of it is companion code to published
  775.  articles, which are also listed below:
  776.  
  777.   
  778.   -     The  Alternate  Multiplex  Interrupt  Specification,
  779.      downloadable                                         as
  780.      <ftp://ftp.simtel.net/pub/simtelnet/msdos/info/altmpx35.zip>
  781.      or
  782.      <ftp://garbo.uwasa.fi/pc/programming/altmpx35.zip>
  783.      
  784.   
  785.   -     Ralf Brown's assembly-language implementation of the
  786.      spec, with utilities in C, is downloadable as
  787.      <ftp://ftp.simtel.net/pub/simtelnet/msdos/asmutil/amisl092.z
  788.      ip>
  789.      or
  790.      <ftp://garbo.uwasa.fi/pc/c-lang/amisl092.zip>
  791.      
  792.   
  793.   -     John  English has created a wonderful C++ class  for
  794.      creating  TSRs which includes several examples.  It  is
  795.      downloadable as:
  796.      <ftp://ftp.simtel.net/pub/simtelnet/msdos/cpluspls/tsr100je.
  797.      zip>
  798.      
  799.   
  800.   -      Douglas  Boling's  MASM  template  for  a  TSR   is
  801.      downloadable                                         as
  802.      <ftp://ftp.simtel.net/pub/simtelnet/msdos/asmutl/template.zi
  803.      p>
  804.      
  805.   
  806.   -     A  posted article mentions Boling's "Strategies  and
  807.      Techniques for Writing State-of-the-Art TSRs that Exploit MS-
  808.      DOS 5", Microsoft Systems Journal, Jan-Feb 1992, Volume 7,
  809.      Number 1, pages 41-59, with examples downloadable in
  810.      <ftp://ftp.simtel.net/pub/simtelnet/msdos/msjournl/msjv7-
  811.      1.zip>
  812.      
  813.   
  814.   -     Code  for  Al Stevens's "Writing Terminate-and-Stay-
  815.      Resident Programs", Computer Language, February 1988, pages
  816.      37-48 and March 1988, pages 67-76 is downloadable as
  817.      <ftp://ftp.simtel.net/pub/simtelnet/msdos/c/tsrc.zip>
  818.      
  819.   
  820.   -    Software examples to accompany Kaare Christian's "Using
  821.      Microsoft C Version 5.1 to Write Terminate-and-Stay-Resident
  822.      Programs", Microsoft Systems Journal, September 1988, Volume
  823.      3, Number 5, pages 47-57 are downloadable as
  824.      <ftp://oak.oakland.edu/pub/msdos/msjournl/msjv3-5.zip>
  825.      
  826.  
  827.  Finally,  there are commercial products, of which TesSeRact
  828.  (for C-language TSRs) is one of the best known.
  829.  
  830.  
  831. ------------------------------
  832.  
  833. Subject: <Q: 8.07> - Why does my interrupt function behave
  834.      strangely?
  835. Date: Sun, 03 Aug 97 21:05:15 CST
  836.  
  837.  
  838.  Interrupt service routines can be tricky, because you  have
  839.  to  do some things differently from "normal" programs.   If
  840.  you  make  a  mistake,  debugging is  a  pain  because  the
  841.  symptoms  may not point at what's wrong.  Your machine  may
  842.  lock  up or behave erratically, or just about anything else
  843.  can  happen.  Here are some things to look for.   (See  <Q:
  844.  8.06>  "How  can  I  write  a  TSR (terminate-stay-resident
  845.  utility)?"  for  general  techniques  that  may  prevent  a
  846.  problem.)
  847.  
  848.  
  849.  First, did you fail to set up the registers at the start of
  850.  your routine?  When your routine begins executing, you  can
  851.  count  on  having CS point to your code segment  and  SS:SP
  852.  point  to some valid stack (of unknown length), and  that's
  853.  it.   In particular, an interrupt service routine must  set
  854.  DS  to  DGROUP  before  accessing  any  data  in  its  data
  855.  segments.  (If you're writing in a high-level language, the
  856.  compiler  may  generate  this code for  you  automatically;
  857.  check  your compiler manual.  For instance, in Borland  and
  858.  Microsoft C, give your function the "interrupt" attribute.)
  859.  
  860.  
  861.  Did  you remember to turn off stack checking when compiling
  862.  your  interrupt  server and any functions  it  calls?   The
  863.  stack  during the interrupt is not where the stack-checking
  864.  code   expects  it  to  be.  (Caution:   Some   third-party
  865.  libraries  have stack checking compiled in,  so  you  can't
  866.  call them from your interrupt service routine.)
  867.  
  868.  
  869.  Next, are you calling any DOS functions (INT 21, 25, or 26)
  870.  in  your routine?  DOS is not re-entrant.  This means  that
  871.  if  your interrupt happens to be triggered while the CPU is
  872.  executing a DOS function, calling another DOS function will
  873.  wreak havoc.  (Some DOS functions are fully re-entrant,  as
  874.  noted in Ralf Brown's interrupt list <Q: 2.03>.  Also, your
  875.  program can test, in a way too complicated to present here,
  876.  when  it's  safe to call non-re-entrant DOS functions.  See
  877.  INT  28,  INT  21 AH=34, and INT 21 AX=5D06  or  5D0B;  and
  878.  consult  {Undocumented  DOS}  by  Andrew  Schulman.    Your
  879.  program  must read both the "InDOS flag" and the  "critical
  880.  error flag".)
  881.  
  882.  
  883.  Is  a  function  in your language library causing  trouble?
  884.  Does  it  depend  on some initializations done  at  program
  885.  startup  that  is  no longer available when  the  interrupt
  886.  executes?  Does it call DOS (see preceding paragraph)?  For
  887.  example,  in  both  Borland and  Microsoft  C  the  memory-
  888.  allocation  functions (malloc(), etc..) call DOS  functions
  889.  and  also  depend  on setups that they can't  get  at  from
  890.  inside an interrupt; so do the standard I/O functions  like
  891.  scanf()  and  printf().  Many other library functions  have
  892.  the same problem, so you can't use them inside an interrupt
  893.  function without special precautions.
  894.  
  895.  
  896.  Is  your  routine simply taking too long?  This  can  be  a
  897.  problem if you're hooking on to the timer interrupt, INT 1C
  898.  or  INT 8.  That interrupt expects to be called about every
  899.  55  ms,  which  is  18.2  times a second.   Therefore  your
  900.  routine,  plus  any others hooked to the  same  interrupts,
  901.  must  execute  in  less than 55 ms.  If  they  use  even  a
  902.  substantial  fraction of that time, you'll see  significant
  903.  slowdowns of your foreground program.  A good discussion is
  904.  downloadable as:
  905.  
  906.  
  907.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/info/intshare.zip
  908.  >
  909.  
  910.  
  911.  Did  you forget to restore all registers at the end of your
  912.  routine?
  913.  
  914.  
  915.  Reader,   Morten   Welinder,  notes  that  programmers   of
  916.  interrupt procedures in Borland/Turbo Pascal 7.0 should  be
  917.  aware  that the high words or the 32-bit registers are  not
  918.  saved automatically and that the run-time library may trash
  919.  them  if,  e.g., you use longint operations.  The easy  way
  920.  around this is to do "Test8086 := 0;" before installing the
  921.  interrupt handler.
  922.  
  923.  
  924.  Did  you  chain improperly to the original interrupt?   You
  925.  need  to restore the stack to the way it was upon entry  to
  926.  your routine, then do a far jump (not call) to the original
  927.  interrupt service routine.
  928.  
  929.  
  930.  (The   process   is  a  little  different   in   high-level
  931.  languages.)
  932.  
  933.  
  934. ------------------------------
  935.  
  936. Subject: <Q: 8.08> - How can I write a device driver?
  937.  
  938.  
  939.  Many books answer this in detail.  Among them are {Advanced
  940.  MS-DOS}  and  {DOS 5: A Developer's Guide},  cited  in  the
  941.  preceding  Q.   Michael Tischer's {PC System  Programming},
  942.  ISBN  1-55755-036-0, has an extensive  treatment,  as  does
  943.  Dettman   and   Kyle's  {DOS  Programmer's  Reference:   2d
  944.  Edition},  ISBN  0-88022-458-4.   For  a  really   in-depth
  945.  treatment,  look for a specialized book like  Robert  Lai's
  946.  {Writing MS-DOS Device Drivers}, ISBN 0-201-13185-4.
  947.  
  948.  
  949. ------------------------------
  950.  
  951. Subject: <Q: 8.09> - What can I use to manage versions of
  952.      software?
  953. Date: Sun, 03 Aug 97 21:07:50 CST
  954.  
  955.  
  956.  A port of the Unix RCS utility is downloadable as:
  957.  
  958.   <ftp://ftp.simtel.net/pub/simtelnet/msdos/gnuish/rcs55ax.z
  959.   ip> (EXE and docs)
  960.   <ftp://ftp.simtel.net/pub/simtelnet/msdos/gnuish/rcs55as.z
  961.   ip> (source)
  962.   <ftp://garbo.uwasa.fi/pc/unix/alrcs5ex.zip>    (EXE    and
  963.   docs?)
  964.  
  965.  This  version  of RCS is no longer limited to one-character
  966.  extensions on filenames (for example, .CPP and .BAS are now
  967.  OK).
  968.  
  969.  
  970.  An  RCS56 is available at a number of archive sites, but it
  971.  appears to be unauthorized.  In response to a query,  Keith
  972.  Petersen, SimTel administrator, said that RCS56 was removed
  973.  from  SimTel  at the author's request because  it  did  not
  974.  contain  source code and thus was in violation of  the  GNU
  975.  copyleft.
  976.  
  977.  
  978.  As  for commercial software, I posted a question asking for
  979.  readers'  experiences  in  July  1993  and  seven   readers
  980.  responded.   PVCS  from Intersolv (formerly  Polymake)  got
  981.  five  positive  reviews, though several  readers  commented
  982.  that it's expensive; RCS from MKS got one positive and  one
  983.  negative review; Burton TLIB got one negative review;  DRTS
  984.  from ILSI got one positive review.
  985.  
  986.  
  987. ------------------------------
  988.  
  989. Subject: <Q: 8.10> - What's this "null pointer assignment"
  990.      after my C
  991.                  program executes?
  992.  
  993.  
  994.  Somewhere  in your program, you assigned a value through  a
  995.  pointer  without  first assigning a value to  the  pointer.
  996.  (This might have been something like a strcpy() or memcpy()
  997.  with  a  pointer as its first argument, not necessarily  an
  998.  actual assignment statement.)
  999.  
  1000.  
  1001.  Your program may look like it ran correctly, but if you get
  1002.  this  message  you  can  be  certain  that  there's  a  bug
  1003.  somewhere.
  1004.  
  1005.  
  1006.  Microsoft and Borland C, as part of their exit code  (after
  1007.  a  call  to  exit() or a return from your  main  function),
  1008.  check  whether  the  location 0000  in  your  data  segment
  1009.  contains a different value from what you started with.   If
  1010.  so,  they  infer  that you must have used an  uninitialized
  1011.  pointer.  This implies that the message will appear at  the
  1012.  end  of  execution of your program regardless of where  the
  1013.  error actually occurred.
  1014.  
  1015.  
  1016.  To  track  down  the problem, you can put exit()  calls  at
  1017.  various  spots  in the program and narrow  down  where  the
  1018.  uninitialized pointer is being used by seeing  which  added
  1019.  exit()  makes the null-pointer message disappear.   Or,  if
  1020.  your  program  was  compiled with small or  medium  models,
  1021.  which use 16-bit data pointers, tell the debugger to set  a
  1022.  watch  at  location  0000 in your data segment.   (If  data
  1023.  pointers are 32 bits, as in the compact and large models, a
  1024.  null  pointer  will  overwrite  the  interrupt  vectors  at
  1025.  0000:0000 and probably lock up your machine.)
  1026.  
  1027.  
  1028.  Under MSC/C++ 7.0, you can declare the undocumented library
  1029.  function:
  1030.  
  1031.   extern _cdecl _nullcheck(void);
  1032.  
  1033.  Sprinkle  calls  to _nullcheck() through  your  program  at
  1034.  regular intervals.
  1035.  
  1036.  
  1037.  Borland's TechFax document TI726 discusses the null pointer
  1038.  assignment from a Borland point of view.  It's one of  many
  1039.  documents downloadable as part of
  1040.  
  1041.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/turbo-
  1042.  c/bchelp10.zip>
  1043.  <ftp://garbo.uwasa.fi/pc/turbopas/bchelp10.zip>
  1044.  
  1045. ------------------------------
  1046.  
  1047. Subject: <Q: 8.11> - How can a batch file tell whether it's
  1048.      being run in a DOS box under Windows?
  1049.  
  1050.  
  1051.  When  Windows  3.0 or 3.1 is running, the  DOS  environment
  1052.  will  contain a definition of the string windir,  in  lower
  1053.  case.  That's not really useful, however, because the batch
  1054.  statement
  1055.  
  1056.   if "%windir%" == "" ...
  1057.  
  1058.  will test for an environment variable WINDIR in upper case.
  1059.  
  1060.  
  1061.  Your only real option is to write a program as suggested by
  1062.  the  following question, and have it return a  value  which
  1063.  your batch file can test via "if errorlevel".
  1064.  
  1065.  
  1066. ------------------------------
  1067.  
  1068. Subject: <Q: 8.12> - How can my program tell if it's running
  1069.      under Windows?
  1070. Date: Sun, 03 Aug 97 21:12:33 CST
  1071.  
  1072.  
  1073.  Execute INT 2F AX=4680.  If AX returns 0, you're in Windows
  1074.  real  mode  or  standard  mode (or under  the  DOS  shell).
  1075.  Otherwise,  call  INT 2F AX=1600.  If AL returns  something
  1076.  other  than  0 or 80, you're in Windows 386 enhanced  mode.
  1077.  See PC Magazine 24 Nov 1992 (xi:20) pages 492-493.
  1078.  
  1079.  
  1080.  For  more information, see PC Magazine 26 May 1992  (xi:10)
  1081.  pages 345-346.  A program, WINMODE, is available as part of
  1082.  
  1083.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/pcmag/vol11n10.zi
  1084.  p>
  1085.  <ftp://garbo.uwasa.fi/pc/pcmagvol/vol11n10.zip>
  1086.  
  1087.  PC  Magazine  29  March 1994 (xiii: 6) pages  312  and  320
  1088.  published a new program, WINVER.  This would be in
  1089.  
  1090.  <ftp://ftp.simtel.net/pub/simtelnet/msdos/pcmag/vol13n06.zi
  1091.  p>
  1092.  <ftp://garbo.uwasa.fi/pc/pcmagvol/vol13n06.zip>
  1093.  
  1094. ------------------------------
  1095.  
  1096. Subject: <Q: 8.13> - How can a program tell whether ANSI.SYS
  1097.      is installed?
  1098.  
  1099.  
  1100.  In DOS 4.0 and above, call INT 2F AX=1A00.  If the value FF
  1101.  is  returned  in  AL,  ANSI.SYS  is  installed.   For  more
  1102.  information, see Ralf Brown's interrupt list (<Q: 2.03>).
  1103.  
  1104.  
  1105. ------------------------------
  1106.  
  1107. Subject: <Q: 8.14> - How do I copyright software that I
  1108.      write?
  1109.  
  1110.  
  1111.  You  can  download  a very comprehensive  answer  from  the
  1112.  Internet. Terry Carroll posts a six-part Copyright  FAQ  to
  1113.  misc.legal, news.answers and other groups.  A short  answer
  1114.  follows, not based on that article.
  1115.  
  1116.  
  1117.  Disclaimer:  I  am  not a lawyer, and  this  is  not  legal
  1118.  advice.   Also, there are very likely to be differences  in
  1119.  copyright law among nations.  No matter where you live,  if
  1120.  significant  money may be involved, get legal advice.   The
  1121.  following is adapted (and greatly condensed) from chapter 4
  1122.  of  the  Chicago Manual of Style (13th edition, ISBN 0-226-
  1123.  10390-0).
  1124.  
  1125.  
  1126.  In  the U.S. (at least), when you write something, you  own
  1127.  the  copyright.   (The  exception  that  matters  most   to
  1128.  programmers is "works made for hire", i.e., code you  write
  1129.  because  your employer or client pays you to.  A  contract,
  1130.  agreed in advance, can vest the copyright in the programmer
  1131.  even  if  an  employee;  otherwise the  employer  owns  the
  1132.  copyright.)  You don't have to register the work  with  the
  1133.  Copyright  Office unless (until) the copyright is infringed
  1134.  and  you  intend to bring suit; however, it  is  easier  to
  1135.  recover  damages  in  court if you did  register  the  work
  1136.  within three months of publication.
  1137.  
  1138.  
  1139.  From paragraph 4.16 of the Chicago Manual:
  1140.  
  1141.   
  1142.   "...  the [copyright] notice consists of three parts:  (1)
  1143.   the  symbol  [C-in-a-circle] (preferred  because  it  also
  1144.   suits   the   requirements  of  the  Universal   Copyright
  1145.   Convention),  the  word 'Copyright', or  the  abbreviation
  1146.   'Copr.',  (2) the year of first publication, and  (3)  the
  1147.   name of the copyright owner.  Most publishers also add the
  1148.   phrase  'All  rights  reserved' because  it  affords  some
  1149.   protection in Central and South American countries...."
  1150.   
  1151.  
  1152.  Surprise:  "(C)"  is legally not the same  as  the  C-in-a-
  1153.  circle,  so  those of us who are ASCII-bound must  use  the
  1154.  word or the abbreviation.
  1155.  
  1156.  
  1157. ------------------------------
  1158.  
  1159. Subject: End
  1160.  
  1161.  (FAQ       updates       can       be       found        at
  1162.  <http://www.premiernet.net/~carlyle>.)
  1163.  (End  of comp.os.msdos.programmer FAQ Version 1997.08  Part
  1164.  4/5)
  1165.  (This text is copyright 1997 by Jeffrey Carlyle. All rights
  1166.  reserved.)
  1167.  
  1168.  
  1169.  
  1170. // Jeffrey Carlyle, Bowling Green, Kentucy USA
  1171. // 
  1172. // comp.os.msdos.programmer FAQ maintainer
  1173. // <http://www.premiernet.net/~carlyle> 
  1174.  
  1175.  
  1176.