
#define SCCSID   "@(#)procdump.c  6.18 92/01/23"

/*
 *      PROCDUMP.C - Kernel Process Dump Routines
 *
 *      This is an OS/2 2.x specific file
 *      IBM Confidential
 *
 *      Copyright (c) IBM Corporation 1987, 1992
 *
 *      All Rights Reserved
 *
 *      This file provides kernel routine to write information to
 *      to popup suppression log file and kernel entry points for
 *      DosDumpProcess and DosSuppressPopUps.
 *
 *****************************************************************************
 *  Change                                                               Chg *
 *  Activity      Date    BY   Reason                                    Num *
 *  --------      ----    ---  -------                                   --- *
 *  74428       10/04/93  ARJ  Enable API code for Testing           NO FLAG *
 *  87725       06/04/94  ARJ  The DumpProcess and PopUpSuppression      001 *
 *                             API's will  not  be supported by any      001 *
 *                             release of OS2.  See Feature 74806        001 *
 *  92587       08/18/94  ARJ  FLUSH CACHE WHEN OPENING THE POPUPLOG     002 *
 *  97464       09/12/94  ARJ  The DumpProcess and PopUpSuppression      003 *
 *                             API's will be supported by Service,       003 *
 *                             and documented by defect 97932.           003 *
 *  157614      06/14/96  DJ/RJM Suppresspopups logging control          004 *
 *****************************************************************************
 */


#define INCL_TYPES
#include <basedef.h>
#define FNO_NUM FNO_PROCDUMP_C          /* for assertion macros */
#include <fnotask.h>                    /* MUST BE BEFORE osmac.h */
#include <osmac.h>
#include <osconst.h>
#include <ostypes.h>
#include <infoseg.h>
#include <mi.h>
#include <proc.h>
#include <error.h>
#include <sigdef.h>
#include <except.h>
#include <dossymc.h>
#include <seldesc.h>
#include <pgexport.h>
#include <vmexport.h>
#include <vmowner.h>
#include <selxport.h>
#include <tkexport.h>
#include <sem.h>
#include <screen.h>
#include <curdir.h>
#include <dirent.h>
#include <find.h>
#include <semxport.h>
#include <tkptda.h>
#include <kmode.h>
#include <pdfile.h>


#define isalpha(c) ((((c) >= 'A') && ((c) <= 'Z')) || (((c) >= 'a') && ((c) <= 'z')))
#define POPUPBUFSIZ 80*24


extern CHAR         DumpProcess;
extern CHAR         SuppressPopUps;
extern CHAR         PopUpLogDrive;                //157614
extern struct InfoSegGDT   SISData;               //157614


//    Moved to sdata.asm for System Anchor Block - f122427
//     KSEMMTX PopUpSem;
extern KSEMMTX PopUpSem;


#pragma data_seg ("CSWAP_DATA", "CSWAPDATA")

static CHAR    szPopUpLogFile[] =
                   "d:\\POPUPLOG.OS2";
static CHAR    szPopUpSeparator[] =
                   "------------------------------------------------------------\r\n"; //157614
static CHAR    szPopUpHeader[] =
//157614           "\r\n%02d-%02d-%4d  %02d:%02d:%02d  SYS%04ld  PID %04lx\r\n%s\r\n";
                   "\r\n%02d-%02d-%4d  %02d:%02d:%02d  SYS%04ld  PID %04lx  TID %04lx  Slot %04lx\r\n%s\r\n"; //157614
static CHAR    szPopUpCRLF[] =
                   "\r\n";
static BYTE    PopUpBuffer[POPUPBUFSIZ];

#pragma data_seg ()


#pragma code_seg("TKSWAP_TEXT", "CODE")

/***EP  VR32DumpProcess - Kernel entry for DosDumpProcess
 *
 *      VR32DumpProcess is called to enable, disable, or perform process
 *      dumps.  The second parameter is only examined if the first parameter
 *      is DDP_ENABLEPROCDUMP.  Likewise, the third parameter is only
 *      examined if the first parameter is DDP_PERFORMPROCDUMP.
 *
 *      The global variable DumpProcess (declared in INIT\INICMD.ASM), which
 *      indicates on which drive to place the process dump log file (or is 0
 *      if process dumps are disabled), may be altered buring bootup by
 *      placing DUMPPROCESS=x in CONFIG.SYS.
 *
 *      ENTRY   sef      System Entry Frame
 *              Flag     Flag indicating enabling/disabling of process dumps
 *              Drive    Drive to place process dump log file
 *              Pid      PID of process to dump
 *
 *      EXIT    Success - NO_ERROR
 *              Error   - ERROR_INVALID_PARAMETER
 *                        ERROR_INVALID_PROCID
 */

ULONG cdecl VR32DumpProcess(THUNKSEF sef, ULONG Flag, ULONG Drive, PID Pid)

