/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Lexmark Corporation, 1989                                   */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = PRDESUB2
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prde_GetPrinterName
 *             prde_GetPrinterFromLogAddress
 *             prde_GetBestFitPrinterName
 *             prde_MatchDirectSpoolerInfo
 *             prde_MatchQueuedSpoolerInfo
 *             prde_GetAppDefaultPrinterName
 *             prde_ReadTerminatedWordFromText
 *             prde_GetDeviceName
 *             prde_WriteHeaderData
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                         /* Convert to C/SET2    CON3201       */
#define INCL_DOSPROCESS                 /* Convert to C/SET2    CON3201       */
#define INCL_DOSSEMAPHORES              /* Convert to C/SET2    CON3201       */
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_SPL
#define INCL_WINSHELLDATA
#define INCL_GPIERRORS
#define INCL_SPLERRORS
#define INCL_SHLERRORS
#define INCL_GPIBITMAPS
#define INCL_DOSMODULEMGR
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    CON3201       */
#undef INCL_GPIBITMAPS
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_SPL
#undef INCL_WINSHELLDATA
#undef INCL_GPIERRORS
#undef INCL_SPLERRORS
#undef INCL_SHLERRORS
#undef INCL_DOSMODULEMGR

#define INCL_DDIBUNDLES
#define INCL_DDIFONTSTRUCS
#define INCL_DDIDEFS
#include <pmddi.h>
#undef INCL_DDIBUNDLES
#undef INCL_DDIFONTSTRUCS
#undef INCL_DDIDEFS

#define INCL_WINP_SELSERVER
#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELSERVER
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                          /* Convert to C/SET2    CON3201       */

#include <prdconse.h>
#include <prddcone.h>
#include <prdpcone.h>
#include <prdecone.h>
#include <prdtcone.h>
#include <prdmcone.h>
#include <prdqcone.h>

#define NO_SYS
#define NO_CONSTANT_INCL
#include <prdinclt.h>
#undef NO_CONSTANT_INCL
#undef NO_SYS

#include <prdmtypt.h>
#include <prdeextf.h>
#include <prdgextf.h>
#include <prdpextf.h>
#include <prdyextf.h>
#include <prdmextf.h>
#include <prduextf.h>


/**********************************************************************/
/* Set up access to external data structures.                         */
/**********************************************************************/
extern lpDCTEntryType       DCT [];
extern lpDDTType            DDT [];

extern CHAR                 szIBMQSTD[];
extern CHAR                 szIBMQESC[];
extern CHAR                 szIBMQRAW[];

extern CHAR                 szBoldString[];
extern CHAR                 szDWideString[];
extern CHAR                 szDHighString[];
extern CHAR                 szQualityString1[];
extern CHAR                 szQualityString2[];
extern CHAR                 szQualityString3[];

extern lpPrtDataEntry       PrinterStateData;
extern lpGlobalCard         GlobalCardData;
extern HMODULE              prdd_ModHandle;
/* extern USHORT               PMVersion; CON3201 - No longer needed */
extern USHORT               DEFAULT_PRINTER;
extern USHORT               DRIVER_TYPE;
extern USHORT               NO_OF_PRINTERS;
extern PCHAR                DriverNameString;

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetPrinterName                                    */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI            PDBInstance;                                   */
/*   FPParamsLst far * param1;                                        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* We choose the PrinterName and LogAddress for this job, using       */
/* SpoolerIniInfo and possibly AppDefaultIniInfo.                     */
/*                                                                    */
/* Recall that PrinterName is e.g. PRINTER1, LogAddress is e.g.       */
/* LPT1 or LPT1Q.                                                     */
/*                                                                    */
/* Structure of SpoolerIniInfo:                                       */
/*                                                                    */
/* This starts with the application name "PM_SPOOLER_PRINTER". For    */
/* each KeyName (which is a logical printer name, such as PRINTER1)   */
/* there is an entry of the following type:                           */
/*                                                                    */
/*   PrinterName=Port;DriverName1,DriverName2...;Queue1,Queue2,...;   */
/*                                                                    */
/* The first call to ReadIniFile that we make just returns a list     */
/* of all KeyNames in SpoolerIniInfo, i.e. all logical printers in    */
/* the system. Subsequent calls (in Match_DirectSpoolerInfo and       */
/* MatchQueuedSpoolerInfo), when given a printer name, return the     */
/* entry for that name.                                               */
/*                                                                    */
/* Search path: if we're given a LogAddress in param1, look through   */
/* SpoolerIniInfo for a printer with that LogAddress. If we're not    */
/* given a LogAddress, find the app default printer and set the       */
/* LogAddress to the port/queue associated with that printer.         */
/*********************************************************************/
#if 0
USHORT pascal prde_GetPrinterName( PDBInstance,
                                   param1,
                                   DriverData )

lpPDBI            PDBInstance;
FPParamsLst far * param1;
pDMDriverStruc    DriverData;
#endif

SHORT prde_GetPrinterName( lpPDBI          PDBInstance,    /* CON3201 */
                           FPParamsLst    *param1,         /* CON3201 */
                           pDMDriverStruc  DriverData )    /* CON3201 */

{
#define TFUNC "GetPrinterName"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    ULONG               Result;           /* return from subfunctions */
    USHORT              LogErrCode;       /* Error code to be logged  */

    if ( (param1->DO.pszLogAddress) &&
         ( *(param1->DO.pszLogAddress) != '\0') )
    {
        /**************************************************************/
        /* We were given a LogAddress. Find the logical printer       */
        /* connected to that LogAddress.                              */
        /**************************************************************/
        Result = prde_GetPrinterFromLogAddress( PDBInstance,
                                                param1 );
        /**************************************************************/
        /* Look at the printer in the DriverData if it exist, if not  */
        /* then get the app default, and finally return null for the  */
        /* printer.                                                   */
        /**************************************************************/
        if ((Result != OK) && (DriverData))
        {
           Result = prde_GetPrinterNameFromDD( PDBInstance, param1,
                                               DriverData );
        }
        if (Result != OK)
        {
           Result = prde_GetBestFitPrinterName( PDBInstance,
                                                param1 );
        }
        if (Result != OK)
        {
           PDBInstance->LPName[0] = '\0';

           /**********************************************************/
           /* Allocate memory for the LogAddress and copy it to PDB. */
           /**********************************************************/
           Result = (ULONG)prdg_AllocGlobalHeapItem(
                       (USHORT)prdu_strlen(param1->DO.pszLogAddress) + 1,
                    /* (PBYTE far *)&(PDBInstance->PDBLogAddress) ); */
                       (PBYTE *)&(PDBInstance->PDBLogAddress) ); /*CON3201*/

           if ( Result != OK )
           {
               PDBInstance->PDBLogAddress = (PBYTE)FNULL;  /* PD00607 */
               TRACE6(TFUNC, "Alloc Glob Heap failed", FNULL, 0);
               LogErrCode = PMERR_NOT_ENOUGH_MEM;
               return (ERROR_NEG);
           }
           (void)prdu_strcpy( (PBYTE)PDBInstance->PDBLogAddress,
                              (PBYTE)param1->DO.pszLogAddress );
           Result = OK;
        }
    }
    else
    {
        /**************************************************************/
        /* We weren't given a LogAddress. Set the logical printer to  */
        /* be the printer in the DD   and print to the port or queue  */
        /* connected to that printer.                                 */
        /**************************************************************/
        if (DriverData)
        {
           Result = prde_GetPrinterNameFromDD( PDBInstance, param1,
                                               DriverData );
        }
        /*************************************************************/
        /* Get the printer associated with the app default and if it */
        /* is not found return a null.                               */
        /*************************************************************/
        if (Result != OK)
        {
           Result = prde_GetBestFitPrinterName( PDBInstance,
                                                param1 );
        }
        if (Result == ERROR_ZERO)
        {
           Result = ERROR_NEG;
        /* return( (USHORT)Result ); */
           return( (SHORT)Result );                        /* CON3201 */
        }
    }
 /* return ( (USHORT)OK ); */
    return ( (SHORT)OK );                                  /* CON3201 */
}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetPrinterNameFromDD                              */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI            PDBInstance;                                   */
/*   FPParamsLst far * param1;                                        */
/*   pDMDriverStruc    DriverData;                                    */
/*                                                                    */
/*********************************************************************/
#if 0
ULONG pascal prde_GetPrinterNameFromDD ( PDBInstance,
                                         param1,
                                         DriverData )

lpPDBI            PDBInstance;
FPParamsLst far * param1;
pDMDriverStruc    DriverData;
#endif

ULONG prde_GetPrinterNameFromDD ( lpPDBI          PDBInstance,  /* CON3201 */
                                  FPParamsLst    *param1,       /* CON3201 */
                                  pDMDriverStruc  DriverData )  /* CON3201 */

