#define SCCSID	"@(#)plddump.c"
/*
 *	Process Dump Worker Routines
 *
 *	IBM Confidential
 *
 *	Copyright (c) IBM Corporation 1992
 *
 *	All Rights Reserved
 *
 *****************************************************************************
 *  Change								 Chg *
 *  Activity	  Date	  BY   Reason					 Num *
 *  --------	  ----	  ---  -------					 --- *
 *  62861	02/28/93  ARJ  Added for Dump Formatter 		 001 *
 *  74428	10/04/93  ARJ  Added Module Name for Dump Formatter	 002 *
 *  78727	03/08/94  ARJ  ldrValidateMteHandle no longer panics and 003 *
 *			  ARJ  Identify SMP kernel			 003 *
 *  77261	03/08/94  ARJ  Recalculate 32 bit stack size		 004 *
 *  92585	09/19/94  ARJ  Always copy and delete the MEMTABLE File  005 *
 *	    The structure of the MTE changed for the 4 MEG Release	D005 *
 *	    Therefore this code is no longer needed			D005 *
 * 100656	09/29/94  DavidJ  Make sure TIB2 is INITLIZED.		     *
 * 115362	06/02/95  ARJ  Dump all MTE's associated with process    006 *
 * 136061	09/22/95  SEG/DBH Handle case where exception handler	 007 *
 *				  has invalid chain pointer		     *
 * 148114	04/26/96  SEG/KDH Replace 136061 with new fix using	     *
 *				  TKCatchFault. 			     *
 *****************************************************************************
 */


#define INCL_SSTODS
#define INCL_DOSERRORS
#define INCL_DOSDATETIME

#define FNO_NUM       FNO_PLDDUMP_C	 /* DRV_\SRC\DOS\DOSINC\fnotask.h  */

#include <fnotask.h>			 /* DRV_\SRC\DOS\DOSINC\	   */
#include <fnomem.h>

#define INCL_DOSERRORS
#define INCL_TYPES

#include <os2defp.h>
#include <basedef.h>
#include <mi.h>
#include <osmac.h>
#include <string.h>
#include <bseerr.h>
#include <bsetib.h>
#include <bsexcpt.h>				      /*		   */
#include <pgexport.h>
#include <tkexport.h>
#include <vmexport.h>
#include <vmowner.h>
#include <selxport.h>
#include <seldesc.h>

#define FOR_EXEHDR	1

#include <exe386.h>
#include <sigdef.h>
#include <dossymc.h>
#include <sem.h>
#include <screen.h>
#include <dirent.h>
#include <except.h>
#include <infoseg.h>
#include <tkptda.h>
#include <ldrxport.h>
#include <ldrvars.h>
#include <basemac.h>
#include <kmode.h>
#include <pdfile.h>
#include <pldxport.h>
#include <pldlocal.h>
#include <pdump.h>

extern CRI criISF;		/* Interrupt stack frame descriptor */
extern CRI criTSF;		/* Trap stack frame descriptor	    */
extern CRI criVSF;		/* VDM Stack Frame		    */
extern CRI criSEF;		/* System Entry Stack Frame (C32)   */
extern CRI criPASCALSEF;	/* System Entry Stack Frame (PASCAL32)*/
extern CRI criSSF;		/* SCI Stack Frame (PASCAL16)	    */
extern CRI criDHF;		/* DevHlp Stack Frame		    */

/***LP	PLD32ApiDump - Worker Routine for Process Level Dump
 *
 *	This function is swappable.
 *
 *	If this routine is being called to perform a dump the user should
 *	pass in -1L in the trap number.
 *
 *	ENTRY
 *		uPID
 *		ulTrapNumber
 *
 *
 *	EXIT
 *		Return Value == 0
 *			No Error.
 *
 *		Return Value != 0
 *				12  Error_Invalid_Access
 *				vmallockhb   can fail
 *				tkpidtoptda can fail
 *
 *	Pseudocode:
 *
 *
 *
 */

#pragma code_seg("TKSWAP_TEXT", "CODE")                /* swap PLD code */

