/*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 = PRDMSUB1
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdm_TranslateOldIniEntry
 *             prdm_GetDeviceName
 *             prdm_PM_DD_Write
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                        /* CON3201 */
#define INCL_DOSPROCESS                /* CON3201 */
#define INCL_DOSSEMAPHORES
#define INCL_WINWINDOWMGR
#define INCL_GPIERRORS
#define INCL_SHLERRORS
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_DOSMODULEMGR
#define INCL_WINFRAMEMGR
#define INCL_WINLISTBOXES
#define INCL_WINBUTTONS
#define INCL_WINERRORS
#define INCL_WINDIALOGS
#define INCL_WINSHELLDATA
#define INCL_WINENTRYFIELDS
#define INCL_WINMESSAGEMGR
#define INCL_WININPUT
#define INCL_WINMENUS
#define INCL_WINPOINTERS
#define INCL_DEV
#define INCL_DOSMISC
#define INCL_GPIERRORS
#include <os2.h>
#undef INCL_DOSPROCESS                    /* CON3201 */
#undef INCL_DOSSEMAPHORES
#undef INCL_WINWINDOWMGR
#undef INCL_GPIERRORS
#undef INCL_SHLERRORS
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_DOSMODULEMGR
#undef INCL_WINFRAMEMGR
#undef INCL_WINLISTBOXES
#undef INCL_WINBUTTONS
#undef INCL_WINERRORS
#undef INCL_WINDIALOGS
#undef INCL_WINSHELLDATA
#undef INCL_WINENTRYFIELDS
#undef INCL_WINMESSAGEMGR
#undef INCL_WININPUT
#undef INCL_WINMENUS
#undef INCL_WINPOINTERS
#undef INCL_DEV
#undef INCL_DOSMISC
#undef INCL_GPIERRORS

#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_MISC
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELSERVER
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_MISC
#undef INCL_WINP_SEI

#define INCL_WINSHELLDATA
/* #include <pmshlp.h>                                              DLM01 */
#define INCL_WINSHELLDATA
#undef INCL_32                            /* CON3201 */

#include <prdconse.h>
#include <prddcone.h>
#include <prdmcone.h>
#include <prdtcone.h>

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

#include <prdmextf.h>
#include <prdeextf.h>
#include <prdyextf.h>
#include <prduextf.h>
#include <prdmtrcf.h>

/**********************************************************************/
/* Set up external accesses                                           */
/**********************************************************************/
extern HMODULE                prdd_ModHandle;
extern PCHAR                  OS2_INI_VERSION;
extern PCHAR                  OS2_INI_MAGIC_NUMBER1;
extern PCHAR                  OS2_INI_MAGIC_NUMBER2;
extern PCHAR                  OS2_INI_THRESHOLD;
extern PCHAR                  DOWNSYSFONTS_THRESHOLD;
extern USHORT                 DRIVER_TYPE;
extern lpDMSettings           DVTDfltDMSettings [];
extern PCHAR                  DriverNameString;
extern USHORT                 DEFAULT_PRINTER;
extern USHORT                 NO_OF_PRINTERS;

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdm_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.        */
/*                                                                    */
/* This function is called from prdm_Dialog. When the user exits from */
/* the Printer Setup dialog with ENTER, this routine ensures that     */
/* the whole driver entry saved will be in the new format. The        */
/* version number is also updated to the current version.             */
/**********************************************************************/
/* CON3201
PBYTE pascal prdm_TranslateOldIniEntry( pSource, pEntryLength )

PBYTE               pSource;
PUSHORT             pEntryLength;
                              */
PBYTE prdm_TranslateOldIniEntry(PBYTE               pSource,
                                PUSHORT             pEntryLength)

