Index: trunk/src/tools/qsysxcpt_pm.cpp
===================================================================
--- trunk/src/tools/qsysxcpt_pm.cpp	(revision 147)
+++ trunk/src/tools/qsysxcpt_pm.cpp	(revision 148)
@@ -212,5 +212,5 @@
                             BOOL bQueryMem = TRUE )
 {
-    fprintf( file, "     <Register name=\"%s\" value=\"%08lX\"", 
+    fprintf( file, "      <Register name=\"%s\" value=\"%08lX\"", 
              pszName, ulValue );
 
@@ -238,7 +238,7 @@
         {
             fprintf( file, ">\n" );
-            qt_excWriteErrorMsg( file, 6, "DosQueryMem returned %lu"
+            qt_excWriteErrorMsg( file, 7, "DosQueryMem returned %lu"
                                  "and flags %08lX", arc, ulFlags );
-            fprintf( file, "     </Register>\n" );
+            fprintf( file, "      </Register>\n" );
         }
     }
@@ -258,6 +258,6 @@
             ulOffset = 0;
 
-    fprintf (file, "     <Frame pointer=\"%08lX\">\n", ulRegEbp);
-    fprintf (file, "      <Location address=\"%08lX\">\n", ulRegEip);
+    fprintf (file, "      <Frame pointer=\"%08lX\">\n", ulRegEbp);
+    fprintf (file, "       <Location address=\"%08lX\">\n", ulRegEip);
     
     arc = DosQueryModFromEIP (&hMod, &ulObject,
@@ -266,9 +266,9 @@
 
     if (arc != NO_ERROR)
-        qt_excWriteErrorMsg (file, 7, "%s: DosQueryModFromEIP returned %lu",
+        qt_excWriteErrorMsg (file, 8, "%s: DosQueryModFromEIP returned %lu",
                              szMod, arc);
     else
-        fprintf (file, "       <Module ID=\"%04lX\" segment=\"%04lX\" "
-                                      "offset=\"%08lX\"/>\n",
+        fprintf (file, "        <Module ID=\"%04lX\" segment=\"%04lX\" "
+                                       "offset=\"%08lX\"/>\n",
                  hMod, ulObject + 1, ulOffset); 
 
@@ -308,5 +308,5 @@
             }
         }
-        fprintf (file, "       <Dump address=\"%08lX\">\n        ", pch);
+        fprintf (file, "        <Dump address=\"%08lX\">\n         ", pch);
         if (arc == NO_ERROR &&
             ulFlags & (PAG_COMMIT|PAG_READ) == (PAG_COMMIT | PAG_READ))
@@ -320,9 +320,9 @@
             qt_excWriteErrorMsg (file, 0, "%08lX: DosQueryMem returned %lu"
                                  "and flags %08lX", pch, arc, ulFlags);
-        fprintf (file, "       </Dump>\n");
-    }
-    
-    fprintf (file, "      </Location>\n");
-    fprintf (file, "     </Frame>\n");
+        fprintf (file, "        </Dump>\n");
+    }
+    
+    fprintf (file, "       </Location>\n");
+    fprintf (file, "      </Frame>\n");
 }
 
@@ -336,5 +336,5 @@
     ULONG ulRegEip = pContextRec->ctx_RegEip;
 
-    fprintf (file, "    <Frames>\n");
+    fprintf (file, "     <Frames>\n");
 
     /* first the trapping address itself */
@@ -362,8 +362,8 @@
                         != (PAG_COMMIT|PAG_READ)))
             {
-                fprintf (file, "     <Frame pointer=\"%08lX\">\n", ulRegEbp);
-                qt_excWriteErrorMsg (file, 6, "DosQueryMem returned %lu "
+                fprintf (file, "      <Frame pointer=\"%08lX\">\n", ulRegEbp);
+                qt_excWriteErrorMsg (file, 7, "DosQueryMem returned %lu "
                                      "and flags %08lX", arc, ulFlags);
-                fprintf (file, "     </Frame>\n");
+                fprintf (file, "      </Frame>\n");
                 /* try go to the next page */
                 /// @todo (r=dmik) I don't know how much it is accurate,
@@ -380,5 +380,5 @@
     }
 
-    fprintf (file, "    </Frames>\n");
+    fprintf (file, "     </Frames>\n");
 }
 