ULONG PLD32ApiDump (ULONG uPID,
		  ULONG ulTrapNumber)
{
    ULONG    rt,    pld_rt,
	     TablePtr,	   count, ulDmpArea;		      /*     61720  */

    HFILE    hfile,
	     hfiletab,
	     *phfile = &hfile,
	     *phfiletab = &hfiletab;

    char     dumpfile[PDUMPFILENAMELENGTH],
	     hdrfile[PDUMPFILENAMELENGTH];

    UCHAR     *memtable[12];				     /*        A005 */

    kPDPB_t  *pkPDPB;
    PLD_MH   *mh;

    if (DumpProcess == '\0')
     { return(ERROR_INVALID_ACCESS); }

    if (uPID == 0L)
     { return(ERROR_INVALID_PROCID); }

    if ((rt = (ULONG)(VMAllocKHB(VM_HKH_PUB_RESRW, sizeof(kPDPB_t),
				 RASOWNER, 0,
				 SSToDS(&pkPDPB)))
	) != PLD_Success)
	   return(rt);		/* storage request fails exit		  */

    /*	Zero out buffer 						  */
    memset(pkPDPB,'\0', sizeof(kPDPB_t));

    pkPDPB->ph.pld_len_PTDA = sizeof(struct ptda_s); /* save size of PTDA */

    pkPDPB->ph.pld_PID	=  uPID;		/* save PID		  */

    rt = (ULONG) TKPidToPTDA((USHORT)uPID,
			      &pkPDPB->ph.ppld_PTDA);

    pkPDPB->ph.pld_ph_Ret_Code	=  rt;		/*Save RC from TKPIDtoPTDA*/

    /* Enter Critical Section - make sure no threads in this PID run	  */
    if (rt == PLD_Success)
       rt = PLDEnterCritSec();

    pld_rt = rt;				       /*	     A005 */

    /* Open Dump File - make sure we have a file to write to		  */
    if (rt == PLD_Success)
     { /* Enter Critical Section Worked make sure we exit Critical Section*/
/********/
       /* Build the filename of the dump files */
       memset(SSToDS(dumpfile), 0, PDUMPFILENAMELENGTH);
       memset(SSToDS(hdrfile), 0, PDUMPFILENAMELENGTH);
       dumpfile[0] = hdrfile[0] = DumpProcess;
       dumpfile[1] = hdrfile[1] = ':';
       dumpfile[2] = hdrfile[2] = '\\';
       strcpy(SSToDS(&dumpfile[3]), DUMPNAME);
       strcpy(SSToDS(&hdrfile[3]), HDRNAME);

       /* Open Data Dump File */
       pld_rt = OpenDump(SSToDS(phfile), SSToDS(dumpfile));

       /* Open Hdr Dump File */
       if (pld_rt == PLD_Success)
	{
	  rt = OpenDump(SSToDS(phfiletab), SSToDS(hdrfile));
	  /* If the second open failed, close the first file. */
	  if (rt != PLD_Success)
	   { /* no action required if these fail	      */
	    pkPDPB->myrc.DMP_OPEN_HDR_RC  = rt;     /*			   */
	    ulDmpArea = PLD_DMP_ALL;		    /*		      A005 */
	    PLDFormatMainHeader(pkPDPB, ulTrapNumber, ulDmpArea);
	    pkPDPB->mh.pld_mh_MHRC = rt;	    /* MAIN HEADER RC A005 */
	    PLDWriteHeaders(hfile, pkPDPB);
	   }
	  else
	  {
       /*********************************************************************/
       /** Both DUMP FILES are open at this point.		      A005 **/
       /** Make sure they get closed.				      A005 **/
       /*********************************************************************/

	  /* Write count to the dump file			  61720   */
	  count = 0;				   /*		  61720   */
	  rt = BfWrite(hfiletab, (UCHAR *) SSToDS(&count), sizeof(ULONG));
	  pkPDPB->myrc.DMP_WRT_CNT_RC	= rt;	     /* 		    */

       /*********************************************************************/
       /** If the first write was successful then get the dump	      A005 **/
       /** information. Note these routines will always return zero   A005 **/
       /*********************************************************************/

	  /*  Format Main Headers				     A005 */
	  ulDmpArea = PLD_DMP_ALL;		  /*		     A005 */
	  rt = PLDFormatMainHeader(pkPDPB, ulTrapNumber, ulDmpArea);

	  /*  Set up Object Information 				  */
	  rt =	PLDObjectInfo(pkPDPB);

	  /*  Set up Thread Information 				  */
	  rt =	PLDThreadInfo(pkPDPB);

	  /*  Get LDT Entries						  */
	  rt =	PLDLDTInfo(pkPDPB);

       /*********************************************************************/
       /** Always write the headers to the DUMP FILE		      A005 **/
       /** THIS ROUTINE CAN FAIL AND GIVE A NON ZERO RETURN CODE      A005 **/
       /*********************************************************************/
	  rt = PLDWriteHeaders(hfile, pkPDPB);
	  pkPDPB->myrc.DMP_WRT_HDR_RC	= rt;	    /*			    */

   /*************************************************************************/
   /** If there are no errors up to now DUMP THE REQUESTED INFORMATIONA005 **/
   /*************************************************************************/
   /** ulDmpArea is 0xXXYYRRRR					      A005 **/
   /**		 XX   - is reserved set to zero 		      A005 **/
   /**		   YY - is the requested area to be dumped	      A005 **/
   /**		 RRRR - is set to zero				      A005 **/
   /*************************************************************************/

	  ulDmpArea	&= PLD_DMP_ALL; 	      /*	    A005 */
	  pkPDPB->myrc.DMP_AREA       = ulDmpArea;	  /*		 */
	  pkPDPB->myrc.DMP_VMAR_RC    = PLD_DMP_VMAR;	  /*		 */
	  pkPDPB->myrc.DMP_VMOB_RC    = PLD_DMP_VMOB;	  /*		 */
	  pkPDPB->myrc.DMP_MTE_RC     = PLD_DMP_MTE;	  /*		 */
	  pkPDPB->myrc.DMP_THREAD_RC  = PLD_DMP_THREAD;   /*		 */
	  pkPDPB->myrc.DMP_LDT_RC     = PLD_DMP_LDT;	  /*		 */

	  if (ulDmpArea & PLD_DMP_VMAR) 	      /*	    A005 */
	  {					      /*	    A005 */
	     rt = PLDWrVmarInfo(hfile, hfiletab, pkPDPB);
						      /*	    A005 */
	     if (rt != PLD_Success)		      /*	    A005 */
	     {					      /*	    A005 */
		pkPDPB->myrc.DMP_VMAR_RC |= rt;       /*	    A005 */
		rt = PLD_Success;		      /*	    A005 */
	     }					      /*	    A005 */
	  }					      /*	    A005 */
	  else					      /*	    A005 */
	  {					      /*	    A005 */
	     pkPDPB->myrc.DMP_VMAR_RC |= PLD_DMP_NOT_REQ; /*	    A005 */
	  }					      /*	    A005 */

	  if (ulDmpArea & PLD_DMP_VMOB) 	      /*	    A005 */
	  {					      /*	    A005 */
	  rt = PLDWrVmobInfo(hfile, hfiletab, pkPDPB);
						      /*	    A005 */
	     if (rt != PLD_Success)		      /*	    A005 */
	     {					      /*	    A005 */
		pkPDPB->myrc.DMP_VMOB_RC |= rt;       /*	    A005 */
		rt = PLD_Success;		      /*	    A005 */
	     }					      /*	    A005 */
	  }					      /*	    A005 */
	  else					      /*	    A005 */
	  {					      /*	    A005 */
	     pkPDPB->myrc.DMP_VMOB_RC |= PLD_DMP_NOT_REQ; /*	    A005 */
	  }					      /*	    A005 */

	  if (ulDmpArea & PLD_DMP_MTE)		      /*	    A005 */
	  {					      /*	    A005 */
	  rt = PLDWrMteInfo(hfile, hfiletab, pkPDPB);
						      /*	    A005 */
	     if (rt != PLD_Success)		      /*	    A005 */
	     {					      /*	    A005 */
		pkPDPB->myrc.DMP_MTE_RC |= rt;	      /*	    A005 */
		rt = PLD_Success;		      /*	    A005 */
	     }					      /*	    A005 */
	  }					      /*	    A005 */
	  else					      /*	    A005 */
	  {					      /*	    A005 */
	     pkPDPB->myrc.DMP_MTE_RC |= PLD_DMP_NOT_REQ; /*	    A005 */
	  }					      /*	    A005 */

	  if (ulDmpArea & PLD_DMP_THREAD)	      /*	    A005 */
	  {					      /*	    A005 */
	  rt = PLDWrThreadInfo(hfile, hfiletab, pkPDPB);
						      /*	    A005 */
	     if (rt != PLD_Success)		      /*	    A005 */
	     {					      /*	    A005 */
		pkPDPB->myrc.DMP_THREAD_RC |= rt;     /*	    A005 */
		rt = PLD_Success;		      /*	    A005 */
	     }					      /*	    A005 */
	  }					      /*	    A005 */
	  else					      /*	    A005 */
	  {					      /*	    A005 */
	     pkPDPB->myrc.DMP_THREAD_RC |= PLD_DMP_NOT_REQ; /*	    A005 */
	  }					      /*	    A005 */

	  if (ulDmpArea & PLD_DMP_LDT)		      /*	    A005 */
	  {					      /*	    A005 */
	  rt = PLDWrLdtInfo(hfile, hfiletab, pkPDPB);
						      /*	    A005 */
	     if (rt != PLD_Success)		      /*	    A005 */
	     {					      /*	    A005 */
		pkPDPB->myrc.DMP_LDT_RC |= rt;	      /*	    A005 */
		rt = PLD_Success;		      /*	    A005 */
	     }					      /*	    A005 */
	  }					      /*	    A005 */
	  else					      /*	    A005 */
	  {					      /*	    A005 */
	     pkPDPB->myrc.DMP_LDT_RC |= PLD_DMP_NOT_REQ; /*	    A005 */
	  }					      /*	    A005 */


	  /** Write the characters "MEMORYTABLE " into the dumpt file  A005 **/
	  memcpy (SSToDS(&memtable),PLD_Mem_Table,12);	 /*	       A005 */

	  rt = BfWrite(hfile, SSToDS(&memtable), 12);	 /*	       A005 */

	  /* Locate address to point to the memory table header */
	  mh = &pkPDPB->mh;
	  TablePtr = (ULONG) ( (UCHAR *) &mh->PLD_Memory_Table -
			       (UCHAR *) mh );

	  /* The current file position is the location of the memory table:
	   * put it into the main header.
	   */
	     rt = WrtCurFilePosToFilePtr(hfile, TablePtr);

	  /* Copy header file to the end of the dump file */
	  rt = CopyDumpHdr(hfile, hfiletab);
	  pkPDPB->myrc.DMP_WRT_MEM_TBL_RC = rt;     /*			    */


	  /** Write the characters "MEM_TAB_END " into the dump file  A005 **/
	  memcpy (SSToDS(&memtable),PLD_Mem_Table_End,12); /*	       A005 */

	  rt = BfWrite(hfile, SSToDS(&memtable), 12);	 /*	       A005 */

	  /******************************************************************/
	  /* Close the dump header file 				    */
	  /******************************************************************/
	  rt = PLDClose(hfiletab);

	  if (rt != PLD_Success)			 /*	       A005 */
	  {						 /*	       A005 */
	     pld_rt = rt;				 /*	       A005 */
	     rt = PLD_Success;				 /*	       A005 */
	  }						 /*	       A005 */

	  /******************************************************************/
	  /* Delete the header						    */
	  /******************************************************************/
	  rt =	PDDel( SSToDS(hdrfile));

	  if (rt != PLD_Success)			 /*	       A005 */
	  {						 /*	       A005 */
	     pld_rt = rt;				 /*	       A005 */
	     rt = PLD_Success;				 /*	       A005 */
	  }						 /*	       A005 */

	}  /** The Main DUMP File must be Closed.		      A005 **/

	  /** Write Return Codes into the dump	file			   **/
	  rt = BfWrite(hfile, (UCHAR *) &pkPDPB->myrc, sizeof(PLD_RET_CODE)); /*      */

	  /******************************************************************/
	  /* Close the dump file					    */
	  /******************************************************************/
	  rt = PLDClose(hfile);

	  if (rt != PLD_Success)			 /*	       A005 */
	  {						 /*	       A005 */
	     pld_rt = rt;				 /*	       A005 */
	     rt = PLD_Success;				 /*	       A005 */
	  }						 /*	       A005 */

	} /* End if the dump file is open			    A005  */

       /*******************************************************************/
       /* Exit critical section - allow all threads in this PID run	  */
       /*******************************************************************/
       rt = PLDExitCritSec();

       if (rt != PLD_Success)				 /*	       A005 */
       {						 /*	       A005 */
	  pld_rt = rt;					 /*	       A005 */
	  rt = PLD_Success;				 /*	       A005 */
       }						 /*	       A005 */

     } /* End if Enter Critical Section 				  */

    rt = pld_rt;					 /*	       A005 */

    VMFreeKHB(VM_HKH_PUB_RESRW,pkPDPB);

    return(rt);

}  /* ***     END  PLD32ApiDump     *** */