{
#define TFUNC "prdm_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       */
    USHORT          Type;               /* Printer Type               */
    PBYTE           pTempDMSettings;    /* Stores old 4019 settings   */

    PBYTE           pTemp;              /* CON3201                    */


    /******************************************************************/
    /* A safe estimate for the size of a new driver entry compared to */
    /* an old one is to add an eighth.                                */
    /******************************************************************/
//  NewEntrySize = 65535;            /* 64K                           */
    NewEntrySize = *pEntryLength + (*pEntryLength >> 3) + 1;
  /* CON3201 *************************************/
  /*Result = SSALLOCSEG ( NewEntrySize,          */
  /*                      &SELECTOROF(pDest),    */
  /*                      0 );                   */
  /***********************************************/

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

    if ( Result != DOS_OK )
    {
        Ring3LOGDOSERR(TFUNC, "SSALLOCMEM Fail", &Result, 1, Result);
        return (PBYTE)NULL;
    }
    pTemp = pDest; /* CON3201 - save the base address so we can generate the
                                the length later                            */

/*  OFFSETOF(pDest) = 0;                                            CON3201 */
    /*CON3201****************************************************************/
    /*Result = SSALLOCSEG ( sizeof(DMSettingsType),                         */
    /*                      &SELECTOROF(TempDMSettings),                    */
    /*                      0 );                                            */
    /************************************************************************/

    Result = SafeSSALLOCMEM ((PVOID)&pTempDMSettings, sizeof(DMSettingsType), 0);
    if ( Result != DOS_OK )
    {
// CON3201        SSFREESEG(SELECTOROF( pDest ));          /* PD00607           */
        SSFREEMEM( pDest );          /* PD00607           */
        Ring3LOGDOSERR(TFUNC, "SSALLOCMEM Fail", &Result, 1, Result);
        return (PBYTE)NULL;
    }

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

    /******************************************************************/
    /* Start copying old entry into new. Copy the driver name and ';'.*/
    /******************************************************************/
    while ( (*pDest++ = *pSource++) != ';');

    /******************************************************************/
    /* Skip past the version number in the source; write the current  */
    /* version number in the dest.                                    */
    /******************************************************************/
    while ( *pSource++ != ';');

    prdu_strcpy(pDest, OS2_INI_VERSION);
    pDest += 3;
    *pDest++ = ';';

    /******************************************************************/
    /* Set separator to null. It will be set to the character after   */
    /* the entry for each logical printer name. This character is ',' */
    /* if there are more printers listed and ';' if not.              */
    /******************************************************************/
    Separator = '\0';

    /******************************************************************/
    /* There might not be any printers listed - in this case the char */
    /* at pSource will be ';'. Copy this across and we're done.       */
    /******************************************************************/
    if (*pSource == ';')
    {
        Separator = ';';
        *pDest++ = *pSource;

    }

    /******************************************************************/
    /* Now both pSource and pDest point to just after the version     */
    /* number. Go through the entry for each logical printer name.    */
    /******************************************************************/
    while (Separator != ';')
    {
        /**************************************************************/
        /* Copy across the <PrinterName>= string.                     */
        /**************************************************************/
        while ( (*pDest++ = *pSource++) != '=');

        /**********************************************************/
        /* 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.  */
        /*                                                        */
        /* Copy across the current printer type, which is 2 bytes */
        /* long.                                                  */
        /**********************************************************/
        *pDest++ = *pSource++;
        *pDest++ = *pSource++;

        /**********************************************************/
        /* Loop for each printer type listed.                     */
        /**********************************************************/
        Separator = '\0';

        while ( !Separator )
        {
            /**********************************************************/
            /* Remember pDest. PD00340                                */
            /**********************************************************/
            pDestHeaderStart = pDest;

            /**************************************************************/
            /*  PD00307 : Read in the Printer type for this entry.        */
            /**************************************************************/
            prdm_ReadWordFromText( Type,
                                   PRINTER_TYPE_LENGTH,
                                   (pSource) );

            /******************************************************/
            /* Read the entry length.                             */
            /******************************************************/
            prdm_ReadWordFromText( TypeEntryLength,
                                   NO_DATA_SIZE_DIGITS,
                                   pSource );

            /**************************************************************/
            /* Adjust pSource to point to the beginning of the entry      */
            /**************************************************************/
            pSource -= (PRINTER_TYPE_LENGTH +
                        NO_DATA_SIZE_DIGITS);


            /**********************************************************/
            /* PD00307 : If it is a 4224 printer we need to get       */
            /* rid of the envelope forms as we copy everything else.  */
            /*                                                        */
            /* If it isn't we just copy the same as we did before.    */
            /**********************************************************/
            if ( (DRIVER_TYPE == DDT_IBM42XX_DRV) &&
                 ( (Type == IBM_4224_MONO) ||
                   (Type == IBM_4224_COLOR) ) )
            {
                /******************************************************/
                /* Call new routine to convert the 4224 INI.          */
                /******************************************************/
                prde_Translate4224Forms( (PBYTE  *)&pSource,
                                         (PBYTE  *)&pDest,
                                         TypeEntryLength);
            }
            else
            {
                /******************************************************/
                /* Copy the PrinterType field in the header.          */
                /******************************************************/
                prdu_memcpy( pDest, pSource, 2);


                pSource += 2;
                pDest += 2;
//              TypeEntryLength += 15;
                TypeEntryLength += 36;         /* PD00285             */

                prdm_WriteTextFromWord( TypeEntryLength,
                                        NO_DATA_SIZE_DIGITS,
                                        pDest );

                pSource += NO_DATA_SIZE_DIGITS;

                /******************************************************/
                /* 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 36 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;

                prdu_memset( pDest, '0',32);  /*PD00285              */
                pDest += 32;


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

                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 );

            /******************************************************/
            /* If the next character is a separator (',' or ';')  */
            /* then we've done all the types listed for this      */
            /* logical printer name.                              */
            /******************************************************/
            if (*pSource == ',' || *pSource == ';')
            {
                /**************************************************/
                /* Set Separator to get out of this loop and copy */
                /* the separator across.                          */
                /**************************************************/
                Separator = *pSource;

                *pDest++ = *pSource++;
            }
        }          /*  ... while more printer type info ...  */
    }
    /******************************************************************/
    /* Finish off the new entry with a null.                          */
    /******************************************************************/
    *pDest = '\0';

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

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

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


#ifdef PRD_DEBUG

/**********************************************************************/
/* LogErr routines...                                                 */
/**********************************************************************/
/* CON3201
void pascal far prdz_Ring3LogErr( Func,
                             Text,
                             ErrCode )

PBYTE   Func;
PBYTE   Text;
USHORT  ErrCode;
*/

void prdz_Ring3LogErr(PBYTE   Func,
                      PBYTE   Text,
                      USHORT  ErrCode)


{
     DebugOutput(Func);
     DebugOutput(": ");
     DebugOutput(Text);
     DebugOutput("\n\r");

     WinSetErrorInfo( MAKEERRORID(SEVERITY_SEVERE,ErrCode),
                      SEI_NOBEEP | SEI_NOPROMPT );
}

/* CON3201
void pascal far prdz_Ring3LogDosErr( Func,
                                     Text,
                                     ErrCode )

PBYTE   Func;
PBYTE   Text;
USHORT  ErrCode;
*/


void prdz_Ring3LogDosErr( PBYTE   Func,
                          PBYTE   Text,
                          USHORT  ErrCode)


{
     DebugOutput(Func);
     DebugOutput(": ");
     DebugOutput(Text);
     DebugOutput("\n\r");

     WinSetErrorInfo( MAKEERRORID(SEVERITY_SEVERE,PMERR_BASE_ERROR),
                      SEI_NOBEEP | SEI_NOPROMPT | SEI_DOSERROR,
                      ErrCode );
}

#endif /* PRD_DEBUG */




/**********************************************************************/
/* Debug routines...                                                  */
/* The functions available all write to the debug terminal and only   */
/* work if the value of the global variable DebugOn is TRUE           */
/* (non-zero). This can be changed using the debugger to easily turn  */
/* on or off the output.                                              */
/*                                                                    */
/* CrLf(VOID)  -  Writes a carriage return/line feed sequence to the  */
/*                the debug terminal.                                 */
/*                                                                    */
/* OutputValue(ULONG Value,USHORT Base) -                             */
/*                Writes the value to the debug terminal in the       */
/*                specified base.                                     */
/*                e.g. OutputValue(DecimalValue, 10);                 */
/*                e.g. OutputValue(BinaryValue, 2);                   */
/*                                                                    */
/* OutputString(PCHAR String) -                                       */
/*                Outputs the specified string to the debug terminal, */
/*                followed by a CrLf.                                 */
/*                                                                    */
/* OutputPair(PCHAR String,ULONG Value,USHORT Base) -                 */
/*                This combines the above two functions by            */
/*                writing the specified string, along with the given  */
/*                value in the given base(s), followed by a CrLf.     */
/*                Note that the bases are specified by pre-defined    */
/*                constants( BINARY, DECIMAL, HEX) and they can       */
/*                be combined using a binary OR.                      */
/*                e.g. OutputPair("Number = ", Number, DECIMAL);      */
/*                e.g. OutputPair("Address = ", Address, BINARY|HEX); */
/*                                                                    */
/**********************************************************************/
VOID Ring3CrLf()
{
    if (DebugOn)
        DebugOutput("\n\r");
}

void Ring3OutputValue(ULONG Value,USHORT Base)
{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    CHAR     Digit;
    CHAR     String[2];

    if ( (Base == 10) && ((LONG)Value < 0) )
    {
        DebugOutput("-");
        Ring3OutputValue( -(LONG)Value,10 );
        return;
    }

    if (Value > Base-1)
    {
        Ring3OutputValue(Value/Base,Base);
    }

    Digit = (CHAR)(Value % Base);
    String[0] = (Digit < 10) ? (Digit + '0') : (Digit + 'A'-10);
    String[1] = 0;
    DebugOutput(String);
}



VOID Ring3OutputString(PCHAR String)
{
    if (DebugOn)
    {
        DebugOutput(String);
        Ring3CrLf();
    }
}



VOID Ring3OutputPrompt(PCHAR String)
{
    if (DebugOn)
    {
        DebugOutput(String);
        Ring3CrLf();
        if (WaitForKey)
            haltproc();
    }
}



VOID Ring3OutputPair(PCHAR String,ULONG Value,USHORT Base)
{
    if (DebugOn)
    {
        DebugOutput(String);
        DebugOutput("  ");
        if (Base & DECIMAL)
        {
            Ring3OutputValue(Value,10);
            DebugOutput("  ");
        }
        if (Base & HEX)
        {
            DebugOutput("0x");
            Ring3OutputValue(Value,16);
            DebugOutput("  ");
        }
        if (Base & BINARY)
        {
            DebugOutput("0b");
            Ring3OutputValue(Value,2);
        }
        Ring3CrLf();
    }
}
/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdm_GetDeviceName                                     */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PBYTE           PrinterName;                                     */
/*                                                                    */
/*   USHORT far *    pPrinterType;                                    */
/*   PBYTE           DeviceName_KeyWord;                              */
/*                                                                    */
/*   See "OS/2 Technical Reference: I/O Subsytems and Device Drivers" */
/*   FillPhysicalDeviceBlock                                          */
/*                                                                    */
/*                                                                    */
/*    Return Code:                                                    */
/*    ------------                                                    */
/*      OK       = We have a valid PDBDeviceName and PDBPrinterType   */
/*                                                                    */
/*      ERROR_ZERO = Logical printer name was not valid.              */
/*                                                                    */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*   ------------                                                     */
/*                                                                    */
/* This function decides printer type based on data in PrinterName    */
/* and the PM_SPOOLER_PRINTER entry.                                  */
/* If the only entry in PM_SPOOLER_PRINTER is an old driver name      */
/* then set printer type to 99. Then we read old entry and get the    */
/* printer type from there.                                           */
/**********************************************************************/
/* CON3201
USHORT pascal prdm_GetDeviceName( PrinterName,
                                  pPrinterType,
                                  DeviceName_KeyWord)
*/

/* CON3201  ***************************************************************/
/*PBYTE                PrinterName;     CON3201     Pointer to Logical    */
                                                 /* printer name          */
/*USHORT     *         pPrinterType;    CON3201     Pointer to PrinterType*/
/*PBYTE                DeviceName_KeyWord;  CON3201 Pointer to DeviceName */

USHORT prdm_GetDeviceName(PBYTE  PrinterName,        /* Pointer to Logical    */
                                                     /* printer name          */
                          USHORT *pPrinterType,      /* Pointer to PrinterType*/
                          PBYTE  DeviceName_KeyWord) /* Pointer to DeviceName */

{
#define TFUNC "prde_GetDeviceName"
    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    PBYTE                pStartPtr;         /* for PM_SPOOLER_PRINTER  */
    PBYTE                pStartPtrOld;      /* for PM_SPOOLER_DD PTR302*/
    PBYTE                IniData;           /* for PM_SPOOLER_DD       */
    BYTE                 Terminator;
    SHORT                i;
    BYTE                 pszWord[100];
    BOOL                 Old_Entry;
    CHAR                 Prntr_Name_Buf[MAX_PRNTR_NAME];
    USHORT               Rc;          /* Return code             */

    Rc = OK;                                /* initialize        */
    pStartPtr = NULL;
    pStartPtrOld = NULL;

    /*********************************************************************/
    /* set printer type to default printer and read device description   */
    /* for the default printer                                           */
    /*********************************************************************/

    *pPrinterType = DEFAULT_PRINTER;

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

    prdu_strcpy(DeviceName_KeyWord,DriverNameString);

    *(DeviceName_KeyWord+DRIVER_NAME_LEN) = '.';

    prdu_strcpy(DeviceName_KeyWord+ DRIVER_NAME_LEN + 1,
                              Prntr_Name_Buf);

    if ( PrinterName ==  FNULL || PrinterName[0] == '\0' )
    {
        return(Rc);
    }

    pStartPtr = prde_ReadIniFile( (PSZ)PrinterName,
                                        (PSZ)"PM_SPOOLER_PRINTER");

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

        Terminator = ',';

        Old_Entry = FALSE;

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

           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))
                       {
                           *pPrinterType = i;

                           prdu_strcpy(DeviceName_KeyWord, DriverNameString);

                           *(DeviceName_KeyWord+DRIVER_NAME_LEN)='.';

                           prdu_strcpy( DeviceName_KeyWord+DRIVER_NAME_LEN+1,
                                        Prntr_Name_Buf);

                           Old_Entry = 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 )
           {
//             prdu_strcpy(DeviceName_KeyWord,DriverNameString); /*PD00302*/

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

                if ( (DRIVER_TYPE == DDT_IBM42XX_DRV) &&
                     (*(++IniData) != ';') )
                {
                    *pPrinterType = 99;

                    prdu_strcpy(DeviceName_KeyWord,DriverNameString);
                }

                /******************************************/
                /* Throw away the other SpoolerIniInfo.   */
                /* Release pStartPtrOld only if it is not */
                /* ERROR_NEG. PD00607                     */
                /******************************************/
             /* CON3201 *************************************/
             /* if (SELECTOROF(pStartPtrOld))               */
             /*     SSFreeSeg(SELECTOROF(pStartPtrOld));    */
             /***********************************************/
                if ((BOOL)pStartPtrOld)
                    SSFreeMem(pStartPtrOld);
           }
        }