{
#define TFUNC "GetPrinterNameFromDD"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    ULONG               Result;           /* return from subfunctions */
    PBYTE               KeyName = FNULL;  /* PD00607                  */
    USHORT              LogErrCode;       /* Error code to be logged  */
    CHAR                LogAddressBuffer[100]; /* temporary buffer    */

    Result = ERROR_NEG;
    if (DriverData)
    {
       if (DriverData->PrinterName[0] != '\0')
       {
          /**************************************************************/
          /* We were given a PrinterName in the DriverData use it if it */
          /* is valid.                                                  */
          /**************************************************************/
          /**************************************************************/
          /* This first call to ReadIniFile with a NULL parameter       */
          /* returns a pointer to a list of all the listed logical      */
          /* printer names separated from each other by one null; the   */
          /* list is terminated by two nulls.                           */
          /**************************************************************/
          KeyName = prde_ReadIniFile( FNULL,
                                      (PSZ)"PM_SPOOLER_PRINTER");

          /**************************************************************/
          /* In the loop below, we read the entry for each              */
          /* logical printer until the one associated in the DriverData */
          /* is found.                                                  */
          /**************************************************************/
          while (*KeyName)
          {
             if (prde_StringsAreEqual (KeyName, DriverData->PrinterName))
             {
                Result = OK;
                break;
             }

             /**********************************************************/
             /* Move on to the next KeyName (i.e. advance until you    */
             /* get past the next null).                               */
             /**********************************************************/
             while (*KeyName++);

          }      /*     for each KeyName...     */
          if (Result == OK)
          {
             prdu_strcpy( (PBYTE) PDBInstance->LPName,
                          (PBYTE) KeyName );

             /*********************************************************/
             /* Clear LogAddressBuffer.                               */
             /*********************************************************/
             LogAddressBuffer[0] = '\0';

             /*********************************************************/
             /* Find the port/queue associated with this printer.     */
             /*********************************************************/
             switch (param1->DcType)
             {
                case OD_DIRECT:
                   Result = prde_MatchDirectSpoolerInfo ( (PBYTE) PDBInstance->
                                                          LPName,
                                                          LogAddressBuffer );
                   break;

                case OD_QUEUED:
                   Result = prde_MatchQueuedSpoolerInfo ( (PBYTE) PDBInstance->
                                                          LPName,
                                                          LogAddressBuffer );
                   break;

                case OD_INFO:
                case OD_MEMORY:
                   Result = prde_MatchDirectSpoolerInfo ( (PBYTE) PDBInstance->
                                                          LPName,
                                                          LogAddressBuffer );
                   if (Result != MATCH)
                   {
                     Result = prde_MatchQueuedSpoolerInfo ((PBYTE) PDBInstance->
                                                             LPName,
                                                             LogAddressBuffer );
                   }
                   break;
             }       /*    EndSwitch   */

             if (Result == MATCH)
             {
                if ( (param1->DO.pszLogAddress) &&
                     ( *(param1->DO.pszLogAddress) != '\0') )
                {
                   Result = (ULONG)prdg_AllocGlobalHeapItem(
                            (USHORT)prdu_strlen(param1->DO.pszLogAddress) + 1,
                         /* (PBYTE far *)&(PDBInstance->PDBLogAddress) ); */
                            (PBYTE *)&(PDBInstance->PDBLogAddress) ); /*CON3201*/

                   if ( Result != OK )
                   {
                      TRACE6(TFUNC, "Alloc Glob Heap failed", FNULL, 0);
                      LogErrCode = PMERR_NOT_ENOUGH_MEM;
                      goto ERR_EXIT;
                   }
                   (void)prdu_strcpy( (PBYTE)PDBInstance->PDBLogAddress,
                                      (PBYTE)param1->DO.pszLogAddress );
                }
                else
                {
                /**********************************************************/
                /* Get memory for the LogAddress and copy it across.      */
                /**********************************************************/
                   Result = (ULONG)prdg_AllocGlobalHeapItem(
                            (USHORT)prdu_strlen( LogAddressBuffer ) + 1,
                         /* (PBYTE far *)&(PDBInstance->PDBLogAddress) ); */
                            (PBYTE *)&(PDBInstance->PDBLogAddress) ); /*CON3201*/

                   if ( Result != OK )
                   {
                      TRACE6(TFUNC, "Alloc Glob Heap failed", FNULL, 0);
                      LogErrCode = PMERR_NOT_ENOUGH_MEM;
                      goto LOGERR_EXIT;
                   }
                   (void)prdu_strcpy( (PBYTE)PDBInstance->PDBLogAddress,
                                      (PBYTE)LogAddressBuffer );
                }
             }
          }
          /**************************************************************/
          /* Throw away SpoolerIniInfo keynames.                        */
          /**************************************************************/
       /* if (SELECTOROF(KeyName))            */
       /*     SSFREESEG(SELECTOROF(KeyName)); */
          if (KeyName)                                     /* CON3201 */
              SSFREEMEM(KeyName);                          /* CON3201 */
       }
    }
    return ( (USHORT)Result );
LOGERR_EXIT:
    TRACE8(TFUNC, "Log error", &LogErrCode, 1);
    LOGERR(TFUNC, "Invalid device", FNULL, 0, LogErrCode);
    PDBInstance->PDBLogAddress = (PBYTE)FNULL;
    *(PDBInstance->LPName) = '\0';
    return(ERROR_ZERO);

ERR_EXIT:
    PDBInstance->PDBLogAddress = (PBYTE)FNULL;
    *(PDBInstance->LPName) = '\0';

    return ERROR_NEG;
}
#undef TFUNC



/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetPrinterFromLogAddress                          */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI            PDBInstance;                                   */
/*   FPParamsLst far * param1;                                        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* Look through the entries for all the listed printers in            */
/* SpoolerIniInfo until we find one that matches the given LogAddess  */
/* for output. We match LogAddress to a port if we're printing        */
/* DIRECT, to a queue if we're QUEUED and to either if we're INFO     */
/* or MEMORY.                                                         */
/**********************************************************************/
#if 0
USHORT pascal prde_GetPrinterFromLogAddress( PDBInstance,
                                             param1 )

lpPDBI            PDBInstance;
FPParamsLst far * param1;
#endif

SHORT prde_GetPrinterFromLogAddress( lpPDBI       PDBInstance,  /* CON3201 */
                                     FPParamsLst *param1 )      /* CON3201 */

{
#define TFUNC "GetPrinterFromLogAddress"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    PBYTE               KeyName = FNULL;  /* keys from SpoolerIniInfo */
                                          /* PD00607                  */
    ULONG               Result;           /* return from subfunctions */
    USHORT              LogErrCode;       /* Error code to be logged  */


    /**************************************************************/
    /* This first call to ReadIniFile with a NULL parameter       */
    /* returns a pointer to a list of all the listed logical      */
    /* printer names separated from each other by one null; the   */
    /* list is terminated by two nulls.                           */
    /**************************************************************/
    KeyName = prde_ReadIniFile( FNULL,
                                (PSZ)"PM_SPOOLER_PRINTER");

    if ((KeyName == (PBYTE)ERROR_NEG) || !KeyName )
    {
        LogErrCode = PMERR_SPL_NO_DATA;
        goto LOGERR_EXIT;
    }

    /**************************************************************/
    /* In the loop below, we read the entry for each              */
    /* logical printer until the one associated with the          */
    /* logical address is found.                                  */
    /**************************************************************/
    while (*KeyName)
    {
        switch (param1->DcType)
        {
            case OD_DIRECT:
                Result = prde_MatchDirectSpoolerInfo ( KeyName,
                                         param1->DO.pszLogAddress );
                break;

            case OD_QUEUED:
                Result = prde_MatchQueuedSpoolerInfo ( KeyName,
                                         param1->DO.pszLogAddress );
                break;

            case OD_INFO:
            case OD_MEMORY:
                Result = prde_MatchDirectSpoolerInfo ( KeyName,
                                         param1->DO.pszLogAddress );
                if (Result != MATCH)
                {
                    Result = prde_MatchQueuedSpoolerInfo ( KeyName,
                                         param1->DO.pszLogAddress );
                }
                break;
        }       /*    EndSwitch   */

        if ( (Result == MATCH) || (Result == ERROR_NEG) )
            break;

        /**********************************************************/
        /* Move on to the next KeyName (i.e. advance until you    */
        /* get past the next null).                               */
        /**********************************************************/
        while (*KeyName++);

    }      /*     for each KeyName...     */

    if (Result == MATCH)
    {
        /**********************************************************/
        /* Copy PrinterName to PDB.                               */
        /**********************************************************/
        prdu_strcpy( (PBYTE) PDBInstance->LPName,
                     (PBYTE) KeyName );

        /**********************************************************/
        /* Allocate memory for the LogAddress and copy it to PDB. */
        /**********************************************************/
        Result = (ULONG)prdg_AllocGlobalHeapItem(
                    (USHORT)prdu_strlen(param1->DO.pszLogAddress) + 1,
                 /* (PBYTE far *)&(PDBInstance->PDBLogAddress) ); */
                    (PBYTE *)&(PDBInstance->PDBLogAddress) ); /*CON3201*/

        if ( Result != OK )
        {
            TRACE6(TFUNC, "Alloc Glob Heap failed", FNULL, 0);
            LogErrCode = PMERR_NOT_ENOUGH_MEM;
            goto ERR_EXIT;
        }
        (void)prdu_strcpy( (PBYTE)PDBInstance->PDBLogAddress,
                                 (PBYTE)param1->DO.pszLogAddress );

        /**************************************************************/
        /* Throw away SpoolerIniInfo keynames.                        */
        /**************************************************************/
     /* if (SELECTOROF(KeyName))            */
     /*     SSFREESEG(SELECTOROF(KeyName)); */
        if (KeyName)                                       /* CON3291 */
            SSFREEMEM(KeyName);                            /* CON3291 */

        /**************************************************************/
        /* Return.                                                    */
        /**************************************************************/
        return OK;
    }
    /******************************************************************/
    /* DEBUG_SEGMENTS fix (AK)                                        */
    /* Throw away SpoolerIniInfo keynames.                            */
    /******************************************************************/
 /* if (SELECTOROF(KeyName))            */
 /*     SSFREESEG(SELECTOROF(KeyName)); */
    if (KeyName)                                           /* CON3291 */
        SSFREEMEM(KeyName);                                /* CON3291 */

    /******************************************************************/
    /* If we got to here, then either one of the calls above gave an  */
    /* error, or we didn't find a match.                              */
    /******************************************************************/
    return ERROR_NEG;

LOGERR_EXIT:
    TRACE8(TFUNC, "Log error", &LogErrCode, 1);
    LOGERR(TFUNC, "Invalid device", FNULL, 0, LogErrCode);

ERR_EXIT:
    PDBInstance->PDBLogAddress = (PBYTE)FNULL;             /* PD00611 */
/*  *(PDBInstance->PDBLogAddress) = FNULL; */
    *(PDBInstance->LPName) = '\0';

    return ERROR_NEG;
}
#undef TFUNC





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetBestFitPrinterName                             */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI            PDBInstance;                                   */
/*   FPParamsLst far * param1;                                        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* We weren't given a LogAddress. Get the port or queue (depending    */
/* on DCType) associated with the app default printer, and use that   */
/* as a LogAddress.                                                   */
/**********************************************************************/
#if 0
USHORT pascal prde_GetBestFitPrinterName( PDBInstance,
                                          param1 )