/***LP	PLDFormatMainHeader - Set up the Main Header for Process Dump
 *
 *	This function is swappable.
 *
 *	ENTRY
 *		kPDPB_t
 *		ulTrapNumber
 *		ulDmpArea
 *
 *	EXIT
 *		Return Value == 0
 *			No Error.	kDB valid, uDB.Cmd verified
 *
 *		All Other Return Values
 *			kDB invalid. (Protection Violation)
 *			Immediately propogate return value
 *			back to the application.
 *	Pseudocode:
 *
 *
 *
 */

ULONG PLDFormatMainHeader (kPDPB_t *pkPDPB,
			   ULONG ulTrapNumber,
			   ULONG ulDmpArea)
{
    ULONG rt  = PLD_Success;
/***   Process Level Dump Kernel Type init to zero for RETAIL		 ***/
    ULONG  PLDKrnlType = 0L;		      /* zero is RETAIL      61720 */

#ifdef DBGSTRICT
/***   Process Level Dump Kernel Type init to one  for DEBUG		 ***/
    PLDKrnlType = PLD_Debug_Krnl;	      /* 0x00010000 is debug 61720 */
#endif

#ifdef SMP
/***   Process Level Dump Kernel Type init for SMP			 ***/
    PLDKrnlType = PLD_SMP_Krnl | PLDKrnlType; /* 0x20000000 is debug  A003 */
#endif

    pkPDPB->mh.pld_mh_ID = PLD_C_TYPE | PLDKrnlType;	 /*	     61720 */
    pkPDPB->mh.pld_mh_TrapType = ulTrapNumber;
    pkPDPB->mh.pld_mh_PDVersion = PLD_C_VerZero;

    /* Get the date and time */
    PLDGetDateTime(&pkPDPB->mh.pld_mh_DateTime);

    /* Get the OS2 Version String */
    PLDGetVerString(&(pkPDPB->mh.VerString),
		    &(pkPDPB->mh.pld_mh_VerSize));

    /* Fill in all EyeCatchers	  */
    memcpy (&pkPDPB->mh.PLD_mh_EyeCatcher[0],PLD_Cmh_EyeCatcher,4);

    memcpy (&pkPDPB->ph.PLD_ph_EyeCatcher[0],PLD_Cph_EyeCatcher,4);

    memcpy (&pkPDPB->tcbH.PLD_tcb_EyeCatcher[0],PLD_Ctcb_EyeCatcher,4);

    memcpy (&pkPDPB->vmarH.PLD_vmar_EyeCatcher[0],PLD_Cvmar_EyeCatcher,4);

    memcpy (&pkPDPB->vmobH.PLD_vmob_EyeCatcher[0],PLD_Cvmob_EyeCatcher,4);

    memcpy (&pkPDPB->mteH.PLD_mte_EyeCatcher[0],PLD_Cmte_EyeCatcher,4);

    memcpy (&pkPDPB->ldtH.PLD_ldt_EyeCatcher[0],PLD_Cldt_EyeCatcher,4);

    pkPDPB->mh.pld_mh_MHRC = PLD_Success;	 /* MAIN HEADER RC     A005 */

    pkPDPB->mh.pld_mh_REQ = ulDmpArea;		 /* AREAs to be DUMPED A005 */

    return(PLD_Success);			 /*		       A005 */

}  /* ***     END  PLDFormatMainHeader	 *** */