/*      if ( SELECTOROF(pStartPtr) )                 CON3201 */
        if ((BOOL)pStartPtr)
        {
/*          SSFreeSeg(SELECTOROF(pStartPtr));        CON3201 */
            SSFreeMem(pStartPtr);
        }
    }  /* if ( (pStartPtr != (PBYTE)ERROR_NEG)) && pStartPtr )      */

return_error:

    return (Rc);
}
#undef TFUNC


/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdm_PM_DD_Write                                       */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PBYTE     LPName               Logical Printer Name              */
/*   PBYTE     DeviceName           Device Name                       */
/*   PBYTE     KeyName              Key Name                          */
/*   PBYTE     OutBuffer            Buffer to write                   */
/*   USHORT    BufferSize           length of OutBuffer               */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function build an appname using LPName, DeviceName and        */
/* DriverName. It writes the buffer for this appname and the given    */
/* KeyName.                                                           */
/*                                                                    */
/**********************************************************************/
/*
USHORT pascal prdm_PM_DD_Write( LPName,
                                DeviceName,
                                KeyName,
                                OutBuffer,
                                BufferSize)

PBYTE       LPName;
PBYTE       DeviceName;
PBYTE       KeyName;
PBYTE       OutBuffer;
USHORT      BufferSize;
                              */