@@ -393,6 +393,6 @@
     if (ptib)
     {
-        fprintf (file, "  <Thread ID=\"%04lX\" slot=\"%04lX\" "
-                                 "priority=\"%04lX\" ",
+        fprintf (file, "   <Thread ID=\"%04lX\" slot=\"%04lX\" "
+                                  "priority=\"%04lX\" ",
                  ptib->tib_ptib2->tib2_ultid, ptib->tib_ordinal,
                  ptib->tib_ptib2->tib2_ulpri);
@@ -405,6 +405,6 @@
     else
     {
-        fprintf (file, "  <Thread ID=\"%04lX\" slot=\"%04lX\" "
-                                 "priority=\"%04lX\" state=\"%02lX\">\n",
+        fprintf (file, "   <Thread ID=\"%04lX\" slot=\"%04lX\" "
+                                  "priority=\"%04lX\" state=\"%02lX\">\n",
                  pThrdRec->tid, pThrdRec->slot, pThrdRec->priority,
                  pThrdRec->state);
@@ -413,6 +413,6 @@
     /* *** registers */
 
-    fprintf (file, "   <CPU>\n"
-                   "    <Registers>\n");
+    fprintf (file, "    <CPU>\n"
+                   "     <Registers>\n");
 
     if  (pContextRec->ContextFlags & CONTEXT_SEGMENTS)
@@ -444,10 +444,10 @@
     }
     
-    fprintf (file, "    </Registers>\n"
-                   "   </CPU>\n");
+    fprintf (file, "     </Registers>\n"
+                   "    </CPU>\n");
 
     /* *** stack */
 
-    fprintf (file, "   <Stack base=\"%08lX\" limit=\"%08lX\">\n",
+    fprintf (file, "    <Stack base=\"%08lX\" limit=\"%08lX\">\n",
              (ULONG) ptib->tib_pstack,
              (ULONG) ptib->tib_pstacklimit);
@@ -458,20 +458,106 @@
     }    
     
-    fprintf (file, "   </Stack>\n"
-                   "  </Thread>\n");
-}
-
-typedef struct _PROCESSINFO
-{
-    /* common values */
-    char *pszFullName;
-    char *pszBaseName;
-    /* direct info pointers */
-    PPIB ppib;
-    PTIB ptib;
-    BOOL bHaveSysState; /**< TRUE when both pProcRec and pLibRec are not NULL */ 
-    QSPREC *pProcRec;   /**< NULL when bHaveSysState is FALSE */
-    QSLREC *pLibRec;    /**< NULL when bHaveSysState is FALSE */
-} PROCESSINFO;
+    fprintf (file, "    </Stack>\n"
+                   "   </Thread>\n");
+}
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/** @internal
+ *  Writes the module description string (if found) as the 'desciption'
+ *  attribute. Returns TRUE if the description was found and written.
+ */
+static BOOL qt_excWriteModuleDesc (FILE *file, char *pszFileName)
+{
+    /* see OS2TK\h\exe.h, OS2TK\h\exe386.h and LXSPEC.INF for details */
+    enum { EXEID = 0x5a4d, LXOffset = 0x3C, sizeof_exe = LXOffset + 4,
+           E32MAGIC = 0x584c, e32_nrestab = 34 * 4,
+           sizeof_e32 = e32_nrestab + 4,
+           max_nresname = 255 + 1 /* trailing 0 */ };
+           
+    UCHAR achBuf [max (max_nresname, max (sizeof_e32, sizeof_exe))];
+
+    BOOL bFound = FALSE;
+    ULONG ul1 = 0, ul2 = 0;
+    
+    HFILE hf = NULL;
+    APIRET arc = NO_ERROR;
+    
+    arc = DosOpen (pszFileName, &hf, &ul1,
+                   0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
+                   OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY,
+                   NULL);
+    if (arc != NO_ERROR)
+        return FALSE;
+
+    do
+    {
+        /* read the old EXE header plus the offset to the LX header */
+        arc = DosRead (hf, achBuf, sizeof_exe, &ul1);
+        if (arc != NO_ERROR || sizeof_exe != ul1)
+            break;
+        
+        if (*(USHORT *) &achBuf == EXEID)
+        {
+            /* go to the LX header */
+            ul1 = *(ULONG *) &achBuf [LXOffset];
+            arc = DosSetFilePtr (hf, (LONG) ul1, FILE_BEGIN, &ul2);
+            if (arc != NO_ERROR || ul1 != ul2)
+                break;
+
+            /* read it upto the e32_nrestab field */
+            arc = DosRead (hf, achBuf, sizeof_e32, &ul1);
+            if (arc != NO_ERROR || sizeof_e32 != ul1 ||
+                *(USHORT *) &achBuf != E32MAGIC)
+                break;
+        }
+        else
+        if (*(USHORT *) &achBuf == E32MAGIC)
+        {
+            /* there may be no old EXE header, but LX only,
+             * read it upto the e32_nrestab field */
+            if (sizeof_e32 > sizeof_exe)
+            {
+                arc = DosRead (hf, achBuf + sizeof_exe,
+                               sizeof_e32 - sizeof_exe, &ul1);
+                if (arc != NO_ERROR || sizeof_e32 - sizeof_exe != ul1)
+                    break;
+            }
+        }
+        else
+            break;
+        
+        /* go to the beginning of the non-resident name table */ 
+        ul1 = *(ULONG *) &achBuf [e32_nrestab];
+        if (ul1)
+        {
+            arc = DosSetFilePtr (hf, (LONG) ul1, FILE_BEGIN, &ul2);
+            if (arc != NO_ERROR || ul1 != ul2)
+                break;
+            
+            /* read the first entry */
+            arc = DosRead (hf, achBuf, max_nresname, &ul1);
+            if (arc != NO_ERROR || max_nresname != ul1)
+                break;
+    
+            /* if the ordinal is 0, then it's a description field (we don't do
+             * the full table search, since it shoud be ordered by ordinals) */
+            if (*(USHORT *) &achBuf [1 + *achBuf] == 0)
+            {
+                /* place the trailing zero */
+                achBuf [1 + *achBuf] = 0;
+                /* write the description attribute */
+                fprintf (file, "\n           desc=\"%s\"", achBuf + 1);
+                bFound = TRUE;
+            }
+        }
+    }
+    while (0);
+    
+    DosClose (hf);
+    return bFound;
+}
 
 /*! \internal
@@ -484,13 +570,31 @@
 {
     static const char *apszOrigins[] = { "self", "imported", "loaded" };
+    
+    FILESTATUS3 Status;
+    APIRET arc = NO_ERROR;
 
     fprintf (file, "   <Module ID=%\"%04lX\" name=\"", hmte);
     qt_excEscapeString (file, pszName);
-    if (ulOrigin >= 1 && ulOrigin <= 3)
-        fprintf (file, "\"\n"
-                       "           origin=\"%s\"/>\n",
-                       apszOrigins [ulOrigin - 1]);
-    else
-        fprintf (file, "\"/>\n");
+    fprintf (file, "\"");
+    
+    arc = DosQueryPathInfo (pszName, FIL_STANDARD, &Status, sizeof (Status));
+
+    if ((ulOrigin >= 1 && ulOrigin <= 3) || arc == NO_ERROR )
+    {
+        fprintf (file, "\n           ");
+        if (ulOrigin >= 1 && ulOrigin <= 3)
+            fprintf (file, " origin=\"%s\"",
+                           apszOrigins [ulOrigin - 1]);
+        if (arc == NO_ERROR)
+            fprintf (file, " timestamp=\"%04d-%02d-%02dT%02d:%02d:%02d\"",
+                     Status.fdateLastWrite.year + 1980,
+                     Status.fdateLastWrite.month, Status.fdateLastWrite.day,
+                     Status.ftimeLastWrite.hours, Status.ftimeLastWrite.minutes,
+                     Status.ftimeLastWrite.twosecs * 2);
+    }
+
+    qt_excWriteModuleDesc (file, pszName);
+
+    fprintf (file, "/>\n");
 }
 
@@ -525,5 +629,7 @@
 }
 
-/** Struct for recursive qt_excWriteModulesOnStack() to reduce stack usage */
+/** @internal
+ *  Struct for recursive qt_excWriteModulesOnStack() to reduce stack usage
+ */
 typedef struct _WMOS_STATE
 {
@@ -621,4 +727,18 @@
     }
 }
