#define SCCSID  "@(#)pdwrfile.c"
/*
 *      Write Program Dump to File
 *
 *      IBM Confidential
 *
 *      Copyright (c) IBM Corporation 1992
 *
 *      All Rights Reserved
 */

#define INCL_SSTODS
#define INCL_DOSERRORS
#define INCL_DOSDATETIME

#define FNO_NUM       FNO_PDWRFILE_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 <stdlib.h>

#include <bseerr.h>
#include <pgexport.h>
#include <tkexport.h>
#include <vmexport.h>
#include <vmowner.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 <pdfile.h>
#include <pldxport.h>


/***LP  MakeSuffix - make the file suffix from an integer
 *
 *      This routine makes a ascii file suffix from an integer
 *      such that integer is modulo 1000.
 *
 *      Entry     *suffix points to the destination file suffix
 *                 count is the integer
 *
 *      Exit       the three byte suffix is filled in with an ascii
 *                 string
 *
 */

void MakeSuffix(UCHAR *suffix, LONG count)
{
   USHORT    i;

  /* Locate suffix pointer at the rightmost suffix character */
   suffix +=2;

  /* Make the suffix string and shove it into the suffix */
   for (i = 0; i < 3 ; ++i, --suffix ) {
      *suffix = (UCHAR) '0' + (UCHAR) (count % 10);
      count /= 10;
   }
}

/***LP  OpenDump - Open a dump file
 *
 *      This routine opens the dump file.
 *
 *      Entry     *dstruct points to a structure that identifies the
 *                 dump data and size
 *
 *      Exit        0 indicates success
 *                    handle to the dump file is returned
 *
 *                 !0 indicates failure (error code is returned)
 *
 */

ULONG  OpenDump(PHFILE phfile, char *filename)
{
   UCHAR   *suffix,
            file_opened;

   USHORT   i;

   LONG     count = 0;

   HFILE    *hfile = phfile;

   ULONG    act,
            attribute,
            openflag,
            openmode,
            rc;

   PULONG   action = SSToDS(&act);

   i = (USHORT) strlen(filename);
   filename[i] = '.';
   suffix = &filename[i + 1];

  /* Set up the file open parameters */
   *action = 0;
   attribute = 0;
   openflag = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
   openmode =
     OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE | OPEN_FLAGS_WRITE_THROUGH;

  /* Try to open the file */
   for (count = 0, file_opened = FALSE;
        count < MAXFILENUMBER && !file_opened;
        ++count) {

       /* Put the suffix into the file */
        MakeSuffix(suffix, count);

       /* Open the file */
        if( rc = PDOpen(&filename[0], hfile, action, 0,
                            attribute, openflag, openmode, 0) )
             return rc;

       /* If the file existed, close it, and try the next file name */
        if(*action & FILE_EXISTED)
             PLDClose(*hfile);
        else
             file_opened = TRUE;
   }

  /* If all filenames are used, use the first filename. */
   if(!file_opened){
       /* Put the suffix into the file */
        MakeSuffix(suffix, 0);

       /* Open the file */
        return( PDOpen(&filename[0], hfile, action, 0,
                            attribute, openflag, openmode, 0) );
   }else
        return(NO_ERROR);
}

/***LP  BfWrite - Write from buffer to file
 *
 *      The worker routines are limited to 64k writes.  This routine
 *      takes input buffers of >64K bytes and performs multiple writes
 *      of <64k bytes.
 *
 *
 *      Entry      hfile  - file handle
 *                *buffer - points to a buffer that is to be written
 *                 size   - the count of the data
 *
 *      Exit        0 indicates success
 *
 *                 !0 indicates failure (error code is returned)
 *
 */

ULONG  BfWrite(HFILE hfile, UCHAR *buffer, ULONG size)
{
   ULONG amount,
         rc;

  /* Write the data to the dumpfile */
   do {

      amount = min( (ULONG) size, WRITESIZE);

      if( rc = PDWrite(hfile, buffer, amount) )
          return rc;

      size -= amount;
      buffer += amount;

   } while ( size > 0 );

   return NO_ERROR;
}

/***LP  WriteWithTableEntry - Write from buffer to file and put table entry
 *                            into the table file
 *
 *      Write dump data into the dump file and produce a table entry in the
 *      table file.
 *
 *      Entry      hfdump - file handle of the dump file
 *                 hftab  - file handle of the table file
 *                *buffer - points to a buffer that is to be written
 *                 size   - the count of the data
 *
 *      Exit        0 indicates success
 *
 *                 !0 indicates failure (error code is returned)
 *
 */