/***LP	PLDObjectInfo - Get Object Information from the Private Arena Only
 *
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDObjectInfo (kPDPB_t *pkPDPB)
{

    PTDA	  *p_PTDA;		/* Pointer to PTDA		    */
    register VMAR *parwrk;		/* Pointer to current arena record  */
    register VMAR *parnext;		/* Pointer to next arena record     */
    register VMAR *parSen;		/* Pointer to arena sentinel	    */

    VMOB	  *pob; 		/* Pointer to object record	    */
    ldrmte_t	  *pobmte;		/* Pointer to MTE record	    */
    ldrsmte_t	  *pobsmte;		/* Pointer to swappable MTE	    */

    PLD_VMARDATA  *pVMARD;
    PLD_VMOBDATA  *pVMOBD;
    PLD_MTEDATA   *pMTED;

  PVOID vmar_rt = NULL,
	vmob_rt = NULL,
	mte_rt	= NULL;

  int	rc = 0; 			/* number of Arena Records     A006 */

  ULONG i  = 0, 			/* index into the ob_outarray	    */
	m  = 0, 			/* index into the mte_outarray	    */
	ah = 0, 			/* number of Arena Records	    */
	mh = 0; 			/* hold index into the mte_outarray */

  USHORT mte_done = 0x0000;		/*			       A006 */

    p_PTDA = pkPDPB->ph.ppld_PTDA;	      /* save PTDA ADDRESS	    */

     /*  Set the size fields						    */
    pkPDPB->vmarH.PLD_vmar_size =	      /* Length of Arena  Record    */
		    sizeof(struct vmar_s);    /*			    */

    pkPDPB->vmobH.PLD_vmob_size =	      /* Length of Object Record    */
		    sizeof(struct vmob_s);    /*			    */

    pkPDPB->mteH.PLD_mte_size = 	      /* Length of MTE non swappable*/
		    sizeof(struct ldrmte_s);  /*			    */

    pkPDPB->mteH.PLD_smte_size =	      /* Length of SMTE  swappable  */
		    sizeof(struct ldrsmte_s); /*			    */

     /*  Point to sentinel for private arena				    */
    parSen = p_PTDA->ptda_ah.ah_parSen; 	/* Map arena sentinel	    */

     /* Map 1st arena record after sentinel				    */
    parnext = pldArMap(parSen->ar_harnext);

     /* Arena area we are using in the pkPDPB structure 		    */
    pVMARD = &pkPDPB->vmarD;

     /* Object area we are using in the pkPDPB structure		    */
    pVMOBD = &pkPDPB->vmobD;

     /* MTE area we are using in the pkPDPB structure			    */
    pMTED = &pkPDPB->mteD;

     /* If there is an area record					    */
    while(parnext != parSen)
    {
       /* This is the arena record we are working with			    */
      parwrk = parnext;

      if (ah < PLD_MAX)
       { /* save the address of this record to dump it latter		    */
	 pVMARD->PLD_vmar_array[ah] = parwrk;
	 ah++;
       } /* if end */
      else
       {
	 pkPDPB->vmarH.PLD_vmar_StrReq++;	  /* Storage Request	    */
	 vmar_rt = PLDGetStorage (sizeof(PLD_VMARDATA));
	 if (vmar_rt != NULL)
	  {
	    pkPDPB->vmarH.PLD_vmar_total =
		    pkPDPB->vmarH.PLD_vmar_total + ah;

	    pVMARD->PLD_vmar_cnt = ah;

	    /* Save pointer to FIRST VMAR			     A001*/
	    if ( pkPDPB->vmarH.PLD_pvmar == NULL )
	     {
		pkPDPB->vmarH.PLD_pvmar =	       /*	     A001*/
			   pVMARD->PLD_vmar_array[0];  /*	     A001*/
	     } /* if end */

	    ah = 0;
	    pVMARD->PLD_vmar_next = vmar_rt;
	    pVMARD = pVMARD->PLD_vmar_next;	 /* this is new storage  */
	    pVMARD->PLD_vmar_array[ah] = parwrk;
	    ah++;
	  } /* if end */
	 else
	  {  pkPDPB->vmarH.PLD_vmar_StrFail++; }  /* Storage Request Failed */
       } /* else end */

       /* Convert the object handle from the arena record to pointer to     */
       /* the object record						    */

      pob = pldHandleMap(parwrk->ar_hob);

       /* Save the pointer to the Object Record in ob_outarray		    */
      if ( i < PLD_MAX)
       { /* save the address of this record to dump it latter		    */
	 pVMOBD->PLD_vmob_array[i] = pob;
	 i++;
       } /* if end */
      else
       {
	 pkPDPB->vmobH.PLD_vmob_StrReq++;	  /* Storage Request	    */

	 vmob_rt = PLDGetStorage (sizeof(PLD_VMOBDATA));
	 if (vmob_rt != NULL)
	  {
	    pkPDPB->vmobH.PLD_vmob_total =
		    pkPDPB->vmobH.PLD_vmob_total + i;

	    pVMOBD->PLD_vmob_cnt = i;

	    /* Save pointer to FIRST VMOB			     A001*/
	    if ( pkPDPB->vmobH.PLD_pvmob == NULL )
	     {
		pkPDPB->vmobH.PLD_pvmob =	       /*	     A001*/
			   pVMOBD->PLD_vmob_array[0];  /*	     A001*/
	     } /* if end */

	    i = 0;
	    pVMOBD->PLD_vmob_next = vmob_rt;
	    pVMOBD = pVMOBD->PLD_vmob_next;	 /* this is new storage  */
	    pVMOBD->PLD_vmob_array[i] = pob;
	    i++;
	  } /* if end */
	 else
	  {  pkPDPB->vmobH.PLD_vmob_StrFail++; }  /* Storage Request Failed */
       } /* else end */

       /*******************************************************************/
       /* We want to dump all MTE's associated with this Process      A006*/
       /* mte_done is set to a non zero value if we dump all MTE's.   A006*/
       /*******************************************************************/

      if ( mte_done == 0x0000 ) /* we still want to dump MTE's        A006*/
       { /* Dump all MTE info available at this time		      A006*/
	rc = LDRGetSem();			    /*		      A006*/
	if ( rc == NO_ERROR )			    /*		      A006*/
	 {  /* start dump all MTE's for this process                  A006*/
						    /*		      A006*/
	   ldrMarkTaskInGraph(p_PTDA, NULL);	    /*		      A006*/
	   ldrFindGraph(TRUE);			    /*		      A006*/
						    /*		      A006*/
	   /* Walk MTE chain to find all MTE's we marked              A006*/
	   for ( pobmte = mte_h;		    /*		      A006*/
		 pobmte != NULL;		    /*		      A006*/
		 pobmte = pobmte->mte_link )	    /*		      A006*/
	      { 				    /*		      A006*/
	      if (pobmte->mte_flags1 & INGRAPH)     /*		      A006*/
		 {				    /*		      A006*/
		 /* This MTE is referenced dump it		      A006*/

      pobsmte = pobmte->mte_swapmte;

       /* Save the pointer to the MTE in mte_array			    */
      if ( m < PLD_MAX )
       {  /* do not save the MTE pointer if we already have it in this array*/
	  /*we are not checking previous arrays therefore dupes are possible*/
	 for (mh = 0; mh < m; mh++)
	  { /* if we have the pointer write over it, otherwise put at end   */
	    if (pobmte == pMTED->PLD_mte_array[mh])
	     { break;  }
	    else
	     { continue;  }
	  } /* for end */
	 if (mh == m)
	  {   /* mh is equal m if no match is found		    */
	     pMTED->PLD_mte_array[m] = pobmte;
	     pMTED->PLD_smte_array[m] = pobsmte;
	     pMTED->PLD_smte_objtab_array[m] = pobsmte->smte_objtab;
	     pMTED->PLD_smte_objtab_size[m] = pobsmte->smte_objcnt *
					     sizeof(struct ldrote_s);

	     pMTED->PLD_smte_path_array[m] = pobsmte->smte_path;      /*A002*/
	     pMTED->PLD_smte_path_size[m] = pobsmte->smte_pathlen;    /*A002*/

	     m++;

	  } /* if end */
       } /* if end */
      else
       {
	 pkPDPB->mteH.PLD_mte_StrReq++; 	  /* Storage Request	    */

	 mte_rt = PLDGetStorage (sizeof(PLD_MTEDATA));
	 if (mte_rt != NULL)
	  {
	    pkPDPB->mteH.PLD_mte_total =
		    pkPDPB->mteH.PLD_mte_total + m;

	    pMTED->PLD_mte_cnt = m;

	    /* Save pointer to FIRST MTE			     A001*/
	    if ( pkPDPB->mteH.PLD_pmte == NULL )
	     {
		pkPDPB->mteH.PLD_pmte = 	       /*	     A001*/
			   pMTED->PLD_mte_array[0];    /*	     A001*/
	     } /* if end */

	    /* Save pointer to FIRST SMTE			     A001*/
	    if ( pkPDPB->mteH.PLD_psmte == NULL )
	     {
		pkPDPB->mteH.PLD_psmte =	       /*	     A001*/
			   pMTED->PLD_smte_array[0];   /*	     A001*/
	     } /* if end */

	    m = 0;
	    pMTED->PLD_mte_next = mte_rt;
	    pMTED = pMTED->PLD_mte_next;	 /* this is new storage  */
	    pMTED->PLD_mte_array[m] = pobmte;
	    pMTED->PLD_smte_array[m] = pobsmte;
	    pMTED->PLD_smte_objtab_array[m] = pobsmte->smte_objtab;
	    pMTED->PLD_smte_objtab_size[m] = pobsmte->smte_objcnt *
					    sizeof(struct ldrote_s);

	    pMTED->PLD_smte_path_array[m] = pobsmte->smte_path;      /* A002*/
	    pMTED->PLD_smte_path_size[m] = pobsmte->smte_pathlen;    /* A002*/

	    m++;

	  } /* if end */
	 else
	  {  pkPDPB->mteH.PLD_mte_StrFail++; }	  /* Storage Request Failed */
       } /* else end */
		 }				    /*		      A006*/
	      } 				    /*		      A006*/
						    /*		      A006*/
	   ldrClearGraph();			    /*		      A006*/
	   LDRClearSem();			    /*		      A006*/
	   mte_done ++; 			    /*		      A006*/
	 }  /* end   dump all MTE's for this process                  A006*/
						    /*		      A006*/
       } /* We have dumped all MTE info available at this time	      A006*/

       /* Map next arena record 					    */
      parnext = pldArMap(parnext->ar_harnext);
    }

    pkPDPB->vmarH.PLD_vmar_total = pkPDPB->vmarH.PLD_vmar_total + ah;
    pVMARD->PLD_vmar_cnt = ah;

    pkPDPB->vmobH.PLD_vmob_total = pkPDPB->vmobH.PLD_vmob_total + i;
    pVMOBD->PLD_vmob_cnt = i;

    pkPDPB->mteH.PLD_mte_total = pkPDPB->mteH.PLD_mte_total + m;
    pMTED->PLD_mte_cnt = m;

    /* Save pointer to FIRST VMAR				     A001*/
    if ( pkPDPB->vmarH.PLD_pvmar == NULL )
     {
	pkPDPB->vmarH.PLD_pvmar =		       /*	     A001*/
		   pVMARD->PLD_vmar_array[0];	       /*	     A001*/
     } /* if end */

    /* Save pointer to FIRST VMOB				     A001*/
    if ( pkPDPB->vmobH.PLD_pvmob == NULL )
     {
	pkPDPB->vmobH.PLD_pvmob =		       /*	     A001*/
		   pVMOBD->PLD_vmob_array[0];	       /*	     A001*/
     } /* if end */

    /* Save pointer to FIRST MTE				     A001*/
    if ( pkPDPB->mteH.PLD_pmte == NULL )
     {
	pkPDPB->mteH.PLD_pmte = 		       /*	     A001*/
		   pMTED->PLD_mte_array[0];	       /*	     A001*/
     } /* if end */

    /* Save pointer to FIRST SMTE				     A001*/
    if ( pkPDPB->mteH.PLD_psmte == NULL )
     {
	pkPDPB->mteH.PLD_psmte =		       /*	     A001*/
		   pMTED->PLD_smte_array[0];	       /*	     A001*/
     } /* if end */

    return(PLD_Success);			    /*		     A005  */

}  /* ***     END  PLDObjectInfo  *** */