USHORT prdm_PM_DD_Write(PBYTE       LPName,
                        PBYTE       DeviceName,
                        PBYTE       KeyName,
                        PBYTE       OutBuffer,
                        USHORT      BufferSize)

{
#define TFUNC "prdm_PM_DD_Write"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    BYTE      AppName[100];    /* Buffer to store app name            */
    PBYTE     pDest;           /* Pointers used to copy information   */
    PBYTE     pSource;         /*                                     */
    USHORT    IniSize;         /* The size of the entry in OS2.INI    */
    SHORT     IniVersionType;  /* Driver version number               */
    PFN       pPrfWriteProfData;
    HMODULE   ModuleHandle;
    USHORT    DosResult;
    BOOL      ModuleOK;


    /******************************************************************/
    /* If any parameter is null then return a null buffer.            */
    /******************************************************************/
    if ( !DeviceName || !KeyName || !LPName )
    {
        return(0);
    }

    /******************************************************************/
    /* Set up the AppName.                                            */
    /******************************************************************/
    AppName[0]  = 'P';
    AppName[1]  = 'M';
    AppName[2]  = '_';
    AppName[3]  = 'D';
    AppName[4]  = 'D';
    AppName[5]  = '_';

    /******************************************************************/
    /* Add LPName.                                                    */
    /******************************************************************/
    pDest = AppName+6;
    pSource = LPName;

    while ( *pDest++ = *pSource++ );

    pDest--;
    *pDest++ = ',';

    /******************************************************************/
    /* Add DeviceName.                                                */
    /******************************************************************/
    pSource = DeviceName;
    while ( *pDest++ = *pSource++ );

/* CON3201 *************************************************************/
//
//  ModuleOK = DosLoadModule( FNULL, 0, "PMSHAPI", &ModuleHandle);
//
//  if ( ModuleOK == DOS_OK )
//  {
//      /**********************************************************/
//      /* Now try and get the address of Prf..                   */
//      /**********************************************************/
//      DosResult = DosGetProcAddr( ModuleHandle,
//                                  "PRFWRITEPROFILEDATA",
//                                   &pPrfWriteProfData);
//      if (DosResult != DOS_OK)
//      {
//          return(0);
//      }
//  }
//  /******************************************************************/
//  /* Write the buffer using AppName and KeyName.                    */
//  /******************************************************************/
//  if ( !pPrfWriteProfData( HINI_SYSTEMPROFILE ,
//                           (PSZ)AppName,
//                           (PSZ)KeyName,
//                           (PVOID)OutBuffer,
//                           (ULONG)BufferSize ))
//  {
//      return (0);
//  }
    if (!(PrfWriteProfileData( HINI_SYSTEMPROFILE ,
                             (PSZ)AppName,
                             (PSZ)KeyName,
                             (PVOID)OutBuffer,
                             (ULONG)BufferSize )))
    {
        return (0);
    }
    return (1);
}
#undef TFUNC