lpPDBI            PDBInstance;
FPParamsLst far * param1;
#endif

SHORT prde_GetBestFitPrinterName( lpPDBI       PDBInstance,
                                  FPParamsLst *param1 )

{
#define TFUNC "GetBestFitPrinterName"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    ULONG               Result;           /* return from subfunctions */
    CHAR                PrinterName[32];  /* buffer for default name  */
    USHORT              LogErrCode;       /* Error code to be logged  */
    CHAR                LogAddressBuffer[100]; /* temporary buffer    */


    /**************************************************************/
    /* We weren't given a LogAddress. Find one by finding the     */
    /* port/queue associated with the app default printer.        */
    /*                                                            */
    /* Get the name of this printer.                              */
    /**************************************************************/
    prde_GetAppDefaultPrinterName ( (PBYTE)PrinterName );

    /**************************************************************/
    /* Clear LogAddressBuffer.                                    */
    /**************************************************************/
    LogAddressBuffer[0] = '\0';

    /**************************************************************/
    /* Find the port/queue associated with this printer.          */
    /**************************************************************/
    switch (param1->DcType)
    {
        case OD_DIRECT:
            Result = prde_MatchDirectSpoolerInfo ( PrinterName,
                                                 LogAddressBuffer );
            break;

        case OD_QUEUED:
            Result = prde_MatchQueuedSpoolerInfo ( PrinterName,
                                                 LogAddressBuffer );
            break;

        case OD_INFO:
        case OD_MEMORY:
            Result = prde_MatchDirectSpoolerInfo ( PrinterName,
                                                 LogAddressBuffer );
            if (Result != MATCH)
            {
                Result = prde_MatchQueuedSpoolerInfo ( PrinterName,
                                                 LogAddressBuffer );
            }
            break;
    }       /*    EndSwitch   */

    if (Result == MATCH)
    {
       if ( (param1->DO.pszLogAddress) &&
            ( *(param1->DO.pszLogAddress) != '\0') )
       {
          Result = (ULONG)prdg_AllocGlobalHeapItem(
                      (USHORT)prdu_strlen(param1->DO.pszLogAddress) + 1,
                   /* (PBYTE far *)&(PDBInstance->PDBLogAddress) ); */
                      (PBYTE *)&(PDBInstance->PDBLogAddress) ); /*CON3201*/

          if ( Result != OK )
          {
              TRACE6(TFUNC, "Alloc Glob Heap failed", FNULL, 0);
              LogErrCode = PMERR_NOT_ENOUGH_MEM;
              goto ERR_EXIT;
          }
          (void)prdu_strcpy( (PBYTE)PDBInstance->PDBLogAddress,
                                   (PBYTE)param1->DO.pszLogAddress );
       }
       else
       {
          /**********************************************************/
          /* Get memory for the LogAddress and copy it across.      */
          /**********************************************************/
          Result = (ULONG)prdg_AllocGlobalHeapItem(
                     (USHORT)prdu_strlen( LogAddressBuffer ) + 1,
                  /* (PBYTE far *)&(PDBInstance->PDBLogAddress) ); */
                     (PBYTE *)&(PDBInstance->PDBLogAddress) ); /*CON3201*/

          if ( Result != OK )
          {
              TRACE6(TFUNC, "Alloc Glob Heap failed", FNULL, 0);
              LogErrCode = PMERR_NOT_ENOUGH_MEM;
              goto LOGERR_EXIT;
          }
          (void)prdu_strcpy( (PBYTE)PDBInstance->PDBLogAddress,
                                       (PBYTE)LogAddressBuffer );
       }

       (void)prdu_strcpy( (PBYTE)PDBInstance->LPName,
                                    PrinterName );

        return OK;
    }
    else
    {
        /**********************************************************/
        /* Either we couldn't find a match or we hit an error.    */
        /**********************************************************/
        goto ERR_EXIT;
    }

LOGERR_EXIT:
    TRACE8(TFUNC, "Log error", &LogErrCode, 1);
    LOGERR(TFUNC, "Invalid device", FNULL, 0, LogErrCode);
    PDBInstance->PDBLogAddress = (PBYTE)FNULL;
    *(PDBInstance->LPName) = '\0';
    return(ERROR_ZERO);

ERR_EXIT:
    PDBInstance->PDBLogAddress = (PBYTE)FNULL;
    *(PDBInstance->LPName) = '\0';

    return ERROR_NEG;
}
#undef TFUNC





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_MatchDirectSpoolerInfo                            */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PBYTE              PrinterName;     e.g. PRINTER1                */
/*   PBYTE              Port;            e.g. LPT1                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function interrogates the SpoolerIniInfo for the given        */
/* PrinterName and returns the first port listed (if Port is          */
/* passed in as NULL) or tries to match the port passed in with       */
/* the ports listed. It returns MATCH or NO_MATCH, or                 */
/* ERROR_NEG if an error occured.                                    */
/*                                                                    */
/* SpoolerIniInfo for a given PrinterName looks like this:            */
/*                                                                    */
/*   PrinterName=Port;DriverName1,DriverName2...;Queue1,Queue2,...;   */
/**********************************************************************/
#if 0
USHORT pascal prde_MatchDirectSpoolerInfo ( PrinterName,
                                            Port )

PBYTE              PrinterName;
PBYTE              Port;
#endif

SHORT prde_MatchDirectSpoolerInfo ( PBYTE PrinterName,     /* CON3201 */
                                    PBYTE Port )           /* CON3201 */

{
#define TFUNC "MatchDSplInfo"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    PBYTE               StartPtr=FNULL;          /* PD00607           */
    BYTE                Terminator;
    BYTE                pszWord[100];


    if ( *PrinterName == '\0' )
    {
        /**************************************************************/
        /* No printer name supplied - error.                          */
        /**************************************************************/
        return ERROR_NEG;
    }

    /******************************************************************/
    /* Get the a pointer to the SpoolerIniEntry for this printer.     */
    /******************************************************************/
    StartPtr = prde_ReadIniFile( PrinterName,(PSZ)"PM_SPOOLER_PRINTER");

    if ((StartPtr == (PBYTE)ERROR_NEG) || !StartPtr )
    {
        return ERROR_NEG;
    }
    if ( *Port == '\0' )
    {
        /**************************************************************/
        /* No port was supplied by the application, so just take the  */
        /* port associated with the PrinterName we were given, if     */
        /* this is non-null.                                          */
        /**************************************************************/
        prde_ReadTerminatedWordFromText ( Port,
                                          &Terminator,
                                          (PBYTE)",;",
                                          &StartPtr );
        /**************************************************************/
        /* DEBUG_SEGMENTS : free up StartPtr segment (AK)             */
        /**************************************************************/
     /* SSFREESEG( SELECTOROF(StartPtr) ); */
        SSFREEMEM( StartPtr );                             /* CON3291 */

        if ( *Port != '\0')
        {
            return MATCH;
        }
        return NO_MATCH;
    }

    /******************************************************************/
    /* A port was supplied by the application so check it against     */
    /* the listed ports.                                              */
    /******************************************************************/
    Terminator = ',';
    while (Terminator != ';')
    {
        prde_ReadTerminatedWordFromText ( pszWord,
                                          &Terminator,
                                          (PBYTE)",;",
                                          &StartPtr );
        /**************************************************************/
        /* DEBUG_SEGMENTS : free up StartPtr segment (AK)             */
        /**************************************************************/
        if (prde_StringsAreEqual (Port, pszWord))
        {
         /* SSFREESEG( SELECTOROF(StartPtr) ); */          /* CON3201 */
            SSFREEMEM( StartPtr );                         /* CON3201 */
            return MATCH;                                  /* CON3201 */
        }
    }
 /* SSFREESEG( SELECTOROF(StartPtr) ); */
    SSFREEMEM( StartPtr );                                 /* CON3201 */
    return NO_MATCH;
}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_MatchQueuedSpoolerInfo                            */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PBYTE              PrinterName;           e.g. PRINTER1          */
/*   PBYTE              Queue;                 e.g. LPT1Q             */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function is like the previous one, but it the queue. Note     */
/* that more than one queue might be listed for each printer. The     */
/* return value is one of ERROR_NEG, NO_MATCH and MATCH.             */
/*                                                                    */
/* PrinterName must be supplied; Queue need not be.                   */
/*                                                                    */
/* SpoolerIniInfo for a given PrinterName looks like this:            */
/*                                                                    */
/*   PrinterName=Port;DriverName1,DriverName2...;Queue1,Queue2,...;   */
/**********************************************************************/
#if 0
USHORT pascal prde_MatchQueuedSpoolerInfo ( PrinterName,
                                            Queue )

PBYTE              PrinterName;
PBYTE              Queue;
#endif

