home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / except2x.zip / exceptq.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  84KB  |  2,134 lines

  1. /**********************************************************************/
  2. /*                                                                    */
  3. /*  EXCEPTQ                                                           */
  4. /*                                                                    */
  5. /* DLL containing an exception handler for gathering trap information */
  6. /* This DLL dumps all important debugging Data and is accessible      */
  7. /* from both 16 bit and 32 bits programs                              */
  8. /**********************************************************************/
  9. /* Version: 2.2             |   Marc Fiammante (FIAMMANT at LGEPROFS) */
  10. /*                          |   La Gaude FRANCE                       */
  11. /*                          |   Internet: fiammante@vnet.ibm.com      */
  12. /* Version: 5.0             |   John Currier  (CURRIER at CLTVM1)     */
  13. /*                          |   Internet: currier@vnet.ibm.com        */
  14. /* Version: 6.0             |   Kim Rasmussen (krasmus@ibm.net)       */
  15. /*                          |   Denmark
  16. /* Version: 6.1             |   Anthony Cruise (CRUISE at YKTVMH)     */
  17. /*                          |   Watson Research                       */
  18. /**********************************************************************/
  19. /*                                                                    */
  20. /**********************************************************************/
  21. /* History:                                                           */
  22. /* --------                                                           */
  23. /*                                                                    */
  24. /* created: Marc Fiammante December 1992                              */
  25. /* changed: John Currier   August   1994                              */
  26. /* changed: Kim Rasmussen, May 1995                                   */
  27. /*    Dump of auto-variables added (32-bit only)                      */
  28. /* changed: Anthony Cruise, May 1995                                  */
  29. /*    Do not dump duplicate lines  (32-bit only)                      */
  30. /* fixed  : Marc Fiammante thanks to Bill Siddall                     */
  31. /*    Dump of auto-variables wrong values                             */
  32. /**********************************************************************/
  33. #define INCL_BASE
  34. #define INCL_DOSEXCEPTIONS
  35. #define INCL_DOSSEMAPHORES   /* Semaphore values */
  36. #include <os2.h>
  37. #include <stdlib.h>
  38. #include <stdio.h>
  39. #include <time.h>
  40. #include "sym.h"
  41. #include "omf.h"
  42.  
  43. #ifndef DWORD
  44. #define DWORD unsigned long
  45. #endif
  46. #ifndef WORD
  47. #define WORD  unsigned short
  48. #endif
  49.  
  50. #define HF_STDERR 2
  51. UCHAR *ProcessName = "DEBUGGEE.EXE";
  52. FILE   *hTrap;
  53. static BOOL   f32bit;
  54. struct debug_buffer
  55.  {
  56.    ULONG   Pid;        /* Debuggee Process ID */
  57.    ULONG   Tid;        /* Debuggee Thread ID */
  58.    LONG    Cmd;        /* Command or Notification */
  59.    LONG    Value;      /* Generic Data Value */
  60.    ULONG   Addr;       /* Debuggee Address */
  61.    ULONG   Buffer;     /* Debugger Buffer Address */
  62.    ULONG   Len;        /* Length of Range */
  63.    ULONG   Index;      /* Generic Identifier Index */
  64.    ULONG   MTE;        /* Module Handle */
  65.    ULONG   EAX;        /* Register Set */
  66.    ULONG   ECX;
  67.    ULONG   EDX;
  68.    ULONG   EBX;
  69.    ULONG   ESP;
  70.    ULONG   EBP;
  71.    ULONG   ESI;
  72.    ULONG   EDI;
  73.    ULONG   EFlags;
  74.    ULONG   EIP;
  75.    ULONG   CSLim;      /* Byte Granular Limits */
  76.    ULONG   CSBase;     /* Byte Granular Base */
  77.    UCHAR   CSAcc;      /* Access Bytes */
  78.    UCHAR   CSAtr;      /* Attribute Bytes */
  79.    USHORT  CS;
  80.    ULONG   DSLim;
  81.    ULONG   DSBase;
  82.    UCHAR   DSAcc;
  83.    UCHAR   DSAtr;
  84.    USHORT  DS;
  85.    ULONG   ESLim;
  86.    ULONG   ESBase;
  87.    UCHAR   ESAcc;
  88.    UCHAR   ESAtr;
  89.    USHORT  ES;
  90.    ULONG   FSLim;
  91.    ULONG   FSBase;
  92.    UCHAR   FSAcc;
  93.    UCHAR   FSAtr;
  94.    USHORT  FS;
  95.    ULONG   GSLim;
  96.    ULONG   GSBase;
  97.    UCHAR   GSAcc;
  98.    UCHAR   GSAtr;
  99.    USHORT  GS;
  100.    ULONG   SSLim;
  101.    ULONG   SSBase;
  102.    UCHAR   SSAcc;
  103.    UCHAR   SSAtr;
  104.    USHORT  SS;
  105. } DbgBuf;
  106. /*-------------------------------------*/
  107. APIRET APIENTRY DOSQUERYMODFROMEIP( HMODULE *phMod,
  108.                                     ULONG *pObjNum,
  109.                                     ULONG BuffLen,
  110.                                     PCHAR pBuff,
  111.                                     ULONG *pOffset,
  112.                                     PVOID Address );
  113. APIRET APIENTRY DosQueryModFromEIP( HMODULE *phMod,
  114.                                     ULONG *pObjNum,
  115.                                     ULONG BuffLen,
  116.                                     PCHAR pBuff,
  117.                                     ULONG *pOffset,
  118.                                     PVOID Address );
  119.  
  120. /*-------------------------------------*/
  121. #define DBG_O_OBJMTE       0x10000000L
  122. #define DBG_C_NumToAddr            13
  123. #define DBG_C_AddrToObject         28
  124. #define DBG_C_Connect              21
  125. #define DBG_L_386                   1
  126. RESULTCODES ReturnCodes;
  127. UCHAR   LoadError[40]; /*DosExecPGM buffer */
  128. USHORT Passes;
  129. UCHAR   Translate[17];
  130. UCHAR   OldStuff[16];
  131. #ifdef USE_DOSDEBUG
  132. void    GetObjects(struct debug_buffer * pDbgBuf,HMODULE hMte,PSZ pName);
  133. #endif
  134. VOID    ListModules(VOID);
  135. void    CheckMem(PVOID Ptr,PSZ MemoryName);
  136. /* Better New WalkStack From John Currier */
  137. static void WalkStack(PUSHORT StackBottom,PUSHORT StackTop,PUSHORT Ebp,PUSHORT ExceptionAddress);
  138. int    Read16CodeView(int fh,int TrapSeg,int TrapOff,CHAR * FileName);
  139. int    Read32PmDebug(int fh,int TrapSeg,int TrapOff,CHAR * FileName);
  140. APIRET GetLineNum(CHAR * FileName, ULONG Object,ULONG TrapOffset);
  141. void GetSymbol(CHAR * SymFileName, ULONG Object,ULONG TrapOffset);
  142. void print_vars(ULONG stackofs);
  143.  
  144. ULONG func_ofs;
  145. ULONG pubfunc_ofs;
  146. char  func_name[128];
  147. ULONG var_ofs = 0;
  148.  
  149. struct {
  150.    BYTE name[128];
  151.    ULONG stack_offset;
  152.    USHORT type_idx;
  153. } autovar_def[100];
  154.  
  155. HMODULE hMod;
  156. ULONG   ObjNum;
  157. ULONG   Offset;
  158. /*-------------------------------------*/
  159. CHAR    Buffer[CCHMAXPATH];
  160.  
  161. typedef ULONG     * _Seg16 PULONG16;
  162. APIRET16 APIENTRY16 DOS16SIZESEG( USHORT Seg , PULONG16 Size);
  163. typedef  APIRET16  (APIENTRY16  _PFN16)();
  164. ULONG  APIENTRY DosSelToFlat(ULONG);
  165. /*-------------------------------------*/
  166. /*- DosQProcStatus interface ----------*/
  167. APIRET16 APIENTRY16 DOSQPROCSTATUS(  ULONG * _Seg16 pBuf, USHORT cbBuf);
  168. #define CONVERT(fp,QSsel) MAKEP((QSsel),OFFSETOF(fp))
  169. #pragma pack(1)
  170. /*  Global Data Section */
  171. typedef struct qsGrec_s {
  172.     ULONG     cThrds;  /* number of threads in use */
  173.     ULONG     Reserved1;
  174.     ULONG     Reserved2;
  175. }qsGrec_t;
  176. /* Thread Record structure *   Holds all per thread information. */
  177. typedef struct qsTrec_s {
  178.     ULONG     RecType;    /* Record Type */
  179.                           /* Thread rectype = 100 */
  180.     USHORT    tid;        /* thread ID */
  181.     USHORT    slot;       /* "unique" thread slot number */
  182.     ULONG     sleepid;    /* sleep id thread is sleeping on */
  183.     ULONG     priority;   /* thread priority */
  184.     ULONG     systime;    /* thread system time */
  185.     ULONG     usertime;   /* thread user time */
  186.     UCHAR     state;      /* thread state */
  187.     UCHAR     PADCHAR;
  188.     USHORT    PADSHORT;
  189. } qsTrec_t;
  190. /* Process and Thread Data Section */
  191. typedef struct qsPrec_s {
  192.     ULONG           RecType;    /* type of record being processed */
  193.                           /* process rectype = 1       */
  194.     qsTrec_t *      pThrdRec;  /* ptr to 1st thread rec for this prc*/
  195.     USHORT          pid;       /* process ID */
  196.     USHORT          ppid;      /* parent process ID */
  197.     ULONG           type;      /* process type */
  198.     ULONG           stat;      /* process status */
  199.     ULONG           sgid;      /* process screen group */
  200.     USHORT          hMte;      /* program module handle for process */
  201.     USHORT          cTCB;      /* # of TCBs in use in process */
  202.     ULONG           Reserved1;
  203.     void   *        Reserved2;
  204.     USHORT          c16Sem;     /*# of 16 bit system sems in use by proc*/
  205.     USHORT          cLib;       /* number of runtime linked libraries */
  206.     USHORT          cShrMem;    /* number of shared memory handles */
  207.     USHORT          Reserved3;
  208.     USHORT *        p16SemRec;   /*ptr to head of 16 bit sem inf for proc*/
  209.     USHORT *        pLibRec;     /*ptr to list of runtime lib in use by */
  210.                                   /*process*/
  211.     USHORT *        pShrMemRec;  /*ptr to list of shared mem handles in */
  212.                                   /*use by process*/
  213.     USHORT *        Reserved4;
  214. } qsPrec_t;
  215. /* 16 Bit System Semaphore Section */
  216. typedef struct qsS16Headrec_s {
  217.     ULONG     RecType;   /* semaphore rectype = 3 */
  218.     ULONG     Reserved1;  /* overlays NextRec of 1st qsS16rec_t */
  219.     ULONG     Reserved2;
  220.     ULONG     S16TblOff;  /* index of first semaphore,SEE PSTAT OUTPUT*/
  221.                           /* System Semaphore Information Section     */
  222. } qsS16Headrec_t;
  223. /*  16 bit System Semaphore Header Record Structure */
  224. typedef struct qsS16rec_s {
  225.     ULONG      NextRec;          /* offset to next record in buffer */
  226.     UINT       s_SysSemOwner ;   /* thread owning this semaphore    */
  227.     UCHAR      s_SysSemFlag ;    /* system semaphore flag bit field */
  228.     UCHAR      s_SysSemRefCnt ;  /* number of references to this    */
  229.                                  /*  system semaphore               */
  230.     UCHAR      s_SysSemProcCnt ; /*number of requests by sem owner  */
  231.     UCHAR      Reserved1;
  232.     ULONG      Reserved2;
  233.     UINT       Reserved3;
  234.     CHAR       SemName[1];       /* start of semaphore name string */
  235. } qsS16rec_t;
  236. /*  Executable Module Section */
  237. typedef struct qsLrec_s {
  238.     void        * pNextRec;    /* pointer to next record in buffer */
  239.     USHORT        hmte;         /* handle for this mte */
  240.     USHORT        Reserved1;    /* Reserved */
  241.     ULONG         ctImpMod;     /* # of imported modules in table */
  242.     ULONG         Reserved2;    /* Reserved */
  243. /*  qsLObjrec_t * Reserved3;       Reserved */
  244.     ULONG       * Reserved3;    /* Reserved */
  245.     UCHAR       * pName;        /* ptr to name string following stru*/
  246. } qsLrec_t;
  247. /*  Shared Memory Segment Section */
  248. typedef struct qsMrec_s {
  249.     struct qsMrec_s *MemNextRec;    /* offset to next record in buffer */
  250.     USHORT    hmem;          /* handle for shared memory */
  251.     USHORT    sel;           /* shared memory selector */
  252.     USHORT    refcnt;        /* reference count */
  253.     CHAR      Memname[1];    /* start of shared memory name string */
  254. } qsMrec_t;
  255. /*  Pointer Record Section */
  256. typedef struct qsPtrRec_s {
  257.     qsGrec_t       *  pGlobalRec;        /* ptr to the global data section */
  258.     qsPrec_t       *  pProcRec;          /* ptr to process record section  */
  259.     qsS16Headrec_t *  p16SemRec;         /* ptr to 16 bit sem section      */
  260.     void           *  Reserved;          /* a reserved area                */
  261.     qsMrec_t       *  pShrMemRec;        /* ptr to shared mem section      */
  262.     qsLrec_t       *  pLibRec;           /*ptr to exe module record section*/
  263. } qsPtrRec_t;
  264. /*-------------------------*/
  265. ULONG * pBuf,*pTemp;
  266. USHORT  Selector;
  267. qsPtrRec_t * pRec;
  268. qsLrec_t   * pLib;
  269. qsMrec_t   * pShrMemRec;        /* ptr to shared mem section      */
  270. qsPrec_t   * pProc;
  271. qsTrec_t   * pThread;
  272. ULONG      ListedThreads=0;
  273. APIRET16 APIENTRY16 DOS16ALLOCSEG(
  274.         USHORT          cbSize,          /* number of bytes requested                   */
  275.         USHORT  * _Seg16 pSel,           /* sector allocated (returned)                 */
  276.         USHORT fsAlloc);                 /* sharing attributes of the allocated segment */
  277. typedef struct
  278.   {
  279.     short int      ilen;     /* Instruction length */
  280.     long           rref;     /* Value of any IP relative storage reference */
  281.     unsigned short sel;      /* Selector of any CS:eIP storage reference.   */
  282.     long           poff;     /* eIP value of any CS:eIP storage reference. */
  283.     char           longoper; /* YES/NO value. Is instr in 32 bit operand mode? **/
  284.     char           longaddr; /* YES/NO value. Is instr in 32 bit address mode? **/
  285.     char           buf[40];  /* String holding disassembled instruction **/
  286.   } * _Seg16 RETURN_FROM_DISASM;
  287. RETURN_FROM_DISASM CDECL16 DISASM( CHAR * _Seg16 Source, USHORT IPvalue,USHORT segsize );
  288. RETURN_FROM_DISASM AsmLine;
  289. static USHORT BigSeg;
  290. static ULONG  Version[2];
  291.  
  292. BYTE *type_name[] = {
  293.    "8 bit signed",
  294.    "16 bit signed",
  295.    "32 bit signed",
  296.    "Unknown (0x83)",
  297.    "8 bit unsigned",
  298.    "16 bit unsigned",
  299.    "32 bit unsigned",
  300.    "Unknown (0x87)",
  301.    "32 bit real",
  302.    "64 bit real",
  303.    "80 bit real",
  304.    "Unknown (0x8B)",
  305.    "64 bit complex",
  306.    "128 bit complex",
  307.    "160 bit complex",
  308.    "Unknown (0x8F)",
  309.    "8 bit boolean",
  310.    "16 bit boolean",
  311.    "32 bit boolean",
  312.    "Unknown (0x93)",
  313.    "8 bit character",
  314.    "16 bit characters",
  315.    "32 bit characters",
  316.    "void",
  317.    "15 bit unsigned",
  318.    "24 bit unsigned",
  319.    "31 bit unsigned",
  320.    "Unknown (0x9B)",
  321.    "Unknown (0x9C)",
  322.    "Unknown (0x9D)",
  323.    "Unknown (0x9E)",
  324.    "Unknown (0x9F)",
  325.    "near pointer to 8 bit signed",
  326.    "near pointer to 16 bit signed",
  327.    "near pointer to 32 bit signed",
  328.    "Unknown (0xA3)",
  329.    "near pointer to 8 bit unsigned",
  330.    "near pointer to 16 bit unsigned",
  331.    "near pointer to 32 bit unsigned",
  332.    "Unknown (0xA7)",
  333.    "near pointer to 32 bit real",
  334.    "near pointer to 64 bit real",
  335.    "near pointer to 80 bit real",
  336.    "Unknown (0xAB)",
  337.    "near pointer to 64 bit complex",
  338.    "near pointer to 128 bit complex",
  339.    "near pointer to 160 bit complex",
  340.    "Unknown (0xAF)",
  341.    "near pointer to 8 bit boolean",
  342.    "near pointer to 16 bit boolean",
  343.    "near pointer to 32 bit boolean",
  344.    "Unknown (0xB3)",
  345.    "near pointer to 8 bit character",
  346.    "near pointer to 16 bit characters",
  347.    "near pointer to 32 bit characters",
  348.    "near pointer to void",
  349.    "near pointer to 15 bit unsigned",
  350.    "near pointer to 24 bit unsigned",
  351.    "near pointer to 31 bit unsigned",
  352.    "Unknown (0xBB)",
  353.    "Unknown (0xBC)",
  354.    "Unknown (0xBD)",
  355.    "Unknown (0xBE)",
  356.    "Unknown (0xBF)",
  357.    "far pointer to 8 bit signed",
  358.    "far pointer to 16 bit signed",
  359.    "far pointer to 32 bit signed",
  360.    "Unknown (0xC3)",
  361.    "far pointer to 8 bit unsigned",
  362.    "far pointer to 16 bit unsigned",
  363.    "far pointer to 32 bit unsigned",
  364.    "Unknown (0xC7)",
  365.    "far pointer to 32 bit real",
  366.    "far pointer to 64 bit real",
  367.    "far pointer to 80 bit real",
  368.    "Unknown (0xCB)",
  369.    "far pointer to 64 bit complex",
  370.    "far pointer to 128 bit complex",
  371.    "far pointer to 160 bit complex",
  372.    "Unknown (0xCF)",
  373.    "far pointer to 8 bit boolean",
  374.    "far pointer to 16 bit boolean",
  375.    "far pointer to 32 bit boolean",
  376.    "Unknown (0xD3)",
  377.    "far pointer to 8 bit character",
  378.    "far pointer to 16 bit characters",
  379.    "far pointer to 32 bit characters",
  380.    "far pointer to void",
  381.    "far pointer to 15 bit unsigned",
  382.    "far pointer to 24 bit unsigned",
  383.    "far pointer to 31 bit unsigned",
  384. };
  385.  
  386. /*--                                 --*/
  387. /*-------------------------------------*/
  388.  
  389.  
  390. typedef  _PFN16 * _Seg16 PFN16;
  391. /*--                                 --*/
  392. static BOOL InForceExit =FALSE;
  393. /*-------------------------------------*/
  394.  
  395. ULONG APIENTRY myHandler (PEXCEPTIONREPORTRECORD       pERepRec,
  396.                           PEXCEPTIONREGISTRATIONRECORD pERegRec,
  397.                           PCONTEXTRECORD               pCtxRec,
  398.                           PVOID                        p)
  399. {
  400.   PCHAR   SegPtr;
  401.   PUSHORT StackPtr;
  402.   PUSHORT ValidStackBottom;
  403.   PUCHAR  TestStackBottom;
  404.   PUCHAR  cStackPtr;
  405.   ULONG Size,Flags,Attr,CSSize;
  406.   APIRET rc;
  407.   APIRET semrc;
  408.   APIRET16 rc16;
  409.   PTIB   ptib;
  410.   PPIB   ppib;
  411.   USHORT Count;
  412.   ULONG  Nest;
  413.   UCHAR  TrapFile[20];
  414.   struct debug_buffer DbgBuf;
  415.   static CHAR Name[CCHMAXPATH];
  416.   /* Do not recurse into Trapper (John Currier) */
  417.    static BOOL fAlreadyTrapped = FALSE;
  418.  
  419.   if (InForceExit) {
  420.       return (XCPT_CONTINUE_SEARCH);
  421.   } /* endif */
  422.   if ((pERepRec->ExceptionNum&XCPT_SEVERITY_CODE)==XCPT_FATAL_EXCEPTION)
  423.   {
  424.     if ((pERepRec->ExceptionNum!=XCPT_PROCESS_TERMINATE)&&
  425.         (pERepRec->ExceptionNum!=XCPT_UNWIND)&&
  426.         (pERepRec->ExceptionNum!=XCPT_SIGNAL)&&
  427.         (pERepRec->ExceptionNum!=XCPT_ASYNC_PROCESS_TERMINATE)) {
  428.         DosEnterMustComplete(&Nest);
  429.         rc=DosGetInfoBlocks(&ptib,&ppib);
  430.         if (rc==NO_ERROR) {
  431.            sprintf(TrapFile,"%d%d.TRP",
  432.                    ppib->pib_ulpid,ptib->tib_ptib2->tib2_ultid);
  433.         } else {
  434.            sprintf(TrapFile,"TRAP.TRP");
  435.         }
  436.         printf("Creating %s\n",TrapFile);
  437.         hTrap=fopen(TrapFile,"a");
  438.         if (hTrap==NULL) {
  439.            printf("hTrap NULL\n");
  440.            hTrap=stdout;
  441.         }
  442.         rc=DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
  443.         setbuf( hTrap, NULL);
  444.         fprintf(hTrap,"--------------------------\n");
  445.         fprintf(hTrap,"Exception %8.8lX Occurred\n",pERepRec->ExceptionNum);
  446.         fprintf(hTrap," at %s ",_strtime(Buffer));
  447.         fprintf(hTrap," %s\n",_strdate(Buffer));
  448.         if ( pERepRec->ExceptionNum     ==         XCPT_ACCESS_VIOLATION)
  449.         {
  450.            switch (pERepRec->ExceptionInfo[0]) {
  451.                 case XCPT_READ_ACCESS:
  452.                 case XCPT_WRITE_ACCESS:
  453.                    fprintf(hTrap,"Invalid linear address %8.8lX\n",pERepRec->ExceptionInfo[1]);
  454.                    break;
  455.                 case XCPT_SPACE_ACCESS:
  456.                   /* Thanks to John Currier              */
  457.                   /* It looks like this is off by one... */
  458.                   fprintf(hTrap,"Invalid Selector: %8.8p",
  459.                                  pERepRec->ExceptionInfo[1] ?
  460.                                  pERepRec->ExceptionInfo[1] + 1 : 0);
  461.                    break;
  462.                 case XCPT_LIMIT_ACCESS:
  463.                    fprintf(hTrap,"Limit access fault\n");
  464.                    break;
  465.                 case XCPT_UNKNOWN_ACCESS:
  466.                    fprintf(hTrap,"Unknown access fault\n");
  467.                    break;
  468.               break;
  469.            default:
  470.                    fprintf(hTrap,"Other Unknown access fault\n");
  471.            } /* endswitch */
  472.         } /* endif */
  473.        /* John Currier's recursion prevention */
  474.          fprintf(hTrap,"\n\n");
  475.  
  476.          if (fAlreadyTrapped)
  477.          {
  478.             fprintf(hTrap, "Exception Handler Trapped...aborting evaluation!\n");
  479.             if (hTrap != stderr)
  480.                fclose(hTrap);
  481.             DosExitMustComplete(&Nest);
  482.             DosUnsetExceptionHandler(pERegRec);
  483.             return (XCPT_CONTINUE_SEARCH);
  484.          }
  485.  
  486.          fAlreadyTrapped = TRUE;
  487.        /* end  John Currier's recursion prevention */
  488.         rc = DosQuerySysInfo(QSV_VERSION_MAJOR,QSV_VERSION_MINOR,
  489.                              Version,sizeof(Version));
  490.         if ((rc==0)&&
  491.             (Version[0]>=20) &&
  492.             (Version[1]>=10) ) {
  493.             /* version must be over 2.1 for DOSQUERYMODFROMEIP */
  494.             fprintf(hTrap,"OS/2 Version %d.%d\n",Version[0]/10,Version[1]);
  495.             rc=DOSQUERYMODFROMEIP( &hMod, &ObjNum, CCHMAXPATH,
  496.                                 Name, &Offset, pERepRec->ExceptionAddress);
  497.             if (rc==0) {
  498.               fprintf(hTrap,"Failing code module internal name : %s\n",Name);
  499.               rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
  500.               fprintf(hTrap,"Failing code module file name : %s\n",Name);
  501.               fprintf(hTrap,"Failing code Object # %d at Offset %x \n",ObjNum+1,Offset);
  502.               if (strlen(Name)>3) {
  503.                  fprintf(hTrap,"      File     Line#  Public Symbol\n");
  504.                  fprintf(hTrap,"  ──────────── ────-  ────────────-\n");
  505.                  rc =GetLineNum(Name,ObjNum,Offset);
  506.  
  507.                  if (rc == 0)
  508.                     print_vars(pCtxRec->ctx_RegEbp);
  509.  
  510.                  /* if no codeview try with symbol files */
  511.                  if (rc!=0) {
  512.                     strcpy(Name+strlen(Name)-3,"SYM"); /* Get Sym File name */
  513.                     GetSymbol(Name,ObjNum,Offset);
  514.                  } /* endif */
  515.               } /* endif */
  516.               fprintf(hTrap,"\n");
  517.             } else {
  518.                fprintf(hTrap,"Invalid execution address\n");
  519.             } /* endif */
  520.         } /* endif */
  521.         fprintf(hTrap,"┌─────────────────────────────────────────────────────────────┐\n");
  522.         if ( (pCtxRec->ContextFlags) & CONTEXT_SEGMENTS ) {
  523.              fprintf(hTrap,"│ GS  : %4.4lX     ",pCtxRec->ctx_SegGs);
  524.              fprintf(hTrap,"FS  : %4.4lX     ",pCtxRec->ctx_SegFs);
  525.              fprintf(hTrap,"ES  : %4.4lX     ",pCtxRec->ctx_SegEs);
  526.              fprintf(hTrap,"DS  : %4.4lX     │\n",pCtxRec->ctx_SegDs);
  527.         } /* endif */
  528.         if ( (pCtxRec->ContextFlags) & CONTEXT_INTEGER  ) {
  529.              fprintf(hTrap,"│ EDI : %8.8lX ",pCtxRec->ctx_RegEdi  );
  530.              fprintf(hTrap,"ESI : %8.8lX ",pCtxRec->ctx_RegEsi  );
  531.              fprintf(hTrap,"EAX : %8.8lX ",pCtxRec->ctx_RegEax  );
  532.              fprintf(hTrap,"EBX : %8.8lX │\n",pCtxRec->ctx_RegEbx  );
  533.              fprintf(hTrap,"│ ECX : %8.8lX ",pCtxRec->ctx_RegEcx  );
  534.              fprintf(hTrap,"EDX : %8.8lX                               │\n",pCtxRec->ctx_RegEdx  );
  535.         } /* endif */
  536.         if ( (pCtxRec->ContextFlags) & CONTEXT_CONTROL  ) {
  537.              void * _Seg16 Ptr16;
  538.              fprintf(hTrap,"│ EBP : %8.8lX ",pCtxRec->ctx_RegEbp  );
  539.              fprintf(hTrap,"EIP : %8.8lX ",pCtxRec->ctx_RegEip  );
  540.              fprintf(hTrap,"EFLG: %8.8lX ",pCtxRec->ctx_EFlags  );
  541.              fprintf(hTrap,"ESP : %8.8lX │\n",pCtxRec->ctx_RegEsp  );
  542.              fprintf(hTrap,"│ CS  : %4.4lX     ",pCtxRec->ctx_SegCs   );
  543.              fprintf(hTrap,"SS  : %4.4lX                                   │",pCtxRec->ctx_SegSs   );
  544.              SegPtr =MAKEP((SHORT)pCtxRec->ctx_SegCs,0);
  545.              rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegCs , &CSSize);
  546.              if (rc16==NO_ERROR) {
  547.                 fprintf(hTrap,"\n│ CSLIM: %8.8lX ",CSSize);
  548.              } else {
  549.                 CSSize=0;
  550.              } /* endif */
  551.              rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegSs , &Size);
  552.              if (rc16==NO_ERROR) {
  553.                 fprintf(hTrap,"SSLIM: %8.8lX                             │",Size);
  554.              } /* endif */
  555.              fprintf(hTrap,"\n└─────────────────────────────────────────────────────────────┘\n");
  556.              BigSeg=((pCtxRec->ctx_RegEip)>0x00010000);
  557.              if (BigSeg) {
  558.                  AsmLine= DISASM( (PVOID) pCtxRec->ctx_RegEip,
  559.                                   (USHORT)pCtxRec->ctx_RegEip, BigSeg );
  560.                  fprintf(hTrap,"\n Failing instruction at CS:EIP : %4.4X:%8.8X is  %s\n\n",
  561.                          pCtxRec->ctx_SegCs,
  562.                          pCtxRec->ctx_RegEip,AsmLine->buf);
  563.                  fprintf(hTrap,"\n┌────────────────────────────────────┐\n");
  564.                  fprintf(hTrap,  "│ Register content analysis          │\n");
  565.                  fprintf(hTrap,  "├────────────────────────────────────┤\n");
  566.                  CheckMem( (PVOID)pCtxRec->ctx_RegEax,"EAX");
  567.                  CheckMem( (PVOID)pCtxRec->ctx_RegEbx,"EBX");
  568.                  CheckMem( (PVOID)pCtxRec->ctx_RegEcx,"ECX");
  569.                  CheckMem( (PVOID)pCtxRec->ctx_RegEdx,"EDX");
  570.                  CheckMem( (PVOID)pCtxRec->ctx_RegEdi,"EDI");
  571.                  CheckMem( (PVOID)pCtxRec->ctx_RegEsi,"ESI");
  572.                  fprintf(hTrap,"└────────────────────────────────────┘\n");
  573.              } else {
  574.                  if (CSSize>pCtxRec->ctx_RegEip) {
  575.                     AsmLine= DISASM(MAKE16P(pCtxRec->ctx_SegCs,
  576.                                             pCtxRec->ctx_RegEip),
  577.                                     (USHORT)pCtxRec->ctx_RegEip, BigSeg );
  578.                     fprintf(hTrap,"\n Failing instruction at CS:IP : %4.4X:%4.4X is   %s\n\n",
  579.                            pCtxRec->ctx_SegCs,
  580.                            pCtxRec->ctx_RegEip,AsmLine->buf);
  581.                  } else {
  582.                      fprintf(hTrap,"Invalid execution address\n");
  583.                  } /* endif */
  584.                  fprintf(hTrap,"\n┌────────────────────────────────────────────┐\n");
  585.                  fprintf(hTrap,  "│ Source Destination registers pair analysis │\n");
  586.                  fprintf(hTrap,  "├────────────────────────────────────────────┤\n");
  587.                  rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegDs , &Size);
  588.                  if (rc16==NO_ERROR) {
  589.                     if ((USHORT)Size<(USHORT)pCtxRec->ctx_RegEsi) {
  590.                        fprintf(hTrap,"│ DS:SI points outside Data Segment          │\n");
  591.                     } else {
  592.                        fprintf(hTrap,"│ DS:SI is a valid source                    │\n");
  593.                     } /* endif */
  594.                  } else {
  595.                        fprintf(hTrap,"│ DS (Data Segment) Is Invalid               │\n");
  596.                  } /* endif */
  597.                  rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegEs , &Size);
  598.                  if (rc16==NO_ERROR) {
  599.                     if ((USHORT)Size<(USHORT)pCtxRec->ctx_RegEdi) {
  600.                        fprintf(hTrap,"│ ES:DI points outside Extra Segment         │\n");
  601.                     } else {
  602.                        fprintf(hTrap,"│ ES:DI is a valid destination               │\n");
  603.                     } /* endif */
  604.                  } else {
  605.                     fprintf(hTrap,"│ ES (Extra Segment) Is Invalid              │\n");
  606.                  } /* endif */
  607.                  fprintf(hTrap,"└────────────────────────────────────────────┘\n");
  608.              } /* endif */
  609.              rc=DosGetInfoBlocks(&ptib,&ppib);
  610.              if (rc==NO_ERROR) {
  611.                 static CHAR Format[10];
  612.                 fprintf(hTrap,"\nThread slot %lu , Id %lu , priority %p\n",
  613.                         ptib->tib_ordinal,
  614.                         ptib->tib_ptib2->tib2_ultid ,
  615.                         ptib->tib_ptib2->tib2_ulpri );
  616.                 Ptr16=ptib->tib_pstack;
  617.                 sprintf(Format,"%8.8lX",Ptr16);
  618.                 fprintf(hTrap,"Stack Bottom : %8.8lX (%4.4s:%4.4s) ;", ptib->tib_pstack ,Format,Format+4);
  619.                 Ptr16=ptib->tib_pstacklimit;
  620.                 sprintf(Format,"%8.8lX",Ptr16);
  621.                 fprintf(hTrap,"Stack Top    : %8.8lX (%4.4s:%4.4s) \n",ptib->tib_pstacklimit,Format,Format+4);
  622.                 fprintf(hTrap,"Process Id : %lu ", ppib->pib_ulpid);
  623.                 rc=DosQueryModuleName(ppib->pib_hmte,CCHMAXPATH, Name);
  624.                 if (rc==NO_ERROR) {
  625.                    fprintf(hTrap,".EXE name : %s\n",Name);
  626.                 } else {
  627.                    fprintf(hTrap,".EXE name : ??????\n");
  628.                 } /* endif */
  629.                /* Better New WalkStack From John Currier */
  630.                WalkStack((PUSHORT)ptib->tib_pstack,
  631.                          (PUSHORT)ptib->tib_pstacklimit,
  632.                          (PUSHORT)pCtxRec->ctx_RegEbp,
  633.                          (PUSHORT)pERepRec->ExceptionAddress);
  634.                 ListModules();
  635.                 Count=0;
  636.                 Translate[0]=0x00;
  637.  
  638.                 fprintf(hTrap,"\n/*----- Stack Bottom ---*/\n");
  639.                 /* round to start of page to check first stack valid page  */
  640.                /* Thanks to John Currier for pointing me the guard page problem */
  641.                 TestStackBottom =(PUCHAR)(((ULONG)ptib->tib_pstack)&0xFFFFE000);
  642.                 Size=0x1000;
  643.                 do {
  644.                    ValidStackBottom =(PUSHORT)TestStackBottom;
  645.                    rc=DosQueryMem(TestStackBottom,&Size,&Attr);
  646.                    TestStackBottom +=0x1000; /* One more page for next test */
  647.                 } while (
  648.                    ( (rc!=0) ||
  649.                      ((Attr&PAG_COMMIT)==0x0U) ||
  650.                      ((Attr&PAG_READ)==0x0U)
  651.                    ) &&
  652.                    (TestStackBottom <(PUCHAR)ptib->tib_pstacklimit)
  653.                 );
  654.                 if ( (rc==0)&&
  655.                      (Attr&PAG_COMMIT) &&
  656.                      (Attr&PAG_READ) &&
  657.                      (ValidStackBottom <(PUSHORT)ptib->tib_pstacklimit)
  658.                    )
  659.                 {
  660.                    fprintf(hTrap,"\n/*----- Accessible Stack Bottom at %p ---*/\n",ValidStackBottom);
  661.                    for (StackPtr=ValidStackBottom;
  662.                         StackPtr<(PUSHORT)ptib->tib_pstacklimit;
  663.                         StackPtr++) {
  664.                         if (Count==0) {
  665.                            if (memcmp(OldStuff,StackPtr,16)){
  666.                                memcpy(OldStuff,StackPtr,16);
  667.                                Passes = 0;
  668.                            } else {
  669.                                if (Passes == 0) {
  670.                                    Passes = 1;
  671.                                    fprintf(hTrap,"  %s\n %8.8X :",Translate,StackPtr);
  672.                                    fprintf(hTrap,"  lines not printed same as above");
  673.                                    strcpy(Translate,"\n");
  674.                                }
  675.                                StackPtr+= 7;
  676.                                continue;
  677.                            }
  678.                         }
  679.                         if (Count==0) {
  680.                            fprintf(hTrap,"  %s\n %8.8X :",Translate,StackPtr);
  681.                            Translate[0]=0x00;
  682.                         } /* endif */
  683.                        /* Change Formatting way (John Currier)*/
  684.                        fprintf(hTrap,"%4.4hX ",*StackPtr >> 8 | *StackPtr << 8);
  685.                         cStackPtr=(PUCHAR)StackPtr;
  686.                         if ((isprint(*cStackPtr)) &&
  687.                             (*cStackPtr>=0x20)  ) {
  688.                            Translate[2*Count]=*cStackPtr;
  689.                         } else {
  690.                            Translate[2*Count]='.';
  691.                         } /* endif */
  692.                         cStackPtr++;
  693.                         if ((isprint(*cStackPtr) )&&
  694.                             ( *cStackPtr >=0x20 )  ) {
  695.                            Translate[2*Count+1]=*cStackPtr;
  696.                         } else {
  697.                            Translate[2*Count+1]='.';
  698.                         } /* endif */
  699.                         Count++;
  700.                         Translate[2*Count]=0x00;
  701.                         if (Count==8) {
  702.                             Count=0;
  703.                         } /* endif */
  704.                    } /* endfor */
  705.                 } /* endif */
  706.                 fprintf(hTrap,"%s\n/*----- Stack Top -----*/\n",Translate);
  707.  
  708.              } /* endif */
  709.         } /* endif */
  710.         if (hTrap!=stdout) {
  711.            fclose(hTrap);
  712.         }
  713.         DosExitMustComplete(&Nest);
  714.         rc=DosUnsetExceptionHandler(pERegRec);
  715.      } /* endif */
  716.   } else {
  717.      /* printf("Other non fatal exception %8.8lx ",pERepRec->ExceptionNum); */
  718.      /* printf("At address                %8.8lx\n",pERepRec->ExceptionAddress); */
  719.   } /* endif */
  720.   return (XCPT_CONTINUE_SEARCH);
  721.  
  722. }
  723. APIRET16 APIENTRY16 SETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
  724.  {
  725.    APIRET rc;
  726.  
  727.    rc=DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
  728.    printf("Set error rc %ld\n",rc);
  729.    pxcpthand->prev_structure=0;
  730.    pxcpthand->ExceptionHandler=&myHandler;
  731.    rc=DosSetExceptionHandler(pxcpthand);
  732.    printf("Set except rc %ld\n",rc);
  733. }
  734. APIRET16 APIENTRY16 UNSETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
  735.  {
  736.    APIRET rc;
  737.    rc=DosUnsetExceptionHandler(pxcpthand);
  738.    printf("Unset except rc %ld\n",rc);
  739. }
  740. VOID ListModules() {
  741.   APIRET   rc;
  742.   APIRET16 rc16;
  743. #ifdef USE_DOSDEBUG
  744.   /**----------------------------------***/
  745.   rc16=DOS16ALLOCSEG( 0xFFFF , &Selector , 0);
  746.   if (rc16==0) {
  747.      pBuf=MAKEP(Selector,0);
  748.      rc16=DOSQPROCSTATUS(pBuf, 0xFFFF );
  749.      if (rc16==0) {
  750.         rc = DosExecPgm(LoadError,          /* Object name buffer */
  751.                         sizeof(LoadError),  /* Length of object name buffer */
  752.                         EXEC_TRACE,         /* Asynchronous/Trace flags */
  753.                         "Debug",            /* Argument string */
  754.                         NULL,               /* Environment string */
  755.                         &ReturnCodes,       /* Termination codes */
  756.                         ProcessName);           /* Program file name */
  757.         if (rc != NO_ERROR) {
  758.             fprintf(hTrap,"rc = %d Process ID %d  Return Code %d \n",
  759.                   rc,
  760.                   ReturnCodes.codeTerminate,
  761.                   ReturnCodes.codeResult);
  762.             return;
  763.         }
  764.        fprintf(hTrap,"Connecting  to PID %d\n",ReturnCodes.codeTerminate);
  765.        DbgBuf.Cmd = DBG_C_Connect; /* Indicate that a Connect is requested */
  766.        DbgBuf.Pid = ReturnCodes.codeTerminate;
  767.        DbgBuf.Tid = 0;
  768.        DbgBuf.Value = DBG_L_386;
  769.        rc = DosDebug(&DbgBuf);
  770.        if (rc != 0) {
  771.            fprintf(hTrap,"DosDebug error: return code = %ld Note %8.8lX\n", rc,DbgBuf.Cmd);
  772.            fprintf(hTrap,"Value          = %8.8lX %ld\n",DbgBuf.Value,DbgBuf.Value);
  773.        }
  774.        fprintf(hTrap,"Connected to PID %d\n",ReturnCodes.codeTerminate);
  775.        /*****************************/
  776.        pRec=(qsPtrRec_t *) pBuf;
  777.        pLib=pRec->pLibRec;
  778.        while (pLib) {
  779.            GetObjects(&DbgBuf,pLib->hmte,pLib->pName);
  780.            pLib =pLib->pNextRec;
  781.        } /* endwhile */
  782.      } else {
  783.        fprintf(hTrap,"DosQProcStatus Failed %hd\n",rc16);
  784.      } /* endif */
  785.   } else {
  786.      fprintf(hTrap,"DosAllocSeg Failed %hd\n",rc16);
  787.   } /* endif */
  788. #else
  789.   PVOID BaseAddress;
  790.   ULONG RegionSize;
  791.   ULONG AllocationFlags;
  792.   HMODULE LastModule;
  793.   static CHAR Name[CCHMAXPATH];
  794.   ULONG Size;
  795.   LastModule=0;
  796.   BaseAddress=(PVOID)0x10000;
  797.   RegionSize =0x3FFFFFFF;
  798.   fprintf(hTrap,"┌─────────────────────────────────────────────────────────────────────────┐\n");
  799.   fprintf(hTrap,"│ List of currently accessed modules (DLLs) object addresses              │");
  800.   rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
  801.   while (rc==NO_ERROR) {
  802.      if ((AllocationFlags&PAG_EXECUTE)&&
  803.          (AllocationFlags&PAG_BASE)) {
  804.         rc=DOSQUERYMODFROMEIP( &hMod, &ObjNum, CCHMAXPATH,
  805.                               Name, &Offset, BaseAddress);
  806.         if (rc==0) {
  807.             if (hMod!=LastModule) {
  808.                rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
  809.                fprintf(hTrap,"\n├─────────────────────────────────────────────────────────────────────────┤\n");
  810.                fprintf(hTrap,"│ Module %-48.48s Handle %8.8d │\n",Name,hMod);
  811.                fprintf(hTrap,"│ Object Number    Address    Length     Flags      Type                  │");
  812.                LastModule=hMod;
  813.             } /* endif */
  814.             fprintf(hTrap,"\n│       % 6.6d    %8.8lX   %8.8lX   %8.8lX ",ObjNum,
  815.                       BaseAddress, RegionSize, AllocationFlags);
  816.             rc16 =DOS16SIZESEG( SELECTOROF(BaseAddress), &Size);
  817.             if (rc16==0) {
  818.                fprintf(hTrap," - 16:16  Selector %4.4hX │",SELECTOROF((PVOID)BaseAddress));
  819.             } else {
  820.                fprintf(hTrap," - 32 Bits              │");
  821.             } /* endif */
  822.         }
  823.      }
  824.      if (AllocationFlags&PAG_FREE) RegionSize =0x10000;
  825.      RegionSize +=0x0FFF;
  826.      RegionSize &=0xFFFFF000;
  827.      BaseAddress=(PVOID)(((PCHAR)BaseAddress)+RegionSize);
  828.      RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
  829.      rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
  830.      while ((rc==ERROR_INVALID_ADDRESS)||
  831.             (rc==ERROR_NO_OBJECT)) {
  832.          BaseAddress=(PVOID)(((PCHAR)BaseAddress)+0x10000);
  833.          if (BaseAddress>(PVOID)0x3FFFFFFF) {
  834.             break;
  835.          } /* endif */
  836.          RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
  837.          rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
  838.      } /* endwhile */
  839.      if (BaseAddress>(PVOID)0x3FFFFFFF) {
  840.         break;
  841.      } /* endif */
  842.   } /* endwhile */
  843.   fprintf(hTrap,"\n└─────────────────────────────────────────────────────────────────────────┘\n");
  844. #endif
  845. }
  846. #ifdef USE_DOSDEBUG
  847. VOID  GetObjects(struct debug_buffer * pDbgBuf,HMODULE hMte,PSZ pName) {
  848.     APIRET rc;
  849.     int  object;
  850.     pDbgBuf->MTE  = (ULONG) hMte;
  851.     rc=0;
  852.     fprintf(hTrap,"DLL %s Handle %d\n",pName,hMte);
  853.     fprintf(hTrap,"Object Number    Address    Length     Flags      Type\n");
  854.     for (object=1;object<256;object++ ) {
  855.         pDbgBuf->Cmd   = DBG_C_NumToAddr;
  856.         pDbgBuf->Pid   = ReturnCodes.codeTerminate;
  857.         pDbgBuf->Value = object; /* Get nth object address in module with given MTE */
  858.         pDbgBuf->Buffer= 0;
  859.         pDbgBuf->Len   = 0;
  860.         rc = DosDebug(pDbgBuf);
  861.         if ((rc == NO_ERROR)&&
  862.             (pDbgBuf->Cmd==NO_ERROR)) {
  863.             ULONG Size;
  864.             ULONG Flags;
  865.             APIRET16 rc16;
  866.             pDbgBuf->Len   = 0;
  867.             pDbgBuf->Value = 0;
  868.             if (pDbgBuf->Addr!=0) {
  869.                 pDbgBuf->Cmd   = DBG_C_AddrToObject;
  870.                 pDbgBuf->Pid   = ReturnCodes.codeTerminate;
  871.                 rc = DosDebug(pDbgBuf);
  872.                 if ((rc != NO_ERROR) ||
  873.                     (pDbgBuf->Cmd|=NO_ERROR)) {
  874.                    pDbgBuf->Len   = 0;
  875.                    pDbgBuf->Value = 0;
  876.                 }
  877.             }
  878.             fprintf(hTrap,"      % 6.6d    %8.8lX   %8.8lX   %8.8lX ",object,
  879.                       pDbgBuf->Addr, pDbgBuf->Len, pDbgBuf->Value);
  880.             if (pDbgBuf->Addr!=0) {
  881.                 rc16 =DOS16SIZESEG( SELECTOROF(pDbgBuf->Addr), &Size);
  882.                 if (rc16==0) {
  883.                    fprintf(hTrap," - 16:16  Selector %4.4hX\n",SELECTOROF((PVOID)pDbgBuf->Addr));
  884.                 } else {
  885.                    fprintf(hTrap," - 32 Bits\n");
  886.                 } /* endif */
  887.             } else {
  888.                fprintf(hTrap," - ?\n");
  889.             } /* endif */
  890.         } else {
  891. //         printf("DosDebug return code = %ld Notification %8.8lX\n", rc,pDbgBuf->Cmd);
  892. //         printf("Value                = %8.8lX %ld\n",pDbgBuf->Value,pDbgBuf->Value);
  893.            break;
  894.         }
  895.     } /* endfor */
  896.     fprintf(hTrap,"\n");
  897. }
  898. #endif
  899. void    CheckMem(PVOID Ptr,PSZ MemoryName) {
  900.    APIRET rc;
  901.    ULONG Size,Flags,Attr;
  902.    Size=1;
  903.    rc=DosQueryMem(Ptr,&Size,&Attr);
  904.    if (rc!=NO_ERROR) {
  905.       fprintf(hTrap,   "│ %3.3s does not point to valid memory │\n",MemoryName);
  906.    } else {
  907.       if (Attr&PAG_FREE) {
  908.          fprintf(hTrap,   "│ %3.3s points to unallocated memory   │\n",MemoryName);
  909.       } else {
  910.          if ((Attr&PAG_COMMIT)==0x0U) {
  911.             fprintf(hTrap,"│ %3.3s points to uncommited  memory   │\n",MemoryName);
  912.          } /* endif */
  913.          if ((Attr&PAG_WRITE)==0x0U) {
  914.             fprintf(hTrap,"│ %3.3s points to unwritable  memory   │\n",MemoryName);
  915.          } /* endif */
  916.          if ((Attr&PAG_READ)==0x0U) {
  917.             fprintf(hTrap,"│ %3.3s points to unreadable  memory   │\n",MemoryName);
  918.          } /* endif */
  919.       } /* endif */
  920.    } /* endif */
  921. }
  922. PUSHORT Convert(USHORT * _Seg16 p16) {
  923.    return p16;
  924. }
  925. /* Better New WalkStack From John Currier */
  926. static void WalkStack(PUSHORT StackBottom, PUSHORT StackTop, PUSHORT Ebp,
  927.                       PUSHORT ExceptionAddress)
  928. {
  929.    PUSHORT  RetAddr;
  930.    PUSHORT  LastEbp;
  931.    APIRET   rc;
  932.    ULONG    Size,Attr;
  933.    USHORT   Cs,Ip,Bp,Sp;
  934.    static char Name[CCHMAXPATH];
  935.    HMODULE  hMod;
  936.    ULONG    ObjNum;
  937.    ULONG    Offset;
  938.    BOOL     fExceptionAddress = TRUE;  // Use Exception Addr 1st time thru
  939.  
  940.    // Note: we can't handle stacks bigger than 64K for now...
  941.    Sp = (USHORT)(((ULONG)StackBottom) >> 16);
  942.    Bp = (USHORT)(ULONG)Ebp;
  943.  
  944.    if (!f32bit)
  945.       Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
  946.  
  947.    fprintf(hTrap,"\nCall Stack:\n");
  948.    fprintf(hTrap,"                                        Source    Line      Nearest\n");
  949.    fprintf(hTrap,"   EBP      Address    Module  Obj#      File     Numbr  Public Symbol\n");
  950.    fprintf(hTrap," ────────  ────────-  ──────── ────  ──────────── ────-  ────────────-\n");
  951.  
  952.    do
  953.    {
  954.       Size = 10;
  955.       rc = DosQueryMem((PVOID)(Ebp+2), &Size, &Attr);
  956.       if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
  957.       {
  958.          fprintf(hTrap,"Invalid EBP: %8.8p\n",Ebp);
  959.          break;
  960.       }
  961.  
  962.       if (fExceptionAddress)
  963.          RetAddr = ExceptionAddress;
  964.       else
  965.          RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
  966.  
  967.       if (RetAddr == (PUSHORT)0x00000053)
  968.       {
  969.          // For some reason there's a "return address" of 0x53 following
  970.          // EBP on the stack and we have to adjust EBP by 44 bytes to get
  971.          // at the real return address.  This has something to do with
  972.          // thunking from 32bits to 16bits...
  973.          // Serious kludge, and it's probably dependent on versions of C(++)
  974.          // runtime or OS, but it works for now!
  975.          Ebp += 22;
  976.          RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
  977.       }
  978.  
  979.       // Get the (possibly) 16bit CS and IP
  980.       if (fExceptionAddress)
  981.       {
  982.          Cs = (USHORT)(((ULONG)ExceptionAddress) >> 16);
  983.          Ip = (USHORT)(ULONG)ExceptionAddress;
  984.       }
  985.       else
  986.       {
  987.          Cs = *(Ebp+2);
  988.          Ip = *(Ebp+1);
  989.       }
  990.  
  991.       // if the return address points to the stack then it's really just
  992.       // a pointer to the return address (UGH!).
  993.       if ((USHORT)(((ULONG)RetAddr) >> 16) == Sp)
  994.          RetAddr = (PUSHORT)(*((PULONG)RetAddr));
  995.  
  996.       if (Ip == 0 && *Ebp == 0)
  997.       {
  998.          // End of the stack so these are both shifted by 2 bytes:
  999.          Cs = *(Ebp+3);
  1000.          Ip = *(Ebp+2);
  1001.       }
  1002.  
  1003.       // 16bit programs have on the stack:
  1004.       //   BP:IP:CS
  1005.       //   where CS may be thunked
  1006.       //
  1007.       //         in dump                 swapped
  1008.       //    BP        IP   CS          BP   CS   IP
  1009.       //   4677      53B5 F7D0        7746 D0F7 B553
  1010.       //
  1011.       // 32bit programs have:
  1012.       //   EBP:EIP
  1013.       // and you'd have something like this (with SP added) (not
  1014.       // accurate values)
  1015.       //
  1016.       //         in dump               swapped
  1017.       //      EBP       EIP         EBP       EIP
  1018.       //   4677 2900 53B5 F7D0   0029 7746 D0F7 B553
  1019.       //
  1020.       // So the basic difference is that 32bit programs have a 32bit
  1021.       // EBP and we can attempt to determine whether we have a 32bit
  1022.       // EBP by checking to see if its 'selector' is the same as SP.
  1023.       // Note that this technique limits us to checking stacks < 64K.
  1024.       //
  1025.       // Soooo, if IP (which maps into the same USHORT as the swapped
  1026.       // stack page in EBP) doesn't point to the stack (i.e. it could
  1027.       // be a 16bit IP) then see if CS is valid (as is or thunked).
  1028.       //
  1029.       // Note that there's the possibility of a 16bit return address
  1030.       // that has an offset that's the same as SP so we'll think it's
  1031.       // a 32bit return address and won't be able to successfully resolve
  1032.       // its details.
  1033.       if (Ip != Sp)
  1034.       {
  1035.          if (DOS16SIZESEG(Cs, &Size) == NO_ERROR)
  1036.          {
  1037.             RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
  1038.             f32bit = FALSE;
  1039.          }
  1040.          else if (DOS16SIZESEG((Cs << 3) + 7, &Size) == NO_ERROR)
  1041.          {
  1042.             Cs = (Cs << 3) + 7;
  1043.             RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
  1044.             f32bit = FALSE;
  1045.          }
  1046.          else
  1047.             f32bit = TRUE;
  1048.       }
  1049.       else
  1050.          f32bit = TRUE;
  1051.  
  1052.  
  1053.       if (fExceptionAddress)
  1054.          fprintf(hTrap," Trap  ->");
  1055.       else
  1056.          fprintf(hTrap," %8.8p", Ebp);
  1057.  
  1058.       if (f32bit)
  1059.          fprintf(hTrap,"  :%8.8p", RetAddr);
  1060.       else
  1061.          fprintf(hTrap,"  %04.04X:%04.04X", Cs, Ip);
  1062.  
  1063.       if (Version[0] >= 20 && Version[1] >= 10)
  1064.       {
  1065.          // Make a 'tick' sound to let the user know we're still alive
  1066.          DosBeep(2000, 1);
  1067.  
  1068.          rc = DosQueryMem((PVOID)RetAddr, &Size, &Attr);
  1069.          if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
  1070.          {
  1071.             fprintf(hTrap,"Invalid RetAddr: %8.8p\n",RetAddr);
  1072.             break; /* avoid infinite loops */
  1073.          } else {
  1074.             rc = DOSQUERYMODFROMEIP(&hMod, &ObjNum, sizeof(Name),
  1075.                                     Name, &Offset, (PVOID)RetAddr);
  1076.             if (rc == NO_ERROR && ObjNum != -1)
  1077.             {
  1078.                static char szJunk[_MAX_FNAME];
  1079.                static char szName[_MAX_FNAME];
  1080.                DosQueryModuleName(hMod, sizeof(Name), Name);
  1081.                _splitpath(Name, szJunk, szJunk, szName, szJunk);
  1082.                fprintf(hTrap,"  %-8s %04X", szName, ObjNum+1);
  1083.  
  1084.                if (strlen(Name) > 3)
  1085.                {
  1086.                   rc = GetLineNum(Name, ObjNum, Offset);
  1087.                   /* if no codeview try with symbol files */
  1088.                   if (rc != NO_ERROR)
  1089.                   {
  1090.                      strcpy(Name+strlen(Name)-3,"SYM");
  1091.                      GetSymbol(Name,ObjNum,Offset);
  1092.                   }
  1093.                }
  1094.             }
  1095.             else
  1096.             {
  1097.                fprintf(hTrap,"  *Unknown*");
  1098.             }
  1099.          }
  1100.       }
  1101.  
  1102.       fprintf(hTrap,"\n");
  1103.  
  1104.       Bp = *Ebp;
  1105.       if (Bp == 0 && (*Ebp+1) == 0)
  1106.       {
  1107.          fprintf(hTrap,"End of Call Stack\n");
  1108.          break;
  1109.       }
  1110.  
  1111.       if (!fExceptionAddress)
  1112.       {
  1113.          LastEbp = Ebp;
  1114.          Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
  1115.          if (f32bit) {
  1116.              print_vars((ULONG)Ebp);
  1117.          } /* endif */
  1118.  
  1119.          if (Ebp < LastEbp)
  1120.          {
  1121.             fprintf(hTrap,"Lost Stack chain - new EBP below previous\n");
  1122.             break;
  1123.          }
  1124.       }
  1125.       else
  1126.          fExceptionAddress = FALSE;
  1127.  
  1128.       Size = 4;
  1129.       rc = DosQueryMem((PVOID)Ebp, &Size, &Attr);
  1130.       if (rc != NO_ERROR)
  1131.       {
  1132.          fprintf(hTrap,"Lost Stack chain - invalid EBP: %8.8p\n", Ebp);
  1133.          break;
  1134.       }
  1135.    } while (TRUE);
  1136.  
  1137.    fprintf(hTrap,"\n");
  1138. }
  1139.  
  1140. void GetSymbol(CHAR * SymFileName, ULONG Object,ULONG TrapOffset)
  1141. {
  1142.    static FILE * SymFile;
  1143.    static MAPDEF MapDef;
  1144.    static SEGDEF   SegDef;
  1145.    static SEGDEF *pSegDef;
  1146.    static SYMDEF32 SymDef32;
  1147.    static SYMDEF16 SymDef16;
  1148.    static char    Buffer[256];
  1149.    static int     SegNum,SymNum,LastVal;
  1150.    static unsigned short int SegOffset,SymOffset,SymPtrOffset;
  1151.    SymFile=fopen(SymFileName,"rb");
  1152.    if (SymFile==0) {
  1153.        /*fprintf(hTrap,"Could not open symbol file %s\n",SymFileName);*/
  1154.        return;
  1155.    } /* endif */
  1156.    fread(&MapDef,sizeof(MAPDEF),1,SymFile);
  1157.    SegOffset= SEGDEFOFFSET(MapDef);
  1158.    for (SegNum=0;SegNum<MapDef.cSegs;SegNum++) {
  1159.         /* printf("Scanning segment #%d Offset %4.4hX\n",SegNum+1,SegOffset); */
  1160.         if (fseek(SymFile,SegOffset,SEEK_SET)) {
  1161.            fprintf(hTrap,"Seek error ");
  1162.            return;
  1163.         }
  1164.         fread(&SegDef,sizeof(SEGDEF),1,SymFile);
  1165.         if (SegNum==Object) {
  1166.            Buffer[0]=0x00;
  1167.            LastVal=0;
  1168.            for (SymNum=0;SymNum<SegDef.cSymbols;SymNum++) {
  1169.               SymPtrOffset=SYMDEFOFFSET(SegOffset,SegDef,SymNum);
  1170.               fseek(SymFile,SymPtrOffset,SEEK_SET);
  1171.               fread(&SymOffset,sizeof(unsigned short int),1,SymFile);
  1172.               fseek(SymFile,SymOffset+SegOffset,SEEK_SET);
  1173.               if (SegDef.bFlags&0x01) {
  1174.                  fread(&SymDef32,sizeof(SYMDEF32),1,SymFile);
  1175.                  if (SymDef32.wSymVal>TrapOffset) {
  1176.                     fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
  1177.                  }
  1178.                  LastVal=SymDef32.wSymVal;
  1179.                  Buffer[0]= SymDef32.achSymName[0];
  1180.                  fread(&Buffer[1],1,SymDef32.cbSymName,SymFile);
  1181.                  Buffer[SymDef32.cbSymName]=0x00;
  1182.                  if (SymDef32.wSymVal>TrapOffset) {
  1183.                     fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
  1184.                     break;
  1185.                  }
  1186.                  /*printf("32 Bit Symbol <%s> Address %p\n",Buffer,SymDef32.wSymVal);*/
  1187.               } else {
  1188.                  fread(&SymDef16,sizeof(SYMDEF16),1,SymFile);
  1189.                  if (SymDef16.wSymVal>TrapOffset) {
  1190.                     fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
  1191.                  }
  1192.                  LastVal=SymDef16.wSymVal;
  1193.                  Buffer[0]=SymDef16.achSymName[0];
  1194.                  fread(&Buffer[1],1,SymDef16.cbSymName,SymFile);
  1195.                  Buffer[SymDef16.cbSymName]=0x00;
  1196.                  if (SymDef16.wSymVal>TrapOffset) {
  1197.                     fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
  1198.                     break;
  1199.                  }
  1200.                  /*printf("16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal);*/
  1201.               } /* endif */
  1202.            }
  1203.            break;
  1204.         } /* endif */
  1205.         SegOffset=NEXTSEGDEFOFFSET(SegDef);
  1206.    } /* endwhile */
  1207.    fclose(SymFile);
  1208. }
  1209. VOID WakeThreads(VOID);
  1210. void APIENTRY ForceExit() {
  1211.     EXCEPTIONREPORTRECORD except;
  1212.     PCHAR  Trap;
  1213.     InForceExit =TRUE;
  1214.     fclose(stderr); /* I don't want error messages since all is intentional */
  1215.     DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
  1216.     DosEnterCritSec();
  1217.     WakeThreads();
  1218.     printf("Exiting by exception\n");
  1219.     Trap=NULL;
  1220.     DosSetPriority(PRTYS_THREAD,PRTYC_FOREGROUNDSERVER,PRTYD_MAXIMUM,0);
  1221.     DosExitCritSec();
  1222.     *Trap=0x00;
  1223. }
  1224. VOID WakeThreads() {
  1225.   APIRET   rc;
  1226.   APIRET16 rc16;
  1227.   qsPrec_t   * pProc;
  1228.   qsTrec_t   * pThread;
  1229.   ULONG      ListedThreads=0;
  1230.   PTIB   ptib;
  1231.   PPIB   ppib;
  1232.   DosGetInfoBlocks(&ptib,&ppib);
  1233.   /**----------------------------------***/
  1234.   rc16=DOS16ALLOCSEG( 0xFFFF , &Selector , 0);
  1235.   if (rc16==0) {
  1236.      pBuf=MAKEP(Selector,0);
  1237.      rc16=DOSQPROCSTATUS(pBuf, 0xFFFF );
  1238.      if (rc16==0) {
  1239.         /*****************************/
  1240.         pRec=(qsPtrRec_t *) pBuf;
  1241.         pProc =(qsPrec_t *)(pRec->pProcRec);
  1242.         ListedThreads=0;
  1243.         while (ListedThreads<pRec->pGlobalRec->cThrds) {
  1244.            int Tid;
  1245.            if (pProc->pThrdRec==NULL) break;
  1246.            ListedThreads+= pProc->cTCB;
  1247.            if (ppib->pib_ulpid==pProc->pid) {
  1248.               for (Tid=0;Tid<pProc->cTCB;Tid++ ) {
  1249.                  pThread =pProc->pThrdRec+Tid;
  1250.                  if (pThread->state==0x09) {
  1251.                     printf("Resuming Thread %d\n",(TID)pThread->tid);
  1252.                     DosResumeThread((TID)pThread->tid);
  1253.                  }
  1254.               } /* endfor */
  1255.               break;
  1256.            } /* endif  */
  1257.            pProc =(qsPrec_t *)( ((PUCHAR)pProc)
  1258.                                  +sizeof(qsPrec_t)
  1259.                                  +sizeof(USHORT)*(pProc->c16Sem+
  1260.                                                   pProc->cLib+
  1261.                                                   pProc->cShrMem)
  1262.                                  +(pProc->cTCB)*sizeof(qsTrec_t));
  1263.  
  1264.         } /* endwhile */
  1265.      } else {
  1266.         printf("DosQProcStatus Failed %hd\n",rc16);
  1267.      } /* endif */
  1268.   } else {
  1269.      printf("DosAllocSeg Failed %hd\n",rc16);
  1270.   } /* endif */
  1271. }
  1272. #include <exe.h>
  1273. #include <newexe.h>
  1274. #define  FOR_EXEHDR  1  /* avoid define conflicts between newexe.h and exe386.h */
  1275. #ifndef DWORD
  1276. #define DWORD long int
  1277. #endif
  1278. #ifndef WORD
  1279. #define WORD  short int
  1280. #endif
  1281. #include <exe386.h>
  1282. #include <fcntl.h>
  1283. #include <sys\stat.h>
  1284. #include <share.h>
  1285. #include <io.h>
  1286. /* ------------------------------------------------------------------ */
  1287. /* Last 8 bytes of 16:16 file when CODEVIEW debugging info is present */
  1288. #pragma pack(1)
  1289.  struct  _eodbug
  1290.         {
  1291.         unsigned short dbug;          /* 'NB' signature */
  1292.         unsigned short ver;           /* version        */
  1293.         unsigned long dfaBase;        /* size of codeview info */
  1294.         } eodbug;
  1295.  
  1296. #define         DBUGSIG         0x424E
  1297. #define         SSTMODULES      0x0101
  1298. #define         SSTPUBLICS      0x0102
  1299. #define         SSTTYPES        0x0103
  1300. #define         SSTSYMBOLS      0x0104
  1301. #define         SSTSRCLINES     0x0105
  1302. #define         SSTLIBRARIES    0x0106
  1303. #define         SSTSRCLINES2    0x0109
  1304. #define         SSTSRCLINES32   0x010B
  1305.  
  1306.  struct  _base
  1307.         {
  1308.         unsigned short dbug;          /* 'NB' signature */
  1309.         unsigned short ver;           /* version        */
  1310.         unsigned long lfoDir;   /* file offset to dir entries */
  1311.         } base;
  1312.  
  1313.  struct  ssDir
  1314.         {
  1315.         unsigned short sst;           /* SubSection Type */
  1316.         unsigned short modindex;      /* Module index number */
  1317.         unsigned long lfoStart;       /* Start of section */
  1318.         unsigned short cb;            /* Size of section */
  1319.         } ;
  1320.  
  1321.  struct  ssDir32
  1322.         {
  1323.         unsigned short sst;           /* SubSection Type */
  1324.         unsigned short modindex;      /* Module index number */
  1325.         unsigned long lfoStart;       /* Start of section */
  1326.         unsigned long  cb;            /* Size of section */
  1327.         } ;
  1328.  
  1329.  struct  ssModule
  1330.    {
  1331.    unsigned short          csBase;             /* code segment base */
  1332.    unsigned short          csOff;              /* code segment offset */
  1333.    unsigned short          csLen;              /* code segment length */
  1334.    unsigned short          ovrNum;             /* overlay number */
  1335.    unsigned short          indxSS;             /* Index into sstLib or 0 */
  1336.    unsigned short          reserved;
  1337.    char              csize;              /* size of prefix string */
  1338.    } ssmod;
  1339.  
  1340.  struct  ssModule32
  1341.    {
  1342.    unsigned short          csBase;             /* code segment base */
  1343.    unsigned long           csOff;              /* code segment offset */
  1344.    unsigned long           csLen;              /* code segment length */
  1345.    unsigned long           ovrNum;             /* overlay number */
  1346.    unsigned short          indxSS;             /* Index into sstLib or 0 */
  1347.    unsigned long           reserved;
  1348.    char                    csize;              /* size of prefix string */
  1349.    } ssmod32;
  1350.  
  1351.  struct  ssPublic
  1352.         {
  1353.         unsigned short  offset;
  1354.         unsigned short  segment;
  1355.         unsigned short  type;
  1356.         char      csize;
  1357.         } sspub;
  1358.  
  1359.  struct  ssPublic32
  1360.         {
  1361.         unsigned long   offset;
  1362.         unsigned short  segment;
  1363.         unsigned short  type;
  1364.         char      csize;
  1365.         } sspub32;
  1366.  
  1367. typedef  struct _SSLINEENTRY32 {
  1368.    unsigned short LineNum;
  1369.    unsigned short FileNum;
  1370.    unsigned long  Offset;
  1371. } SSLINEENTRY32;
  1372. typedef  struct _FIRSTLINEENTRY32 {
  1373.    unsigned short LineNum;
  1374.    unsigned short FileNum;
  1375.    unsigned short numlines;
  1376.    unsigned short segnum;
  1377. } FIRSTLINEENTRY32;
  1378.  
  1379. typedef  struct _SSFILENUM32 {
  1380.     unsigned long first_displayable;  /* Not used */
  1381.     unsigned long number_displayable; /* Not used */
  1382.     unsigned long file_count;         /* number of source files */
  1383. } SSFILENUM32;
  1384.  
  1385.  struct  DbugRec {                       /* debug info struct ure used in linked * list */
  1386.     struct  DbugRec far *pnext;          /* next node *//* 013 */
  1387.    char far          *SourceFile;               /* source file name *013 */
  1388.    unsigned short          TypeOfProgram;       /* dll or exe *014* */
  1389.    unsigned short          LineNumber;          /* line number in source file */
  1390.    unsigned short          OffSet;              /* offset into loaded module */
  1391.    unsigned short          Selector;            /* code segment 014 */
  1392.    unsigned short          OpCode;              /* Opcode replaced with BreakPt */
  1393.    unsigned long     Count;                     /* count over Break Point */
  1394. };
  1395.  
  1396. typedef  struct  DbugRec DBUG, far * DBUGPTR;     /* 013 */
  1397. char szNrPub[128];
  1398. char szNrLine[128];
  1399. char szNrFile[128];
  1400.  struct  new_seg *pseg;
  1401.  struct  o32_obj *pobj;        /* Flat .EXE object table entry */
  1402.  struct  ssDir *pDirTab;
  1403.  struct  ssDir32 *pDirTab32;
  1404. unsigned char *pEntTab;
  1405. unsigned long lfaBase;
  1406. #pragma pack()
  1407. /* ------------------------------------------------------------------ */
  1408.  
  1409. APIRET GetLineNum(CHAR * FileName, ULONG Object,ULONG TrapOffset) {
  1410.    APIRET rc;
  1411.    int ModuleFile;
  1412.    static  struct  exe_hdr old;
  1413.    static  struct  new_exe new;
  1414.    static  struct  e32_exe e32;
  1415.    strcpy(szNrPub,"   N/A ");
  1416.    strcpy(szNrLine,"   N/A  ");
  1417.    strcpy(szNrFile,"             ");
  1418.    ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
  1419.    if (ModuleFile!=-1) {
  1420.       /* Read old Exe header */
  1421.       if (read( ModuleFile ,(void *)&old,64)==-1L) {
  1422.         fprintf(hTrap,"Could Not Read old exe header %d\n",errno);
  1423.         close(ModuleFile);
  1424.         return 2;
  1425.       }
  1426.       /* Seek to new Exe header */
  1427.       if (lseek(ModuleFile,(long)E_LFANEW(old),SEEK_SET)==-1L) {
  1428.         fprintf(hTrap,"Could Not seek to new exe header %d\n",errno);
  1429.         close(ModuleFile);
  1430.         return 3;
  1431.       }
  1432.       if (read( ModuleFile ,(void *)&new,64)==-1L) {
  1433.         fprintf(hTrap,"Could Not read new exe header %d\n",errno);
  1434.         close(ModuleFile);
  1435.         return 4;
  1436.       }
  1437.       /* Check EXE signature */
  1438.       if (NE_MAGIC(new)==E32MAGIC) {
  1439.          /* Flat 32 executable */
  1440.          rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
  1441.          if (rc==0) {
  1442.              fprintf(hTrap,"%s",szNrFile);
  1443.              fprintf(hTrap,"%s",szNrLine);
  1444.              fprintf(hTrap,"%s",szNrPub);
  1445.          } /* endif */
  1446.          close(ModuleFile);
  1447.          /* rc !=0 try with DBG file */
  1448.          if (rc!=0) {
  1449.             strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
  1450.             ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
  1451.             if (ModuleFile!=-1) {
  1452.                rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
  1453.                if (rc==0) {
  1454.                   fprintf(hTrap,"%s",szNrFile);
  1455.                   fprintf(hTrap,"%s",szNrLine);
  1456.                   fprintf(hTrap,"%s",szNrPub);
  1457.                } /* endif */
  1458.                close(ModuleFile);
  1459.             }
  1460.          } /* endif */
  1461.          return rc;
  1462.       } else {
  1463.          if (NE_MAGIC(new)==NEMAGIC) {
  1464.             /* 16:16 executable */
  1465.             if ((pseg = ( struct  new_seg *) calloc(NE_CSEG(new),sizeof( struct  new_seg)))==NULL) {
  1466.                fprintf(hTrap,"Out of memory!");
  1467.                close(ModuleFile);
  1468.                return -1;
  1469.             }
  1470.             if (lseek(ModuleFile,E_LFANEW(old)+NE_SEGTAB(new),SEEK_SET)==-1L) {
  1471.                fprintf(hTrap,"Error %u seeking segment table in %s\n",errno,FileName);
  1472.                free(pseg);
  1473.                close(ModuleFile);
  1474.                return 9;
  1475.             }
  1476.  
  1477.             if (read(ModuleFile,(void *)pseg,NE_CSEG(new)*sizeof( struct  new_seg))==-1) {
  1478.                fprintf(hTrap,"Error %u reading segment table from %s\n",errno,FileName);
  1479.                free(pseg);
  1480.                close(ModuleFile);
  1481.                return 10;
  1482.             }
  1483.             rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
  1484.             if (rc==0) {
  1485.                fprintf(hTrap,"%s",szNrFile);
  1486.                fprintf(hTrap,"%s",szNrLine);
  1487.                fprintf(hTrap,"%s",szNrPub);
  1488.             } /* endif */
  1489.             free(pseg);
  1490.             close(ModuleFile);
  1491.             /* rc !=0 try with DBG file */
  1492.             if (rc!=0) {
  1493.                strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
  1494.                ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
  1495.                if (ModuleFile!=-1) {
  1496.                   rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
  1497.                   if (rc==0) {
  1498.                      fprintf(hTrap,"%s",szNrFile);
  1499.                      fprintf(hTrap,"%s",szNrLine);
  1500.                      fprintf(hTrap,"%s",szNrPub);
  1501.                   } /* endif */
  1502.                   close(ModuleFile);
  1503.                }
  1504.             } /* endif */
  1505.             return rc;
  1506.  
  1507.          } else {
  1508.             /* Unknown executable */
  1509.             fprintf(hTrap,"Could Not find exe signature");
  1510.             close(ModuleFile);
  1511.             return 11;
  1512.          }
  1513.       }
  1514.       /* Read new Exe header */
  1515.    } else {
  1516.       fprintf(hTrap,"Could Not open Module File %d",errno);
  1517.       return 1;
  1518.    } /* endif */
  1519.    return 0;
  1520. }
  1521. char fname[128],ModName[80];
  1522. char ename[128],dummy[128];
  1523. int Read16CodeView(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
  1524.     static unsigned short int offset,NrPublic,NrLine,NrEntry,numdir,namelen,numlines,line;
  1525.     static int ModIndex;
  1526.     static int bytesread,i,j;
  1527.     ModIndex=0;
  1528.     /* See if any CODEVIEW info */
  1529.     if (lseek(fh,-8L,SEEK_END)==-1) {
  1530.         fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
  1531.         return(18);
  1532.     }
  1533.  
  1534.     if (read(fh,(void *)&eodbug,8)==-1) {
  1535.        fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
  1536.        return(19);
  1537.     }
  1538.     if (eodbug.dbug!=DBUGSIG) {
  1539.        /* fprintf(hTrap,"\nNo CodeView information stored.\n"); */
  1540.        return(100);
  1541.     }
  1542.  
  1543.     if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
  1544.        fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
  1545.        return(20);
  1546.     }
  1547.  
  1548.     if (read(fh,(void *)&base,8)==-1) {
  1549.        fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
  1550.        return(21);
  1551.     }
  1552.  
  1553.     if (lseek(fh,base.lfoDir-8,SEEK_CUR)==-1) {
  1554.        fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
  1555.        return(22);
  1556.     }
  1557.  
  1558.     if (read(fh,(void *)&numdir,2)==-1) {
  1559.        fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
  1560.        return(23);
  1561.     }
  1562.  
  1563.     /* Read dir table into buffer */
  1564.     if (( pDirTab = ( struct  ssDir *) calloc(numdir,sizeof( struct  ssDir)))==NULL) {
  1565.        fprintf(hTrap,"Out of memory!");
  1566.        return(-1);
  1567.     }
  1568.  
  1569.     if (read(fh,(void *)pDirTab,numdir*sizeof( struct  ssDir))==-1) {
  1570.        fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
  1571.        free(pDirTab);
  1572.        return(24);
  1573.     }
  1574.  
  1575.     i=0;
  1576.     while (i<numdir) {
  1577.        if (pDirTab[i].sst!=SSTMODULES) {
  1578.            i++;
  1579.            continue;
  1580.        }
  1581.        NrPublic=0x0;
  1582.        NrLine=0x0;
  1583.        /* point to subsection */
  1584.        lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
  1585.        read(fh,(void *)&ssmod.csBase,sizeof(ssmod));
  1586.        read(fh,(void *)ModName,(unsigned)ssmod.csize);
  1587.        ModIndex=pDirTab[i].modindex;
  1588.        ModName[ssmod.csize]='\0';
  1589.        i++;
  1590.        while (pDirTab[i].modindex ==ModIndex && i<numdir) {
  1591.           /* point to subsection */
  1592.           lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
  1593.           switch(pDirTab[i].sst) {
  1594.             case SSTPUBLICS:
  1595.                bytesread=0;
  1596.                while (bytesread < pDirTab[i].cb) {
  1597.                    bytesread += read(fh,(void *)&sspub.offset,sizeof(sspub));
  1598.                    bytesread += read(fh,(void *)ename,(unsigned)sspub.csize);
  1599.                    ename[sspub.csize]='\0';
  1600.                    if ((sspub.segment==TrapSeg) &&
  1601.                        (sspub.offset<=TrapOff) &&
  1602.                        (sspub.offset>=NrPublic)) {
  1603.                        NrPublic=sspub.offset;
  1604.                        sprintf(szNrPub,"%s %s (%s) %04hX:%04hX\n",
  1605.                                (sspub.type==1) ? " Abs" : " ",ename,ModName,
  1606.                                sspub.segment, sspub.offset
  1607.                                );
  1608.                    }
  1609.                }
  1610.                break;
  1611.  
  1612.             case SSTSRCLINES2:
  1613.             case SSTSRCLINES:
  1614.                if (TrapSeg!=ssmod.csBase) break;
  1615.                namelen=0;
  1616.                read(fh,(void *)&namelen,1);
  1617.                read(fh,(void *)ename,namelen);
  1618.                ename[namelen]='\0';
  1619.                /* skip 2 zero bytes */
  1620.                if (pDirTab[i].sst==SSTSRCLINES2) read(fh,(void *)&numlines,2);
  1621.                read(fh,(void *)&numlines,2);
  1622.                for (j=0;j<numlines;j++) {
  1623.                   read(fh,(void *)&line,2);
  1624.                   read(fh,(void *)&offset,2);
  1625.                   if (offset<=TrapOff && offset>=NrLine) {
  1626.                      NrLine=offset;
  1627.                      sprintf(szNrLine,"% 6hu", line);
  1628.                      sprintf(szNrFile,"%  13.13s ", ename);
  1629.                      /*sprintf(szNrLine,"%04hX:%04hX  line #%hu  (%s) (%s)\n",
  1630.                              ssmod.csBase,offset,line,ModName,ename); */
  1631.                   }
  1632.                }
  1633.                break;
  1634.           } /* end switch */
  1635.           i++;
  1636.        } /* end while modindex */
  1637.     } /* End While i < numdir */
  1638.     free(pDirTab);
  1639.     return(0);
  1640. }
  1641.  
  1642. #define MAX_USERDEFS 150
  1643. #define MAX_POINTERS 150
  1644.  
  1645. USHORT userdef_count;
  1646. USHORT pointer_count;
  1647.  
  1648. struct one_userdef_rec {
  1649.    USHORT idx;
  1650.    USHORT type_index;
  1651.    BYTE   name[33];
  1652. } one_userdef[MAX_USERDEFS];
  1653.  
  1654. struct one_pointer_rec {
  1655.    USHORT idx;
  1656.    USHORT type_index;
  1657.    BYTE   type_qual;
  1658.    BYTE   name[33];
  1659. } one_pointer[MAX_POINTERS];
  1660.  
  1661. int Read32PmDebug(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
  1662.     static unsigned int CurrSymSeg, NrSymbol,offset,NrPublic,NrFile,NrLine,NrEntry,numdir,namelen,numlines,line;
  1663.     static int ModIndex;
  1664.     static int bytesread,i,j;
  1665.     static int pOffset;
  1666.     static SSLINEENTRY32 LineEntry;
  1667.     static SSFILENUM32 FileInfo;
  1668.     static FIRSTLINEENTRY32 FirstLine;
  1669.     static BYTE dump_vars = FALSE;
  1670.     static USHORT idx;
  1671.  
  1672.     ModIndex=0;
  1673.     /* See if any CODEVIEW info */
  1674.     if (lseek(fh,-8L,SEEK_END)==-1) {
  1675.         fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
  1676.         return(18);
  1677.     }
  1678.  
  1679.     if (read(fh,(void *)&eodbug,8)==-1) {
  1680.        fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
  1681.        return(19);
  1682.     }
  1683.     if (eodbug.dbug!=DBUGSIG) {
  1684.        /*fprintf(hTrap,"\nNo CodeView information stored.\n");*/
  1685.        return(100);
  1686.     }
  1687.  
  1688.     if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
  1689.        fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
  1690.        return(20);
  1691.     }
  1692.  
  1693.     if (read(fh,(void *)&base,8)==-1) {
  1694.        fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
  1695.        return(21);
  1696.     }
  1697.  
  1698.     if (lseek(fh,base.lfoDir-8+4,SEEK_CUR)==-1) {
  1699.        fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
  1700.        return(22);
  1701.     }
  1702.  
  1703.     if (read(fh,(void *)&numdir,4)==-1) {
  1704.        fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
  1705.        return(23);
  1706.     }
  1707.  
  1708.     /* Read dir table into buffer */
  1709.     if (( pDirTab32 = ( struct  ssDir32 *) calloc(numdir,sizeof( struct  ssDir32)))==NULL) {
  1710.        fprintf(hTrap,"Out of memory!");
  1711.        return(-1);
  1712.     }
  1713.  
  1714.     if (read(fh,(void *)pDirTab32,numdir*sizeof( struct  ssDir32))==-1) {
  1715.        fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
  1716.        free(pDirTab32);
  1717.        return(24);
  1718.     }
  1719.  
  1720.     i=0;
  1721.     while (i<numdir) {
  1722.        if ( pDirTab32[i].sst !=SSTMODULES) {
  1723.            i++;
  1724.            continue;
  1725.        }
  1726.        NrPublic=0x0;
  1727.        NrSymbol=0;
  1728.        NrLine=0x0;
  1729.        NrFile=0x0;
  1730.        CurrSymSeg = 0;
  1731.        /* point to subsection */
  1732.        lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
  1733.        read(fh,(void *)&ssmod32.csBase,sizeof(ssmod32));
  1734.        read(fh,(void *)ModName,(unsigned)ssmod32.csize);
  1735.        ModIndex=pDirTab32[i].modindex;
  1736.        ModName[ssmod32.csize]='\0';
  1737.        i++;
  1738.        while (pDirTab32[i].modindex ==ModIndex && i<numdir) {
  1739.           /* point to subsection */
  1740.           lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
  1741.           switch(pDirTab32[i].sst) {
  1742.             case SSTPUBLICS:
  1743.                bytesread=0;
  1744.                while (bytesread < pDirTab32[i].cb) {
  1745.                    bytesread += read(fh,(void *)&sspub32.offset,sizeof(sspub32));
  1746.                    bytesread += read(fh,(void *)ename,(unsigned)sspub32.csize);
  1747.                    ename[sspub32.csize]='\0';
  1748.                    if ((sspub32.segment==TrapSeg) &&
  1749.                        (sspub32.offset<=TrapOff) &&
  1750.                        (sspub32.offset>=NrPublic)) {
  1751.                        NrPublic = pubfunc_ofs = sspub32.offset;
  1752.                        sprintf(szNrPub,"%s %s (%s) %04X:%08X\n",
  1753.                                (sspub32.type==1) ? " Abs" : " ",ename,ModName,
  1754.                                sspub32.segment, sspub32.offset
  1755.                                );
  1756.                    }
  1757.                }
  1758.                break;
  1759.  
  1760.             /* Read symbols, so we can dump the variables on the stack */
  1761.             case SSTSYMBOLS:
  1762.                bytesread=0;
  1763.                while (bytesread < pDirTab32[i].cb) {
  1764.                   static USHORT usLength;
  1765.                   static BYTE b1, b2;
  1766.                   static BYTE bType, *ptr;
  1767.                   static ULONG ofs;
  1768.                   static ULONG last_addr = 0;
  1769.                   static BYTE str[256];
  1770.                   static struct symseg_rec       symseg;
  1771.                   static struct symauto_rec      symauto;
  1772.                   static struct symproc_rec      symproc;
  1773.  
  1774.                   /* Read the length of this subentry */
  1775.                   bytesread += read(fh, &b1, 1);
  1776.                   if (b1 & 0x80) {
  1777.                      bytesread += read(fh, &b2, 1);
  1778.                      usLength = ((b1 & 0x7F) << 8) + b2;
  1779.                   }
  1780.                   else
  1781.                      usLength = b1;
  1782.  
  1783.                   ofs = tell(fh);
  1784.  
  1785.                   bytesread += read(fh, &bType, 1);
  1786.  
  1787.                   switch(bType) {
  1788.                      case SYM_CHANGESEG:
  1789.                         read(fh, &symseg, sizeof(symseg));
  1790.                         CurrSymSeg = symseg.seg_no;
  1791.                         break;
  1792.  
  1793.                      case SYM_PROC:
  1794.                         read(fh, &symproc, sizeof(symproc));
  1795.                         read(fh, str, symproc.name_len);
  1796.                            str[symproc.name_len] = 0;
  1797.  
  1798.                         if ((CurrSymSeg == TrapSeg) &&
  1799.                             (symproc.offset<=TrapOff) &&
  1800.                             (symproc.offset>=NrSymbol)) {
  1801.  
  1802.                            dump_vars = TRUE;
  1803.                            var_ofs = 0;
  1804.                            NrSymbol = symproc.offset;
  1805.                            func_ofs = symproc.offset;
  1806.  
  1807.                            strcpy(func_name, str);
  1808.                         }
  1809.                         else {
  1810.                            dump_vars = FALSE;
  1811.                         }
  1812.                         break;
  1813.  
  1814.                      case SYM_AUTO:
  1815.                         if (!dump_vars)
  1816.                            break;
  1817.  
  1818.                         read(fh, &symauto, sizeof(symauto));
  1819.                         read(fh, str, symauto.name_len);
  1820.                         str[symauto.name_len] = 0;
  1821.  
  1822.                         strcpy(autovar_def[var_ofs].name, str);
  1823.                         autovar_def[var_ofs].stack_offset = symauto.stack_offset;
  1824.                         autovar_def[var_ofs].type_idx = symauto.type_idx;
  1825.                         var_ofs++;
  1826.                         break;
  1827.  
  1828.                   }
  1829.  
  1830.                   bytesread += usLength;
  1831.  
  1832.                   lseek(fh, ofs+usLength, SEEK_SET);
  1833.                }
  1834.                break;
  1835.  
  1836.             case SSTTYPES:
  1837.                bytesread=0;
  1838.                idx = 0x200;
  1839.                userdef_count = 0;
  1840.                pointer_count = 0;
  1841.                while (bytesread < pDirTab32[i].cb) {
  1842.                   static struct type_rec         type;
  1843.                   static struct type_userdefrec  udef;
  1844.                   static struct type_pointerrec  point;
  1845.                   static struct type_funcrec     func;
  1846.                   static struct type_structrec   struc;
  1847.                   static struct type_list1       list1;
  1848.                   static struct type_list2       list2;
  1849.                   static struct type_list2_1     list2_1;
  1850.                   static ULONG  ofs;
  1851.                   static BYTE   str[256], b1, b2;
  1852.                   static USHORT n;
  1853.  
  1854.                   /* Read the length of this subentry */
  1855.                   ofs = tell(fh);
  1856.  
  1857.                   read(fh, &type, sizeof(type));
  1858.                   bytesread += sizeof(type);
  1859.  
  1860.                   switch(type.type) {
  1861.                      case TYPE_USERDEF:
  1862.                         if (userdef_count > MAX_USERDEFS)
  1863.                            break;
  1864.  
  1865.                         read(fh, &udef, sizeof(udef));
  1866.                         read(fh, str, udef.name_len);
  1867.                         str[udef.name_len] = 0;
  1868.  
  1869.                         // Insert userdef in table
  1870.                         one_userdef[userdef_count].idx = idx;
  1871.                         one_userdef[userdef_count].type_index = udef.type_index;
  1872.                         memcpy(one_userdef[userdef_count].name, str, min(udef.name_len+1, 32));
  1873.                         one_userdef[userdef_count].name[32] = 0;
  1874.                         userdef_count++;
  1875.                         break;
  1876.  
  1877.                      case TYPE_POINTER:
  1878.                         if (pointer_count > MAX_POINTERS)
  1879.                            break;
  1880.  
  1881.                         read(fh, &point, sizeof(point));
  1882.                         read(fh, str, point.name_len);
  1883.                         str[point.name_len] = 0;
  1884.  
  1885.                         // Insert userdef in table
  1886.                         one_pointer[pointer_count].idx = idx;
  1887.                         one_pointer[pointer_count].type_index = point.type_index;
  1888.                         memcpy(one_pointer[pointer_count].name, str, min(point.name_len+1, 32));
  1889.                         one_pointer[pointer_count].name[32] = 0;
  1890.                         one_pointer[pointer_count].type_qual = type.type_qual;
  1891.                         pointer_count++;
  1892.                         break;
  1893.                   }
  1894.  
  1895.                   ++idx;
  1896.  
  1897.                   bytesread += type.length;
  1898.  
  1899.                   lseek(fh, ofs+type.length+2, SEEK_SET);
  1900.                }
  1901.                break;
  1902.  
  1903.             case SSTSRCLINES32:
  1904.                if (TrapSeg!=ssmod32.csBase) break;
  1905.                /* read first line */
  1906.                read(fh,(void *)&FirstLine,sizeof(FirstLine));
  1907.                if (FirstLine.LineNum!=0) {
  1908.                   fprintf(hTrap,"Missing Line table information\n");
  1909.                   break;
  1910.                } /* endif */
  1911.                numlines= FirstLine.numlines;
  1912.                /* Other type of data skip 4 more bytes */
  1913.                if (FirstLine.segnum!=0) {
  1914.                   lseek(fh,4,SEEK_CUR);
  1915.                }
  1916.                for (j=0;j<numlines;j++) {
  1917.                   read(fh,(void *)&LineEntry,sizeof(LineEntry));
  1918.                   if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) {
  1919.                      NrLine=LineEntry.Offset;
  1920.                      NrFile=LineEntry.FileNum;
  1921.                      /*pOffset =sprintf(szNrLine,"%04X:%08X  line #%hu ",
  1922.                              ssmod32.csBase,LineEntry.Offset,
  1923.                              LineEntry.LineNum);*/
  1924.                     sprintf(szNrLine,"% 6hu", LineEntry.LineNum);
  1925.                   }
  1926.                }
  1927.                if (NrFile!=0) {
  1928.                   read(fh,(void *)&FileInfo,sizeof(FileInfo));
  1929.                   namelen=0;
  1930.                   for (j=1;j<=FileInfo.file_count;j++) {
  1931.                      namelen=0;
  1932.                      read(fh,(void *)&namelen,1);
  1933.                      read(fh,(void *)ename,namelen);
  1934.                      if (j==NrFile) break;
  1935.                   }
  1936.                   ename[namelen]='\0';
  1937.                   /*  pOffset=sprintf(szNrLine+pOffset," (%s) (%s)\n",ename,ModName);*/
  1938.                   sprintf(szNrFile,"%  13.13s ",ename);
  1939.                } else {
  1940.                   /* strcat(szNrLine,"\n"); avoid new line for empty name fill */
  1941.                  strcpy(szNrFile,"             ");
  1942.                } /* endif */
  1943.                break;
  1944.           } /* end switch */
  1945.  
  1946.           i++;
  1947.        } /* end while modindex */
  1948.     } /* End While i < numdir */
  1949.     free(pDirTab32);
  1950.     return(0);
  1951. }
  1952.  
  1953. BYTE *var_value(void *varptr, BYTE type)
  1954. {
  1955.    static BYTE value[128];
  1956.    APIRET rc;
  1957.  
  1958.    strcpy(value, "Unknown");
  1959.  
  1960.    if (type == 0)
  1961.       sprintf(value, "%hd", *(signed char *)varptr);
  1962.    else if (type == 1)
  1963.       sprintf(value, "%hd", *(signed short *)varptr);
  1964.    else if (type == 2)
  1965.       sprintf(value, "%ld", *(signed long *)varptr);
  1966.    else if (type == 4)
  1967.       sprintf(value, "%hu", *(BYTE *)varptr);
  1968.    else if (type == 5)
  1969.       sprintf(value, "%hu", *(USHORT *)varptr);
  1970.    else if (type == 6)
  1971.       sprintf(value, "%lu", *(ULONG *)varptr);
  1972.    else if (type == 8)
  1973.       sprintf(value, "%f", *(float *)varptr);
  1974.    else if (type == 9)
  1975.       sprintf(value, "%f", *(double *)varptr);
  1976.    else if (type == 10)
  1977.       sprintf(value, "%f", *(long double *)varptr);
  1978.    else if (type == 16)
  1979.       sprintf(value, "%s", *(char *)varptr ? "TRUE" : "FALSE");
  1980.    else if (type == 17)
  1981.       sprintf(value, "%s", *(short *)varptr ? "TRUE" : "FALSE");
  1982.    else if (type == 18)
  1983.       sprintf(value, "%s", *(long *)varptr ? "TRUE" : "FALSE");
  1984.    else if (type == 20)
  1985.       sprintf(value, "%c", *(char *)varptr);
  1986.    else if (type == 21)
  1987.       sprintf(value, "%lc", *(short *)varptr);
  1988.    else if (type == 22)
  1989.       sprintf(value, "%lc", *(long *)varptr);
  1990.    else if (type == 23)
  1991.       sprintf(value, "void");
  1992.    else if (type >= 32) {
  1993.       ULONG Size,Attr;
  1994.       Size=1;
  1995.       rc=DosQueryMem((void*)*(ULONG *)varptr,&Size,&Attr);
  1996.       if (rc) {
  1997.          sprintf(value, "0x%p invalid", *(ULONG *)varptr);
  1998.       } else {
  1999.          sprintf(value, "0x%p", *(ULONG *)varptr);
  2000.          if (Attr&PAG_FREE) {
  2001.             strcat(value," unallocated memory");
  2002.          } else {
  2003.             if ((Attr&PAG_COMMIT)==0x0U) {
  2004.                strcat(value," uncommited");
  2005.             } /* endif */
  2006.             if ((Attr&PAG_WRITE)==0x0U) {
  2007.                strcat(value," unwritable");
  2008.             } /* endif */
  2009.             if ((Attr&PAG_READ)==0x0U) {
  2010.                strcat(value," unreadable");
  2011.             } /* endif */
  2012.          } /* endif */
  2013.       } /* endif */
  2014.    }
  2015.  
  2016.    return value;
  2017. }
  2018.  
  2019. /* Search the table of userdef's - return TRUE if found */
  2020. BOOL search_userdefs(ULONG stackofs, USHORT var_no)
  2021. {
  2022.    USHORT pos;
  2023.  
  2024.    for(pos = 0; pos < userdef_count && one_userdef[pos].idx != autovar_def[var_no].type_idx; pos++);
  2025.  
  2026.    if (pos < userdef_count) {
  2027.       if (one_userdef[pos].type_index >= 0x80 && one_userdef[pos].type_index <= 0xDA) {
  2028.          fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
  2029.                  autovar_def[var_no].stack_offset,
  2030.                  autovar_def[var_no].name,
  2031.                  one_userdef[pos].name,
  2032.                  var_value((void *)(stackofs+autovar_def[var_no].stack_offset),
  2033.                            one_userdef[pos].type_index-0x80));
  2034.          return TRUE;
  2035.       }
  2036.       else /* If the result isn't a simple type, let's act as we didn't find it */
  2037.          return FALSE;
  2038.    }
  2039.  
  2040.    return FALSE;
  2041. }
  2042.  
  2043. BOOL search_pointers(ULONG stackofs, USHORT var_no)
  2044. {
  2045.    USHORT pos, upos;
  2046.    static BYTE str[35];
  2047.    BYTE   type_index;
  2048.  
  2049.    for(pos = 0; pos < pointer_count && one_pointer[pos].idx != autovar_def[var_no].type_idx; pos++);
  2050.  
  2051.    if (pos < pointer_count) {
  2052.       if (one_pointer[pos].type_index >= 0x80 && one_pointer[pos].type_index <= 0xDA) {
  2053.          strcpy(str, type_name[one_pointer[pos].type_index-0x80]);
  2054.          strcat(str, " *");
  2055.          fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
  2056.                  autovar_def[var_no].stack_offset,
  2057.                  autovar_def[var_no].name,
  2058.                  str,
  2059.                  var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
  2060.          return TRUE;
  2061.       }
  2062.       else { /* If the result isn't a simple type, look for it in the other lists */
  2063.          for(upos = 0; upos < userdef_count && one_userdef[upos].idx != one_pointer[pos].type_index; upos++);
  2064.  
  2065.          if (upos < userdef_count) {
  2066.             strcpy(str, one_userdef[upos].name);
  2067.             strcat(str, " *");
  2068.             fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
  2069.                     autovar_def[var_no].stack_offset,
  2070.                     autovar_def[var_no].name,
  2071.                     str,
  2072.                     var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
  2073.             return TRUE;
  2074.          }
  2075.          else { /* If it isn't a userdef, for now give up and just print as much as we know */
  2076.             sprintf(str, "Pointer to type 0x%X", one_pointer[pos].type_index);
  2077.  
  2078.             fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
  2079.                     autovar_def[var_no].stack_offset,
  2080.                     autovar_def[var_no].name,
  2081.                     str,
  2082.                     var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
  2083.  
  2084.             return TRUE;
  2085.          }
  2086.       }
  2087.    }
  2088.  
  2089.    return FALSE;
  2090. }
  2091.  
  2092. void print_vars(ULONG stackofs)
  2093. {
  2094.    USHORT n, pos;
  2095.    BOOL   AutoVarsFound=FALSE;
  2096.  
  2097. /*   stackofs += stack_ebp; */
  2098.    if (func_ofs == pubfunc_ofs) {
  2099.       for(n = 0; n < var_ofs; n++) {
  2100.          if (AutoVarsFound==FALSE) {
  2101.              AutoVarsFound=TRUE;
  2102.              fprintf(hTrap, "List of auto variables at EBP %p in %s:\n",stackofs, func_name);
  2103.              fprintf(hTrap,"Offset Name                 Type                              Value            \n");
  2104.              fprintf(hTrap,"────── ──────────────────── ───────────────────────────────── ─────────────────\n");
  2105.          }
  2106.  
  2107.          /* If it's one of the simple types */
  2108.          if (autovar_def[n].type_idx >= 0x80 && autovar_def[n].type_idx <= 0xDA)
  2109.          {
  2110.             fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
  2111.                     autovar_def[n].stack_offset,
  2112.                     autovar_def[n].name,
  2113.                     type_name[autovar_def[n].type_idx-0x80],
  2114.                     var_value((void *)(stackofs+autovar_def[n].stack_offset),
  2115.                               autovar_def[n].type_idx-0x80));
  2116.          }
  2117.          else { /* Complex type, check if we know what it is */
  2118.             if (!search_userdefs(stackofs, n)) {
  2119.                if (!search_pointers(stackofs, n)) {
  2120.                   fprintf(hTrap, "%- 6d %-20.20s 0x%X\n",
  2121.                                  autovar_def[n].stack_offset,
  2122.                                  autovar_def[n].name,
  2123.                                  autovar_def[n].type_idx);
  2124.                }
  2125.             }
  2126.          }
  2127.       }
  2128.       if (AutoVarsFound==FALSE) {
  2129.           fprintf(hTrap, "  No auto variables found in %s.\n", func_name);
  2130.       }
  2131.       fprintf(hTrap, "\n");
  2132.    }
  2133. }
  2134.