/***LP	PLDThreadInfo - Get Thread Information
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDThreadInfo (kPDPB_t *pkPDPB)
{

    PTDA	  *p_PTDA;		/* Pointer to PTDA		    */
    tcb_t	  *pTCBwrk;		/*Pointer to TCB we are working with*/
    PVOID	  tcb_rt = NULL;
    register PLD_TCBDATA  *pTCBD;
    struct tib_s   *p_TIB;		/* Pointer to Thread Information Blk*/
    SEL 	       sel;		/* selector from the TCB	    */
    ULONG uESP	= 0L;
    struct kmreg_s  ulReg;		/* Return desc info pointer	    */
    PKMREG   pulReg = SSToDS(&ulReg);
    struct seldesc_s  desc;		/* Return desc info pointer	    */
    USHORT got_str;			/* result code			    */
    USHORT cur_tcb;			/* Current TCB Ordinal Number	    */
    ULONG rt = 0,			/* result code			    */
	  cb = 0,			/* index into the tcb_array	    */
	  act_size = 0; 		/* actual size			    */

    p_PTDA = pkPDPB->ph.ppld_PTDA;	    /* save PTDA ADDRESS	    */
    got_str=pkPDPB->tcbH.PLD_tcb_StrFail;   /* Storage Request Failed	    */

     /*  Set the size fields						    */
    pkPDPB->tcbH.PLD_tcb_size = 	      /* Length of TCB		    */
		    sizeof(struct tcb_s);     /*			    */

     /* TCB area we are using in the pkPDPB structure			    */
    pTCBD = &pkPDPB->tcbD;

     /* Current tcb will be used latter 				    */
    cur_tcb = pTCBCur->TCBOrdinal;	    /* pTCBCur is global in system  */

     /* Loop to examine all TCBs					    */
    for(pTCBwrk  = p_PTDA->ptda_pTCBHead;   /* First in list of active TCBs */
	pTCBwrk != NULL;		    /* Termination condition	    */
	pTCBwrk  = pTCBwrk->TCBpTCBNext)    /* Get the next TCB in the list */
    {

      if (cb >= PLD_MAX)		 /* if there is no room in the array*/
       {
	 pkPDPB->tcbH.PLD_tcb_StrReq++;     /* Request Storage		    */

	 tcb_rt = PLDGetStorage (sizeof(PLD_TCBDATA));
	 if (tcb_rt != NULL)
	  {
	    pTCBD->PLD_tcb_cnt = cb;

	    cb = 0;
	    pTCBD->PLD_tcb_next = tcb_rt;
	    pTCBD = pTCBD->PLD_tcb_next;	 /* this is new storage  */
	  } /* if end */
	 else
	  {  pkPDPB->tcbH.PLD_tcb_StrFail++; }	/* Storage Request Failed   */
       } /* if end */

      /* if we have some to put the information then DO IT		    */
      if (got_str == pkPDPB->tcbH.PLD_tcb_StrFail)
       {
	 /*******************************************************************/
	 /* save the address of this record to dump it latter		    */
	 /* Thread ID for this Thread					    */
	 /*******************************************************************/
	 p_TIB = pTCBwrk->TCBptib;

	 if (p_TIB->tib_ptib2 !=NULL)				     // 100656 davidj
	   pTCBD->tcbent[cb].t_tid = p_TIB->tib_ptib2->tib2_ultid;
	 else							     // 100656 davidj
	   pTCBD->tcbent[cb].t_tid = (ULONG)pTCBwrk->TCBOrdinal;     // 100656 davidj

	 /* Thread Control Block for this Thread			   */
	 pTCBD->tcbent[cb].tcbaddr = pTCBwrk;

	 /* save the current TCB in this THREAD 			   */
	 pTCBD->tcbent[cb].tcb_cur = cur_tcb;

	 /* Client Register information for this Thread 		   */
	 pTCBD->tcbent[cb].criaddr = pTCBwrk->TCB_pcriFrameType;

	 /* Length of Client Register Information for this Thread	   */
	 pTCBD->tcbent[cb].crisize = sizeof(struct cri_s);

	 /* Registers for this Thread					   */
	 pTCBD->tcbent[cb].regaddr = pTCBwrk->TCB_pFrameBase;

	 /* Registers size for this Thread				   */
	 pTCBD->tcbent[cb].regsize =
		      ((PCRI)(pTCBwrk->TCB_pcriFrameType))->cri_ulSize;

	 if (pTCBwrk->TCB_pcriFrameType == &criISF)
	  { pTCBD->tcbent[cb].critype = PLD_criISF; }
	 else
	  {
	    if (pTCBwrk->TCB_pcriFrameType == &criTSF)
	     { pTCBD->tcbent[cb].critype = PLD_criTSF; }
	    else
	     {
	       if (pTCBwrk->TCB_pcriFrameType == &criVSF)
		{ pTCBD->tcbent[cb].critype = PLD_criTSF; }
	       else
		{
		  if (pTCBwrk->TCB_pcriFrameType == &criSEF)
		   { pTCBD->tcbent[cb].critype = PLD_criSEF; }
		  else
		   {
		     if (pTCBwrk->TCB_pcriFrameType == &criPASCALSEF)
		      { pTCBD->tcbent[cb].critype = PLD_criPASCALSEF; }
		     else
		      {
		      if (pTCBwrk->TCB_pcriFrameType == &criSSF)
		       { pTCBD->tcbent[cb].critype = PLD_criSSF; }
		      else
		       {
			 if (pTCBwrk->TCB_pcriFrameType == &criDHF)
			  { pTCBD->tcbent[cb].critype = PLD_criDHF; }
			 else
			  { pTCBD->tcbent[cb].critype = PLD_criUNK; }
		       } /* else end DHF*/
		      } /* else end SSF*/
		   } /* else end PASCALSEF*/
		} /* else end SEF*/
	     } /* else end VSF*/
	  } /* else end ISF */

	 /******************************************************************/
	 /* Stack address for this Thread				   */
	 /* Get user STACK as it appears now not			   */
	 /******************************************************************/
	 if ((rt = KMQueryAllClientRegisters(pTCBwrk, pulReg)
	      ) != PLD_Success)
	  {
	    pTCBD->tcbent[cb].stkaddr  = NULL;	    /* can not get the stack*/
	    pkPDPB->tcbH.PLD_tcb_StkRC = (USHORT) rt; /* stack request failed A005 */
	    rt = PLD_Success;			    /*		       A005 */
	  }
	  else
	  { /* pTCBD->tcbent[cb].stkaddr  = (PVOID) ulReg;  */
	    pTCBD->tcbent[cb].stkaddr  = (PVOID) pulReg->kmreg_esp;
	    uESP = pulReg->kmreg_esp;		   /* User ESP		   */
	    sel = (SEL) (PVOID) pulReg->kmreg_ss;  /* User Stack Selector  */
	  } /* the Users ESP  */

	 /******************************************************************/
	 /*		  Stack size for this Thread			   */
	 /* First, get the stack segment selector of the target thread	   */
	 /* Get the segment descriptor information			   */
	 /******************************************************************/
	 if ((pTCBD->tcbent[cb].stkaddr != NULL) &&
	    ((rt = SELGetDescInfo(sel,
			    p_PTDA->ptda_handle,   /* PTDA HANDLE	*/
			    SSToDS(&desc)))
	     == PLD_Success) )
	 { /************************************************************/
	   /* we have the descriptor info			       */
	   /* Finally, check bit 22 of the first DWORD		       */
	   /* 0 = 16 bit seg 1 = 32 bit seg			       */
	   /************************************************************/
	   if(!(desc.desc_attr & D_COPER32))
	     { /* this is a 16 bit selector			       */
	       pTCBD->tcbent[cb].stkaddr_sel16 = sel;	   /* 16 bit selector*/
	       uESP = 0x0000ffff & uESP;	       /* take off high bits */
	       pTCBD->tcbent[cb].stkaddr_off16 = (USHORT)uESP;/*16 bit offset*/

	       /* Readjust Stack address for this  16 bit Thread	*/
	       pTCBD->tcbent[cb].stkaddr =
			 (PVOID) (uESP +
				  desc.desc_laddr);

	       pTCBD->tcbent[cb].stksize =	     /* Length in bytes*/
		  (ULONG) ((ULONG) desc.desc_cb - uESP);
	     }
	   else
	     { /* this is a 32 bit selector    */
	       /* Stack size was recalculated by defect 77261	       C004 */
	       if (pTCBwrk->TCBpStack == -1)	    /* TCBpSTACK Invalid    */
	       {				    /* TCBpSTACK Invalid    */
		/* need to readjust the stack values			    */
		pTCBD->tcbent[cb].stksize =	    /* Length in bytes	    */
	       (ULONG)((ULONG)	p_TIB->tib_pstacklimit -   /* End of Stack	   */
			(ULONG)pTCBD->tcbent[cb].stkaddr);/* Current ESP    */
	       }				    /* TCBpSTACK Invalid    */
	       else				    /*TCBpSTACK IS valid    */
	       {				    /*TCBpSTACK IS valid    */
		pTCBD->tcbent[cb].stksize =	     /* Length in bytes      */
		      ((pTCBwrk->TCBpStack +	    /* Virtal base of STACK */
			pTCBwrk->TCBcbStackMax) -   /* Virtual size of STACK*/
			(ULONG)pTCBD->tcbent[cb].stkaddr);/* Current ESP    */
	       }				    /*TCBpSTACK IS valid    */


	 //   Remove all of this code with defect 77261 	       D004
	 //   Stacks grow DOWN
	 //
	 //
	 //    act_size =			    /* Actual Stack size    */
	 //	  (ULONG) ((uESP  -		    /* User ESP 	    */
	 //		  (ULONG) pTCBwrk->TCBpStack ) + 1);/* base of stack*/
	 //
	 //    if (act_size > pTCBwrk->TCBcbStackCur)
	 //	{ /* Adjust the stack address for this thread		    */
	 //	  pTCBD->tcbent[cb].stkaddr  =
	 //		  (PVOID) (pTCBwrk->TCBpStack +     /* base of stack */
	 //			   pTCBwrk->TCBcbStackCur); /* committed size*/
	 //
	 //	  /* Stack size for this Thread 			    */
	 //	  pTCBD->tcbent[cb].stksize =	    /* Length in bytes	    */
	 //		 (( act_size -		    /* actual size	    */
	 //		    pTCBwrk->TCBcbStackCur) /* committed size	    */
	 //		    + 1);		    /* last byte	    */
	 //	} /* if end */
	 //    else
	 //	{
	 //	  /* Stack size for this Thread 			    */
	 //	  pTCBD->tcbent[cb].stksize =	    /* Length in bytes	    */
	 //		 ((pTCBwrk->TCBcbStackCur - /* committed size	    */
	 //		    act_size)		    /* actual size	    */
	 //		    + 1);		    /* last byte	    */
	 //	} /* if end */
	     }
	 } /* we could not get the descriptor info		       */
	 else					   /*		   A005    */
	 {					   /*		   A005    */
	   pkPDPB->tcbH.PLD_tcb_StkRC = (USHORT) rt; /*request failedA005  */
	   rt = PLD_Success;			   /*		   A005    */
	 }					   /*		   A005    */

	 /*  This is the total number of TCBs in this dump		    */
	 pkPDPB->tcbH.PLD_tcb_total ++;

	 cb++;

       } /* if end */
      else
       {
	 got_str=pkPDPB->tcbH.PLD_tcb_StrFail;	/* Storage Request Failed   */
       } /* else end */

    } /* end for loop */

    pTCBD->PLD_tcb_cnt = cb;

    return(PLD_Success);			   /*		   A005    */

}  /* ***     END  PLDThreadInfo  *** */

