home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ERRABORT.ZIP / ERRABORT.C < prev    next >
C/C++ Source or Header  |  1989-09-11  |  27KB  |  775 lines

  1. /* errabort.c - A debugging tool for OS/2 programmers.
  2.  *
  3.  * This DLL is to be called after first calling any OS/2 function and
  4.  * testing for expected return codes.  "Testing for expected return
  5.  * codes" means, for example, testing for zero (successful completion)
  6.  * IN EVERY CASE, and testing for errors that your program anticipates
  7.  * and has code to handle, such as "File not found" when calling
  8.  * 'DosOpen ()'.
  9.  *
  10.  * Any other error return presumably is one that your program did not
  11.  * anticipate and cannot properly handle.  In that case, a call to this
  12.  * DLL will result in the display of an error message, and a termination
  13.  * of your program.  The error message includes your program's name,
  14.  * the name of the function within your program that made the call to an
  15.  * OS/2 function, the line number where the call to this program originated
  16.  * (which should be the line immediately following the call to the OS/2
  17.  * function that returned an unexpected error code), the name of the OS/2
  18.  * function being called, the number of the error code, and a message
  19.  * associated with the error code.
  20.  *
  21.  * If you are not presently testing EVERY OS/2 function call's return
  22.  * value, then you may be surprised by some of the error messages (and
  23.  * program aborts) that calls to this program will give you.  I have
  24.  * found return codes that are not documented as being among those
  25.  * returned by certain functions, for example.  In other cases, return
  26.  * codes that I anticipated (such as 'ERROR_FILE_NOT_FOUND' and
  27.  * 'ERROR_PATH_NOT_FOUND' from 'DosFindFirst ()') were NOT returned;
  28.  * instead I got 'ERROR_NO_MORE_FILES' (it surprised me; maybe it
  29.  * wouldn't surprise you).  Since this program is a DLL, it is certainly
  30.  * cheap enough to include a call to it after every  OS/2 call, at least
  31.  * during debugging.  I modify the ERRCHK macro (included as part of this
  32.  * package) to conditionally generate code depending on the state of a
  33.  * global debugging flag, which makes it easy to remove even the calls.
  34.  *
  35.  * This program with all its associated materials is explicitly placed into
  36.  * the public domain.  Feel free to use it, modify it, or incorporate it
  37.  * into your own programs, whether for your own use or for sale; in short,
  38.  * enjoy.  And if you have something of your own that is useful but was
  39.  * tedious to produce, share it with the rest of us.
  40.  *
  41.  * If you have questions or comments about this program, I am:
  42.  *
  43.  * Author:  Wayne Kovsky                BIX:              wkovsky
  44.  *            Pinnacle Software            CompuServe:        76164,3504
  45.  *            299 Village Street
  46.  *            Millis, MA  02054
  47.  */
  48.  
  49. #define INCL_DOS
  50.  
  51. #include <os2.h>
  52. #include <os2local.h>
  53. /* The '#include os2local.h' statement gets these items included in
  54.  * your program, in case you did not get that file when you got this
  55.  * program.  Your programs that CALL 'errabort ()' will need the first
  56.  * two items as well.
  57.  *
  58.  * extern void EXPENTRY errabort (PSZ pszProgramName, PSZ pszFunctionName,
  59.  *           PSZ pszCallerName, USHORT usLineNum, USHORT usReturn) ;
  60.  *
  61.  *    #define ERRCHK(os2name)    if (usRC != 0) { \
  62.  *            errabort (pszProgramName, #os2name, pszFunctionName, __LINE__, usRC) ; \
  63.  *        }
  64.  *
  65.  *
  66.  *    #define STDIN    0
  67.  *    #define STDOUT    1
  68.  *    #define STDERR    2
  69.  */
  70.  
  71. /* Since this is destined to be a DLL, we must provide our own versions
  72.  * of C library functions 'strlen ()' and 'itoa ()'.
  73.  */
  74. static USHORT FAR PASCAL mystrlen (PSZ pszString) ;
  75. static void FAR PASCAL myitoa (USHORT usNumber, PSZ pszMessage) ;
  76.  
  77. int _acrtused = 0 ;            /* Prevent C startup code being included. */
  78.  
  79. /* What follows is the error text for every documented error code I could
  80.  * find.  It is a LOT of text, and it accounts for the majority of the
  81.  * bulk the finished DLL contains; there is very little executable code.
  82.  * It is for precisely this reason that this is a DLL:  every program you
  83.  * are working on can use this single copy of all this bulk, and let OS/2
  84.  * manage the memory requirements.
  85.  *
  86.  * Most of these messages originated in the "BSEERR.H" file that is
  87.  * in "OS2TOOLS\INCLUDE" as part of the Microsoft OS/2
  88.  * Programmer's Toolkit.  That include file has all error messages
  89.  * in terse upper case for use in C programs; I converted them to
  90.  * these more descriptive messages.  In addition, there were a few
  91.  * duplicates (i.e., two different "#define" names for the same
  92.  * error code); in those cases I (arbitrarily) selected one and
  93.  * discarded the other.
  94.  *
  95.  * Some errors not documented in the "BSEERR.H" file were found in
  96.  * Ray Duncan's book "Advanced OS/2 Programming", first edition,
  97.  * published by Microsoft Press, 1989, ISBN 1-55615-045-8, in
  98.  * Appendix A, pp. 697-706.  I requested and received Mr. Duncan's
  99.  * permission to include those here.
  100.  *
  101.  * Note that many error messages are simply "RESERVED".  I have attempted
  102.  * to conserve space by leaving "holes" in this table of error messages
  103.  * wherever these "RESERVED" error numbers occur.  This means we cannot
  104.  * use the error number as an index into this table, but instead must
  105.  * search the table for a match.  Since this is an "Oh my God, something
  106.  * horrible must have happened!" kind of program, I have followed my
  107.  * long-standing rule to keep it as bulletproof as possible; thus, I have
  108.  * not even so much as done a binary search here.  For a program that
  109.  * does so little and then kills your process, it seemed to me that
  110.  * performance was not much of an issue ... your mileage may vary.
  111.  */
  112. static struct ErrorList {
  113.     USHORT usErrorNum ;
  114.     PSZ pszErrorText ;
  115. } ErrorArray [] = {
  116.     0, "No error",                /* Note that this still ends in abort! */
  117.     1, "Invalid function number",
  118.     2, "File not found",
  119.     3, "Path not found",
  120.     4, "Too many open files",
  121.     5, "Access denied",
  122.     6, "Invalid handle",
  123.     7, "Memory control blocks destroyed",
  124.     8, "Not enough memory",
  125.     9, "Invalid memory block address",
  126.     10, "Invalid environment",
  127.     11, "Invalid format",
  128.     12, "Invalid access code",
  129.     13, "Invalid data",
  130.     14, "Unknown unit",            /* From Duncan - but see error 20. */
  131.     15, "Invalid disk drive",
  132.     16, "Cannot remove current directory",
  133.     17, "Not same device",
  134.     18, "No more files",
  135.     19, "Disk write-protected",
  136.     20, "Invalid unit",            /* From BSEERR.H - but see error 14. */
  137.     21, "Drive not ready",
  138.     22, "Unknown command",
  139.     23, "Data error (CRC)",
  140.     24, "Bad request structure length",
  141.     25, "Seek error",
  142.     26, "Not DOS disk",
  143.     27, "Sector not found",
  144.     28, "Printer out of paper",
  145.     29, "Write fault",
  146.     30, "Read fault",
  147.     31, "General failure",
  148.     32, "Sharing violation",
  149.     33, "Lock violation",
  150.     34, "Invalid disk change",
  151.     35, "FCB unavailable",
  152.     36, "Sharing buffer exceeded",
  153. #if defined INCLUDE_RESERVED
  154.     37, "RESERVED",
  155.     38, "RESERVED",
  156.     39, "RESERVED",
  157.     40, "RESERVED",
  158.     41, "RESERVED",
  159.     42, "RESERVED",
  160.     43, "RESERVED",
  161.     44, "RESERVED",
  162.     45, "RESERVED",
  163.     46, "RESERVED",
  164.     47, "RESERVED",
  165.     48, "RESERVED",
  166.     49, "RESERVED",
  167. #endif /* #if defined INCLUDE_RESERVED */
  168.     50, "Unsupported network request",
  169.  
  170.     /* Error codes from 51 through 72 from Ray Duncan's book cited above. */
  171.     51, "Remote machine not listening",
  172.     52, "Duplicate name on network",
  173.     53, "Network name not found",
  174.     54, "Network busy",
  175.     55, "Device no longer exists on network",
  176.     56, "NetBIOS command limit exceeded",
  177.     57, "Error in network adapter hardware",
  178.     58, "Incorrect response from network",
  179.     59, "Unexpected network error",
  180.     60, "Remote adapter incompatible",
  181.     61, "Print queue full",
  182.     62, "Insufficient memory for print file",
  183.     63, "Print file canceled",
  184.     64, "Network name deleted",
  185.     65, "Network access denied",
  186.     66, "Incorrect network device type",
  187.     67, "Network name not found",
  188.     68, "Network name limit exceeded",
  189.     69, "NetBIOS session limit exceeded",
  190.     70, "File sharing temporarily paused",
  191.     71, "Network request not accepted",
  192.     72, "Print or disk redirection paused",
  193. #if defined INCLUDE_RESERVED
  194.     73, "RESERVED",
  195.     74, "RESERVED",
  196.     75, "RESERVED",
  197.     76, "RESERVED",
  198.     77, "RESERVED",
  199.     78, "RESERVED",
  200.     79, "RESERVED",
  201. #endif /* #if defined INCLUDE_RESERVED */
  202.     80, "File already exists",
  203.     81, "Duplicate FCB",
  204.     82, "Cannot make directory",
  205.     83, "Fail on INT 24H (critical error)",
  206.     84, "Out of structures (too many redirections)",
  207.     85, "Already assigned (duplicate redirection)",
  208.     86, "Invalid password",
  209.     87, "Invalid parameter",
  210.     88, "Network write fault",
  211.     89, "No process slots available",
  212.     90, "Not frozen",
  213.     91, "Timer service table overflow",
  214.     92, "Timer service table duplicate",
  215.     93, "No items to work on",
  216. #if defined INCLUDE_RESERVED
  217.     94, "RESERVED", 
  218. #endif /* #if defined INCLUDE_RESERVED */
  219.     95, "Interrupted system call",
  220. #if defined INCLUDE_RESERVED
  221.     96, "RESERVED", 
  222.     97, "RESERVED", 
  223.     98, "RESERVED", 
  224.     99, "RESERVED", 
  225. #endif /* #if defined INCLUDE_RESERVED */
  226.     100, "Too many semaphores",
  227.     101, "Exclusive semaphore already owned",
  228.     102, "Semaphore is set",
  229.     103, "Too many exclusive semaphore requests",
  230.     104, "Operation invalid at interrupt time",
  231.     105, "Semaphore owner died",
  232.     106, "Semaphore user limit exceeded",
  233.     107, "Disk change (insert drive B disk into drive A)",
  234.     108, "Drive locked",
  235.     109, "Broken pipe (write on pipe with no reader)",
  236.     110, "Open failed due to explicit fail command",
  237.     111, "Buffer overflow",
  238.     112, "Disk full",
  239.     113, "No more search handles",
  240.     114, "Invalid target handle",
  241.     115, "Protection violation",
  242.     116, "Vio/Kbd request error",
  243.     117, "Invalid category",
  244.     118, "Invalid verify switch",
  245.     119, "Driver does not support DosDevIOCtl",
  246.     120, "Call not implemented",
  247.     121, "Semaphore timeout",
  248.     122, "Insufficient data in buffer",
  249.     123, "Invalid name",
  250.     124, "Invalid level",
  251.     125, "No volume label",
  252.     126, "Module not found",
  253.     127, "Procecure not found",
  254.     128, "Wait no children",
  255.     129, "Child not complete",
  256.     130, "Invalid handle for direct disk access",
  257.     131, "Negative seek",
  258.     132, "Seek on device or pipe",
  259.     133, "Drive has previously joined drives",
  260.     134, "Drive is already joined",
  261.     135, "Drive is already substituted",
  262.     136, "Drive is not joined",
  263.     137, "Drive is not substituted",
  264.     138, "Cannot join to joined drive",
  265.     139, "Cannot substitute to substituted drive",
  266.     140, "Cannot join to substituted drive",
  267.     141, "Cannot substitute to joined drive",
  268.     142, "Drive is busy",
  269.     143, "Cannot join or substitute to directory on same drive",
  270.     144, "Must be subdirectory of root",
  271.     145, "Joined directory must be empty",
  272.     146, "Path is already used in substitute",
  273.     147, "Path is already used in join",
  274.     148, "Path is being used by another process",
  275.     149, "Target directory is already substitute target",
  276.     150, "System trace error",
  277.     151, "Invalid event count",
  278.     152, "Too many DosMuxSemWait waiters",
  279.     153, "Invalid list format",
  280.     154, "Volume label too long",
  281.     155, "Too many TCBs",
  282.     156, "Signal refused",
  283.     157, "Segment is discarded",
  284.     158, "Segment was not locked",
  285.     159, "Bad thread ID address",
  286.     160, "Bad arguments",
  287.     161, "Bad pathname",
  288.     162, "Signal already pending",
  289.     163, "Uncertain media",
  290.     164, "No more threads available",
  291.     165, "Monitors not supported",
  292.     166, "UNC driver not installed",
  293.     167, "Lock failed",
  294.     168, "Swap I/O failed",
  295.     169, "Swapin failed",
  296.     170, "Busy",
  297. #if defined INCLUDE_RESERVED
  298.     171, "RESERVED",
  299.     172, "RESERVED",
  300.     173, "RESERVED",
  301.     174, "RESERVED",
  302.     175, "RESERVED",
  303.     176, "RESERVED",
  304.     177, "RESERVED",
  305.     178, "RESERVED",
  306.     179, "RESERVED",
  307. #endif /* #if defined INCLUDE_RESERVED */
  308.     180, "Invalid segment number",
  309.     181, "Invalid call gate",
  310.     182, "Invalid ordinal",
  311.     183, "Already exists",
  312.     184, "No child process",
  313.     185, "Child process is still alive",
  314.     186, "Invalid flag number",
  315.     187, "Semaphore not found",
  316.     188, "Invalid starting code segment",
  317.     189, "Invalid stack segment",
  318.     190, "Invalid module type",
  319.     191, "Invalid EXE signature",
  320.     192, "EXE marked invalid",
  321.     193, "Invalid EXE format",
  322.     194, "Iterated data exceeds 64k",
  323.     195, "Invalid minimum allocation size",
  324.     196, "DYNLINK from invalid ring",
  325.     197, "IOPL not enabled in CONFIG.SYS",
  326.     198, "Invalid segment descriptor privilege level (SEGDPL)",
  327.     199, "Automatic data segment exceeds 64k",
  328.     200, "Ring 2 segment must be movable",
  329.     201, "Relocation chain exceeds segment limit",
  330.     202, "Infinite loop in relocation chain",
  331.     203, "Environment variable not found",
  332.     204, "Not current country",
  333.     205, "No signal sent",
  334.     206, "Filename exceeds size range",
  335.     207, "Ring 2 stack in use",
  336.     208, "Meta expansion too long",
  337.     209, "Invalid signal number",
  338.     210, "Thread 1 inactive",
  339.     211, "File system information not available",
  340.     212, "Locked",
  341.     213, "Bad dynamic link",
  342.     214, "Too many modules",
  343.     215, "Nesting not allowed",
  344.     216, "Cannot shrink Ring 2 stack",        /* Duncan */
  345. #if defined INCLUDE_RESERVED
  346.     217, "RESERVED",
  347.     218, "RESERVED",
  348.     219, "RESERVED",
  349.     220, "RESERVED",
  350.     221, "RESERVED",
  351.     222, "RESERVED",
  352.     223, "RESERVED",
  353.     224, "RESERVED",
  354.     225, "RESERVED",
  355.     226, "RESERVED",
  356.     227, "RESERVED",
  357.     228, "RESERVED",
  358.     229, "RESERVED",
  359. #endif /* #if defined INCLUDE_RESERVED */
  360.     230, "Bad pipe",
  361.     231, "Pipe busy",
  362.     232, "No data",
  363.     233, "Pipe not connected",
  364.     234, "More data",
  365. #if defined INCLUDE_RESERVED
  366.     235, "RESERVED",
  367.     236, "RESERVED",
  368.     237, "RESERVED",
  369.     238, "RESERVED",
  370.     239, "RESERVED",
  371. #endif /* #if defined INCLUDE_RESERVED */
  372.     240, "Virtual circuit disconnected",
  373. #if defined INCLUDE_RESERVED
  374.     241, "RESERVED",
  375.     242, "RESERVED",
  376.     243, "RESERVED",
  377.     244, "RESERVED",
  378.     245, "RESERVED",
  379.     246, "RESERVED",
  380.     247, "RESERVED",
  381.     248, "RESERVED",
  382.     249, "RESERVED",
  383.     250, "RESERVED",
  384.     251, "RESERVED",
  385.     252, "RESERVED",
  386.     253, "RESERVED",
  387.     254, "RESERVED",
  388.     255, "RESERVED",
  389.     256, "RESERVED",
  390.     257, "RESERVED",
  391.     258, "RESERVED",
  392.     259, "RESERVED",
  393.     260, "RESERVED",
  394.     261, "RESERVED",
  395. #endif /* #if defined INCLUDE_RESERVED */
  396.     262, "Stack too large",            /* Duncan */
  397. #if defined INCLUDE_RESERVED
  398.     263, "RESERVED",
  399.     264, "RESERVED",
  400.     265, "RESERVED",
  401.     266, "RESERVED",
  402.     267, "RESERVED",
  403.     268, "RESERVED",
  404.     269, "RESERVED",
  405.     270, "RESERVED",
  406.     271, "RESERVED",
  407.     272, "RESERVED",
  408.     273, "RESERVED",
  409.     274, "RESERVED",
  410.     275, "RESERVED",
  411.     276, "RESERVED",
  412.     277, "RESERVED",
  413.     278, "RESERVED",
  414.     279, "RESERVED",
  415.     281, "RESERVED",
  416.     282, "RESERVED",
  417.     283, "RESERVED",
  418.     284, "RESERVED",
  419.     285, "RESERVED",
  420.     286, "RESERVED",
  421.     287, "RESERVED",
  422.     288, "RESERVED",
  423.     289, "RESERVED",
  424.     290, "RESERVED",
  425.     291, "RESERVED",
  426.     292, "RESERVED",
  427.     293, "RESERVED",
  428.     294, "RESERVED",
  429.     295, "RESERVED",
  430.     296, "RESERVED",
  431.     297, "RESERVED",
  432.     298, "RESERVED",
  433.     299, "RESERVED",
  434.     300, "RESERVED",
  435.     301, "RESERVED",
  436.     302, "RESERVED",
  437. #endif /* #if defined INCLUDE_RESERVED */
  438.     303, "Invalid process ID",
  439.     304, "Invalid priority level delta",
  440.     305, "Not descendant",
  441.     306, "Requestor not Session Manager",
  442.     307, "Invalid priority class",
  443.     308, "Invalid scope",
  444.     309, "Invalid thread ID",
  445.     310, "Cannot shrink DosSubSet segment",
  446.     311, "Out of memory",
  447.     312, "Memory block overlap",
  448.     313, "Invalid size parameter",
  449.     314, "Invalid flag parameter",
  450.     315, "Invalid segment selector",
  451.     316, "Message too long",
  452.     317, "Message ID not found",
  453.     318, "Unable to access message file",
  454.     319, "Invalid message file format",
  455.     320, "Invalid insertion variable count",
  456.     321, "Unable to perform function",
  457.     322, "Unable to wakeup",
  458.     323, "Invalid system semaphore handle",
  459.     324, "No timers available",
  460. #if defined INCLUDE_RESERVED
  461.     325, "RESERVED",
  462. #endif /* #if defined INCLUDE_RESERVED */
  463.     326, "Invalid timer handle",
  464.     327, "Invalid date/time",
  465.     328, "Internal system error",
  466.     329, "Current queue name does not exist",
  467.     330, "Currrent process not queue owner",
  468.     331, "Current process owns queue",
  469.     332, "Duplicate queue name",
  470.     333, "Queue element does not exist",
  471.     334, "Insufficient queue memory",
  472.     335, "Invalid queue name",
  473.     336, "Invalid queue priority",
  474.     337, "Invalid queue handle",
  475.     338, "Queue link not found",
  476.     339, "Queue memory error",
  477.     340, "Previous queue record was at end of queue",
  478.     341, "Process has no access to queues",
  479.     342, "Queue empty",
  480.     343, "Queue name does not exist",
  481.     344, "Queues not initialized",
  482.     345, "Unable to access queues",
  483.     346, "Unable to add new queue",
  484.     347, "Unable to initialize queues",
  485. #if defined INCLUDE_RESERVED
  486.     348, "RESERVED",
  487. #endif /* #if defined INCLUDE_RESERVED */
  488.     349, "Invalid mask",
  489.     350, "Invalid pointer to parameter",
  490.     351, "VIO aptr",
  491.     352, "VIO rptr",
  492.     353, "VIO cptr",
  493.     354, "VIO lptr",
  494.     355, "Unsupported video mode",
  495.     356, "Invalid cursor width value",
  496.     357, "Invalid attribute",
  497.     358, "Invalid row value",
  498.     359, "Invalid column value",
  499.     360, "Invalid top row value",
  500.     361, "Invalid bottom row value",
  501.     362, "Invalid right column value",
  502.     363, "Invalid left column value",
  503.     364, "SCS call",
  504.     365, "SCS value",
  505.     366, "Invalid wait flag setting",
  506.     367, "Screen not previously locked",
  507.     368, "SGS not Session Manager",
  508.  
  509.     /* BSEERR.H has 2 definitions for 369 through 371. */
  510.     369, "Invalid session ID",
  511.     370, "No sessions available",
  512.     371, "Session not found",
  513.  
  514.     372, "Title cannot be changed",
  515.     373, "Invalid parameter",
  516.     374, "No device",
  517.     375, "Invalid wait parameter",
  518.     376, "Invalid length",
  519.     377, "Invalid echo mode mask",
  520.     378, "Invalid input mode mask",
  521.     379, "Invalid monitor parameters",
  522.     380, "Invalid device name",
  523.     381, "Invalid device handle",
  524.     382, "Buffer too small",
  525.     383, "Buffer empty",
  526.     384, "Data record too large",
  527.     385, "No MOUSE device",
  528.     386, "Invalid handle",
  529.     387, "Invalid parameters",
  530.     388, "Can't reset",
  531.     389, "Invalid display parameters",
  532.     390, "Invalid module",
  533.     391, "Invalid entry point",
  534.     392, "Invalid function mask",
  535.     393, "No MOUSE no data",
  536.     394, "No MOUSE pointer drawn",
  537.     395, "Invalid frequency",
  538.     396, "Cannot find COUNTRY.SYS file",
  539.     397, "Cannot open COUNTRY.SYS file",
  540.  
  541.     /* BSEERR.H has 2 definitions for 398. */
  542.     398, "No country or codepage",
  543.  
  544.     399, "NLS table truncated",
  545.     400, "NLS invalid type",
  546.     401, "NLS type not found",
  547.     402, "Function for Task Manager only",
  548.     403, "Invalid ASCIIZ string",
  549.     404, "VioDeRegister not allowed",
  550.     405, "No pop-up screen allocated",
  551.     406, "Pop-up already on screen",
  552.     407, "Function for Task Manager only",
  553.     408, "Invalid ASCIIZ string",
  554.     409, "Invalid replacement mask",
  555.     410, "KbdRegister not allowed",
  556.     411, "KbdDeRegister not allowed",
  557.     412, "Function for Task Manager only",
  558.     413, "Invalid ASCIIZ string",
  559.     414, "Invalid replacement mask",
  560.     415, "MouRegister not allowed",
  561.     416, "MouDeRegister not allowed",
  562.     417, "Invalid action",
  563.     418, "INIT called more than once",
  564.     419, "Screen group not found",
  565.     420, "Caller is not shell",
  566.     421, "Invalid parameters",
  567.     422, "Save/restore function already owned",
  568.     423, "Thread unblock by VioModeUndo or VioSavRedrawUndo",
  569.     424, "Invalid function",
  570.     425, "Function for Task Manager only",
  571.     426, "VioRegister not allowed",
  572.     427, "No VioModeWait thread exists",
  573.     428, "No VioSavRedrawWait thread exists",
  574.     429, "Invalid in background",
  575.     430, "Illegal during popup",
  576.     431, "Caller not baseshell",
  577.     432, "Invalid status request",
  578.     433, "Invalid wait parameter",
  579.     434, "Cannot lock screen",
  580.     435, "Invalid wait parameter",
  581.     436, "Invalid handle",
  582.     437, "Illegal during lock",
  583.     438, "Invalid length",
  584.     439, "Invalid Kbd handle",
  585.     440, "No more Kbd handles",
  586.     441, "Cannot create logical keyboard",
  587.     442, "Code page load incomplete",
  588.     443, "Invalid codepage ID",
  589.     444, "No codepage support",
  590.     445, "Kbd focus required",
  591.     446, "Kbd focus already active",
  592.     447, "Keyboard subsystem busy",
  593.     448, "Invalid codepage",
  594.     449, "Cannot get Kbd focus",
  595.     450, "Session is not selectable",
  596.     451, "Session not in foreground",
  597.     452, "Session not parent of specified child",
  598.     453, "Invalid session start mode",
  599.     454, "Invalid session start option",
  600.     455, "Invalid session bonding option",
  601.     456, "Invalid session select option",
  602.     457, "Session started in background",
  603.     458, "Invalid session stop option",
  604.     459, "Reserved parameters not zero",
  605.     460, "Process not parent",
  606.     461, "Invalid data length",
  607.     462, "Parent session not bound",
  608.     463, "Retry request block allocation",
  609.     464, "Kbd unavailable for detached process",
  610.     465, "Vio unavailable for detached process",
  611.     466, "Mouse unavailable for detached process",
  612.     467, "No font available to support mode",
  613.     468, "User font active",
  614.     469, "Invalid codepage",
  615.     470, "System displays do not support codepage",
  616.     471, "Current display does not support codepage",
  617.     472, "Invalid code page",
  618.     473, "Codepage list is too small",
  619.     474, "Codepage not moved",
  620.     475, "Mode switch initialization error",
  621.     476, "Code page not found",
  622.     477, "Unexpected slot returned",
  623.     478, "Invalid trace option",
  624.     479, "Internal resource error",
  625.     480, "Shell initialization error",
  626.     481, "No Task Manager hard errors",
  627.     482, "Codepage switch incomplete",
  628.     483, "Error during transparent pop-up",
  629.     484, "Critical section overflow",
  630.     485, "Critical section underflow",
  631.     486, "Reserved parameter is not zero",
  632.     487, "Invalid address",
  633.     488, "Zero selectors requested",
  634.     489, "Not enough selectors available",
  635.     490, "Invalid selector",
  636.     491, "Invalid program type",
  637.     492, "Invalid program control",
  638.     493, "Invalid program inheritance option",
  639.     494, "Function not allowed in PM window",
  640.     495, "Function not allowed in non-PM screen group",
  641.     496, "Shield alreay owned",
  642.     497, "No more Vio handles",
  643.     498, "Vio error occurred, see error log",
  644.     499, "Invalid display context",
  645.     500, "No console",
  646.     501, "No console",
  647.     502, "Invalid Mouse handle",
  648.     503, "Invalid debugging parms",
  649.     504, "Function not allowed in PM window",
  650.     505, "Function not allowed in non-PM screen group",
  651.     506, "Invalid icon file"
  652. } ;
  653.  
  654. /* Here are some messages that we will use to display the error. */
  655. static UCHAR szUnexpectedMessage [] = "\r\n\aUnexpected error return " ;
  656. static UCHAR szFromOS2Message [] = " from OS/2 function \"" ;
  657. static UCHAR szParensMessage [] = " ()\".\r\n\"" ;
  658. static UCHAR szProgramNameMsg [] = "\"\r\nCaller program:  \"" ;
  659. static UCHAR szPeriod [] = "\"." ;
  660. static UCHAR szFunctionNameMsg [] = "\r\nCaller function:  \"" ;
  661. static UCHAR szNearMessage [] = "\r\nNear line number:  " ;
  662. static UCHAR szPeriod1 [] = ".\r\n" ;
  663. static UCHAR szNoErrorText [] = "(No error text available)" ;
  664.  
  665.     
  666.     
  667. void EXPENTRY errabort (PSZ pszProgramName, PSZ pszFunctionName,
  668.                PSZ pszCallerName, USHORT usLineNum, USHORT usReturn)
  669. {
  670.     USHORT cbChars ;        /* Characters we asked 'DosWrite ()' to write. */
  671.     USHORT cbBytes ;        /* Characters actually written by 'DosWrite ()'. */
  672.     USHORT i ;
  673.     UCHAR szMessage [20] ;    /* A result buffer for 'myitoa ()'. */
  674.  
  675.     /* Nothing much to do here, really.  Just display some 'canned' text,
  676.      * adding caller-supplied text where appropriate, with the odd
  677.      * conversion (via 'myitoa ()') or strlen (via 'mystrlen ()').
  678.      *
  679.      * I decided to use 'DosWrite ()' instead of 'VioWrtTTY ()' so that
  680.      * these messages will be captured in the 'stderr' file even if it
  681.      * is redirected.  Again, performance is believed (by me) not to be
  682.      * an issue in this program because of its nature, but NEVER missing
  683.      * a message generated by it IS rather important.  If 'stderr' is not
  684.      * redirected (the usual case), OS/2 will convert these 'DosWrite ()'
  685.      * calls into 'VioWrtTTY ()' anyway.
  686.      */
  687.     DosWrite (STDERR, szUnexpectedMessage, sizeof (szUnexpectedMessage) - 1,
  688.       &cbBytes) ;
  689.     myitoa (usReturn, szMessage) ;
  690.     if ((cbChars = mystrlen (szMessage)) > 0)
  691.         DosWrite (STDERR, szMessage, cbChars, &cbBytes) ;
  692.     DosWrite (STDERR, szFromOS2Message, sizeof (szFromOS2Message) - 1,
  693.       &cbBytes) ;
  694.     if ((cbChars = mystrlen (pszFunctionName)) > 0)
  695.         DosWrite (STDERR, pszFunctionName, cbChars, &cbBytes) ;
  696.     DosWrite (STDERR, szParensMessage, sizeof (szParensMessage) - 1,
  697.       &cbBytes) ;
  698.     for (i = 0 ; i <= sizeof (ErrorArray) ; ++i) {
  699.         if (ErrorArray [i].usErrorNum == usReturn) {
  700.             if ((cbChars = mystrlen (ErrorArray [i].pszErrorText)) > 0)
  701.                 DosWrite (STDERR, ErrorArray [i].pszErrorText,
  702.                   cbChars, &cbBytes) ;
  703.             break ;
  704.         }
  705.         else if (ErrorArray [i].usErrorNum > usReturn) {
  706.             DosWrite (STDERR, szNoErrorText, sizeof (szNoErrorText) - 1,
  707.               &cbBytes) ;
  708.             break ;
  709.         }
  710.     }
  711.     DosWrite (STDERR, szProgramNameMsg, sizeof (szProgramNameMsg) - 1,
  712.       &cbBytes) ;
  713.     if ((cbChars = mystrlen (pszProgramName)) > 0)
  714.         DosWrite (STDERR, pszProgramName, cbChars, &cbBytes) ;
  715.     DosWrite (STDERR, szPeriod, sizeof (szPeriod) - 1, &cbBytes) ;
  716.     DosWrite (STDERR, szFunctionNameMsg, sizeof (szFunctionNameMsg) - 1,
  717.       &cbBytes) ;
  718.     if ((cbChars = mystrlen (pszCallerName)) > 0)
  719.         DosWrite (STDERR, pszCallerName, cbChars, &cbBytes) ;
  720.     DosWrite (STDERR, szPeriod, sizeof (szPeriod) - 1, &cbBytes) ;
  721.     DosWrite (STDERR, szNearMessage, sizeof (szNearMessage) - 1,
  722.       &cbBytes) ;
  723.     myitoa (usLineNum, szMessage) ;
  724.     if ((cbChars = mystrlen (szMessage)) > 0)
  725.         DosWrite (STDERR, szMessage, cbChars, &cbBytes) ;
  726.     DosWrite (STDERR, szPeriod1, sizeof (szPeriod1) - 1, &cbBytes) ;
  727.     DosExit (EXIT_PROCESS, 1) ;
  728. }
  729.  
  730.  
  731. /* We don't want to include 'strlen ()', so we rolled our own.
  732.  * Of course, the astute and experienced reader will recognize the
  733.  * code as a variant of one of the three presented in the original
  734.  * edition of K&R; however, they won't admit it, as it will show
  735.  * their age ...
  736.  */
  737. static USHORT FAR PASCAL mystrlen (PSZ pszString)
  738. {
  739.     USHORT cbCount = 0 ;
  740.  
  741.     while (*pszString++)        /* Count characters. */
  742.         ++cbCount ;
  743.     return cbCount ;
  744. }
  745.  
  746.  
  747. /* This private version of 'itoa ()' is not strictly compatible with
  748.  * ANSI 'itoa ()', unlike the relationship between 'strlen ()' and
  749.  * 'mystrlen ()' above.  If you ever decide to use the library
  750.  * version instead of this one, it is not as simple as just changing
  751.  * the name.  Be sure you look up 'itoa ()' first.
  752.  */
  753. static void FAR PASCAL myitoa (USHORT usNumber, PSZ pszMessage)
  754. {
  755.     USHORT usWork, i, j ;
  756.     UCHAR ucChar ;
  757.  
  758.     usWork = usNumber ;
  759.     i = 0 ;
  760.     *pszMessage = '\0' ;
  761.  
  762.     /* First, generate digits in reverse order. */
  763.     do {
  764.         pszMessage [++i] = (UCHAR) (usWork % 10) + '0' ;
  765.     } while ((usWork /= 10) != 0) ;
  766.  
  767.     /* Now reverse the string to correct the order. */
  768.     usWork = i ;
  769.     for (j = 0 ; j < usWork ; ++j, --i) {
  770.         ucChar = pszMessage [i] ;
  771.         pszMessage [i] = pszMessage [j] ;
  772.         pszMessage [j] = ucChar ;
  773.     }
  774. }
  775.