{

     // If Flag is DDP_DISABLEPROCDUMP
   if (Flag == 0L)
   {
       DumpProcess = '\0';
       return (NO_ERROR);
   }
   // Else if Flag is DDP_ENABLEPROCDUMP and Drive is alphabetic character
   else if (Flag == 1L && (!(Drive & 0xFFFFFF00L)) && isalpha((UCHAR)Drive))
   {
       DumpProcess = (UCHAR)Drive;
       return (NO_ERROR);
   }
   // Else if Flag is DDP_PERFORMPROCDUMP
   else if (Flag == 2L && DumpProcess != '\0')
   {
      return (PLD32ApiDump ((Pid ? Pid : pPTDACur->ptda_Pid), -1L));
   }
   // Otherwise the parameters were not specified correctly
   else
       return (ERROR_INVALID_PARAMETER);
}


/***EP  VR32SuppressPopUps - Kernel entry for DosSuppressPopUps
 *
 *      VR32SuppressPopUps is called to enable or disable suppress of
 *      popups on a system-wide scale.  The second parameter is only
 *      examined if the first parameter is SPU_ENABLESUPPRESSION.
 *
 *      The global variable SuppressPopUps (declared in INIT\INICMD.ASM),
 *      which indicates on which drive to place the popup suppression log
 *      file (or is 0 if popup suppression is disabled), may be altered
 *      buring bootup by placing SUPPRESSPOPUPS=x in CONFIG.SYS.
 *
 *      157614 changes SuppressPopUps in the following way:  By default  
 *      logging is active.  SuppressPopUps now controls only the         
 *      suppression of the PopUp.  PopUpLogDrive controls the logging.   
 *      PopUpLogDrive is set to an initial value of 2 to indicate that   
 *      PopUpLogDrive should be initialised to the Boot Drive.  Having   
 *      called the logging function once, PopUpLogDrive is converted to  
 *      the boot drive.  Thereafter DosSuppressPopUps controls these     
 *      values.  A special value of SUPPRESSPOPUPS=0 will force the      
 *      original behaviour with logging disabled and popups enabled.     
 *
 *      ENTRY   sef      System Entry Frame
 *              Flag     Flag indicating enabling/disabling of popup suppression
 *              Drive    Drive to place popup suppression log file
 *
 *      EXIT    Success - NO_ERROR
 *              Error   - ERROR_INVALID_PARAMETER
 */

ULONG cdecl VR32SuppressPopUps(THUNKSEF sef, ULONG Flag, ULONG Drive)

{

#define  SPU_DISENABLESUPPRESSION 0L                         //157614
#define  SPU_ENABLESUPPRESSION    1L                         //157614
#define  SPU_NOLOGCHANGE          2L                         //157614
#define  SPU_DRIVEMASK            0xFFFFFF00L                //157614
                                                             //157614
   if (Flag &~(SPU_NOLOGCHANGE+SPU_ENABLESUPPRESSION))       //157614
      return (ERROR_INVALID_PARAMETER);                      //157614
                                                             //157614
   if ((Flag & SPU_NOLOGCHANGE) && (Drive))                  //157614
      return (ERROR_INVALID_PARAMETER);                      //157614
                                                             //157614
   if (Flag & SPU_ENABLESUPPRESSION) SuppressPopUps=1L;      //157614
// Else Flag is SPU_DISABLESUPPRESSION                       //157614
   else SuppressPopUps=0L;                                   //157614
                                                             //157614
// Only respecify logging if SPU_NOLOGCHANGE is not          //157614
// specified.                                                //157614
   if (!(Flag & SPU_NOLOGCHANGE)) {                          //157614
                                                             //157614
   // If Drive is zero reset the drive to null               //157614
   // (turn off logging)                                     //157614
   // or If Drive specified then it must be a single alpha.  //157614
                                                             //157614
      if ((!Drive) ||                                        //157614
         (!(Drive & SPU_DRIVEMASK) && isalpha((UCHAR)Drive)))//157614
         PopUpLogDrive=(UCHAR)Drive;                         //157614
                                                             //157614
   } /* endif */                                             //157614
                                                             //157614
   return (NO_ERROR);                                        //157614

/* removed by 157614
 *  // If Flag is SPU_DISABLESUPPRESSION
 *  if (Flag == 0L)
 *  {
 *      SuppressPopUps = '\0';
 *      return (NO_ERROR);
 *  }
 *
 *  // Else if Flag is SPU_ENABLESUPPRESSION and Drive is alphabetic character
 *  else if (Flag == 1L && (!(Drive & 0xFFFFFF00L)) && isalpha((UCHAR)Drive))
 *  {
 *      SuppressPopUps = (UCHAR)Drive;
 *      return (NO_ERROR);
 *  }
 *  // Otherwise the parameters were not specified correctly
 *  else
 *      return (ERROR_INVALID_PARAMETER);
*/

}

/***EP  PDLogPopUp - Log popup to popup suppression log file
 *
 *      PDLogPopUp logs the proper information to the popup suppression
 *      log file.
 *
 *      ENTRY   Msg      message number
 *              cIns     count of message inserts
 *              pIns     pointer to message inserts
 *
 *      EXIT    NONE
 */