/***LP	PLDLDTInfo - Get LDT Information (Entries)
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDLDTInfo (kPDPB_t *pkPDPB)
{

    PTDA	  *p_PTDA;		/* Pointer to PTDA		    */
    register PLD_LDTDATA  *pLDTD;

    USHORT	   selector, i;
    LDTENTRY	  *Descriptor;

    ULONG m  = 0;		       /* index into the ldt_array	   */

   p_PTDA = pkPDPB->ph.ppld_PTDA;      /* save PTDA ADDRESS		   */

     /* LDT area we are using in the pkPDPB structure			    */
   pLDTD = &pkPDPB->ldtD;

  /* Point to the LDT */
   Descriptor = (LDTENTRY *) p_PTDA->ptda_ldtaddr;

  /* Traverse the LDT, dumping valid Descriptors			    */
   for (i = 0;
	i < MAXLDTENTRIES;
	++i, ++Descriptor)

     /* If the descriptor is valid, save it				  */
      if(DescriptorValid(Descriptor))
       {
	  /* Calculate the Selector					  */
	 selector = (USHORT) ((i << RPL_TI_SIZE) | TI | DPLValue(Descriptor));

	 if (m < MAXLDTENTRIES) 	   /* if there is room in the array*/
	  { /* save this selector and Descriptor to dump it latter	   */
	    pLDTD->ldta[m].PLD_ldt_sel = (ULONG) selector;
	    memcpy (&(pLDTD->ldta[m].PLD_ldt),Descriptor,8);

	    m++;

	  } /* if end */
	 else
	  { pkPDPB->ldtH.PLD_ldt_RC = 1; }     /* LDT Array is to small   */
       }

    /* Save pointer to FIRST LDT				      A001*/
    if ( pkPDPB->ldtH.PLD_pldt == NULL )
     { pkPDPB->ldtH.PLD_pldt = (VOID *) &pLDTD->ldta[0]; }   /*       A001*/

    pkPDPB->ldtH.PLD_ldt_total = pkPDPB->ldtH.PLD_ldt_total + m;

    pkPDPB->ldtH.PLD_ldt_size = 		   /* Length of selector and*/
		(m * (sizeof(struct _ldtarray)));  /* LDTENTRY		    */

    pLDTD->PLD_ldt_cnt = m;

    return(PLD_Success);			   /*		   A005    */

}  /* ***     END  PLDLDTInfo  *** */

/***LP	PLDGetStorage - Get Storage
 *
 *	Entry	   stor_size - Length of storage to get
 *
 *	Exit	   storage address - if successful
 *		   NULL 	   - if unsuccessful
 *
 */

PVOID  PLDGetStorage(ULONG stor_size)
{
   PLONG	   pstor_addr;

   if ( (ULONG)(VMAllocKHB(VM_HKH_PUB_RESRW, stor_size,
				RASOWNER, 0,
				SSToDS(&pstor_addr))) != PLD_Success)

       return(NULL);

    /*	Zero out buffer and return				       */
    memset(pstor_addr, 0, stor_size);
    return((PVOID)pstor_addr);

}   /* ****    PLDGetStorage   *************** */

/***LP	WrtCurFilePosToFilePtr
 *
 *	Write the current file position to the location indicated by FilePtr.
 *	Then return the file position to the same location prior to the
 *	function call.
 *
 *	Entry	   hfile -   file handle
 *		   FilePtr - position to which current file position is
 *			     to be written
 *
 *	Exit	   PLD_Success if successful
 *		   !0 if error (return code indicates error)
 *
 */

ULONG  WrtCurFilePosToFilePtr(HFILE hfile, ULONG FilePtr)

{
   ULONG	   rc,
		   CurPos;

  /* Get the current file position */
   if (rc = GetFilePtr(hfile, SSToDS(&CurPos)) )
       return rc;

  /* Position the file pointer to the input file address */
   if (rc = PDSeek(hfile, FilePtr, FILE_BEGIN, NULL))
       return rc;

  /* Write the current file position to the specified file pointer */
   if (rc = BfWrite(hfile, (UCHAR *) SSToDS(&CurPos), sizeof(ULONG)))
       return rc;

  /* Reposition the file pointer */
   return(PDSeek(hfile, CurPos, FILE_BEGIN, NULL));
}

/***LP	PLDWriteHeaders - Write PLD Headers
 *
 *	Write the PLD Headers
 *
 *	Entry	   hfile -   file handle
 *
 *	Exit	   PLD_Success if successful
 *		   !0 if error (return code indicates error)
 *
 */

ULONG  PLDWriteHeaders(HFILE hfile, kPDPB_t *pkPDPB)

{
   ULONG    NextPtr,
	    SummaryPtr,
	    rc;


   PLD_MH  *mh = &pkPDPB->mh;

   PLD_PH  *ph = &pkPDPB->ph;

/* Main Header*/
  /* Dump the main header */
   if(rc = BfWrite(hfile, (UCHAR *) &pkPDPB->mh, sizeof(PLD_MH)) )
      return rc;

  /* Locate address to point to the Version String */
   NextPtr = (ULONG) ( (UCHAR *) &mh->pld_mh_VerOff -
		       (UCHAR *) mh );

  /* The current file position is the location of the Version String:
   * put it into the main header.
   */
   if(rc = WrtCurFilePosToFilePtr(hfile, NextPtr))
      return rc;

  /* Write the version string. */
   if(rc = BfWrite(hfile, (UCHAR *) mh->VerString, mh->pld_mh_VerSize) )
      return rc;

  /* Locate address to point to the process header */
   NextPtr = (ULONG) ( (UCHAR *) &mh->ProcessTable -
		       (UCHAR *) mh );

  /* The current file position is the location of the process table:
   * put it into the main header.
   */
   if(rc = WrtCurFilePosToFilePtr(hfile, NextPtr))
      return rc;

/* Process Header */
  /* Get the location of pointer to the thread header. */
   if(rc = GetFilePtr(hfile, SSToDS(&NextPtr)) )
      return rc;
   NextPtr += (ULONG) ( (UCHAR *) &pkPDPB->ph.ThreadTable -
			(UCHAR *) &pkPDPB->ph );

  /* Dump the process header. */
   if(rc = BfWrite(hfile, (UCHAR *) &pkPDPB->ph, sizeof(PLD_PH)) )
      return rc;

  /* The current file position is the location of the thread table:
   * put it into the process header.
   */
   if(rc = WrtCurFilePosToFilePtr(hfile, NextPtr))
      return rc;

/* Thread Header */
  /* Get the location of pointer to the VMAR header. */
   if(rc = GetFilePtr(hfile, SSToDS(&NextPtr)) )
      return rc;
  /* Save this pointer to later calculate SummaryPtr */
   SummaryPtr = NextPtr;
   NextPtr += (ULONG) ( (UCHAR *) &pkPDPB->tcbH.VmarTable -
			(UCHAR *) &pkPDPB->tcbH );
   SummaryPtr += (ULONG) ( (UCHAR *) &pkPDPB->tcbH.ThreadSummary -
			 (UCHAR *) &pkPDPB->tcbH );

  /* Dump the thread header. */
   if(rc = BfWrite(hfile, (UCHAR *) &pkPDPB->tcbH, sizeof(PLD_TCBHDR)) )
      return rc;

  /* Write the summary header */
   if(rc = WrtCurFilePosToFilePtr(hfile, SummaryPtr))
      return rc;
  /* Now, write the summary table. */
   if(rc = PLDWrThreadSumm(hfile, pkPDPB))
      return rc;

  /* The current file position is the location of the VMAR header:
   * put it into the thread header.
   */
   if(rc = WrtCurFilePosToFilePtr(hfile, NextPtr))
      return rc;

/* VMAR Header */
  /* Get the location of pointer to the VMOB header. */
   if(rc = GetFilePtr(hfile, SSToDS(&NextPtr)) )
      return rc;
   NextPtr += (ULONG) ( (UCHAR *) &pkPDPB->vmarH.VmobTable -
			(UCHAR *) &pkPDPB->vmarH );

  /* Dump the VMAR header. */
   if(rc = BfWrite(hfile, (UCHAR *) &pkPDPB->vmarH, sizeof(PLD_VMARHDR)) )
      return rc;

  /* The current file position is the location of the VMOB header:
   * put it into the arena header.
   */
   if(rc = WrtCurFilePosToFilePtr(hfile, NextPtr))
      return rc;

/* VMOB Header */
  /* Get the location of pointer to the MTE header. */
   if(rc = GetFilePtr(hfile, SSToDS(&NextPtr)) )
      return rc;
   NextPtr += (ULONG) ( (UCHAR *) &pkPDPB->vmobH.MteTable -
			(UCHAR *) &pkPDPB->vmobH );

  /* Dump the VMOB header. */
   if(rc = BfWrite(hfile, (UCHAR *) &pkPDPB->vmobH, sizeof(PLD_VMOBHDR)) )
      return rc;

  /* The current file position is the location of the MTE header:
   * put it into the object header.
   */
   if(rc = WrtCurFilePosToFilePtr(hfile, NextPtr))
      return rc;

/* MTE Header */
  /* Get the location of pointer to the LDT header. */
   if(rc = GetFilePtr(hfile, SSToDS(&NextPtr)) )
      return rc;
   NextPtr += (ULONG) ( (UCHAR *) &pkPDPB->mteH.LdtTable -
			(UCHAR *) &pkPDPB->mteH );

  /* Dump the MTE header. */
   if(rc = BfWrite(hfile, (UCHAR *) &pkPDPB->mteH, sizeof(PLD_MTEHDR)) )
      return rc;

  /* The current file position is the location of the LDT header:
   * put it into the mte header.
   */
   if(rc = WrtCurFilePosToFilePtr(hfile, NextPtr))
      return rc;

/* LDT Header */

  /* Dump the LDT header. */
   if(rc = BfWrite(hfile, (UCHAR *) &pkPDPB->ldtH, sizeof(PLD_LDTHDR)) )
      return rc;

   return NO_ERROR;
}