ULONG WriteWithTableEntry(HFILE hfdump, HFILE hftab, UCHAR *buffer, ULONG size)
{
   ULONG             count,
                     rc;

   DUMPTABLEENTRY    TableEntry;


  /* Position the file pointer to the beginning of the file;
   * this has the count of table entries.
   */
   if (rc = PDSeek(hftab, 0, FILE_BEGIN, NULL))
       return rc;

  /* Read the number of table entries. */
   if(rc = PDRead(hftab, (UCHAR *) SSToDS(&count), sizeof(ULONG)) )
       return rc;

  /* Increment the number of table entries. */
   ++count;

  /* Position the file pointer back to the beginning of the file. */
   if (rc = PDSeek(hftab, 0, FILE_BEGIN, NULL))
       return rc;

  /* Write the number of table entries. */
   if(rc = PDWrite(hftab, (UCHAR *) SSToDS(&count), sizeof(ULONG)) )
       return rc;

  /* Position the file pointer to the end of the file. */
   if (rc = PDSeek(hftab, 0, FILE_END, NULL))
       return rc;

  /* Get the location of pointer to the process section control block. */
   if(rc = GetFilePtr(hfdump, SSToDS(&TableEntry.FileOffset)) )
      return rc;

  /* Fill in the table entry */
   TableEntry.LinearAddress = buffer;
   TableEntry.Size = size;

  /* Write to the dump file */
   if(rc = BfWrite(hfdump, buffer, size) )
       return rc;

  /* Write to the table file */
   if(rc = BfWrite(hftab, (UCHAR *) SSToDS(&TableEntry), sizeof(DUMPTABLEENTRY)) )
       return rc;

   return NO_ERROR;
}

/***LP  CopyDumpHdr - Copy the dump header to the dump data file
 *
 *      Copy the header table to the dump data file
 *
 *      Entry      hfdump - file handle of the dump file
 *                 hftab  - file handle of the table file
 *
 *      Exit        0 indicates success
 *
 *                 !0 indicates failure (error code is returned)
 *
 */

ULONG CopyDumpHdr(HFILE hfdump, HFILE hftab)
{
   ULONG             rc = 0,
                     i = 0,
                     HdrCnt = 0,
                     storsize = 0,
                     hldsize = sizeof(DUMPTABLEENTRY);         /*     61720 */

   PVOID             storaddr = NULL;
   DUMPTABLEENTRY    TableEntry;

  /* Position the file pointer to the beginning of the file;
   * this has the count of table entries.
   */
   if (rc = PDSeek(hftab, 0, FILE_BEGIN, NULL))
       return rc;

  /* Read the size of the table */
   if(rc = PDRead(hftab, SSToDS(&HdrCnt), sizeof(ULONG)) )
      return rc;

  /* Write the size of the table */
   if(rc = PDWrite(hfdump, SSToDS(&HdrCnt), sizeof(ULONG)) )
      return rc;

   /*   Get the storage for read and write operations             */
   while (storaddr == NULL)                                    /*     61720 */
    {
      /* Big Buffer or Small Buffer                                   61720 */
      if (i == 0)                                              /*     61720 */
      {     /* Big   Buffer                               */
          storsize = hldsize * HdrCnt;                         /*     61720 */
          storaddr = PLDGetStorage (storsize);                 /*     61720 */
      }
      else  /* Small Buffer                                           61720 */
      {
          storsize = hldsize;
          storaddr = SSToDS(&TableEntry);
      }
                                                               /*     61720 */
      if (storaddr == NULL)                                    /*     61720 */
      {  i++;  } /* if end */                                  /*     61720 */

    } /* end while storaddr == null  */

   /* we will always have storage when we get here be safe               */
   /* Zero out buffer                                                    */

   memset(storaddr, 0, storsize);                              /*     61720 */

   while ( (HdrCnt > 0) && (rc == NO_ERROR) )                  /*     61720 */
    {
      if (i == 0)     /*  LARGE BUFFER         */
        HdrCnt  = 0;                                           /*     61720 */
      else            /*  SMALL buffer         */
        HdrCnt  = HdrCnt - 1;

      /* Read a table entry */
      rc = PDRead(hftab, storaddr, storsize);

      /* Write a table entry */
      if(rc == NO_ERROR)
         rc = PDWrite(hfdump, storaddr, storsize);

    } /* end while */

    if (i == 0)                                                /*     61720 */
        VMFreeKHB(VM_HKH_PUB_RESRW,storaddr);                  /*     61720 */

   return rc;
}