+
+/** @internal Simple process info struct */
+typedef struct _PROCESSINFO
+{
+    /* common values */
+    char *pszFullName;
+    char *pszBaseName;
+    /* direct info pointers */
+    PPIB ppib;
+    PTIB ptib;
+    BOOL bHaveSysState; /**< TRUE when both pProcRec and pLibRec are not NULL */ 
+    QSPREC *pProcRec;   /**< NULL when bHaveSysState is FALSE */
+    QSLREC *pLibRec;    /**< NULL when bHaveSysState is FALSE */
+} PROCESSINFO;
 
 /*! \internal
@@ -1014,14 +1134,14 @@
 
                 fprintf (file,
-                         "<Trap timestamp=\"%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d\" "
-                               "version=\"1.0\"\n"
+                         "<Trap timestamp=\"%04d-%02d-%02dT%02d:%02d:%02d\"" //%c%02d:%02d\""
+                              " version=\"1.0\"\n"
                          "      generator=\"Qt Library Version %s\"\n"
                          "      xmlns=\"http://db.hugaida.com/xml/os2/sys/Trap\">\n",
                          dt.year, dt.month, dt.day,
                          dt.hours, dt.minutes, dt.seconds,
-                         (dt.timezone > 0 ? '-' : '+'),
-                         abs (dt.timezone / 60),
-                         abs (dt.timezone % 60),
-                         QT_VERSION_STR );
+                         //(dt.timezone > 0 ? '-' : '+'),
+                         //abs (dt.timezone / 60),
+                         //abs (dt.timezone % 60),
+                         QT_VERSION_STR);
 
                 XcptPvt::file = file;