SHORT prde_MatchQueuedSpoolerInfo ( PBYTE PrinterName,     /* CON3201 */
                                    PBYTE Queue )          /* CON3201 */

{
#define TFUNC "MatchQSplInfo"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    PBYTE               StartPtr=FNULL;          /* PD00607           */
    BYTE                Terminator;
    BYTE                pszWord[100];


    if ( *PrinterName == '\0' )
    {
        /**************************************************************/
        /* No printer name supplied - error.                          */
        /**************************************************************/
        return ERROR_NEG;
    }

    /******************************************************************/
    /* Get the a pointer to the SpoolerIniEntry for this printer.     */
    /******************************************************************/
    StartPtr = prde_ReadIniFile( PrinterName,
                                 (PSZ)"PM_SPOOLER_PRINTER");
    if ((StartPtr == (PBYTE)ERROR_NEG) || !StartPtr )
    {
        return ERROR_NEG;
    }

    /******************************************************************/
    /* Skip past port (i.e. get to the character ;).                  */
    /******************************************************************/
    while ( *StartPtr++ != ';');

    /******************************************************************/
    /* Skip past DriverName.                                          */
    /******************************************************************/
    while ( *StartPtr++ != ';');

    /******************************************************************/
    /* Now deal with the queue name.                                  */
    /******************************************************************/
    if ( *Queue == '\0' )
    {
        /**************************************************************/
        /* No Queue was supplied, so take the first Queue             */
        /* associated with the PrinterName we were given, if it is    */
        /* not null.                                                  */
        /**************************************************************/
        prde_ReadTerminatedWordFromText ( Queue,
                                          &Terminator,
                                          (PBYTE)",;",
                                          &StartPtr );
        /**************************************************************/
        /* DEBUG_SEGMENTS : free up StartPtr segment (AK)             */
        /**************************************************************/
     /* SSFREESEG( SELECTOROF(StartPtr) ); */
        SSFREEMEM( StartPtr );                            /* CIB3201 */
        if ( *Queue != '\0')
        {
            return MATCH;
        }
        return NO_MATCH;
    }
    else
    {
        /**************************************************************/
        /* A Queue was supplied. Try to match it.                     */
        /**************************************************************/
        Terminator = ',';
        while (Terminator != ';')
        {
            prde_ReadTerminatedWordFromText ( pszWord,
                                              &Terminator,
                                              (PBYTE)",;",
                                              &StartPtr );
            /**********************************************************/
            /* DEBUG_SEGMENTS : free up StartPtr segment (AK)         */
            /**********************************************************/
            if (prde_StringsAreEqual (Queue, pszWord))
            {
             /* SSFREESEG( SELECTOROF(StartPtr) ); */
                SSFREEMEM( StartPtr );                     /* CON3201 */
                return MATCH;
            }
        }
     /* SSFREESEG( SELECTOROF(StartPtr) ); */
        SSFREEMEM( StartPtr );                             /* CON3201 */
        return NO_MATCH;
    }
}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetAppDefaultPrinterName                          */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   CHAR              PrinterName[32];       e.g. PRINTER1           */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function queries the AppDefaultIniInfo and returns the        */
/* PrinterName listed there. It makes no attempt to check whether     */
/* this printer is associated with our driver.                        */
/**********************************************************************/
#if 0
USHORT pascal prde_GetAppDefaultPrinterName ( PrinterName )

PBYTE             PrinterName;
#endif

USHORT prde_GetAppDefaultPrinterName ( PBYTE PrinterName ) /* CON3201 */

{
    PBYTE           NamePtr;


/*  WinQueryProfileString( hab,                                      CON3201 */
    PrfQueryProfileString( HINI_PROFILE,
                           "PM_SPOOLER",
                           "PRINTER",
                           "",
                           PrinterName,
                           32 );

    /******************************************************************/
    /* Make sure the printer name is null terminated.                 */
    /******************************************************************/
    for ( NamePtr = PrinterName;
          *NamePtr;
          NamePtr++ )
    {
        if ( *NamePtr == ';' )
        {
            *NamePtr = '\0';
            break;
        }
    }

    return OK;
}





/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_ReadTerminatedWordFromText                        */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PBYTE              pszWord;        place to read word into       */
/*   PBYTE              pTerminator;    terminator of the word read   */
/*   PBYTE              AllowedTerminators;                           */
/*   PBYTE far *        pStartPtr;      ptr to where to start reading */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function reads characters starting at StartPtr until it       */
/* reaches one of the AllowedTerminators, or until it meets a null,   */
/* then it copies the word                                            */
/* starting at StartPtr into pszWord, terminating it with a null.     */
/* The terminator that was encountered is recorded and returned.      */
/* The function returns an error if none of the AllowedTerminators    */
/* is reached within 100 characters. It cannot cope with a null       */
/* character for a terminator. StartPtr is updated so that it         */
/* points to the character after the terminator.                      */
/*                                                                    */
/* This function is used for reading spooler and printer .ini         */
/* entries. For instance if we want to read the queue associated      */
/* with a given printer (from SpoolerIniEntry) it might end with a    */
/* ; or (if more than one queue is listed) it might end in ,.         */
/* We need to know which character it ended with so that we know      */
/* whether to look for another queue or not.                          */
/*                                                                    */
/* NOTE: This function doesn't test whether the buffer pszWord is     */
/* big enough for the string being written, except for the 100        */
/* char maximum. This could cause problems if e.g. we get invalid     */
/* spooler data with a printer name of more than 32 characters.       */
/**********************************************************************/
#if 0
USHORT pascal far prde_ReadTerminatedWordFromText ( pszWord,
                                                    pTerminator,
                                                    AllowedTerminators,
                                                    pStartPtr )

PBYTE              pszWord;
PBYTE              pTerminator;
PBYTE              AllowedTerminators;
PBYTE far *        pStartPtr;
#endif

SHORT prde_ReadTerminatedWordFromText ( PBYTE  pszWord,            /* CON3201 */
                                        PBYTE  pTerminator,        /* CON3201 */
                                        PBYTE  AllowedTerminators, /* CON3201 */
                                        PBYTE *pStartPtr )         /* CON3201 */

{
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    SHORT       i;

    /******************************************************************/
    /* If pszWord is NULL, return an error.                           */
    /******************************************************************/
    if (!pszWord)
        return ERROR_NEG;

    for (i=0;i<100 ;i++ )
    {
        pszWord[i] = *(*pStartPtr)++;
        if (prdu_stroccur(pszWord[i], AllowedTerminators))
        {
            *pTerminator = pszWord[i];
            pszWord[i] = '\0';
            return OK;
        }
    }
    return ERROR_NEG;
}



/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetDeviceName                                     */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*   FillPhysicalDeviceBlock                                          */
/*                                                                    */
/*   FPParamsLst far   * param1;                                      */
/*   DMDriverStruc far * pDriverData;                                 */
/*   lpPDBI              PDBInstance;                                 */
/*                                                                    */
/*    Return Code:                                                    */
/*    ------------                                                    */
/*      OK       = We have a valid PDBDeviceName and PDBPrinterType   */
/*                                                                    */
/*      ERROR_ZERO = The only entry in PM_SPOOLER_PRINTER is an old   */
/*                 driver name.                                       */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* This function decides printer type based on data in driver data    */
/* or what is in PM_SPOOLER_PRINTER entry.                            */
/**********************************************************************/
#if 0
USHORT pascal prde_GetDeviceName( param1,
                                  pDriverData,
                                  PDBInstance)

FPParamsLst far *    param1;
pDMDriverStruc far * pDriverData;            /* Pointer to DriverData */
lpPDBI               PDBInstance;
#endif

USHORT prde_GetDeviceName( FPParamsLst    *param1,         /* CON3201 */
                           pDMDriverStruc *pDriverData,    /* CON3201 */
                           lpPDBI          PDBInstance)    /* CON3201 */