/***LP	PLDWrVMARInfo - Write VM Arena Records Information
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDWrVmarInfo (HFILE hfile, HFILE hfiletab, kPDPB_t *pkPDPB)
{

    struct _vmardata *pCurr = NULL;    /*Pointer to current structure	   */

    PLD_PH  *ph = &pkPDPB->ph;

    register PLD_VMARDATA *pVMARD;

  ULONG rt = 0, 			/* result code			    */
	cb = 0; 			/* index into the tcb_array	    */

    /* Write the PTDA, NOTE: This structure is only written once	    */
    rt = WriteWithTableEntry(hfile, hfiletab,
		    (UCHAR *) ph->ppld_PTDA, ph->pld_len_PTDA);
    pkPDPB->myrc.DMP_PTDA_DATA_RC  = rt;	       /*		   */

     /* VMAR area we are using in the pkPDPB structure			    */
    pVMARD = &pkPDPB->vmarD;

    while (pVMARD != NULL)
    {
      for (cb = 0;
	   cb < pVMARD->PLD_vmar_cnt;
	   cb++)
       {
	  /* write the VMAR to the file        */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pVMARD->PLD_vmar_array[cb],
		       pkPDPB->vmarH.PLD_vmar_size);
	  if (rt != PLD_Success)
	   {
	     pkPDPB->myrc.DMP_VMAR_DATA_RC  = rt;	  /*		   */
	   } /* if end */

       } /* for end */

       pVMARD = pVMARD->PLD_vmar_next;		   /* this is new storage  */

       if (pCurr != NULL)
	{ VMFreeKHB(VM_HKH_PUB_RESRW,pCurr); } /* if end */

       pCurr = pVMARD;

    } /* end while */

    if (pkPDPB->myrc.DMP_PTDA_DATA_RC != PLD_Success)	  /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_PTDA_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_VMAR_DATA_RC != PLD_Success)	  /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_VMAR_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    return(PLD_Success);				  /*		   */

}  /* ***     END  PLDWrVmarInfo  *** */

/***LP	PLDWrVMOBInfo - Write VM Object Records Information
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDWrVmobInfo (HFILE hfile, HFILE hfiletab, kPDPB_t *pkPDPB)
{

    struct _vmobdata *pCurr = NULL;    /*Pointer to current structure	   */

    register PLD_VMOBDATA *pVMOBD;

  ULONG rt = 0, 			/* result code			    */
	cb = 0; 			/* index into the tcb_array	    */

     /* VMOB area we are using in the pkPDPB structure			    */
    pVMOBD = &pkPDPB->vmobD;

    while (pVMOBD != NULL)
    {
      for (cb = 0;
	   cb < pVMOBD->PLD_vmob_cnt;
	   cb++)
       {
	  /* write the VMOB to the file        */
	 rt = WriteWithTableEntry(hfile, hfiletab,
		      (UCHAR *) pVMOBD->PLD_vmob_array[cb],
		      pkPDPB->vmobH.PLD_vmob_size);
	  if (rt != PLD_Success)
	   {
	     pkPDPB->myrc.DMP_VMOB_DATA_RC  = rt;	  /*		   */
	   } /* if end */

       } /* for end */

       pVMOBD = pVMOBD->PLD_vmob_next;		   /* this is new storage  */

       if (pCurr != NULL)
	{ VMFreeKHB(VM_HKH_PUB_RESRW,pCurr); } /* if end */

       pCurr = pVMOBD;

    } /* end while */

    if (pkPDPB->myrc.DMP_VMOB_DATA_RC != PLD_Success)	  /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_VMAR_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    return(PLD_Success);				  /*		   */

}  /* ***     END  PLDWrVmobInfo  *** */

/***LP	PLDWrMTEInfo - Write Module Table Entry Information
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDWrMteInfo (HFILE hfile, HFILE hfiletab, kPDPB_t *pkPDPB)
{

    struct _mtedata *pCurr = NULL;     /*Pointer to current structure	   */

    register PLD_MTEDATA *pMTED;

  ULONG rt = 0, 			/* result code			    */
	cb = 0; 			/* index into the tcb_array	    */

     /* MTE  area we are using in the pkPDPB structure			    */
    pMTED = &pkPDPB->mteD;

    while (pMTED != NULL)
    {
      for (cb = 0;
	   cb < pMTED->PLD_mte_cnt;
	   cb++)
       {
	  /* write the MTE  to the file        */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pMTED->PLD_mte_array[cb],
		       pkPDPB->mteH.PLD_mte_size);
	  if (rt != PLD_Success)     /* 	      */
	   {							/*	   */
	     pkPDPB->myrc.DMP_MTE_DATA_RC = rt; 		/*	   */
	   } /* if end */					/*	   */

	  /* write the SMTE to the file        */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pMTED->PLD_smte_array[cb],
		       pkPDPB->mteH.PLD_smte_size);
	  if (rt != PLD_Success)     /* 	      */
	   {							/*	   */
	     pkPDPB->myrc.DMP_SMTE_DATA_RC = rt;		/*	   */
	   } /* if end */					/*	   */

	  /* write the MTE Object Table to the file	   */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pMTED->PLD_smte_objtab_array[cb],
				 pMTED->PLD_smte_objtab_size[cb]);
	  if (rt != PLD_Success)     /* 	      */
	   {							/*	   */
	     pkPDPB->myrc.DMP_SMTEO_DATA_RC = rt;		/*	   */
	   } /* if end */					/*	   */

  /**************************************************************************/
  /* D005 The structure of the MTE changed for the 4 MEG Release       D005 */
  /* D005 Therefore this code is no longer needed		       D005 */
  /**************************************************************************/
  /* D005  *****************************************************************/
  /* D005  * write the MTE_MODNAME				       A002*/
  /* D005  *****************************************************************/
  /* D005 if ( (rt == PLD_Success)   && 			    *  A002*/
  /* D005      (pMTED->PLD_mte_modname_array[cb] != NULL) ) {	    *  A002*/
  /* D005     rt = WriteWithTableEntry(hfile, hfiletab, 		      D005 */
  /* D005	     ( ((UCHAR *) pMTED->PLD_mte_modname_array[cb]) + 1),     D005 */
  /* D005	     (ULONG) *( (PCHAR) pMTED->PLD_mte_modname_array[cb] ) )  D005 */
  /* D005							    *  A002*/
  /* D005  }  * if end						       A002*/
  /**************************************************************************/

	  /*****************************************************************/
	  /* write the SMTE_PATH				       A002*/
	  /*****************************************************************/
	  rt = WriteWithTableEntry(hfile, hfiletab,
		     (UCHAR *) pMTED->PLD_smte_path_array[cb],
			       pMTED->PLD_smte_path_size[cb]); /*  A002*/
	  if (rt != PLD_Success)     /* 	      */
	   {							/*	   */
	     pkPDPB->myrc.DMP_SMTEP_DATA_RC = rt;		/*	   */
	   } /* if end */					/*	   */

       } /* for end */

       pMTED = pMTED->PLD_mte_next;		 /* this is new storage  */

       if (pCurr != NULL)
	{ VMFreeKHB(VM_HKH_PUB_RESRW,pCurr); } /* if end */

       pCurr = pMTED;

    } /* end while */

    if (pkPDPB->myrc.DMP_MTE_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_MTE_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_SMTE_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_SMTE_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_SMTEO_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_SMTEO_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_SMTEP_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_SMTEP_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    return(PLD_Success);				  /*		   */

}  /* ***     END  PLDWrMteInfo  *** */

