home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / cpluspls / tsr100je.zip / TSR.DOC < prev    next >
Text File  |  1993-03-22  |  15KB  |  315 lines

  1.  
  2.  
  3.                                                                 Page 1
  4.  
  5.     Class TSR: an abstract base class for DOS resident programs.
  6.     ------------------------------------------------------------
  7.  
  8.       Author: John English (je@unix.brighton.ac.uk)
  9.               Department of Computing
  10.               University of Brighton
  11.               Brighton BN2 4GJ, England.
  12.  
  13.       Copyright (c) J.English 1993.
  14.  
  15.       Permission is granted to use copy and distribute the
  16.       information contained in this file provided that this
  17.       copyright notice is retained intact and that any software
  18.       or other document incorporating this file or parts thereof
  19.       makes the source code for the TSR class of which this file
  20.       is a part freely available.
  21.  
  22.  
  23.     1. Introduction.
  24.     ----------------
  25.     This class provides a framework for writing memory-resident DOS
  26.     programs (TSRs).  TSRs produced using this class can be woken up
  27.     by a specific key (the "hotkey") or after a specified number of
  28.     timer ticks (the "timeslice") or a combination of both.  Writing
  29.     TSRs unaided is a non-trivial task, but this class provides the
  30.     essential TSR functionality which allows you to concentrate on
  31.     your application-specific requirements.  TSRs written using this
  32.     class will require a PC/AT compatible machine running DOS version
  33.     3 or higher.  Compile them with Borland C++ version 3.0 or higher.
  34.  
  35.     To create a TSR using this class, you must derive a class for your
  36.     application from it.  You must supply a function "main" in your
  37.     application class, which will be called whenever the TSR is woken
  38.     up.  To create a TSR, declare an instance of your derived class.
  39.  
  40.     A program built using an instance of your class can make itself
  41.     resident using the member function "run", it can test if a copy
  42.     is already loaded using the member function "loaded", and it can
  43.     unload a previously loaded copy using the member function "unload".
  44.     A foreground copy can also communicate with a resident copy using
  45.     the functions "request" and "respond".  Each TSR must be given a
  46.     unique name up to 32 characters long which can be used to identify
  47.     it once it is made resident.
  48.  
  49.     The constructor and "run" will set an internal status code if any
  50.     errors are detected.  If "run" returns, this will show the cause
  51.     of the error.  The status can be tested during program execution
  52.     using the member function "status".  This can be used to display
  53.     meaningful error messages or to return as the program exit status.
  54.     The member function "name" returns the name of the TSR, which can
  55.     also be used in error messages.
  56.  
  57.     If you find this class useful or have any suggestions as to how it
  58.     can be enhanced, please contact the author at one of the addresses
  59.     given above.  E-mail and postcards will both be welcome!
  60.  
  61.  
  62.     2. Deriving a new TSR class "MyTSR" from class TSR.
  63.     ---------------------------------------------------
  64.     The constructor for your derived class "MyTSR" must invoke the
  65.     constructor for class TSR.  The constructor for class TSR takes
  66.  
  67.  
  68.                                                                 Page 2
  69.  
  70.     two parameters:
  71.  
  72.       * a unique string which will be used to identify your TSR, and
  73.  
  74.       * the size in bytes of the stack to be used when the resident
  75.         part of your TSR is active.  If no stack size is specified,
  76.         the default stack size is taken to be 1024 bytes.
  77.  
  78.     Class MyTSR must also provide a definition of a member function
  79.     called "main" which will contain the application-specific code
  80.     for your TSR.  This will be executed whenever your TSR is woken
  81.     up.  It must be declared as follows:
  82.  
  83.         void main (int hotkey);
  84.  
  85.     Class MyTSR may also provide a destructor (~MyTSR), but this will
  86.     only be called when the TSR is not made resident.
  87.  
  88.     Having created a derived class, you should then declare a single
  89.     instance of this class in your program, as for example:
  90.  
  91.         MyTSR my_tsr;
  92.  
  93.     You must not declare more than one instance of a class derived
  94.     from TSR in your program.
  95.  
  96.     Your program can obtain status information by calling the following
  97.     member functions:
  98.  
  99.       my_tsr.name ();
  100.           This returns the name of the TSR instance (as specified
  101.           in the constructor call to class TSR).
  102.  
  103.       my_tsr.loaded ();
  104.           This returns an integer result which will be non-zero
  105.           if a copy of the TSR is already loaded.
  106.  
  107.       my_tsr.status ();
  108.           This returns an integer result which will be non-zero
  109.           if any errors have been detected by the constructor or
  110.           by "run".  The error codes are as follows:
  111.  
  112.             1: incompatible DOS version (version 3 or higher required)
  113.             2: attempt to declare more than one instance of a TSR
  114.             3: unable to create stack of specified size
  115.             4: cannot allocate self-identify multiplex function
  116.             5: TSR already loaded
  117.             6: failed to make TSR resident (unlikely to occur)
  118.             7: user "startup" function reported failure
  119.  
  120.       my_tsr.unload ();
  121.           This attempts to unload a previously-loaded copy of the
  122.           TSR.  It returns an integer result which will be non-zero
  123.           if it failed, as follows:
  124.  
  125.             1: TSR not loaded, so it cannot be unloaded.
  126.             2: Something else has hooked the same interrupts, so it
  127.                cannot be unloaded.
  128.  
  129.  
  130.                                                                 Page 3
  131.  
  132.             3: Unable to free memory, so it cannot be unloaded (but it
  133.                will now be disabled and will no longer respond to the
  134.                hotkey or to timer ticks).  This is unlikely to occur.
  135.             4: unable to free TSR environment space (although the TSR
  136.                itself will have been successfully unloaded). This is
  137.                unlikely to occur.
  138.  
  139.  
  140.     3. Making your TSR resident.
  141.     ----------------------------
  142.     To make your TSR resident in memory, call the member function
  143.     "run".  "Run" requires two parameters:
  144.  
  145.       * A value representing the hotkey to be used to activate the
  146.         TSR.  This is described further below.
  147.  
  148.       * An optional timeslice size.  This is an integer giving the
  149.         number of timer ticks between TSR activations (a timer tick
  150.         is approximately 55 milliseconds).  If this parameter is
  151.         omitted or zero, the TSR will only be activated when the
  152.         hotkey is pressed.   
  153.  
  154.     The hotkey should be a combination of values from the following
  155.     list:
  156.  
  157.       Modifiers: TSR::ALT, TSR::CTRL, TSR::LSHIFT, TSR::RSHIFT
  158.       Keycodes:  TSR::KEY_A to TSR::KEY_Z, TSR::KEY_0 to TSR::KEY_9,
  159.                  TSR::ENTER, TSR::SPACE, TSR::F1 to TSR::F10
  160.  
  161.     The hotkey value must not use more than one of the values from
  162.     the "keycodes" list above.  If you do not wish a hotkey to be
  163.     used, specify a value of TSR::NONE for the hotkey parameter.
  164.     Some examples of valid hotkey specifications are shown below:
  165.  
  166.         my_tsr.run (TSR::ALT + TSR::F1);
  167.             // "my_tsr" should be woken up whenever Alt-F1 is pressed.
  168.  
  169.         my_tsr.run (TSR::LSHIFT + TSR::RSHIFT);
  170.             // "my_tsr" should be woken up whenever the left and right
  171.             // shift keys are pressed at the same time.
  172.  
  173.     If you specify a hotkey of TSR::NONE and no timeslice is specified
  174.     either, "main" will never be woken up.  You can use this to load
  175.     interrupt handlers (using "startup" and "shutdown" as described
  176.     below) which need to remain resident but do not need to interact
  177.     with the user in any way.  "Main" should be an empty function if
  178.     this is the case, since it will never be called.
  179.  
  180.     If the TSR is installed successfully, "run" will not return.
  181.     If "run" returns, it indicates that an error has occurred.  The
  182.     member function "status" (see above) can be used to determine
  183.     the cause of the error.
  184.  
  185.  
  186.     4. Writing the member function "main".
  187.     --------------------------------------
  188.     "MyTSR::main" (the main function of your derived class) will be
  189.     called whenever the TSR is woken up, either as the result of the
  190.     hotkey being pressed or the specified timeslice expiring.  The
  191.  
  192.  
  193.                                                                 Page 4
  194.  
  195.     parameter "hotkey" will be non-zero if the TSR was woken up by
  196.     the hotkey being pressed and zero if it was woken up because the
  197.     timeslice expired.  "Main" cannot perform operations which call
  198.     DOS functions 00 - 0C (character I/O), 48 (allocate memory), 4C
  199.     (terminate process) or 3E (close file, standard files only), but
  200.     otherwise it is a normal C++ function.
  201.     
  202.     The following member functions can be used within "main":
  203.  
  204.       void pause ();
  205.           This should be called whenever your "main" function is
  206.           performing any lengthy processing.  It allows other TSRs
  207.           to execute while your TSR is active.
  208.  
  209.       void sync ();
  210.           Timed activations normally occur every N timer ticks after
  211.           "run" is called.  This function resets the timer so that
  212.           the next timed activation will happen N timer ticks from
  213.           now, rather than when the current timer count expires.
  214.           This can be useful to resynchronise timed activations if
  215.           a hotkey is used to enable/disable TSR activity.
  216.  
  217.       int userbreak ();
  218.           This returns a non-zero result if "control-break" has been
  219.           pressed since it was last called.  This can be polled from
  220.           "main" if control-break detection is required.
  221.  
  222.     Your class may also overload the following functions to perform
  223.     error recovery for the resident part of your program:
  224.  
  225.       critical_code critical_error (int n);
  226.           Called when a critical error (Abort, Retry, Fail?) occurs
  227.           during execution of "main".  You must not call any DOS
  228.           services other than functions 00 - 0C within this function.
  229.           The result must be one of the values TSR::IGNORE, TSR::RETRY
  230.           or TSR::FAIL.  The default action for this function is to
  231.           return TSR::FAIL.
  232.  
  233.       void dos_error (int fn, int ce, int cs, int ip);
  234.           Called when an illegal DOS function is called from within
  235.           "main" or "critical_error" (see above).  The parameter "fn"
  236.           is the function code from register AH; "ce" is non-zero if
  237.           the error occurred while a critical error was being handled;
  238.           "cs" and "ip" are the segment and offset of the return address
  239.           from the offending interrupt.  If this function is called it
  240.           indicates a bug in your "main" or "critical_error" functions.
  241.           You must not use any DOS services in this function (although
  242.           BIOS services can still be used).  The default action is to
  243.           reset the screen to text mode if it is in graphics mode and
  244.           then display an error message.
  245.  
  246.     These functions should not be called directly; they will be called
  247.     automatically if an error occurs during execution of "main".
  248.  
  249.  
  250.     5. Initialisation and finalisation.
  251.     -----------------------------------
  252.     Since a TSR which is made resident does not exit in the normal way,
  253.     the destructor for your TSR will only be called if it is not made
  254.  
  255.  
  256.                                                                 Page 5
  257.  
  258.     resident.  However, you may need to perform some initialisation when
  259.     the TSR is made resident (e.g. hooking interrupts) and finalisation
  260.     when it is unloaded (e.g. restore the original interrupt vectors).
  261.     There are two virtual functions which can be overloaded to perform
  262.     this sort of initialisation and finalisation:
  263.  
  264.       void startup ();
  265.         Called by "run" when the TSR is being installed in memory.  This
  266.         can be used to provide application-specific initialisation (e.g.
  267.         hooking interrupts).  The default is to do nothing.
  268.  
  269.       void shutdown ();
  270.         Called by "unload" when the TSR is being unloaded from memory.
  271.         This can be used to provide application-specific finalisation
  272.         (e.g. restoring hooked interrupt vectors).  The default is to
  273.         do nothing.
  274.  
  275.     These functions should not be called directly; they will be called
  276.     automatically during TSR loading and unloading.
  277.  
  278.  
  279.     6. Communicating with a resident TSR.
  280.     -------------------------------------
  281.     Sometimes it may be necessary to communicate with a resident copy of
  282.     a TSR from a foreground program to adjust its parameters in some way.
  283.     The functions "request" and "respond" provide a method to perform
  284.     such communication.  The program should provide an appropriate
  285.     implementation for the virtual function "respond", which has the
  286.     following specification:
  287.  
  288.         int respond (int fn, int far& p1, int far& p2);
  289.  
  290.     The parameter "fn" will be a function code in the range 0 to 127, and
  291.     the parameters "p1" and "p2" can be used for an application-specific
  292.     parameter list (which could be the segment and offset of a far pointer
  293.     of a lengthier parameter list).
  294.  
  295.     A copy of the program loaded in the foreground can communicate with
  296.     a previously-loaded resident copy by calling the function "request".
  297.     "Request" requires three reference-to-integer parameters which will
  298.     be used to call "respond" in the resident copy; the first one should
  299.     contain the function code to be passed to "respond" and the remaining
  300.     two will be passed to "respond" as the parameters "p1" and "p2".  The
  301.     result from "respond" will be stored in the first parameter, and the
  302.     final values of "p1" and "p2" produced by "respond" will be stored in
  303.     the last two.  "Request" returns zero if the call is successful, and
  304.     a non-zero result (TSR::NOT_LOADED) if there is no resident copy to
  305.     communicate with.
  306.  
  307.  
  308.     7. A plea for feedback.
  309.     -----------------------
  310.     If you use this class, please contact the author via the addresses
  311.     at the beginning; if you don't have e-mail access please send me a
  312.     postcard (I like postcards!) just to let me know you've looked at
  313.     it.  Feel free to suggest enhancements, find bugs or (better still)
  314.     fix them and send me patches.  Happy hacking!
  315.