{
#define TFUNC "prde_GetDeviceName"
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    PBYTE                StartPtr=FNULL;   /* for PM_SPOOLER_PRINTER  */
                                           /* PD00607                 */
    BYTE                 Terminator;
    CHAR                 pdriv_DeviceName[32];
    SHORT                i;
    BYTE                 pszWord[100];
    BYTE                 szCaption[40];
    BOOL                 Old_Entry;
    CHAR                 Prntr_Name_Buf[MAX_PRNTR_NAME];
    CHAR                 szMsg[SLEN_BOX_MESSAGE];
    USHORT               Rc;          /* Return code             */
    ULONG                IniSize;     /* Ini entry size PD00302  */
/*  PFN    CON3201       pPrfQueryProfSz; */ /*PD00302              */
    USHORT               DosResult;       /*PD00302              */
    HMODULE              ModuleHandle;    /*PD00302              */
    BOOL                 ModuleOK;        /*PD00302              */
    PBYTE                pStartPtrOld=FNULL; /* for PM_SPOOLER_DD PTR302*/
                                             /* PD00607                 */
    PBYTE                IniData;            /* for PM_SPOOLER_DD       */
    BOOL                 ChangeDriverData; /*PD00452            */

    Rc = OK;                                /* initialize        */
    PDBInstance->DfltPrtType = FALSE;       /* initialize        */
    ChangeDriverData = FALSE;               /* initialize PD00452 */

    /**********************************************************/
    /* Get the address of Prf..  PD00302                      */
    /**********************************************************/
 /* CON3201 **********************************************************/
 /* ModuleOK = DosLoadModule( FNULL, 0, "PMSHAPI", &ModuleHandle);   */
 /*                                                                  */
 /* DosResult = DosGetProcAddr( ModuleHandle,                        */
 /*                             "PRFQUERYPROFILESIZE",               */
 /*                             &pPrfQueryProfSz);                   */
 /********************************************************************/
    /**************************************************************/
    /* Get DeviceName of DriverData.                              */
    /**************************************************************/
    if ( *pDriverData )
    {
        prdu_strcpyN(pdriv_DeviceName,
                     param1->DO.pdriv->szDeviceName,32);

        if ( pdriv_DeviceName[0] != '\0' )
        {
            for (i = 0; i < NO_OF_PRINTERS; i++)
            {
                /**********************************************************/
                /* Read description string from the RC file.              */
                /**********************************************************/
                WinLoadString( hab,
                           prdd_ModHandle,
                           IDS_FIRST_PRINTER + i,
                           MAX_PRNTR_NAME,
                           (PSZ)Prntr_Name_Buf );

                /******************************************************/
                /* Now compare strings. If they match then build a    */
                /* keyword to read PM_SPOOLER_DD entry in INI file.   */
                /******************************************************/
                if ( !prdu_strcmp(
                          pdriv_DeviceName,
                          Prntr_Name_Buf))
                {
                     PDBInstance->PrinterType = i;

                     prdu_strcpy( PDBInstance->PDBDeviceName,
                                        DriverNameString );

                    *(PDBInstance->PDBDeviceName+DRIVER_NAME_LEN) = '.';

                    prdu_strcpy(
                           PDBInstance->PDBDeviceName+DRIVER_NAME_LEN+1,
                           Prntr_Name_Buf);

                    /******************************************************/
                    /* Make sure there exist an ini entry for this device.*/
                    /******************************************************/
/* CON3201          if ( pPrfQueryProfSz( HINI_SYSTEMPROFILE ,                */
                    if ( PrfQueryProfileSize( HINI_SYSTEMPROFILE ,
                                            (PSZ)"PM_SPOOLER_DD" ,
                                            (PSZ)PDBInstance->PDBDeviceName,
                                            (PULONG)&IniSize) )
                    {
                        return OK;
                    }
                    else
                    {
                        /**************************************************/
                        /* Check old format driver if there is an ini for */
                        /* this printer then do not invalidate the driver */
                        /* data. PD00417                                  */
                        /**************************************************/
/* CON3201              if ( pPrfQueryProfSz( HINI_SYSTEMPROFILE ,           */
                        if ( PrfQueryProfileSize( HINI_SYSTEMPROFILE ,
                                          (PSZ)"PM_SPOOLER_DD" ,
                                          (PSZ)DriverNameString,
                                          (PULONG)&IniSize) )
                        {
                            /******************************************/
                            /* Pass the driver name string instead of */
                            /* DeviceName. PD00436                    */
                            /******************************************/
                            *(PDBInstance->PDBDeviceName+DRIVER_NAME_LEN) = '\0';

                            if( StartPtr = prde_ReadOldConfig(
                                                PDBInstance->LPName,
                                                PDBInstance->PDBDeviceName,
                                                &PDBInstance->PrinterType) )
                            {

                            /* SSFREESEG(SELECTOROF(StartPtr)); */
                               SSFREEMEM(StartPtr);        /* CON3291 */
                               return OK;
                            }

                            *(PDBInstance->PDBDeviceName+DRIVER_NAME_LEN) = '.';
                        }
                    }
                }  /* if (!=prdu_strcmpN( ... */

            } /* for (i = 0; i < ....  */

            *pDriverData = NULL;

        } /* if (pdriv_DeviceName != NULL)   */

        else
        {
            *pDriverData = NULL;
        }

    }   /*   if ( *pDriverData )     */

READ_LAST_SELECTED_DEVICE:
    /*********************************************************************/
    /* set printer type to default printer and read device description   */
    /* for the default printer                                           */
    /*********************************************************************/
    PDBInstance->PrinterType = DEFAULT_PRINTER;

    PDBInstance->DfltPrtType = TRUE;        /* This flag will be used to */
                                            /* get dflt setting          */

    WinLoadString( hab,
                   prdd_ModHandle,
                   IDS_FIRST_PRINTER + DEFAULT_PRINTER,
                   MAX_PRNTR_NAME,
                   (PSZ)Prntr_Name_Buf );

    prdu_strcpy(PDBInstance->PDBDeviceName,
                          DriverNameString);

    *(PDBInstance->PDBDeviceName+DRIVER_NAME_LEN) = '.';

    prdu_strcpy(PDBInstance->PDBDeviceName+ DRIVER_NAME_LEN + 1,
                              Prntr_Name_Buf);

 /* (PBYTE)StartPtr = prde_ReadIniFile( PDBInstance->LPName, */
    StartPtr = prde_ReadIniFile( PDBInstance->LPName,      /* CON3201 */
                                      (PSZ)"PM_SPOOLER_PRINTER");


    if ( (StartPtr != (PBYTE)ERROR_NEG) && StartPtr )
    {
        /***********************************************************/
        /* first ';' is for logical printer address                */
        /***********************************************************/
        while ( *StartPtr++ != ';');

     /* (BYTE)Terminator = ','; */
        Terminator = ',';                                  /* CON3201 */

        Old_Entry = FALSE;

        while ( Terminator != ';' )
        {
            prde_ReadTerminatedWordFromText (pszWord,
                                             &Terminator,
                                             (PBYTE)",;",
                                             &StartPtr);

           if ( !prdu_strcmpN( (PBYTE)pszWord,DriverNameString,
                               DRIVER_NAME_LEN ))
           {

               if ( pszWord[ DRIVER_NAME_LEN ] != '.')
               {
                   /**********************************************************/
                   /* This is an old entry and it was not converted to new   */
                   /* format at install time. If we don't find  a valid      */
                   /* Name we will issue error.                              */
                   /**********************************************************/
                   Old_Entry = TRUE;
               }
               else
               {
                   for ( i = 0; i < NO_OF_PRINTERS; i++ )
                   {
                       /**********************************************************/
                       /* description string from the RC file.                   */
                       /**********************************************************/
                       WinLoadString( hab,
                                      prdd_ModHandle,
                                      IDS_FIRST_PRINTER + i,
                                      MAX_PRNTR_NAME,
                                      (PSZ)Prntr_Name_Buf );

                       /******************************************************/
                       /* Now compare strings. If they match then build a    */
                       /* keyword to read PM_SPOOLER_DD entry in INI file.   */
                       /******************************************************/
                       if ( !prdu_strcmp(pszWord+8,
                                         Prntr_Name_Buf))
                       {
                           PDBInstance->PrinterType = i;

                           prdu_strcpy(PDBInstance->PDBDeviceName,
                                       DriverNameString);

                           *(PDBInstance->PDBDeviceName+DRIVER_NAME_LEN)='.';

                           prdu_strcpy(
                           PDBInstance->PDBDeviceName+DRIVER_NAME_LEN+1,
                           Prntr_Name_Buf);

                           Old_Entry = FALSE;

                           PDBInstance->DfltPrtType = FALSE;

                           Terminator = ';';

                           break;
                       }  /* if (!=prdu_strcmpN( ... */


                   } /* for (i = 0; i < ....  */

               } /* else                */

           }  /* if (!prdu_strcmp((PBYTE)pszWord,(PBYTE)DriverNameString)) */

        } /* while (Terminator != ';')   */
        if ( Old_Entry )
        {

            /**********************************************************/
            /* This is an old entry and it was not converted to new   */
            /* format at install time. Read old entry and make sure   */
            /* it is not empty. PD00300                               */
            /**********************************************************/
            pStartPtrOld = (PBYTE)prde_ReadIniFile( DriverNameString,
                                                 (PSZ)"PM_SPOOLER_DD" );

            if ( pStartPtrOld != (PBYTE)ERROR_NEG )
            {

                IniData = pStartPtrOld;

                for ( ; (*IniData != ';') && (*IniData != '\0');
                            IniData++ );

            }

            /******************************************/
            /* Throw away the other SpoolerIniInfo    */
            /******************************************/
         /* if (SELECTOROF(pStartPtrOld))            */
         /*     SSFreeSeg(SELECTOROF(pStartPtrOld)); */
            if (pStartPtrOld)                              /* CON3201 */
                SSFreeMem(pStartPtrOld);                   /* CON3201 */

        }
     /* if ( SELECTOROF(StartPtr) ) */
        if ( StartPtr )
        {
         /* SSFREESEG(SELECTOROF(StartPtr)); */
            SSFREEMEM(StartPtr);                           /* CON3201 */
        }
    }  /* if ( (StartPtr != (PBYTE)ERROR_NEG)) && StartPtr )      */


    return (Rc);
}
#undef TFUNC