VOID PDLogPopUp(ULONG Msg, ULONG cIns, PCHAR pIns)
{
    ULONG    ulAct;            // action taken by DosOpen
    ULONG    cbBuf = 0;        // number of bytes placed in buffer
    ULONG    cbIns;            // number of bytes in insert
    ULONG    rc;               // return code
    HFILE    hfLog;            // file handle of popup suppression log file
    PCHAR    pb;               // byte pointer
    DATETIME sDT;              // date/time structure
//157614 PVOID    PopUpHdrIns[9];   // popup's header inserts
    PVOID    PopUpHdrIns[11];   // popup's header inserts            157614

    // Request exclusive access to popup suppression log file
    while ((rc = KSEMRequestMutex((HKSEM)&PopUpSem, -1L)) == ERROR_INTERRUPT);
    if (rc != NO_ERROR)
        return;

    // Changing SuppressPopUps to always log the traps, therefore           //157614
    // we need to check to see if the SuppressPopUps drive has              //157614
    // been set.  If it hasn't, the set it to log to the boot drive.        //157614
                                                                            //157614
    if (PopUpLogDrive==2)                  // default from initialisation   //157614
       PopUpLogDrive = SISData.SIS_BootDrv + 'A' - 1;  // use boot dtrive   //157614


    // Set drive letter for popup suppression log file
    szPopUpLogFile[0] = PopUpLogDrive;     //157614
//    szPopUpLogFile[0] = SuppressPopups;  //157614


    // Open popup suppression log file                   A002   ADDED 0x4000L
    if (PDOpen(szPopUpLogFile,
               SSToDS(&hfLog),
               SSToDS(&ulAct),
               0x00L,
               0x00L,
               0x11L,
               0x2000L | 0x4000L | 0x80L | 0x10L | 0x02L,
               NULL))
        goto popuperr2;

    // If popup suppression log file already exists
    if (ulAct == 1)
    {
        // Seek to end of popup suppression log file
        if (PDSeek(hfLog, 0L, 2L, (SSToDS(&ulAct))))
            goto popuperr1;

        // Place popup separator into buffer
        cbBuf = sizeof(szPopUpSeparator) - 1;
        memcpy(PopUpBuffer, szPopUpSeparator, cbBuf);
    }

    // Obtain current date and time
    PLDGetDateTime(SSToDS(&sDT));

    // Place popup header into buffer
    PopUpHdrIns[0] = (PVOID)sDT.month;
    PopUpHdrIns[1] = (PVOID)sDT.day;
    PopUpHdrIns[2] = (PVOID)sDT.year;
    PopUpHdrIns[3] = (PVOID)sDT.hours;
    PopUpHdrIns[4] = (PVOID)sDT.minutes;
    PopUpHdrIns[5] = (PVOID)sDT.seconds;
    PopUpHdrIns[6] = (PVOID)Msg;
    PopUpHdrIns[7] = (PVOID)pPTDACur->ptda_Pid;
    PopUpHdrIns[8] = (PVOID)pTCBCur->TCBOrdinal; //157614
    PopUpHdrIns[9] = (PVOID)pTCBCur->TCBNumber; //157614

#ifdef INCDEBUG
//157614    PopUpHdrIns[8] = pPTDACur->ptda_pszproc ? pPTDACur->ptda_pszproc : "";
    PopUpHdrIns[10] = pPTDACur->ptda_pszproc ? pPTDACur->ptda_pszproc : ""; //157614
#endif

    cbBuf += TKVSprintf(PopUpBuffer + cbBuf,
                        POPUPBUFSIZ - cbBuf,
                        szPopUpHeader,
                        SSToDS((int *)PopUpHdrIns));

    // Place message inserts into buffer
    pb = pIns;
    while (cIns-- > 0 && cbBuf < POPUPBUFSIZ)
    {
        if (*pb != '\0')
        {
            // Place current message insert into buffer, making sure
            // entire insert will fit in buffer (if not, truncate)
            cbIns = strlen(pb);
            if (cbBuf + cbIns > (POPUPBUFSIZ - (sizeof(szPopUpCRLF)-1)))
                cbIns = (POPUPBUFSIZ - (sizeof(szPopUpCRLF)-1)) - cbBuf;
            memcpy(PopUpBuffer + cbBuf, pb, cbIns);
            cbBuf += cbIns;
            pb += cbIns;

            // Place carriage return and line feed into buffer
            memcpy(PopUpBuffer + cbBuf, szPopUpCRLF, sizeof(szPopUpCRLF)-1);
            cbBuf += sizeof(szPopUpCRLF)-1;
        }
        pb++;   // Skip ending NULL
    }

    // Write buffer to popup suppression log file
    PDWrite(hfLog, PopUpBuffer, cbBuf);

    // Close popup suppression log file
popuperr1:
    PLDClose(hfLog);

    // Release exclusive access to popup suppression log file
popuperr2:
    KSEMReleaseMutex((HKSEM)&PopUpSem);
}