/***LP	PLDWrThreadSumm - Write Thread Summary
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDWrThreadSumm (HFILE hfile, kPDPB_t *pkPDPB)
{

    register PLD_TCBDATA  *pTCBD;

  ULONG rt = 0, 			/* result code			    */
	cb = 0, 			/* index into the tcb_array	    */
	ent_size = 0,			/* tcbent size			    */
	wrt_size = 0;			/* size to write		    */

     /* TCB area we are using in the pkPDPB structure			    */
    pTCBD = &pkPDPB->tcbD;

    ent_size = sizeof(PLD_TCBENTRY);

    while (pTCBD != NULL)
    {
       /* write the Thread Summary Info    */
       if (rt == PLD_Success)
	{
	   wrt_size = ent_size * pTCBD->PLD_tcb_cnt;

	   rt = BfWrite(hfile,
			(UCHAR *) &pTCBD->tcbent[0],
			wrt_size);
	} /* if end */

       pTCBD = pTCBD->PLD_tcb_next;		    /* this is new storage  */

    } /* end while */

    return(rt);

}  /* ***     END  PLDWrThreadSumm  *** */

/***LP	PLDWrThreadInfo - Write Thread Information
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDWrThreadInfo (HFILE hfile, HFILE hfiletab, kPDPB_t *pkPDPB)
{

    struct _tcbdata  *pCurr = NULL;    /* Pointer to current structure	    */
    struct tib_s   *p_TIB;	       /* Pointer to TIB		    */
    struct _EXCEPTIONREGISTRATIONRECORD *p_except; /* exception handler     */

    register PLD_TCBDATA  *pTCBD;

  ULONG rt = 0, 			/* result code			    */
	cb = 0; 			/* index into the tcb_array	    */

    ljmp_t lj;				/* KDH - TKLongjmp buffer - 148114  */

     /* TCB area we are using in the pkPDPB structure			    */
    pTCBD = &pkPDPB->tcbD;

    while (pTCBD != NULL)
    {
      for (cb = 0;
	   cb < pTCBD->PLD_tcb_cnt;
	   cb++)
       {
	  /* write the TCB to the file	      */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pTCBD->tcbent[cb].tcbaddr,
		       pkPDPB->tcbH.PLD_tcb_size);
	  if (rt != PLD_Success)
	   {
	     pkPDPB->myrc.DMP_TCB_DATA_RC = rt; 		/*	   */
	   } /* if end */

	  /* write the CRI to the file	      */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pTCBD->tcbent[cb].criaddr,
		       pTCBD->tcbent[cb].crisize);
	  if (rt != PLD_Success)
	   {
	     pkPDPB->myrc.DMP_CRI_DATA_RC = rt; 		/*	   */
	   } /* if end */

	  /* write the REGISTERS to the file  */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pTCBD->tcbent[cb].regaddr,
		       pTCBD->tcbent[cb].regsize);
	  if (rt != PLD_Success)
	   {
	     pkPDPB->myrc.DMP_REG_DATA_RC = rt; 		/*	   */
	   } /* if end */

	  /* write the STACK	 to the file  */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) pTCBD->tcbent[cb].stkaddr,
		       pTCBD->tcbent[cb].stksize);
	  if (rt != PLD_Success)
	   {
	     pkPDPB->myrc.DMP_STK_DATA_RC = rt; 		/*	   */
	   } /* if end */

	  p_TIB = pTCBD->tcbent[cb].tcbaddr->TCBptib; /* Pointer to TIB     */

	  /* write the TIB to the file	      */
	  rt = WriteWithTableEntry(hfile, hfiletab,
		       (UCHAR *) p_TIB,
		       sizeof(struct tib_s));
	  if (rt != PLD_Success)
	   {
	     pkPDPB->myrc.DMP_TIB_DATA_RC = rt; 		/*	   */
	   } /* if end */

	  p_except = p_TIB->tib_pexchain;	     /* Exception Chain     */

	  /* SEG/KDH - Register a fault handler to handle the case where
	   * the exception chain pointer is bad - Defect 148114
	   */
	  if (TKCatchFault(SSToDS(&lj)) == NO_ERROR) {
	     while (p_except != END_OF_CHAIN) {
	       /* write the Exception handlers to the file	  */
	       rt = WriteWithTableEntry(hfile, hfiletab,
			    (UCHAR *) p_except,
			    sizeof(struct _EXCEPTIONREGISTRATIONRECORD));
	       if (rt != PLD_Success) {
		  pkPDPB->myrc.DMP_XCP_DATA_RC = rt;		     /* 	*/
	       } /* if end */

	       /*--------------------------------------------------------------*/
	       /* 136061 Catch bad pointer early.			       */
	       /*							       */
	       /*if ((p_except->prev_structure < p_TIB->tib_pstacklimit) ||    */
	       /*    (p_except->prev_structure > p_TIB->tib_pstack)) {	       */
	       /*  p_except->prev_structure = END_OF_CHAIN;		       */
	       /* }							       */
	       /*							       */
	       /* 136061						       */
	       /*--------------------------------------------------------------*/

	       p_except = p_except->prev_structure;

	     } /* while end */
	     TKClrFault();
	  }
	  else p_except = END_OF_CHAIN;

	  /* write the TIB2 to the file        */
	  if ( p_TIB->tib_ptib2 != NULL )			// 100656 davidj
	  {
	    /* write the TIB2 to the file	 */
	    rt = WriteWithTableEntry(hfile, hfiletab,
			 (UCHAR *) p_TIB->tib_ptib2,
			 sizeof(struct tib2_s));
	  }							// 100656 davidj
	  else							// 100656 davidj
	     {
	      rt =  ERROR_INVALID_DATA; 			// 100656 davidj
	     } /* if end */

	    if (rt != PLD_Success)
	     {
	       pkPDPB->myrc.DMP_TIB2_DATA_RC = rt;		  /*	     */
	     } /* if end */

       } /* for end */

       pTCBD = pTCBD->PLD_tcb_next;		    /* this is new storage  */

       if (pCurr != NULL)
	{ VMFreeKHB(VM_HKH_PUB_RESRW,pCurr); } /* if end */

       pCurr = pTCBD;

    } /* end while */

    if (pkPDPB->myrc.DMP_TCB_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_TCB_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_CRI_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_CRI_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_REG_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_REG_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_STK_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_STK_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_TIB_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_TIB_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_XCP_DATA_RC	!= PLD_Success)   /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_XCP_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    if (pkPDPB->myrc.DMP_TIB2_DATA_RC	 != PLD_Success)  /*		   */
     {							  /*		   */
       return(pkPDPB->myrc.DMP_TIB2_DATA_RC);		  /*		   */
     } /* if end */					  /*		   */

    return(PLD_Success);				  /*		   */

}  /* ***     END  PLDWrThreadInfo  *** */

/***LP	PLDWrLDTInfo - Write LDT Information
 *
 *	ENTRY
 *		pkPDPB = Pointer to Process Level Dump Buffer
 *
 *	EXIT
 *		Return Value == 0
 *			No Error
 *
 *	Pseudocode:
 */

ULONG  PLDWrLdtInfo (HFILE hfile, HFILE hfiletab, kPDPB_t *pkPDPB)
{

  register PLD_LDTDATA *pLDTD;

  ULONG rt = 0; 			/* result code			    */

     /* LDTD area we are using in the pkPDPB structure			    */
    pLDTD = &pkPDPB->ldtD;

    /* write the LDT  to the file as one block	      */
    rt = WriteWithTableEntry(hfile, hfiletab,
		  (UCHAR *) &pLDTD->ldta[0],
		  pkPDPB->ldtH.PLD_ldt_size);

    return(rt);

}  /* ***     END  PLDWrLdtInfo  *** */