#ifdef OMIT_OLD_CODE

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetPrinterIniInfo                                 */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI               PDBInstance                                 */
/*   pDMDriverStruc       DriverData                                  */
/*   PUSHORT              pIniVersionType;  says whether .ini entry   */
/*                                          is in current format,     */
/*                                          previous format, or so    */
/*                                          old we can't use it.      */
/*   PBYTE far *          pStartPtr         To be returned as a       */
/*                                          pointer to the start      */
/*                                          of PrinterIniInfo for     */
/*                                          the PrinterType.          */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function points to printer information in INI file given the  */
/* logical PrinterName (e.g. PRINTER1) and PDBDeviceName.             */
/*                                                                    */
/* To do this we read PrinterIniInfo, the .ini entry written by       */
/* our driver. The entry consists of a list of all the logical        */
/* printers associated with our driver; for each printer there is the */
/* PrinterType associated with that printer, followed by              */
/* config information.                                                */
/* Here's an example:                                                 */
/*                                                                    */
/* IBM42XX.DRV;050;PRINTER1=0901213<lots of config info>              */
/* PRINTER2=0901213<info>                                             */
/*                                                                    */
/* How to read this: there is a driver name followed by ;, then a     */
/* version number followed by ;, then a printer name followed by      */
/* =. If this is not the printer we want we scan through till we      */
/* hit the sequence ,<PrinterName>=. If it is, continue reading.      */
/* The first two digits after = (09 in this example) are the          */
/* PrinterType - in prddcone.h we see that 9 corresponds to           */
/* IBM_PRO_PRINTER_XL24E.                                             */
/* The next 5 digits (01213) tell us how long this entry is so if     */
/* this is not the printer we are looking for (as in this case)       */
/* we skip 1213 characters and start reading again. In this case      */
/* that takes us to 0201213 etc., the beginning of the entry for      */
/* next logical printer name                                          */
/* the beginning of the entry for the printer we                      */
/* want. This function returns a pointer to the start of the          */
/* 09213 bit.                                                         */
/**********************************************************************/
#if 0
BOOL pascal prde_GetPrinterIniInfo( PDBInstance,
                                 DriverData,
                                 pIniVersionType,
                                 pStartPtr)

lpPDBI               PDBInstance;
pDMDriverStruc       DriverData;
PUSHORT              pIniVersionType;
PBYTE far *          pStartPtr;
#endif

BOOL prde_GetPrinterIniInfo( lpPDBI          PDBInstance,
                             pDMDriverStruc  DriverData,
                             PUSHORT         pIniVersionType,
                             PBYTE          *pStartPtr)

{
#define TFUNC "GetPrinterIniInfo"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    ULONG               Result;           /* return from subfunctions */
    PBYTE               SavePtr=FNULL;    /* PD00607                  */
    USHORT              LogErrCode;       /* Error code to be logged  */

    *pStartPtr = (PBYTE)prde_ReadIniFile( PDBInstance->PDBDeviceName,
                                          (PSZ)"PM_SPOOLER_DD");

    /******************************************************************/
    /* if dflt printer type flag is set we use the dflt setting.      */
    /******************************************************************/
    if ( !PDBInstance->DfltPrtType )
    {
        if (*pStartPtr == (PBYTE)ERROR_NEG )
        {
            TRACE6(TFUNC, "ReadIniFile failed", FNULL, 0);
            goto ERR_EXIT;
        }
        else
        {
            SavePtr = *pStartPtr;

            /*********************************************************/
            /* Skip past the path.                                   */
            /*********************************************************/
            while ( *(*pStartPtr)++ != ';' );

            /*********************************************************/
            /* Next there might or might not be a version number.    */
            /* We don't use this PrinterIniInfo if the version       */
            /* number is missing or if it is not current.            */
            /* Instead we read old Ini entry if there is one.        */
            /* If there is no data we use the default setting.       */
            /*********************************************************/
            if ( (*(*pStartPtr) == ';') && prdu_strcmp(
                                             PDBInstance->PDBDeviceName,
                                             DriverNameString) )
            {
                /*****************************************************/
                /* No version number - don't use this data.          */
                /* Read the old Ini format.                          */
                /*****************************************************/
                *pStartPtr = (PBYTE)prde_ReadIniFile(
                                          DriverNameString,
                                          (PSZ)"PM_SPOOLER_DD");
                if (*pStartPtr != (PBYTE)ERROR_NEG )
                {
                    /*************************************************/
                    /* Throw away the other SpoolerIniInfo. PD00147  */
                    /*************************************************/
                 /* if (SELECTOROF(SavePtr))           */
                 /*    SSFreeSeg(SELECTOROF(SavePtr)); */
                    if (SavePtr)
                       SSFreeMem(SavePtr);

                    SavePtr = *pStartPtr;
                }
            }
            *pStartPtr = SavePtr;

            /*****************************************************************/
            /* Find entry for PrinterName in PrinterIniInfo.                 */
            /*****************************************************************/
            Result=prde_GetPrinterNameEntry( PDBInstance,
                                             pIniVersionType,
                                             pStartPtr );
            if (Result != OK)
            {
                /*************************************************************/
                /* We haven't got an entry for the PrinterName we chose      */
                /* in prde_GetPrinterName. As a second best, we look for     */
                /* the first PrinterName entry in PrinterIniInfo.            */
                /*                                                           */
                /* Note that if prde_GetPrinterNameEntry is passed a null    */
                /* PrinterName, it will grab the first entry and will        */
                /* fill in the PrinterName.                                  */
                /*************************************************************/
                *pStartPtr = SavePtr;
                *( PDBInstance->LPName ) = '\0';

                Result=prde_GetPrinterNameEntry( PDBInstance,
                                                 pIniVersionType,
                                                 pStartPtr );
               if ( Result != OK )
               {
                   /*************************************************************/
                   /* We couldn't find anything suitable                        */
                   /* in PrinterIniInfo. Set *pStartPtr to NULL and get the     */
                   /* PrinterType fron the DriverData if possible, otherwise use*/
                   /* default.                                                  */
                   /*************************************************************/
                   *pStartPtr = NULL;
               }

            }

        }

    } /* if ( !PDBInstance->DfltPrtType )    */
    else
    {
        *pStartPtr = NULL;
    }
OK_EXIT:
    return OK;

ERR_EXIT:
    return ERROR_NEG;
}
#undef TFUNC

#endif
#ifdef OMIT_OLD_CODE

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetPrinterNameEntry                               */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   CHAR                 PrinterName[32];                            */
/*   PUSHORT              pIniVersionType;  says whether .ini entry   */
/*                                          is in current format,     */
/*                                          previous format, or so    */
/*                                          old we can't use it.      */
/*   PBYTE far *          pStartPtr         To be returned as a       */
/*                                          pointer to the start      */
/*                                          of PrinterIniInfo for     */
/*                                          the PrinterName.          */
/*                                          Starts off pointing to    */
/*                                          start of PrinterIniInfo.  */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* We're given a pointer (*pStartPtr) to the start of the .ini entry  */
/* for our driver, which looks like e.g.                              */
/*                                                                    */
/* IBM42XX.DRV;050;PRINTER1=090101213<lots of config info>            */
/* 0201213<info>0901213<info>,PRINTER2=070101213<info>0701213<info>   */
/*                                                                    */
/* We return a pointer to just after the = sign for the logical       */
/* printer we're after.                                               */
/*                                                                    */
/* Also return the IniVersionType.                                    */
/**********************************************************************/
#if 0
BOOL pascal prde_GetPrinterNameEntry( PDBInstance,
                                      pIniVersionType,
                                      pStartPtr )


lpPDBI               PDBInstance;
PUSHORT              pIniVersionType;
PBYTE far *          pStartPtr;
#endif

BOOL prde_GetPrinterNameEntry( lpPDBI   PDBInstance,       /* CON3201 */
                               PUSHORT  pIniVersionType,   /* CON3201 */
                               PBYTE   *pStartPtr )        /* CON3201 */

{
#define TFUNC "GetPrinterNameEntry"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    PBYTE                PrinterName;
    BYTE                Terminator;       /* Passed to subfunction    */
    CHAR                CurrentName[32];  /* Read from IniInfo        */
    ULONG               Result;           /* return from subfunctions */


    /******************************************************************/
    /* Exit if StartPtr is null.                                      */
    /******************************************************************/
    if ( !*pStartPtr )
    {
        return ERROR_NEG;
    }

    PrinterName = (PBYTE)PDBInstance->LPName;
    /******************************************************************/
    /* Scan through PrinterIniInfo. Note that initially *pStartPtr    */
    /* points to the beginning of the driver path (e.g. IBM42XX.DRV). */
    /******************************************************************/
    /******************************************************************/
    /* Skip past the path.                                            */
    /******************************************************************/
    while ( *(*pStartPtr)++ != ';' );

    /******************************************************************/
    /* Next there might or might not be a version number. We don't    */
    /* use this PrinterIniInfo if the version number is missing or    */
    /* if it is not current.                                          */
    /******************************************************************/
    if ( *(*pStartPtr) == ';')
    {
        /**************************************************************/
        /* No version number - don't use this data.                   */
        /**************************************************************/
        return ERROR_NEG;
    }

    /******************************************************************/
    /* The version number is 3 bytes followed by ';'. Check this is   */
    /* in the .ini file. Note we must do this here otherwise the      */
    /* next fn call might cause a trap.                               */
    /******************************************************************/
    if ( *(*pStartPtr + 3) != ';')
        return ERROR_NEG;

    /******************************************************************/
    /* Set VersionNumber to point to the number, finished by a null.  */
    /******************************************************************/
    (void)  prde_ReadTerminatedWordFromText(
                                         (PBYTE)PDBInstance->IniVersion,
                                         &Terminator,
                                         (PBYTE)";",
                                         pStartPtr );

    /******************************************************************/
    /* The .ini format changed Nov 90, but we support the previous    */
    /* .ini format. Work out here whether the .ini format is          */
    /* INI_VERSION_CURRENT, INI_VERSON_PREVIOUS or                    */
    /* INI_VERSION_DONT_USE.                                          */
    /******************************************************************/
    *pIniVersionType = prde_GetIniVersionType(
                                     (PBYTE)PDBInstance->IniVersion );

    if ( *pIniVersionType == INI_VERSION_DONT_USE)      /* SG 5/07/91 */
    {
        /**************************************************************/
        /* The version number of PrinterIniInfo is less than the      */
        /* number expected by the driver.                             */
        /**************************************************************/
        return ERROR_NEG;
    }

    /******************************************************************/
    /* We're now pointing to the beginning of the name of the first   */
    /* listed printer. Read it.                                       */
    /******************************************************************/
    /*******************************************************************/
    /* If no PrinterName was given then we return with the first      */
    /* listed printer.                                                */
    /******************************************************************/
    if ( PrinterName[0] == '\0' )
    {
        Result = prde_ReadTerminatedWordFromText( PrinterName,
                                                  &Terminator,
                                                  (PBYTE)"=",
                                                  pStartPtr );
        if ( Result != OK )
        {
            /**********************************************************/
            /* Couldn't find entry.                                   */
            /**********************************************************/
            return ERROR_NEG;
        }
        /**************************************************************/
        /* Note that now *pStartPtr points to just after the '=' sign.*/
        /**************************************************************/
        return OK;
    }

    /******************************************************************/
    /* We want to compare the listed printers with the given          */
    /* PrinterName until we find a match.                             */
    /******************************************************************/
    while (TRUE)
    {
        Result = prde_ReadTerminatedWordFromText( CurrentName,
                                                  &Terminator,
                                                  (PBYTE)"=",
                                                  pStartPtr );
        if ( Result != OK )
        {
            /**********************************************************/
            /* Couldn't find another entry. As we haven't found a     */
            /* match yet, return error.                               */
            /**********************************************************/
            return ERROR_NEG;
        }

        if ( !prdu_strcmpN( (PBYTE)CurrentName,
                                      (PBYTE)PrinterName, 32 ))
        {
            /**********************************************************/
            /* We've found a match. *pStartPtr now points to just     */
            /* after the = sign for the right printer. Return.        */
            /**********************************************************/
            return OK;
        }

        /**************************************************************/
        /* We haven't found a match yet. Move on to start of next     */
        /* printer name, which starts after the next , found.         */
        /**************************************************************/
        while ( *(*pStartPtr)++ != ',' )
        {
            /**********************************************************/
            /* If we hit a null then we've come to the end of         */
            /* PrinterIniInfo - return error.                         */
            /**********************************************************/
            if ( !*(*pStartPtr) )
                return ERROR_NEG;
        }
    }
}
#undef TFUNC