/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdm_SelectOldDriver                                   */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*   PBYTE           PrinterName;                                     */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/* This function select the old driver if it exists. It reads the     */
/* PM_SPOOLER_DD Ini entry to see if the old driver exist.            */
/* If it exist it then read PM_SPOOLER_PRINTER entry using the given  */
/* Logical printer. If there exist one of our drive then we add       */
/* the old driver to that list.                                       */
/**********************************************************************/
USHORT prdm_SelectOldDriver(PBYTE PrinterName )


{
#define TFUNC "prdm_SelectOldDriver"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    PFN                  pPrfQueryProfSz;   /*                         */
    PFN                  pPrfWriteProfString;
    USHORT               DosResult;         /*                         */
    HMODULE              ModuleHandle;      /*                         */
    BOOL                 ModuleOK;          /*                         */
    ULONG                IniSize;           /* Ini entry size          */
    PBYTE                pStartPtr;         /* for PM_SPOOLER_PRINTER  */
    PBYTE                OldIniBuffer;      /* for PM_SPOOLER_DD PTR302*/
    PBYTE                NewIniBuffer;      /* for PM_SPOOLER_DD PTR302*/
    BYTE                 Terminator;
    BYTE                 pszWord[100];
    USHORT               Rc;                /*                         */
    PBYTE                pDest;             /* Pointers used to copy   */
    PBYTE                pSource;           /* back into OS2.INI       */
    USHORT               Version;           /* PM Version Number       */
    ERRORID              Error;
    PBYTE                pNewIniBuffer;     /* CON3201                 */

    NewIniBuffer    = FNULL;
    Rc = 0;
/* CON3201 ************************************************************/
// We will be using version 2.0+ so we will not check for version
//  /******************************************************/
//  /* Get the OS version.                                */
//  /******************************************************/
//  if (DOS_OK != DosGetVersion(&Version))
//  {
//      Rc = 0;
//      goto ERROR_RETURN;
//  }
//
//  /********************************************************/
//  /* Return if not 1.3.0 or 1.3.1                         */
//  /********************************************************/
//  if ( (HIBYTE(Version) != 10) && (LOBYTE(Version) != 30) )
//  {
//      Rc = 0;
//      goto ERROR_RETURN;
//  }
//  /**********************************************************/
//  /* Get the address of Prf..                               */
//  /**********************************************************/
//  ModuleOK = DosLoadModule( FNULL, 0, "PMSHAPI", &ModuleHandle);
//
//  DosResult = DosGetProcAddr( ModuleHandle,
//                              "PRFQUERYPROFILESIZE",
//                              &pPrfQueryProfSz);
//  if ( DosResult != DOS_OK )
//  {
//      Rc = 0;
//      goto ERROR_RETURN;
//  }
//
//  DosResult = DosGetProcAddr( ModuleHandle,
//                              "PRFWRITEPROFILESTRING",
//                              &pPrfWriteProfString);
//  if ( DosResult != DOS_OK )
//  {
//      Rc = 0;
//      goto ERROR_RETURN;
//  }
//
//  /**************************************************/
//  /* Check old format driver if there is an ini for */
//  /* this printer then we select it.                */
//  /**************************************************/
//  if ( !pPrfQueryProfSz( HINI_SYSTEMPROFILE ,
//                        (PSZ)"PM_SPOOLER_DD" ,
//                        (PSZ)DriverNameString,
//                        (PULONG)&IniSize) )
//  {
//      Rc = 0;
//      goto ERROR_RETURN;
//  }
//
//  if ( PrinterName ==  FNULL || PrinterName[0] == '\0' )
//  {
//      Rc = 0;
//      goto ERROR_RETURN;
//  }

    /**************************************************/
    /* Check old format driver if there is an ini for */
    /* this printer then we select it.                */
    /**************************************************/
    if ( !PrfQueryProfileSize( HINI_SYSTEMPROFILE ,
                          (PSZ)"PM_SPOOLER_DD" ,
                          (PSZ)DriverNameString,
                          (PULONG)&IniSize) )
    {
        Rc = 0;
        goto ERROR_RETURN;
    }

    pStartPtr = prde_ReadIniFile( (PSZ)PrinterName,
                                  (PSZ)"PM_SPOOLER_PRINTER");


    if ( (pStartPtr != (PBYTE)ERROR_NEG) && pStartPtr )
    {

        OldIniBuffer = pStartPtr;

        /******************************************************************/
        /* Get hold of a segment to store the new copy of the driver data.*/
        /******************************************************************/
        /* CON3201 ********************************************************/
        /*DosResult = SSALLOCSEG( 65535, &SELECTOROF(NewIniBuffer), 0 ); **/
        /******************************************************************/
        DosResult = SafeSSALLOCMEM( (PVOID)&pNewIniBuffer, 65535, 0 );
        if ( DosResult != DOS_OK )
        {
// CON3201  if ( SELECTOROF(pStartPtr) )            /* PD00607            */
// CON3201      SSFreeSeg(SELECTOROF(pStartPtr));

            if ( pStartPtr )            /* PD00607            */
                SSFreeMem(pStartPtr);

            Rc = 0;
            goto ERROR_RETURN;
        }

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

        /***********************************************************/
        /* first ';' is for logical printer address                */
        /***********************************************************/
        while ( *pStartPtr++ != ';');

        Terminator = ',';

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

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

               if ( pszWord[ DRIVER_NAME_LEN ] == '.')
               {
                   /***************************************************/
                   /* Copy the data into NewIniBuffer up to our       */
                   /* driver name.                                    */
                   /***************************************************/
                   for ( pDest = NewIniBuffer, pSource = OldIniBuffer;
                         pSource < pStartPtr;  )
                   {
                       *pDest++ = *pSource++;
                   }
                   *pDest--;
                   *pDest++ = ',';      /* seperator                 */

                   /***************************************************/
                   /* This is a new entry and we must put driver name */
                   /* back in there.                                  */
                   /***************************************************/
                   for ( pSource = DriverNameString;
                         *pSource; )
                   {
                       *pDest++ = *pSource++;
                   }

                   /*******************************************/
                   /* Copy the data after our driver name.    */
                   /*******************************************/
                   pSource = pStartPtr;
                   *pSource--;            /* copy last seperator      */

                   while ( *pSource )
                   {
                        *pDest++ = *pSource++;
                   }

                   *pDest = '\0';       /* null terminator    */

                   /***************************************************/
                   /* Write PM_SPOOLER_PRINTER entry.                 */
                   /***************************************************/
/* CON3201         DosResult = pPrfWriteProfString( HINI_SYSTEMPROFILE,      */
/* CON3201                                       (PSZ)"PM_SPOOLER_PRINTER",  */
/* CON3201                                       (PSZ)PrinterName,           */
/* CON3201                                       (PVOID)NewIniBuffer);       */

                   DosResult = PrfWriteProfileString( HINI_SYSTEMPROFILE,
                                                 (PSZ)"PM_SPOOLER_PRINTER",
                                                 (PSZ)PrinterName,
                                                 (PVOID)NewIniBuffer);

                   Error = WinGetLastError(hab);

               }
               Rc = 1;
               Terminator = ';';

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

        } /* while (Terminator != ';')   */

//      if ( SELECTOROF(pStartPtr) )             /* PD00607               */
//CON3201   SSFreeSeg(SELECTOROF(pStartPtr));

        if ( pStartPtr )             /* PD00607               */
            SSFreeMem(pStartPtr);

    }  /* if ( (pStartPtr != (PBYTE)ERROR_NEG)) && pStartPtr )      */
    else
    {
        Rc = 0;
    }

ERROR_RETURN:

    if ( NewIniBuffer )
/*      SSFREESEG(SELECTOROF(NewIniBuffer));  CON3201 */
        SSFREEMEM(NewIniBuffer);

    return (Rc);
}
#undef TFUNC