#endif
#ifdef OMIT_OLD_CODE

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_GetPrinterTypeEntry                               */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   lpPDBI               PDBInstance;                                */
/*   USHORT               IniVersionType;                             */
/*   PBYTE far *          pStartPtr;        To be returned as a       */
/*                                          pointer to the start      */
/*                                          of PrinterIniInfo for     */
/*                                          the PrinterType.          */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* We're give a pointer (*pStartPtr) to the start of the driver's     */
/* .ini entry for our printer, e.g.                                   */
/*                                                                    */
/* 090101213<lots of config info>0201213<info>0901213<info>,          */
/*                                                                    */
/* We read the first two digits, which give the PrinterType, then     */
/* go through the entry to find the start of the config info for      */
/* that type. We return a pointer to the start of that info.          */
/*                                                                    */
/**********************************************************************/
#if 0
BOOL pascal prde_GetPrinterTypeEntry( PDBInstance,
                                      pStartPtr )


lpPDBI               PDBInstance;
PBYTE far *          pStartPtr;
#endif

BOOL prde_GetPrinterTypeEntry( lpPDBI  PDBInstance,        /* CON3201 */
                               PBYTE  *pStartPtr )         /* CON3201 */

{
#define TFUNC "GetPrinterTypeEntry"
    /******************************************************************/
    /* Local variables.                                               */
    /******************************************************************/
    USHORT              CurrentType;      /* Read from IniInfo        */
    USHORT              IniEntryLength;   /* length of PrinterIniEntry*/
                                          /* for a particular type    */


    /******************************************************************/
    /* Exit if *pStartPtr is null.                                    */
    /******************************************************************/
    if ( !(*pStartPtr) )
    {
        return ERROR_NEG;
    }

    if ( !prdu_strcmp( PDBInstance->PDBDeviceName,DriverNameString ) )
    {
        /******************************************************************/
        /* Read the type for the given printer (note that *pStartPtr      */
        /* points to the type).                                           */
        /******************************************************************/
        prdm_ReadWordFromText( PDBInstance->PrinterType,
                               PRINTER_TYPE_LENGTH,
                               (*pStartPtr) );
    }
    else
    {
        /******************************************************************/
        /* We know the printer type. But there was no setting in the ini  */
        /* entry. We must use the setting in the old ini entry.           */
        /******************************************************************/
        *pStartPtr += PRINTER_TYPE_LENGTH;

    }
    /*******************************************************************/
    /* Now *pStartPtr points to just after the selected type, i.e. it */
    /* points to the start of the info for the first type listed      */
    /* for the current PrinterName.                                   */
    /*                                                                */
    /* Scan through all the type entries until we match the type      */
    /* that we just read.                                             */
    /******************************************************************/
    while ( *(*pStartPtr) && *(*pStartPtr) != ',' && *(*pStartPtr) != ';' )
    {
        /**************************************************************/
        /* Read in the Printer type for this entry.                   */
        /**************************************************************/
        prdm_ReadWordFromText( CurrentType,
                               PRINTER_TYPE_LENGTH,
                               (*pStartPtr) );

        TRACE4(TFUNC, "Printer type", &PrinterType, 1);

        if ( CurrentType == PDBInstance->PrinterType )
        {
            /**********************************************************/
            /* We have found the correct entry.                       */
            /* Move on to the next entry. We must read the length of  */
            /* this entry first.                                      */
            /**********************************************************/
            prdm_ReadWordFromText( IniEntryLength,
                                   NO_DATA_SIZE_DIGITS,
                                   (*pStartPtr) );

            /**********************************************************/
            /* Move *pStartPtr back to the beginning of the entry     */
            /* and return.                                            */
            /**********************************************************/
            *pStartPtr -= (PRINTER_TYPE_LENGTH + NO_DATA_SIZE_DIGITS);


            /*************************************************************/
            /* The Ini entry is in old format. Call TranslateOldIniEntry */
            /* which grabs a new buffer, and trows away the current      */
            /* buffer. It returns a pointer to new one.                  */
            /*************************************************************/
            *pStartPtr = prde_TranslateOldIniEntry(PDBInstance,
                                                   *pStartPtr,
                                                   (PUSHORT)&IniEntryLength);
            return OK;

        }

        /**************************************************************/
        /* Move on to the next entry. We must read the length of      */
        /* this entry first.                                          */
        /**************************************************************/
        prdm_ReadWordFromText( IniEntryLength,
                               NO_DATA_SIZE_DIGITS,
                               (*pStartPtr) );

        *pStartPtr += IniEntryLength -
                            (PRINTER_TYPE_LENGTH + NO_DATA_SIZE_DIGITS);
    }
    /******************************************************************/
    /* If we got to here, we got to the end of PrinterIniInfo without */
    /* finding the right entry.                                       */
    /******************************************************************/
    *pStartPtr = FNULL;
    return OK;
}
#undef TFUNC

#endif
#ifdef OMIT_OLD_CODE
/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_TranslateOldIniEntry                              */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/* PBYTE                pSource          ptr to start of old entry    */
/* PUSHORT              pEntryLength     ptr to length of old entry   */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* There is a requirement to make old format .ini entries readable    */
/* by the new merged code.                                            */
/*                                                                    */
/* This function takes the driver's .ini entry for old versions of    */
/* 42xx, 52xx and 4019 (i.e. pre-merged versions) and creates from    */
/* it an entry in the new format, without losing information. It      */
/* throws away the old entry and returns a pointer to the new.        */
/*                                                                    */
/**********************************************************************/
#if 0
PBYTE pascal prde_TranslateOldIniEntry( PDBInstance,
                                        pSource,
                                        pEntryLength )

lpPDBI              PDBInstance;
PBYTE               pSource;
PUSHORT             pEntryLength;
#endif

PBYTE prde_TranslateOldIniEntry( lpPDBI  PDBInstance,      /* CON3201 */
                                 PBYTE   pSource,          /* CON3201 */
                                 PUSHORT pEntryLength )    /* CON3201 */

{
#define TFUNC "prde_TranslateOldIniEntry"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT          Result;             /* return from functions      */
    USHORT          NewEntrySize;       /* size of new .ini entry     */
    PBYTE           pDest;              /* ptr into new .ini entry    */
    BYTE            Separator;          /* keeps track of where we are*/
    USHORT          TypeEntryLength;    /* size of old 42xx/52xx      */
                                        /*   printer type entry       */
    PBYTE           pDestHeaderStart;   /* ptr to start of header     */
    lpDMSettings    TempDMSettings;     /* stores old 4019 info       */

    /******************************************************************/
    /* A safe estimate for the size of a new driver entry compared to */
    /* an old one is to add an eighth.                                */
    /******************************************************************/

    NewEntrySize = *pEntryLength + (*pEntryLength >> 3) + 1;

    Result = SafeSSALLOCMEM ( &pDest,
                               NewEntrySize,
                               0 );

    if ( Result != DOS_OK )
    {
       return (PBYTE)NULL;
    }


    Result = SafeSSALLOCMEM ( &TempDMSettings              /* CON3201 */
                               sizeof(DMSettingsType),     /* CON3201 */
                               0 );                        /* CON3201 */

    if ( Result != DOS_OK )
    {
        return (PBYTE)NULL;
    }

 /* OFFSETOF(TempDMSettings) = 0; */                       /* CON3201 */

    /**********************************************************/
    /* We must convert an old-style 42xx or 52xx entry. The   */
    /* differences are: header increased by 15 bytes and      */
    /* entry length (for each printer type) increased by 15.  */
    /*                                                        */
    /**********************************************************/

    /**********************************************************/
    /* Remember pDest. PD00340                                */
    /**********************************************************/
    pDestHeaderStart = pDest;

    /******************************************************/
    /* Copy the PrinterType field in the header.          */
    /******************************************************/
    prdu_memcpy( pDest, pSource, 2);

    pSource += 2;
    pDest += 2;

    /******************************************************/
    /* Read the entry length, add 15, and write it.       */
    /******************************************************/
    prdm_ReadWordFromText( TypeEntryLength,
                           NO_DATA_SIZE_DIGITS,
                           pSource );

    TypeEntryLength += 15;

    prdm_WriteTextFromWord( TypeEntryLength,
                            NO_DATA_SIZE_DIGITS,
                            pDest );

    /******************************************************/
    /* Copy more of the header up to the start of the     */
    /* new fields. This is 31 bytes' worth.               */
    /******************************************************/
    prdu_memcpy( pDest, pSource,31);

    pSource += 31;
    pDest += 31;

    /******************************************************/
    /* Write 15 zeroes into the dest buffer.              */
    /******************************************************/
    prdu_memset( pDest, '0',3);
    pDest += 3;

    prdu_memset( pDest, '1',1);  /* set SimDup to default */
    pDest += 1;                  /* PD00058               */

    prdu_memset( pDest, '0',11);
    pDest += 11;

    /******************************************************/
    /* Copy the rest of the info for this printer type.   */
    /* Length still to copy is TypeEntryLength - 53.      */
    /******************************************************/
    TypeEntryLength -= 53;

    prdu_memcpy( pDest, pSource, TypeEntryLength);

    pSource += TypeEntryLength;
    pDest += TypeEntryLength;
    /***************************************************/
    /* The first byte in DfltFontInfo is font type     */
    /* (resident, card etc). The constants for the     */
    /* types are different in the old and new styles   */
    /* so convert this.  PD00340                       */
    /***************************************************/
    prde_ReadHeaderData( TempDMSettings,
                         pDestHeaderStart,
                         INI_VERSION_CURRENT );

    prde_TranslateOldBody( pDestHeaderStart+HEADER_LENGTH,
                           TempDMSettings );

    /******************************************************************/
    /* Finish off the new entry with a null.                          */
    /******************************************************************/
    *pDest++ = ';';
    *pDest = '\0';

    /******************************************************************/
    /* We've translated the whole of the driver entry. Throw away the */
    /* segment containing the old driver entry.                       */
    /******************************************************************/
 /* SSFREESEG(SELECTOROF( pSource )); */
    SSFREEMEM(Source );                                    /* CON3201 */

    /******************************************************************/
    /* For 4019, we allocated space for TempDMSettings. Free this.    */
    /******************************************************************/
 /* SSFREESEG ( SELECTOROF(TempDMSettings) ); */
    SSFREEmem ( TempDMSettings );

    /******************************************************************/
    /* Reset EntryLength to the length of the new entry.              */
    /******************************************************************/
    *pEntryLength = OFFSETOF( pDest );

    /******************************************************************/
    /* Return a pointer to the start of the new entry.                */
    /******************************************************************/
 /* OFFSETOF(pDest) = 0; */                                /* CON3201 */
    return ( pDest );
}
#undef TFUNC

#endif

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prde_WriteHeaderData                                   */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PBYTE            pDest          where to start writing to        */
/*   lpDMSettings     pDMSettings    what to write                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function writes the fixed length header data from           */
/*   DMSettings to the INI entry for the given printer.               */
/*                                                                    */
/**********************************************************************/
#if 0
void pascal prde_WriteHeaderData( pDest, pDMSettings )

PBYTE             pDest;
lpDMSettings      pDMSettings;
#endif

void prde_WriteHeaderData( PBYTE        pDest,
                           lpDMSettings pDMSettings )

{
#define TFUNC "prde_WriteHeaderData"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT      Work;          /* Working word                        */
    USHORT      i;             /* Loop variable                       */

    /******************************************************************/
    /* Write the printer type code.                                   */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->PrinterType,
                            PRINTER_TYPE_LENGTH,
                            pDest );

    /******************************************************************/
    /* Write the total size of the entry for this printer.            */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->INIEntrySize,
                            NO_DATA_SIZE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the orientation.                                         */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->Orientation,
                            ORIENTATION_LENGTH,
                            pDest );

    /******************************************************************/
    /* Write the resolution.                                          */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->Resolution,
                            RESOLUTION_LENGTH,
                            pDest );

    /******************************************************************/
    /* Write the form feed state.                                     */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->FFSet,
                            FORM_FEED_LENGTH,
                            pDest );

    /******************************************************************/
    /* Write the default spool file type.                             */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->DefaultSpoolIndex,
                            SPOOL_INDEX_LENGTH,
                            pDest );

    /******************************************************************/
    /* Write the Pel Addressable font type.                           */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->PelAddrFontType) + '0';

    /******************************************************************/
    /* Write the index of the current Source configeration.           */
    /* This is an index into the DVTSourceList in the printer's DDT.  */
    /* The value held in the INI file for the two dual paper tray     */
    /* configerations on the Qs is a special case.   The same index   */
    /* is used for both (the one with no envelope tray); the          */
    /* current configeration then depends on the value in             */
    /* AddedFeed.                                                     */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->SourceIndex,
                            NO_INFO_SIZE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the Envelope Feed type.                                  */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->AddedFeed) + '0';

    /******************************************************************/
    /* Write the current form number.                                 */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->SelectedForm,
                            NO_FORM_CNT_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the number of forms.                                     */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->NumberOfForms,
                            NO_FORM_CNT_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the number of available cards.                           */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->NumberAvailCards,
                            NO_FONT_CNT_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the number of owned cards.                               */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->NumberOwnedCards,
                            NO_FONT_CNT_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the number of shipped cards.                             */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->ShippedCardCount,
                            NO_INFO_SIZE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the number of download fonts.                            */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->NumberOfDownFonts,
                            NO_FONT_CNT_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the flag indicating download code page memory available. */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->DownCPMemAvail) + '0';

    /******************************************************************/
    /* Write the number of added code pages.                          */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->NoOfAddedCPs,
                            NO_CODE_PAGE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the index of the initial code page - the index is into   */
    /* the DVTCodePageList.                                           */
    /******************************************************************/
    Work = pDMSettings->InitCodePage + 1;

    prdm_WriteTextFromWord( Work,
                            NO_CODE_PAGE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the reload type for the initial code page.               */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->InitCPReloadType) + '0';

    /******************************************************************/
    /* New fields MJB 30/10/90                                        */
    /******************************************************************/
    /******************************************************************/
    /* Memory option for the 4019 family                              */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->MemoryOption,
                            NO_MEM_OPT_DIGITS,
                            pDest );

    /******************************************************************/
    /* Resident font set: entry level or full set (might be needed    */
    /* on Heritage E)                                                 */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->ResFontSet) + '0';

    /******************************************************************/
    /* Printing mode on 3816: simplex, duplex or tumble duplex.       */
    /* Use DUPLEX_FLAG to indicate whether duplex option is enabled   */
    /* on the 4019 Heritage printer.                                  */
    /******************************************************************/
    Work = ( pDMSettings->SimDup +
             (pDMSettings->DuplexEnabled ? DUPLEX_FLAG : 0) ) + '0';
    *pDest++ = (BYTE)Work;

    /******************************************************************/
    /* Default source.                                                */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->DefaultSource,
                           NO_DEF_SOURCE_DIGITS,
                           pDest );

    /******************************************************************/
    /* Band compression.                                              */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->BandCompression) + '0';

    /******************************************************************/
    /* Down load system fonts.                                        */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->DownSysFonts) + '0';

    /******************************************************************/
    /* PD00136 : Disable outline fonts...                             */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->DisableOutlineFonts) + '0';

    /******************************************************************/
    /* DIAL/NILE : Write the MachineType.                             */
    /******************************************************************/
    *pDest++ = (BYTE)(pDMSettings->MachineType) + '0';

    /******************************************************************/
    /* Write the default outline font point size     PD00137          */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->DfltFontPointSz,
                            NO_POINTSIZE_DIGITS,
                            pDest );
    /**************************************************************************/
    /* PD00769 : Write out Printer Patterns byte to INI                       */
    /* PADDING_LENGTH reduced by 1 to 24 bytes.                               */
    /**************************************************************************/
    *pDest++ = (BYTE)(pDMSettings->PrinterPatterns) + '0';

    /******************************************************************/
    /* There are 24 unused bytes, reserved for future expansion.      */
    /* Note: we can't leave nulls in the .ini entry (null means end   */
    /* of the string), so write zeroes. prdm_WriteTextFromWord can't  */
    /* cope with fields of large length (e.g. 9 ) so do it manually.  */
    /******************************************************************/
    for ( i = PADDING_LENGTH; i; i--)
        *pDest++ = '0';

    /******************************************************************/
    /* That's all the new fields 30/10/90.                            */
    /******************************************************************/
    /******************************************************************/
    /* Write the size of the source form data.                        */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->SourceDataSize,
                            NO_DATA_SIZE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the length of the default metrics path.                  */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->MetricsPathLength,
                            PATHNAME_SIZE_LENGTH,
                            pDest );

    /******************************************************************/
    /* Write the size of the card data.                               */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->CardDataSize,
                            NO_DATA_SIZE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the size of the download font data.                      */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->DownFontDataSize,
                            NO_DATA_SIZE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the size of the code page data.                          */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->CodePageDataSize,
                            NO_DATA_SIZE_DIGITS,
                            pDest );

    /******************************************************************/
    /* Write the size of the default font info.                       */
    /******************************************************************/
    prdm_WriteTextFromWord( pDMSettings->DfltFontInfoSize,
                            NO_INFO_SIZE_DIGITS,
                            pDest );

}
#undef TFUNC

