/*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 = PRDMDLG
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdm_Dialog
 *
 * 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
#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
#include <os2.h>
#undef INCL_DOSPROCESS                  /* Convert to C/SET2    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

#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

#define INCL_WINSHELLDATA
/* #include <pmshlp.h>                                              DLM99 */
#define INCL_WINSHELLDATA
#undef INCL_32                          /* Convert to C/SET2    CON3201       */

#include <prdconse.h>
#include <prddcone.h>
#include <prdmcone.h>
#include <prdqcone.h>
#include <prdtcone.h>
#include <prdecone.h>                                   /* PD00651    */

#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>


/**********************************************************************/
/* Declarations of global data structures.                            */
/**********************************************************************/
DModeDataType       DMData;
lpDMSettings        pDMSettings;
pDMDriverStruc      pDMDrivData;
DMIniEntryType      DMIniEntry[LARGEST_NO_OF_PRINTERS];

CHAR         szCaption[40];
CHAR         szMessage[SLEN_BOX_MESSAGE];
BYTE         SrcDirBuffer[80];
BYTE         TrgDirBuffer[80];
BYTE         SrcFileName[80];
BYTE         TrgFileName[80];


/**********************************************************************/
/* Set up external accesses                                           */
/**********************************************************************/
extern lpDDTType              DDT [];
extern HMODULE                prdd_ModHandle;
extern lpPrtDataEntry         PrinterStateData;

extern USHORT                 DEFAULT_PRINTER;
extern USHORT                 NO_OF_PRINTERS;
extern PCHAR                  OS2_INI_VERSION;
extern PCHAR                  OS2_DD_MAGIC_NUMBER;
extern PCHAR                  OS2_DD_MAGIC_NUMBER2;   /* PD00587 */
extern PCHAR                  OS2_DD_MAGIC_NUMBER3;   /* PD00651 */
extern PCHAR                  OS2_DD_MAGIC_NUMBER4;   /* PD00769 - 600DPI */
extern PCHAR                  OS2_INI_THRESHOLD;
extern PCHAR                  OS2_INI_MAGIC_NUMBER1;
extern USHORT                 DRIVER_TYPE;
extern PCHAR                  DriverNameString;

extern BYTE                UStoNLS238X [];               /* PD00651, PD00657  */
extern BYTE                NLStoUS238X [];               /* PD00651, PD00657  */
extern BYTE                UStoNLS239X [];               /* PD00651, PD00657  */
extern BYTE                NLStoUS239X [];               /* PD00651, PD00657  */

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdm_Dialog                                            */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PDRIVDATA           DriverData;   Pointer to the driver data     */
/*   PBYTE               DriverName;   Pointer to the driver name     */
/*   PBYTE               PrinterName;  Pointer to the printer name    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function controls the running of the printer device driver  */
/*   section of the control panel.  It scans the file 'OS2.INI' which */
/*   contains the current values for the various parameters and if it */
/*   finds an entry for the printer driver it reads in the values -   */
/*   otherwise it sets the default values.  It then enters the        */
/*   DB_PP_TYPEn dialog box which controls the data type, the         */
/*   selected form, the orientation, print quality and forms control. */
/*   From this dialog box it is then possible to access the           */
/*   FORMS_CONTROL dialog box which controls form names, dimensions   */
/*   and units.  When the user exits the dialog box with an ENTER     */
/*   command then the changes which have been made are written back to*/
/*   OS2.INI file otherwise the data in OS2.INI is left as it was.    */
/*                                                                    */
/*   CHANGES:                                                         */
/*                                                                    */
/*   Any extra options which are to be selectable from the control    */
/*   panel will have to be handled in the functions in this file.     */
/*   Changes will have to be made to the dialog box itself (use the   */
/*   dialog box editor), to the functions which handle the messages   */
/*   from the dialog box (documentation on how to write these         */
/*   functions is given in the application writers guide), the format */
/*   of the OS2.INI entry will have to be changed as this is the only */
/*   place changes from the information from the control panel can be */
/*   stored (this impacts the enable functions and the query functions*/
/*   which also use the OS2.INI file entry), the information will     */
/*   have to be set up (possibly with defaults when there is no       */
/*   OS2.INI entry) and written to OS2.INI on an ENTER message from   */
/*   the dialog box.  You may also require code to catch any invalid  */
/*   entries from the user and give error messages (see the checking  */
/*   of form dimensions and clip regions for an example of this).     */
/*                                                                    */
/* Logic is as follows:                                               */
/*   SearchName =                                                     */
/*       PrinterName passed in, or (if null)                          */
/*       DriverData name, or (if also null)                           */
/*       Application default name, or (if not found)                  */
/*       First name in IBM?2XX list (in INI file)                     */
/*                                                                    */
/*   Look in INI file for logical printer entry                       */
/*                                                                    */
/*   If no data found (EntrySize == 0) then                           */
/*      Get default printer info (ProII/5202)                         */
/*      Write '\0' to SearchName                                      */
/*   else                                                             */
/*       read the inidata into DMSettings                             */
/*                                                                    */
/*   If flags == 0 or 2 then                                          */
/*      If ( driver data valid &&                                     */
/*           printer type matches inidata &&                          */
/*           ( SearchName matches DrivData (both null if no name      */
/*                provided and ap-default/1st-in-list not found) ||   */
/*             No name provided (using ap-default/1st-in-list/default)*/
/*         )                                                          */
/*         use driver data for dialog / writing out to DrivData       */
/*      else                                                          */
/*         use ini data for dialog / writing to DrivData              */
/*                                                                    */
/*                                                                    */
/*   IF (Flags == 1)    (Note: PrinterName never NULL)                */
/*     call Current Options Box - using passed in PrinterName         */
/*       update DMSettings and return OK or CANCEL in Result          */
/*     IF (Result == OK)                                              */
/*       write to INI file - including original PrinterName passed in */
/*       update DriverData with values from DMSettings, and the passed*/
/*       in PrinterName.                                              */
/*     ENDIF                                                          */
/*   ELSE if (Flags == 0)                                             */
/*     call Job Set Up Box -                                          */
/*       update DMDriverData and return OK or CANCEL in Result        */
/*   ENDIF                                                            */
/*                                                                    */
/*   IF (OK returned || Flags == 2)                                   */
/*     copy DMDriverData -> General Data                              */
/*     copy '\0' to DrivData name if !PrinterName && !DrivDataName    */
/*     else copy SearchName ('/0' if no match found)                  */
/*                                                                    */
/*   return (with GeneralData)                                        */
/*                                                                    */
/**********************************************************************/
#if 0
USHORT pascal prdm_Dialog( DriverData,
                           DriverName,
                           DeviceName,
                           PrinterName,
                           uFlags )

PDRIVDATA           DriverData;
PBYTE               DriverName;
PBYTE               DeviceName;
PBYTE               PrinterName;
ULONG               uFlags;
#endif

USHORT prdm_Dialog( PDRIVDATA DriverData,                  /* CON3201 */
                    PBYTE     DriverName,                  /* CON3201 */
                    PBYTE     DeviceName,                  /* CON3201 */
                    PBYTE     PrinterName,                 /* CON3201 */
                    ULONG     uFlags )                     /* CON3201 */

{
#define TFUNC "prdm_Dialog"

    /******************************************************************/
    /* Local Variables                                                */
    /******************************************************************/
    USHORT    IniSize;         /* The size of the entry in OS2.INI    */
                               /* for the printer driver              */
    USHORT    Result;          /* Function call return values         */
    USHORT    Result2;         /* PD00761 : need a newn value for this*/
    PBYTE     pDest;           /* Pointers used to copy information   */
    PBYTE     pSource;         /* back into OS2.INI                   */
    PBYTE     DataStart;       /* Start of the printer data in OS2.INI*/
    SHORT     i, j;            /* Loop control variables              */
    PBYTE     OutBuffer;       /* The new OS2.INI entry for the driver*/
    BYTE      DecimalPoint[3]; /* Character used as a decimal point   */
    BYTE      CountryCode[4];  /* Country code stored in OS2.INI      */
    USHORT    RetVal;          /* The value to return at the end of   */
                               /* prdm_Dialog                         */
#if 0
//  USHORT    SelectedPrinter; /* Currently selected printer          */
                               /* PD00292 : delete unused variables   */
#endif
    USHORT    PrinterType;     /* Printer type being handled          */
    USHORT    TypeEntryLen;    /* The length of the INI entry for a   */
                               /* particular printer type.            */
    HPOINTER  HourGlass;       /* Cursor put up while waiting...      */
 /* lpPrtDataEntry far *  lplpPrinterData; */
    lpPrtDataEntry     *  lplpPrinterData;                 /* CON3201 */
                               /* Pointer to pointer to printer state */
    lpDMIniEntry    pIniEntry; /* Pointer to INI entry for given      */
                               /* printer                             */
    pDMDriverStruc  pGenData;  /* Pointer to general driver data      */
    pDMDriverStruc  pTemp;     /* PD00615                             */
    CHAR      SpareMem[35];     /* Buffer for printer name            */
    PCHAR     pszIniVersion;
    ULONG     ulIniVersion;
    ULONG     ulMagic;
    ULONG     ulMagic2;
    ULONG     ulMagic3;
    ULONG     ulMagic4;        /* PD00769 - 600DPI */
    PCHAR     pszIniThreshold;
    ULONG     ulLowOldDD;
    PCHAR     pszIniMagicNumber1;
    ULONG     ulHighOldDD;
/*  PFN       pPrfQueryProfSz;             CON3201 */
/*  PFN       pPrfQueryProfData;           CON3201 */
    HMODULE   ModuleHandle;
    USHORT    DosResult;
    BOOL      ModuleOK;
/*  USHORT    Temp; */         /* PD00292 : delete unused variables   */
    HWND      HwndOwner;
    BOOL      LPNameNull;
    CHAR      SearchName[35];
    CHAR      InitialPrinterName[35];    /* Buffer for printer name    */
    PBYTE     Ptr;
    BOOL      DriverEqualsINI;
    BOOL      DriverDataValid;
    BOOL      DriverDataConvert;
    BOOL      DriverDataConvert2;
    BOOL      MinorDriverDataConvert;                              /* PD00665 */
/*  BOOL      ConvertForm1; */
/*  BOOL      ConvertForm2; */
    BOOL      DriverDataLPNameNull;
    PCHAR     KeyWord;               /* to read PM_SPOOLER_DD         */
    CHAR      szBuffer[ARG_DEVICE_NAME_LENGTH];
    CHAR      Prntr_Name_Buf[MAX_PRNTR_NAME];
    CHAR      DeviceName_KeyWord[MAX_PRNTR_NAME+8];
    ULONG     DrvDataFormNo1;
    pFormInfoStruc     pFormInfo1;
    PULONG    OldDriverStructure;
    PBYTE     OldPrinterName;
    PBYTE     pSourceDD;
    BOOL      NullPrinterName;
    BYTE      VersionBuf[5];
#if 0
//  PBYTE     KeyNameBuffer;   /* to store all key names   PD00441    */
//  PBYTE     KeyName;         /*                          PD00441    */
#endif
    USHORT    NoOfResidentFonts;                  /* PD00651, PD00657 */


    /******************************************************************/
    /*                                                                */
    /* Format for entries in OS2.INI:                                 */
    /*                                                                */
    /* <dd>\0                                                         */
    /* <path>;<opt>;<prn>=<propt>,<prn>=<popt>,...,<prn>=<propt>;     */
    /*                                                                */
    /* Note that the data returned from WinQueryProfileData is the    */
    /* data following the null terminator of the device driver <dd>   */
    /*                                                                */
    /* Where <dd> is the name of the device driver (eg IBM4201) and   */
    /* <path> is the fully qualified pathname,                        */
    /* eg C:\OS2\DLL\IBM4201.DRV,                                     */
    /* <opt> are any options for the device driver and <prn> is the   */
    /* name of a printer (eg PRINTER1) and <popt> are any options     */
    /* for the printer.  The fields <opt> and <popt> are used only    */
    /* by the device driver and so the format is wholly up to the     */
    /* device driver subject to the constraints that:                 */
    /*                                                                */
    /*  1. They do not contain the characters ; , . = as these have   */
    /*     special meaning in the OS2.INI file.                       */
    /*  2. They should not use control characters (ie the file should */
    /*     be readable as text)                                       */
    /*                                                                */
    /******************************************************************/

    /******************************************************************/
    /* Set up the return value.  Set the pointers to any memory which */
    /* may be allocated to Null to allow controlled exit on an error  */
    /* (through Error_Return label).                                  */
    /******************************************************************/
    RetVal = (USHORT)OK;

    OutBuffer = FNULL;

    prdm_ReadyDMData();

    /******************************************************************/
    /* Set the ModHandle and global pointers.                         */
    /******************************************************************/
    DMData.HModule = prdd_ModHandle;

    pDMSettings = &DMData.Settings;
    pDMDrivData = &DMData.DriverData;

    /******************************************************************/
    /* Clear the Printer INI entry structure to Zero/FNULL.           */
    /* This will set the change flag for each printer type to none    */
    /* changed.                                                       */
    /******************************************************************/
    (void) prdu_memset( (PBYTE)DMIniEntry,
                         0,
                        (sizeof(DMIniEntryType) * NO_OF_PRINTERS) );

    /**************************************************************/
    /* Store the current Cursor shape.                            */
    /**************************************************************/
    DMData.CursorHandle = (PULONG)WinQueryPointer( HWND_DESKTOP );

    /******************************************************************/
    /* Set the cursor to the hour glass pointer.                      */
    /******************************************************************/
    HourGlass = WinQuerySysPointer( HWND_DESKTOP,
                                    SPTR_WAIT,
                                    FALSE );

    Result = WinSetPointer( HWND_DESKTOP,
                            HourGlass );

    TRACE6(TFUNC, "Set pointer result", &Result, 1);

    /******************************************************************/
    /* Read OS2.INI to get the decimal point character.               */
    /******************************************************************/
    if (TRUE)   /* @@@ use Win, not Prf call */
    {
   /* CON3201 *********************************************************/
   /* Win no longer supported have to use Prf call                    */
   /*   if ( !WinQueryProfileString( hab,                             */
   /*                            "PM_National",*/ /* application name */
   /*                            "sDecimal",   */ /* key name         */
   /*                            ".",          */ /* default          */
   /*                            DecimalPoint, */ /* returned value   */
   /*                            3 ) )         */ /* maximum length   */
   /*******************************************************************/

        if (( PrfQueryProfileString( HINI_USERPROFILE,
                                 "PM_National",   /* application name */
                                 "sDecimal",      /* key name         */
                                 ".",             /* default          */
                                 DecimalPoint,    /* returned value   */
                                 3 ) ) == 0)           /* maximum length   */
        {
            Ring3LOGERR(TFUNC, "Cant read INI file", FNULL, 0,
                                               PMERR_OPENING_INI_FILE );
            RetVal = (USHORT)DPDM_ERROR;
            goto Error_Return;
        }
    }
    else
    {
         /*************************************************************/
         /* Prf call uses OS2.INI if HINI_USERPROFILE is first parm.  */
         /* It uses OS2SYS.INI if HINI_SYSTEMPROFILE                  */
         /*************************************************************/
        if ( !PrfQueryProfileString( HINI_USERPROFILE,
                                 "PM_National",   /* application name */
                                 "sDecimal",      /* key name         */
                                 ".",             /* default          */
                                 DecimalPoint,    /* returned value   */
                                 3L ) )           /* maximum length   */
        {
            Ring3LOGERR(TFUNC, "Cant read INI file", FNULL, 0,
                                               PMERR_OPENING_INI_FILE );
            RetVal = (USHORT)DPDM_ERROR;
            goto Error_Return;
        }
    }
    DMData.DecimalPoint = *DecimalPoint;

    /******************************************************************/
    /* Read OS2.INI to find out which country code has been selected. */
    /******************************************************************/
/* CON3201 - must use Prf call and not Win, Win is not supported in   */
/*           in 32 bit code                                           */
/*  if (TRUE) */ /* @@@ use Win, not Prf call */
//  {
//      if ( !WinQueryProfileString( hab,
//                               "PM_National",   /* application name */
//                               "iCountry",      /* key name         */
//                               "1",             /* default          */
//                               CountryCode,     /* returned value   */
//                               3 ) )            /* maximum length   */
//      {
//          Ring3LOGERR(TFUNC, "Cant read INI file", FNULL, 0,
//                                             PMERR_OPENING_INI_FILE );
//          RetVal = (USHORT)DPDM_ERROR;
//          goto Error_Return;
//      }
//  }
//  else
//  {
/*      if ( !PrfQueryProfileString( HINI_USERPROFILE,                CON3201 */
        if (( PrfQueryProfileString( HINI_USERPROFILE,
                                 "PM_National",   /* application name */
                                 "iCountry",      /* key name         */
                                 "1",             /* default          */
                                 CountryCode,     /* returned value   */
                                 3L ) ) == 0)     /* maximum length   */
        {
            Ring3LOGERR(TFUNC, "Cant read INI file", FNULL, 0,
                                               PMERR_OPENING_INI_FILE );
            RetVal = (USHORT)DPDM_ERROR;
            goto Error_Return;
        }
//  }

    /******************************************************************/
    /* For US (and American Canadian) set the default form to the     */
    /* Letter form; in all other cases use A4.                        */
    /******************************************************************/
    if (((CountryCode[0] == '1') && (CountryCode[1] == '\0')) ||
         !prdu_strcmpN(CountryCode,"55",3) )                       /* PD00812 */
    {
        DMData.DefaultForm = DEFAULT_PAPER_FORM_US;
    }
    else
    {
        DMData.DefaultForm = DEFAULT_PAPER_FORM_NONUS;
    }

    /******************************************************************/
    /* Calcuate the hex value of the IniVersion from the              */
    /* OS2_INI_VERSION string.                                        */
    /******************************************************************/
    pszIniVersion = OS2_INI_VERSION;
    ulIniVersion = 0;
    while (*pszIniVersion)
    {
        ulIniVersion = (ulIniVersion << 4) + (*pszIniVersion++ - '0');
    }

    /*******************************************************************/
    /* Also calcuate the hex value of the OS2_DD_MAGIC_NUMBER string.  */
    /*******************************************************************/
    pszIniVersion = OS2_DD_MAGIC_NUMBER;
    ulMagic = 0;
    while (*pszIniVersion)
    {
        ulMagic = (ulMagic << 4) + (*pszIniVersion++ - '0');
    }

    /*******************************************************************/
    /* Also calcuate the hex value of the OS2_DD_MAGIC_NUMBER2 string. */
    /*******************************************************************/
    pszIniVersion = OS2_DD_MAGIC_NUMBER2;
    ulMagic2 = 0;
    while (*pszIniVersion)
    {
        ulMagic2 = (ulMagic2 << 4) + (*pszIniVersion++ - '0');
    }

    /*******************************************************************/
    /* PD00651, PD00657 :                                              */
    /* Also calcuate the hex value of the OS2_DD_MAGIC_NUMBER3 string. */
    /*******************************************************************/
    pszIniVersion = OS2_DD_MAGIC_NUMBER3;
    ulMagic3 = 0;
    while (*pszIniVersion)
    {
        ulMagic3 = (ulMagic3 << 4) + (*pszIniVersion++ - '0');
    }

    /*******************************************************************/
    /* PD00769 - 600DPI :                                              */
    /* Also calcuate the hex value of the OS2_DD_MAGIC_NUMBER4 string. */
    /*******************************************************************/
    pszIniVersion = OS2_DD_MAGIC_NUMBER4;
    ulMagic4 = 0;
    while (*pszIniVersion)
    {
        ulMagic4 = (ulMagic4 << 4) + (*pszIniVersion++ - '0');
    }

    pszIniThreshold = OS2_INI_THRESHOLD;
    ulLowOldDD = 0;
    while (*pszIniThreshold)
    {
        ulLowOldDD = (ulLowOldDD << 4) + (*pszIniThreshold++ - '0');
    }

    pszIniMagicNumber1 = OS2_INI_MAGIC_NUMBER1;
    ulHighOldDD = 0;
    while (*pszIniMagicNumber1)
    {
        ulHighOldDD = (ulHighOldDD << 4) + (*pszIniMagicNumber1++ - '0');
    }
/*  CON3201 - comment out for now at least
**  ModuleOK = DosLoadModule( FNULL, 0, "PMSHAPI", &ModuleHandle);
**
**  if (ModuleOK == DOS_OK)
**  {
**      DosResult = DosGetProcAddr( ModuleHandle,
**                                 "PRFQUERYPROFILEDATA",
**                                 &pPrfQueryProfData);
**      DosResult = DosGetProcAddr( ModuleHandle,
**                                  "PRFQUERYPROFILESIZE",
**                                  &pPrfQueryProfSz);
**  }
*/
    LPNameNull = (BOOL)(DMData.PrinterName[0] == '\0');  /* PD00185   */

    /* PD00041 */
    DriverDataValid = FALSE;
    DriverDataConvert = FALSE;
    MinorDriverDataConvert = FALSE;                            /* PD00665 */

    /**********************************************************************/
    /* If this is old driver then allocate a segment and convert the      */
    /* the driver data.                                                   */
    /*                                                                    */
    /* PD00587 : Now we have 2 old driverdata formats                     */
    /* PD00651 : Now we have 3 old driverdata formats                     */
    /* PD00769 - 600DPI : Now we have 4 old driverdata formats            */
    /**********************************************************************/

    if ( ( ( DriverData->lVersion >= ulLowOldDD )  &&
            ( DriverData->lVersion < ulHighOldDD ) ) ||
             ( (DriverData->lVersion >= ulMagic) &&
               (DriverData->lVersion <  ulMagic4) ) )
    {
     /* Result = SSALLOCSEG(sizeof(DMDriverStruc), &SELECTOROF(pGenData), 0); */
        Result = SafeSSALLOCMEM(&pGenData, sizeof(DMDriverStruc), 0); /*CON3201*/
        if (Result != DOS_OK)
        {
           return ((ULONG)ERROR_ZERO);
        }

/*      OFFSETOF(pGenData) = 0;                                    CON3201 */
        prdu_memset((PBYTE)pGenData, 0, sizeof(DMDriverStruc));


        /********************************************************************/
        /* Make sure the old driver data is big enough so that there is no  */
        /* trap while trying to reference it.  If it is big enough then     */
        /* convert.                                                         */
        /********************************************************************/

        if ((USHORT)DriverData->cb >= 99)
        {
           /****************************************************************/
           /*  PD00587 : if it is a migratable version prior to 200        */
           /****************************************************************/
           if ( ( DriverData->lVersion >= ulLowOldDD )  &
                   ( DriverData->lVersion < ulHighOldDD ) )
           {
               Result = prde_TranslateOldDriverData ( pGenData,
                                                      DriverData);
           }

           /****************************************************************/
           /*  PD00587 : if it is a migratable version between 250 and     */
           /*  275 just copy the old version and add in the new resolution */
           /*  field.  Set the value of the new resolution to the old      */
           /*  resolution.                                                 */
           /*                                                              */
           /*  PD00651 : if it is a migratable version between 250 and 278 */
           /*  600DPI :                                                    */
           /*  PD00769 : if it is a migratable version between 250 and 310 */
           /****************************************************************/
           if ( (DriverData->lVersion >= ulMagic) &&
                (DriverData->lVersion <  ulMagic4) )
           {
               if ( (DriverData->lVersion >= ulMagic3) )
               {
                   prdu_memcpy( (PBYTE)pGenData,
                                (PBYTE)DriverData->abGeneralData,
                                 sizeof(DMDriverStruc) - ( sizeof(USHORT)
                                 + sizeof(ULONG) ) );
/*                 pGenData->PrinterPatterns = 0; */
                   pGenData->Resolution3 = pGenData->Resolution2;
               }
               else if ( (DriverData->lVersion >= ulMagic2) )
               {
                  /************************************************************/
                  /*  PD00651 : If it is a migratable version between 275 and */
                  /*  278 just copy everything up to MachineType.             */
                  /*  MachineMachineType was set to zero when we cleared      */
                  /*  the allocated memory.  It will be set to a valid value  */
                  /*  when we have access to INI information.                 */
                  /************************************************************/
                  /************************************************************/
                  /* PD00769 : Updated for new printer patterns field in 310  */
                  /* 600DPI : Updated for new Resolution3 field in 310        */
                  /************************************************************/
                   prdu_memcpy( (PBYTE)pGenData,
                                (PBYTE)DriverData->abGeneralData,
                                 sizeof(DMDriverStruc) - ( 2*sizeof(USHORT)
                                 + sizeof(ULONG) ) );

/*                 pGenData->PrinterPatterns = 0; */
                   pGenData->Resolution3 = pGenData->Resolution2;

               }
               else
               {
                  /************************************************************/
                  /*  PD00651 : If it is a migratable version prior to 275,   */
                  /*  copy everything up to Resolution2, then set Resolution2 */
                  /*  to match Resolution.  MachineType was set to zero when  */
                  /*  we cleared the allocated memory.  It will be set to a   */
                  /*  valid value when we have access to INI information.     */
                  /************************************************************/
                  /************************************************************/
                  /* PD00769 : Updated for new printer patterns field in 310  */
                  /* 600DPI : Updated for new Resolution3 field in 310        */
                  /************************************************************/
                  prdu_memcpy( (PBYTE)pGenData,
                               (PBYTE)DriverData->abGeneralData,
                               (sizeof(DMDriverStruc) - (2 * sizeof(LONG) +
                                2 * sizeof(USHORT))) );

                  pGenData->Resolution2 = pGenData->Resolution;
/*                pGenData->PrinterPatterns = 0; */
                  pGenData->Resolution3 = pGenData->Resolution;
               }

               /***************************************************************/
               /*  PD00665: Set new flag so we don't overwrite driver data    */
               /*  fields with DMSettings fields unecessarily.                */
               /***************************************************************/
               MinorDriverDataConvert = TRUE;
               Result = OK;
           }

           if (Result == OK)
           {
              DriverDataConvert = TRUE;
              if ( pGenData->PrinterName[0] == 0 )
              {
                 NullPrinterName = TRUE;
              }
              else
              {
                 NullPrinterName = FALSE;
              }
           }
           else
           {
           /* SSFREESEG ( SELECTOROF(pGenData) ); */
              SSFREEMEM ( pGenData );                              /* CON3201 */
           }
        }
        else
        {
        /* SSFREESEG ( SELECTOROF(pGenData) ); */
           SSFREEMEM ( pGenData );                                 /* CON3201 */
        }

    }
    else
    {
       pGenData = (pDMDriverStruc)(DriverData->abGeneralData);

       /******************************************************************/
       /* Note if driverdata contains garbage such that the strlen looks */
       /* beyond the end of the segment then this traps. Thus ensure that*/
       /* a zero is always present. But first check DriverData->cb field */
       /******************************************************************/
       /* Check driver data size before putting null terminator in       */
       /* PrinterName field. PD00638                                     */
       /******************************************************************/
       if ( DriverData->cb >= sizeof(DRIVDATA) + sizeof(DMDriverStruc) -1 )
       {
           pGenData->PrinterName[34] = '\0';

           DriverDataValid =
               ( DriverData->cb >= sizeof(DRIVDATA) + sizeof(DMDriverStruc) -1) &&
               ( DriverData->lVersion >= ulMagic )                   &&
               ( prdu_strlen( (PBYTE) pGenData->PrinterName ) < 33 ) &&
               ( pGenData->DriverType == DRIVER_TYPE );
       }
    }

    DriverDataLPNameNull = (!DriverDataValid && !DriverDataConvert) ||
                     (pGenData->PrinterName[0] == '\0');

    if ( LPNameNull )
    {
        if ( DriverDataLPNameNull )
        {
            Ptr = SpareMem;
            /******************************************************/
            /* Can now make the call                              */
            /******************************************************/
/*          if ( !pPrfQueryProfSz( HINI_USERPROFILE ,                 CON3201 */
            if ( !PrfQueryProfileSize( HINI_USERPROFILE ,
                                   (PSZ)"PM_SPOOLER" ,
                                   (PSZ)"PRINTER",
                                   (PULONG)&IniSize) )
            {
                *Ptr++ = ';';
                *Ptr   = '\0';
                goto Copy_LPName;
/*              RetVal = (USHORT)DPDM_ERROR; */
/*              goto Error_Return;           */
            }
            if ( IniSize > 33 )
            {
                *Ptr++ = ';';
                *Ptr   = '\0';
                goto Copy_LPName;
            }
/*          if ( !pPrfQueryProfData( HINI_USERPROFILE,                CON3201 */
            if ( !PrfQueryProfileData( HINI_USERPROFILE,
                                    (PSZ)"PM_SPOOLER",
                                    (PSZ)"PRINTER",
                                    (PVOID)SpareMem,
                                    (PULONG)&IniSize ) )
            {
                *Ptr++ = ';';
                *Ptr   = '\0';
#if 0
//              Ring3LOGERR(TFUNC, "Cant read INI file", FNULL, 0,
//                                        PMERR_OPENING_INI_FILE );
//              RetVal = (USHORT)DPDM_ERROR;
//              goto Error_Return;
#endif
            }

            /******************************************************/
            /* If empty return error. PD00208                     */
            /******************************************************/
#if 0
//          if ( *SpareMem == ';')
//          {
//              HwndOwner = WinQueryActiveWindow(HWND_DESKTOP,TRUE);

//              (VOID)prdm_DispConversionMsg( HwndOwner,
//                                         IDS_INV_DFLT_PRINTER,
//                                         SLEN_BOX_MESSAGE,
//                                         DB_TXT_DUMMY,
//                                         MB_OK | MB_WARNING );

//              RetVal = (USHORT)DPDM_ERROR;
//              goto Error_Return;
//          }
#endif

            /******************************************************/
            /* Terminate name with null.                          */
            /******************************************************/
Copy_LPName:
            for ( Ptr = SpareMem; *Ptr != ';' && *Ptr ; Ptr++ );

            *Ptr = '\0';

            prdu_strcpyN( SearchName, SpareMem, 32);
        }
        else /* if DriverDataLPNameNull ..... */
        {
            /**********************************************************/
            /* Have a driver name: lets use this.                     */
            /**********************************************************/
            prdu_strcpyN( SearchName, pGenData->PrinterName, 32);

        }
    }
    else /* if LPNameNull ... */
    {
        /**************************************************************/
        /* Note SearchName no more than 32 chars long)                */
        /**************************************************************/

        prdu_strcpyN( SearchName, PrinterName, 32 );

        /**************************************************************/
        /* Save copy of initial PrinterName (for flags = 1 case).     */
        /* note this is full length (up to 256)                       */
        /**************************************************************/
        prdu_strcpy(InitialPrinterName, PrinterName );
    }


    prdu_strcpyN( DMData.PrinterName, SearchName, 32 ); /* PD00185   */

    /******************************************************************/
    /* If DeviceName is not null then compare it to printer descripti-*/
    /* on defined in .RC file.                                        */
    /* If found match then build a keyword to read OS2.INI file.      */
    /* Otherwise  check DeviceName in driver data. SG                 */
    /******************************************************************/
 /* HwndOwner = WinQueryActiveWindow(HWND_DESKTOP,TRUE); */
    HwndOwner = WinQueryActiveWindow(HWND_DESKTOP);        /* CON3201 */
    PrinterType = 99;
    KeyWord = NULL;                         /* clear KeyWord          */
    DeviceName_KeyWord[0] = '\0';           /* initialize             */

    if ( DeviceName !=  FNULL && DeviceName[0] != '\0' )
    {
        for ( i = 0; i < NO_OF_PRINTERS; i++ )
        {
            /**********************************************************/
            /* description string from the Rc  file.                  */
            /**********************************************************/
            WinLoadString( hab,
                           DMData.HModule,
                           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(DeviceName,
                               Prntr_Name_Buf))
            {
                PrinterType = i;

                prdu_strcpy(DeviceName_KeyWord,DriverNameString);

                *(DeviceName_KeyWord+7) = '.';

                prdu_strcpy(DeviceName_KeyWord+8,
                             Prntr_Name_Buf);

                KeyWord = DeviceName_KeyWord;

                /************************************************************/
                /* Check DeviceName field in DriverData. If the device name */
                /* description is same as the one in DeviceName then driver */
                /* data is for same printer type and it is OK to use the    */
                /* driver data. otherwise the driver data is not valid. SG  */
                /************************************************************/
                DriverDataValid = (DriverDataValid &&
                ( !prdu_strcmpN( DeviceName, DriverData->szDeviceName, 32 )));

                DriverDataConvert2 = DriverDataConvert;

                /***********************************************************/
                /* Make sure that the device name is correct.  If it is not*/
                /* then deallocate the buffer.                             */
                /***********************************************************/

                DriverDataConvert = (DriverDataConvert &&
                ( !prdu_strcmpN( DeviceName, DriverData->szDeviceName, 32 )));

                if (DriverDataConvert2 && !DriverDataConvert)
                {
               /* SSFREESEG(SELECTOROF(pGenData)); */
                  SSFREEMEM( pGenData );                        /* CON3201 */
                }
                break;
            } /* if (!prdu_strcmpN...    */

        } /* for (i = 0; i < NO_OF_PRINTERS; i++)   */
    }
    /******************************************************************/
    /* If KeyWord is null (description in DeviceName was not a valid  */
    /* printer type) check DeviceName in DriverData. If that is valid */
    /* printer type use that else issue error msg. SG                 */
    /******************************************************************/
    if ( KeyWord == NULL)
    {
        if ( (DriverData->cb >= sizeof(DRIVDATA) + sizeof(DMDriverStruc) -1)
             && (DriverData->szDeviceName[0] != '\0') )
        {
            for ( i = 0; i < NO_OF_PRINTERS; i++ )
            {
                /**********************************************************/
                /* description string from the RC  file.                  */
                /**********************************************************/
                WinLoadString( hab,
                               DMData.HModule,
                               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(DriverData->szDeviceName,
                                   Prntr_Name_Buf))
                {

                    prdu_strcpy(DeviceName_KeyWord,DriverNameString);

                    *(DeviceName_KeyWord+7) = '.';

                    prdu_strcpy(DeviceName_KeyWord+8,
                                 Prntr_Name_Buf);

                    /******************************************************/
                    /* Make sure there exist an ini entry for this device.*/
                    /* PD00302                                            */
                    /******************************************************/

/*                  if ( pPrfQueryProfSz( HINI_SYSTEMPROFILE ,        CON3201 */
                    if ( PrfQueryProfileSize( HINI_SYSTEMPROFILE ,
                         (PSZ)"PM_SPOOLER_DD" ,
                         (PSZ)DeviceName_KeyWord,
                         (PULONG)&IniSize) )
                    {
                        PrinterType = i;
                        KeyWord = DeviceName_KeyWord;
                    }
                    break;

                } /* if (!prdu_strcmpN...    */

            } /* for (i = 0; i < NO_OF_PRINTERS; i++)   */
        }
        /***************************************************************/
        /* if KeyWord is NULL (DeviceName and DriverData->DeviceName   */
        /* was not a valid printer type) issue error and return.       */
        /***************************************************************/
        if ( KeyWord == NULL )
        {

            if (prdm_GetDeviceName( SearchName,
                                    &PrinterType,
                                    DeviceName_KeyWord ) != OK)
            {
                (VOID)prdm_DispConversionMsg( HwndOwner,
                                           IDS_INV_DEVICENAME,
                                           SLEN_BOX_MESSAGE,
                                           DB_TXT_DUMMY,
                                           MB_OK | MB_WARNING );

                goto Error_Return;
            }

        }
        KeyWord = DeviceName_KeyWord;
    }

    /******************************************************************/
    /* Read data from OS2.INI. A pointer to a buffer is returned.     */
    /* PD00441                                                        */
    /******************************************************************/
    DataStart = prde_ReadPrinterProperties(SearchName,
                                           KeyWord,
                                           &PrinterType);


#ifdef OMIT_OLD_CODE
//  /******************************************************************/
//  /* Read data from OS2.INI and a pointer to a buffer is returned.  */
//  /******************************************************************/
//  DataStart = prde_PM_DD_Read(SearchName,
//                              KeyWord,
//                              &PrinterType);
//
//  if (DataStart == (PBYTE)ERROR_NEG )
//  {
//      DataStart = FNULL;
//  }
//  /******************************************************************/
//  /* PD00441:                                                       */
//  /* If there is no printer setting for this logical printer. Read  */
//  /* all the logical printers and see if there is printer setting   */
//  /* for any logical printer. If yes then use this setting instead  */
//  /* of default setting. The OS2 1.3.0 has a problem which does not */
//  /* give us the logical printer name and if there is no driver data*/
//  /* we use the application default printer.                        */
//  /******************************************************************/
//  if ( DataStart == FNULL )
//  {
//      /******************************************************************/
//      /* Find out the size of the PM_SPOOLER_PRINTER entry returned in  */
//      /* IniSize.                                                       */
//      /******************************************************************/
//
//      if ( pPrfQueryProfSz( HINI_USERPROFILE,                       CON3201 */
//      if ( PrfQueryProfileSize( HINI_USERPROFILE,
//                            (PSZ)"PM_SPOOLER_PRINTER",
//                            (PSZ)FNULL,
//                            (PULONG)&IniSize) )
//      {
//          KeyNameBuffer = FNULL;
//       /* Result = SSALLOCSEG(IniSize, &SELECTOROF(KeyNameBuffer), 0); */
//          Result = SSALLOCMEM(&KeyNameBuffer, IniSize, 0);  /* CON3201 */
//          if (Result != DOS_OK)
//          {
//              goto PM_DD_READ_END;
//          }
//          /**************************************************************/
//          /* Read PM_SPOOLER_PRINTER entry with a null key name. this   */
//          /* returns a list of all listed logical printer name seperated*/
//          /* from each other by one null. The list is terminated by two */
//          /* nulls.                                                     */
//          /**************************************************************/
//          if ( pPrfQueryProfData( HINI_USERPROFILE,                 CON3201 */
//          if ( PrfQueryProfileData( HINI_USERPROFILE,
//                                  (PSZ)"PM_SPOOLER_PRINTER",
//                                  (PSZ)FNULL,
//                                  (PVOID)KeyNameBuffer,
//                                  (PULONG)&IniSize ) )
//          {
//              KeyName =  KeyNameBuffer;
//              while ( *KeyName && (DataStart == FNULL) )
//              {
//                 /****************************************************/
//                 /* Read data from OS2.INI for this logical printer. */
//                 /****************************************************/
//                 DataStart = prde_PM_DD_Read(KeyName,
//                                             KeyWord,
//                                             &PrinterType);
//                 if ( DataStart != FNULL )
//                 {
//                     /***********************************************/
//                     /* Need printername to copy into driver data.  */
//                     /***********************************************/
//                     prdu_strcpyN ( SearchName, KeyName, 32 );
//                     break;
//                 }
//
//                 while ( *KeyName++ );  /* get next key name*/
//
//              }  /* while ( *KeyName && (DataStart == FNULL) )      */
//
//
//          }  /* if ( pPrfQueryProfData( HINI_USERPROFILE,           */
//
//       /* SSFREESEG(SELECTOROF(KeyNameBuffer)); */
//          SSFREEMEM( KeyNameBuffer );                    /* CON3201 */
//
//      }  /* if ( pPrfQueryProfSz( HINI_USERPROFILE,                 */
//
//  } /* if ( DataStart == FNULL )                                    */
PM_DD_READ_EBD:
#endif
    /******************************************************************/
    /* This should never occur. This is just a safety check.          */
    /******************************************************************/
    if ( PrinterType >= NO_OF_PRINTERS )
    {
        PrinterType = DEFAULT_PRINTER;
        DataStart = FNULL;
        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);
    }

    DMData.IniVersionType = INI_VERSION_CURRENT;

    /******************************************************************/
    /* If nothing has been found here, then we are going to use the   */
    /* default printer info.                                          */
    /******************************************************************/
    /**************************************************************/
    /* Either:                                                    */
    /* a. PrinterName not found                                   */
    /* b. DriverData name not found                               */
    /* c. Ap. default name not found                              */
    /*                                                            */
    /*  FirstName may or may not have been found.                 */
    /**************************************************************/
#if 0
//  if ( !EntrySize && LPNameNull && DriverDataLPNameNull &&
//                    FirstName && FirstEntrySize )
//  {
        /**********************************************************/
        /* No name specified and the application default was not  */
        /* valid so if there is a first entry then use it, other- */
        /* wise use the default default.                          */
        /**********************************************************/
//      EntrySize = FirstEntrySize;
//      NameStart = FirstName;
//      DataStart = FirstDataStart;
//      ResidualData = FirstResidualData;

        /**********************************************************/
        /* Need printername to copy into driver data.             */
        /**********************************************************/
//      for ( Ptr2 = SpareMem,Ptr = FirstName; *Ptr != '='; )
//      {
//          *Ptr2++ = *Ptr++;
//      }
//      *Ptr2 = '\0';

//      prdu_strcpyN ( SearchName, SpareMem, 32 );
//  }
#endif
PROCESS_ENTRY:
/*  if ( !EntrySize ) */
    if ( DataStart == FNULL )
    {
        /**********************************************************/
        /* There is no configuration information available.       */
        /**********************************************************/

        /**********************************************************/
        /* Now load up the defaults                               */
        /**********************************************************/
        if ( prdm_LoadDMDataDefaults( PrinterType ) != OK )
        {
            RetVal = (USHORT)DPDM_ERROR;
            goto Error_Return;
        }

        /****************************************************************/
        /* If migrating then check the form numbers.  If the old form   */
        /* number is not in the valid range then get the default form   */
        /* for that country.                                            */
        /****************************************************************/

        if (DriverDataConvert)
        {
           if (pGenData->FormNumber1 >= pDMSettings->NumberOfForms)
           {
              pGenData->FormNumber1 = DMData.DefaultForm;
           }
           if (pGenData->FormNumber2 >= pDMSettings->NumberOfForms)
           {
              pGenData->FormNumber2 = DMData.DefaultForm;
           }

           pGenData->FormInfo1.FormType =
              DDT[PrinterType]->DDTDefinedForms[pGenData->FormNumber1].FormType;
           pGenData->FormInfo1.FormUnits =
              *DDT[PrinterType]->DDTDefinedForms[pGenData->FormNumber1].FormData;
           WinLoadString( hab,
                          DMData.HModule,
                          DDT[PrinterType]->
                          DDTDefinedForms[pGenData->FormNumber1].FormNameId,
                          SLEN_BOX_MESSAGE,
                          (PSZ)szMessage );

           /**************************************************************/
           /* Copy the form name into buffer                             */
           /**************************************************************/
           pSourceDD = szMessage;

           for ( i = 0; *pSourceDD != '\0'; pSourceDD++ )
           {
              pGenData->FormInfo1.FormName[i++] = (*pSourceDD == ALT_POINT)
                                     ? DMData.DecimalPoint : *pSourceDD;
           }

           pGenData->FormInfo2.FormType =
              DDT[PrinterType]->DDTDefinedForms[pGenData->FormNumber2].FormType;
           pGenData->FormInfo2.FormUnits =
              *DDT[PrinterType]->DDTDefinedForms[pGenData->FormNumber2].FormData;
           WinLoadString( hab,
                          DMData.HModule,
                          DDT[PrinterType]->
                          DDTDefinedForms[pGenData->FormNumber2].FormNameId,
                          SLEN_BOX_MESSAGE,
                          (PSZ)szMessage );

           /**************************************************************/
           /* Copy the form name into buffer                             */
           /**************************************************************/
           pSourceDD = szMessage;

           for ( i = 0; *pSourceDD != '\0'; pSourceDD++ )
           {
              pGenData->FormInfo2.FormName[i++] = (*pSourceDD == ALT_POINT)
                                     ? DMData.DecimalPoint : *pSourceDD;
           }
        }

        /**********************************************************/
        /* save searched name                                     */
        /**********************************************************/
        prdu_strcpyN( (PBYTE) SpareMem, (PBYTE) SearchName,32 );
        SearchName[0] = '\0';

    }
#if 0
//  else /* if entrysize .... */
#endif
    else /* (DataStart == FNULL */
    {
    /******************************************************************/
    /* If an entry for the logical printer is found copy there will   */
    /* an entry for at least one printer type.  For each printer type */
    /* entry allocate memory off the DMIniEntry structure and         */
    /* copy the data across.  First get the type of the current       */
    /* printer.                                                       */
    /******************************************************************/
        /**************************************************************/
        /* SearchName contains the name found in INI, or '\0' for     */
        /* defaults.                                                  */
        /**************************************************************/

        pSource = DataStart;

        /**********************************************************/
        /* We already know what the printer type is.              */
        /* By pass the printer type field.                        */
        /**********************************************************/
        pSource += PRINTER_TYPE_LENGTH;

        /**********************************************************/
        /* Read in the total length of the entry for this         */
        /* printer.                                               */
        /**********************************************************/
        prdm_ReadWordFromText( TypeEntryLen,
                               NO_DATA_SIZE_DIGITS,
                               pSource );

        TRACE6(TFUNC, "Entry length", &TypeEntryLen, 1);

        /**********************************************************/
        /* Allocate memory for new entry.                         */
        /* DMIniEntry is an array of size = NO_OF_PRINTERS.       */
        /* Currently the code does not support multi tasking at   */
        /* DevMode time. Later we will use this array to re_enter */
        /* the code. SG                                           */
        /**********************************************************/
        pIniEntry = &DMIniEntry[PrinterType];

     /* Result = SSALLOCSEG( TypeEntryLen,                 */
     /*                      &SELECTOROF(pIniEntry->Data), */
     /*                      0 );                          */
        Result = SafeSSALLOCMEM( &(pIniEntry->Data),
                             TypeEntryLen, 0 );        /* CON3201 */

        if ( Result != DOS_OK )
        {
         /* Ring3LOGDOSERR(TFUNC, "SSALLOCSEG Fail", &Result, 1, Result); */
            Ring3LOGDOSERR(TFUNC, "SSALLOCMEM Fail", &Result, 1, Result);/*CON3201*/
            RetVal = (USHORT)DPDM_ERROR;
            goto Error_Return;
        }

/*      OFFSETOF(pIniEntry->Data) = 0;                              CON3201 */

        /**********************************************************/
        /* Reset pSource to point to the beginning of the entry   */
        /* for this printer.                                      */
        /**********************************************************/
        pSource -= (PRINTER_TYPE_LENGTH + NO_DATA_SIZE_DIGITS);

        /**********************************************************/
        /* Copy the data for this printer type across to its new  */
        /* home ( a remarkably sophisticated bijou residence for  */
        /* a modern 'data chunk' around town .. hmmmm ).          */
        /**********************************************************/
        TRACE6(TFUNC, "Copy data across", pSource, 8);

        for ( i = 0, pDest = pIniEntry->Data; i < TypeEntryLen; i++)
            *pDest++ = *pSource++;

        pIniEntry->BufferSize = TypeEntryLen;
        pIniEntry->EntrySize  = TypeEntryLen;


        /**************************************************************/
        /* Read in the header and body data for this printer type.    */
        /**************************************************************/
        TRACE6(TFUNC, "Read header data", FNULL, 0);

        prde_ReadHeaderData( pDMSettings,
                             DMIniEntry[PrinterType].Data,
                             DMData.IniVersionType );

        prdm_ReadBodyData( PrinterType );

        /**************************************************************/
        /* If migrating driver data then get the forms out of the INI */
        /* If the form number is not valid then get the default form  */
        /* number for that country.                                   */
        /**************************************************************/

        if (DriverDataConvert)
        {
/*         ConvertForm1 = TRUE; */                       /* PD00292 */
/*         ConvertForm2 = TRUE; */
           if (pGenData->FormNumber1 >= pDMSettings->NumberOfForms)
           {
              pGenData->FormNumber1 = DMData.DefaultForm;
           }
           if (pGenData->FormNumber2 >= pDMSettings->NumberOfForms)
           {
              pGenData->FormNumber2 = DMData.DefaultForm;
           }
           /* PD00292 */
/*         prde_TranslateOldDriverDataFrm( pGenData,                     */
/*                        DMIniEntry[PrinterType].Data +  HEADER_LENGTH, */
/*                        ConvertForm1, ConvertForm2 );                  */

           prde_TranslateOldDriverDataFrm( pGenData,
                          DMIniEntry[PrinterType].Data +  HEADER_LENGTH,
                          TRUE, TRUE );

        }
    } /* if EntrySize ... */

    /******************************************************************/
    /* At this point have printer (may be default) info and name      */
    /* SearchName ('\0' for default)                                  */
    /******************************************************************/

    /******************************************************************/
    /* Now, compare driverdata passed in with this info               */
    /*  Use driver data if it is valid, printertype matches inidata,  */
    /* and either names match or no name is provided.                 */
    /******************************************************************/
    DriverEqualsINI = FALSE;
    if (DriverDataValid)
    {
//     DriverEqualsINI = (
//           ( pGenData->PrinterType == pDMSettings->PrinterType)  &&
//           ( ( !prdu_strcmpN( SearchName, pGenData->PrinterName, 32) ||
//               (LPNameNull && DriverDataLPNameNull)    )   )
//                       );
       /***********************************************************************/
       /* PD00823 : User driver data instead of ini data when printer types   */
       /* match.                                                              */
       /***********************************************************************/
       DriverEqualsINI = (pGenData->PrinterType == pDMSettings->PrinterType);
    }

    if (DriverDataConvert)
    {
//     DriverEqualsINI = (
//           (DriverDataConvert) &&
//           ( (pGenData->PrinterType == pDMSettings->PrinterType)  &&
//           ( ( !prdu_strcmpN( SearchName, pGenData->PrinterName, 32) ) ||
/*             ( !EntrySize && SearchName[0] == 0) || */
//             ( (DataStart == FNULL) && SearchName[0] == 0) ||
//               (LPNameNull && DriverDataLPNameNull)    )   )
//                    );
       /***********************************************************************/
       /* PD00823 : User driver data instead of ini data when printer types   */
       /* match.                                                              */
       /***********************************************************************/
       DriverEqualsINI = (pGenData->PrinterType == pDMSettings->PrinterType);

       /*******************************************************************/
       /* NULL out the printer name if it could not be found previously.  */
       /*******************************************************************/

       if (SearchName[0] == 0)
       {
          pGenData->PrinterName[0] = 0;
       }
    }


    if ( uFlags == 0x00 || uFlags == 0x02 )
    {
        /**************************************************************/
        /* We are going to use the driver data if it matches the INI  */
        /* data; otherwise use the INI data.                          */
        /**************************************************************/
        if (DriverEqualsINI)
        {
            /**********************************************************/
            /* First all the fields that are common to the old 42XX   */
            /* driver. Note that the last field (PrinterName) is not  */
            /* used.                                                  */
            /**********************************************************/
            pDMDrivData->PrinterType   = pGenData->PrinterType;
            pDMDrivData->Resolution    = pGenData->Resolution;
            pDMDrivData->Orientation   = pGenData->Orientation;
            pDMDrivData->NumberOfForms = pGenData->NumberOfForms;
            pDMDrivData->FormNumber1   = pGenData->FormNumber1;
            pDMDrivData->FormNumber2   = pGenData->FormNumber2;

            /******************************************************************/
            /*  Now the new fields defined for versions 200 to 203.           */
            /*                                                                */
            /*  PD00665 : If MinorDriverDataConvert is on, then all these     */
            /*  fields are present.                                           */
            /******************************************************************/
            if (!DriverDataConvert || MinorDriverDataConvert)
            {
               /**********************************************************/
               /* Now the new fields defined for versions 200 to 203.    */
               /**********************************************************/
               pDMDrivData->DriverType          = DRIVER_TYPE;
               pDMDrivData->SimDup              = pGenData->SimDup;
               pDMDrivData->DuplexEnabled       = pGenData->DuplexEnabled;
               pDMDrivData->Type                = pGenData->Type;
               pDMDrivData->Index               = pGenData->Index;
               pDMDrivData->CodePageNo          = pGenData->CodePageNo;
               pDMDrivData->DLoadSysFonts       = pGenData->DLoadSysFonts;

               prdu_strcpy( (PBYTE) pDMDrivData->CardName,
                            (PBYTE) pGenData->CardName );
            }
            else
            {
               /**********************************************************/
               /* Now the new fields defined for versions 200 to 203.    */
               /* Note DuplexEnabled is not used.                        */
               /**********************************************************/
               pDMDrivData->DriverType     = DRIVER_TYPE;
               pDMDrivData->SimDup         = pDMSettings->SimDup;
               pDMDrivData->DLoadSysFonts  = pDMSettings->DownSysFonts;
               pDMDrivData->DuplexEnabled  = 0;
               pDMDrivData->Type           = DMData.DfltFontInfo.Info.Type;

               pDMDrivData->Index   = DMData.DfltFontInfo.Info.Index;

               pDMDrivData->CodePageNo  =
                                       DMData.DfltFontInfo.Info.CodePageNo;
               prdu_strcpy( (PBYTE) pDMDrivData->CardName,
                            (PBYTE) DMData.DfltFontInfo.CardName );

            }

            /**********************************************************/
            /* Now the new fields defined for versions 204 upwards .. */
            /**********************************************************/
            /******************************************************************/
            /* PD00615: Change *'s to country dependent decimal in driver data*/
            /*  form names.                                                   */
            /******************************************************************/
            for ( i = 0; pGenData->FormInfo1.FormName[i] != '\0'; i++ )
            {
               pDMDrivData->FormInfo1.FormName[i] =
                  (pGenData->FormInfo1.FormName[i] == ALT_POINT)
                                      ? DMData.DecimalPoint :
                                          pGenData->FormInfo1.FormName[i];
            }


            pDMDrivData->FormInfo1.FormType  = pGenData->FormInfo1.FormType;
            pDMDrivData->FormInfo1.FormUnits = pGenData->FormInfo1.FormUnits;

            /******************************************************************/
            /* PD00615: Change *'s to country dependent decimal in driver data*/
            /*  form names.                                                   */
            /******************************************************************/
            for ( i = 0; pGenData->FormInfo2.FormName[i] != '\0'; i++ )
            {
               pDMDrivData->FormInfo2.FormName[i] =
                  (pGenData->FormInfo2.FormName[i] == ALT_POINT)
                                      ? DMData.DecimalPoint :
                                          pGenData->FormInfo2.FormName[i];
            }

            pDMDrivData->FormInfo2.FormType  = pGenData->FormInfo2.FormType;
            pDMDrivData->FormInfo2.FormUnits = pGenData->FormInfo2.FormUnits;

            /******************************************************************/
            /*  PD00136... added in version 207                               */
            /*                                                                */
            /*  PD00665 : If MinorDriverDataConvert is on, then the field     */
            /*  is present.                                                   */
            /******************************************************************/
            if (!DriverDataConvert || MinorDriverDataConvert)
            {
               pDMDrivData->DisableOutlineFonts = pGenData->DisableOutlineFonts;
            }
            else
            {
               pDMDrivData->DisableOutlineFonts = pDMSettings->DisableOutlineFonts;
            }

            /******************************************************************/
            /*  PD00137...                                                    */
            /*  PD00665 : If MinorDriverDataConvert is on, then the field     */
            /*  is present.                                                   */
            /******************************************************************/
            if (!DriverDataConvert || MinorDriverDataConvert)
            {
               pDMDrivData->DfltFontPointSz = pGenData->DfltFontPointSz;
            }
            else
            {
               pDMDrivData->DfltFontPointSz = pDMSettings->DfltFontPointSz;
            }
            /******************************************************************/
            /*  PD00587: have added a new resolution field so we can do       */
            /*  360x360.  Added in version 265.                               */
            /******************************************************************/
            pDMDrivData->Resolution2 = pGenData->Resolution2;

            /******************************************************************/
            /*  PD00651 : Read in whether or not it is an NLS machine or not  */
            /******************************************************************/
            pDMDrivData->MachineType = pGenData->MachineType;

            /******************************************************************/
            /* PD00769 :  Update for new field added in 310                   */
            /******************************************************************/
            pDMDrivData->PrinterPatterns = pGenData->PrinterPatterns;

            /******************************************************************/
            /*  600DPI : Added a new resolution field so we can do 600x600.   */
            /******************************************************************/
            pDMDrivData->Resolution3 = pGenData->Resolution3;

            /******************************************************************/
            /*  PD00651 : Set the default font when switching between NLS and */
            /*  US 23XX printers.                                             */
            /******************************************************************/
            if (DDT[PrinterType]->DDTFontFlags & DDT_NLS_FONTS_OPTIONAL)
            {
               if (pDMDrivData->MachineType != 0)
               {
                  /***************************************************************/
                  /*  If it is an 23XX printer and the machine type has changed  */
                  /***************************************************************/
                  if ((pDMSettings->MachineType == US_MACHINE) &&
                      (pDMDrivData->MachineType == NLS_MACHINE))
                  {
                     if ( ((pDMSettings->PrinterType == IBM_NILE_24) ||
                          (pDMSettings->PrinterType == IBM_TIBER_24)) )
                        pDMDrivData->Index = NLStoUS239X[pGenData->Index];
                     else
                        pDMDrivData->Index = NLStoUS238X[pGenData->Index];

                     pDMDrivData->MachineType = US_MACHINE;
                  }
                  else if ((pDMSettings->MachineType == NLS_MACHINE) &&
                           (pDMDrivData->MachineType == US_MACHINE))
                  {
                     if ( ((pDMSettings->PrinterType == IBM_NILE_24) ||
                           (pDMSettings->PrinterType == IBM_TIBER_24)) )
                        pDMDrivData->Index = UStoNLS239X[pGenData->Index];
                     else
                        pDMDrivData->Index = UStoNLS238X[pGenData->Index];

                     pDMDrivData->MachineType = NLS_MACHINE;
                  }
               }
               else
               {
                  /************************************************************/
                  /*  If there is no previous Machine Type then get the       */
                  /*  number of resident fonts and then range check the index */
                  /************************************************************/
                  if ( (pDMSettings->PrinterType == IBM_NILE_9) ||
                       (pDMSettings->PrinterType == IBM_TIBER_9) )
                  {
                      if (pDMSettings->MachineType == NLS_MACHINE)
                      {
                          NoOfResidentFonts = NLS_9WIRE;
                      }
                      else
                      {
                          NoOfResidentFonts = US_9WIRE;
                      }
                  }
                  else /* its a 24-wire */
                  {
                      if (pDMSettings->MachineType == NLS_MACHINE)
                      {
                          NoOfResidentFonts = NLS_24WIRE;
                      }
                      else
                      {
                          NoOfResidentFonts = US_24WIRE;
                      }
                  }

                  if (pDMDrivData->Index > NoOfResidentFonts)
                  {
                     pDMDrivData->Index = 0;
                  }
                  else
                     pDMDrivData->Index = pGenData->Index;
               }
            }
        }
        else
        {
            /**********************************************************/
            /* First all the fields that are common to the old 42XX   */
            /* driver.                                                */
            /**********************************************************/
            pDMDrivData->PrinterType   = pDMSettings->PrinterType;
            pDMDrivData->Resolution    = pDMSettings->Resolution;
            pDMDrivData->Orientation   = pDMSettings->Orientation;
            pDMDrivData->NumberOfForms = 1;
            pDMDrivData->FormNumber1   = pDMSettings->SelectedForm;
            pDMDrivData->FormNumber2   = pDMSettings->SelectedForm;

            /**********************************************************/
            /* Now the new fields defined for versions 200 to 203.    */
            /* Note DuplexEnabled is not used.                        */
            /**********************************************************/
            pDMDrivData->DriverType     = DRIVER_TYPE;
            pDMDrivData->SimDup         = pDMSettings->SimDup;
            pDMDrivData->DLoadSysFonts  = pDMSettings->DownSysFonts;
            pDMDrivData->DuplexEnabled  = 0;
            pDMDrivData->Type           = DMData.DfltFontInfo.Info.Type;

            pDMDrivData->Index   = DMData.DfltFontInfo.Info.Index;

            pDMDrivData->CodePageNo  =
                                    DMData.DfltFontInfo.Info.CodePageNo;
            prdu_strcpy( (PBYTE) pDMDrivData->CardName,
                         (PBYTE) DMData.DfltFontInfo.CardName );

            /**********************************************************/
            /* Now the new fields defined for versions 204 upwards .. */
            /* Use the same value for form1 as form2.                 */
            /**********************************************************/
            DrvDataFormNo1 = prdm_FindDfltFormNo();
            pFormInfo1     = prdm_FindFormInfo( DrvDataFormNo1 );

            prdu_strcpy( (PBYTE) pDMDrivData->FormInfo1.FormName,
                         (PBYTE) pFormInfo1->FormName );

            pDMDrivData->FormInfo1.FormType  = pFormInfo1->FormType;
            pDMDrivData->FormInfo1.FormUnits = pFormInfo1->FormUnits;

            prdu_strcpy( (PBYTE) pDMDrivData->FormInfo2.FormName,
                         (PBYTE) pFormInfo1->FormName );

            pDMDrivData->FormInfo2.FormType  = pFormInfo1->FormType;
            pDMDrivData->FormInfo2.FormUnits = pFormInfo1->FormUnits;

            /******************************************************************/
            /*  PD00136... added in version 207                               */
            /******************************************************************/
            pDMDrivData->DisableOutlineFonts = pDMSettings->DisableOutlineFonts;

            /******************************************************************/
            /*  PD00137...                                                    */
            /******************************************************************/
            pDMDrivData->DfltFontPointSz = pDMSettings->DfltFontPointSz;

            /******************************************************************/
            /*  PD00587: Add in new resolution field as we had to add an      */
            /*  extra resolution to do 360x360.                               */
            /******************************************************************/
            pDMDrivData->Resolution2         = pDMSettings->Resolution;

            /******************************************************************/
            /*  PD00665, 651 : Read in whether or not it is an NLS machine    */
            /*  or not                                                        */
            /******************************************************************/
            pDMDrivData->MachineType = pDMSettings->MachineType;

            /******************************************************************/
            /* PD00769 : New field added in version 310                       */
            /******************************************************************/
            pDMDrivData->PrinterPatterns = pDMSettings->PrinterPatterns;

            /******************************************************************/
            /*  600DPI : Added new resolution field for 600DPI on the 4029's  */
            /******************************************************************/
            pDMDrivData->Resolution3 = pDMSettings->Resolution;
        }

        if (SearchName[0] == '\0')
        {
            /**********************************************************/
            /* Use name we searched for in ini file.                  */
            /**********************************************************/
            prdu_strcpyN( pDMDrivData->PrinterName, SpareMem, 32 );
        }
        else
            /**********************************************************/
            /* found name                                             */
            /**********************************************************/
            prdu_strcpyN( pDMDrivData->PrinterName, SearchName, 32 );
    }

    /**************************************************************************/
    /* PD00205 : Call prde_GetResources to set up some strings we need        */
    /*  for default font list processing.                                     */
    /**************************************************************************/
    prde_GetResources();

    if ( uFlags == 0x00 )
    {
        /**************************************************************/
        /* Go into the JOB_SET_UP dialog box.  This allows the user   */
        /* to update only a limited subset of printer options.  The   */
        /* result of the dialog is only passed back in DriverData     */
        /* This returns when the user selects either the ENTER or     */
        /* CANCEL options from the DB_CURRENT_OPTIONS dialog box.     */
        /* Result is TRUE for ENTER; FALSE for CANCEL.                */
        /**************************************************************/
        TRACE6(TFUNC, "Call Job Set Up box", FNULL, 0);

        DMData.DialogId = DDT[pDMSettings->PrinterType]->DDTJSU_DialogId;

     /* HwndOwner = WinQueryActiveWindow(HWND_DESKTOP,TRUE); */
        HwndOwner = WinQueryActiveWindow(HWND_DESKTOP);    /* CON3201 */

        Result    =  WinDlgBox( (HWND)HWND_DESKTOP,
                                HwndOwner,
                                (PFNWP)prdm_JobSetUpDlgProc,
                                DMData.HModule,
                                DMData.DialogId,
                                (PVOID)NULL );

/*      WinLockWindow(HwndOwner,FALSE);  CON3201 - Does nothing               */
    }
    else if ( uFlags == 0x01 )
    {
        /**************************************************************/
        /* Go into the DB_PP_TYPEn dialog box.  This call             */
        /* returns when the user selects either the ENTER or CANCEL   */
        /* options from the DB_CURRENT_OPTIONS dialog box.            */
        /* Result is TRUE for ENTER; FALSE for CANCEL.                */
        /**************************************************************/
        TRACE6(TFUNC, "Call Current Options", FNULL, 0);

        DMData.DialogId = DDT[pDMSettings->PrinterType]->DDTPP_DialogId;

     /* HwndOwner = WinQueryActiveWindow(HWND_DESKTOP,TRUE); */
        HwndOwner = WinQueryActiveWindow(HWND_DESKTOP);

        Result    =  WinDlgBox( (HWND)HWND_DESKTOP,
                                HwndOwner,
                                (PFNWP)prdm_MainDlgProc,
                                DMData.HModule,
                                DMData.DialogId,
                                (PVOID)NULL );

/*      WinLockWindow(HwndOwner,FALSE);                               CON3201 */
    }


    if ( (uFlags == 0x01) && (Result) )
    {
        /**************************************************************/
        /* Note - in this case, the name we will write to INI and to  */
        /* DriverData is the passed in name (never NULL), which is    */
        /* held in InitialPrinterName.                                */
        /**************************************************************/

        /**************************************************************/
        /* User selected ENTER so we must update the OS2.INI file.    */
        /**************************************************************/
        TRACE6(TFUNC, "Update INI file", FNULL, 0);

        /**************************************************************/
        /* Determine the size of entry in the OS2.INI file which we   */
        /* will need for the new data.                                */
        /**************************************************************/
        IniSize = DMIniEntry[PrinterType].EntrySize + 2;

        TRACE6(TFUNC, "Segment size", &IniSize, 1);

        /**********************************************************************/
        /* Allocate the required buffer.                                      */
        /*  PD00761 : Change Result to Result2 so that the value in Result is */
        /*  not lost before the next if check.                                */
        /**********************************************************************/
     /* Result2 = SSALLOCSEG( IniSize, &SELECTOROF(OutBuffer), 0 ); */
        Result2 = SafeSSALLOCMEM( &OutBuffer, IniSize, 0 );        /* CON3201 */

        if ( Result2 != DOS_OK )
        {
         /* Ring3LOGDOSERR(TFUNC, "SSALLOCSEG fail", &Result2, 1, Result2); */
            Ring3LOGDOSERR(TFUNC, "SSALLOCMEM fail", &Result2, 1, Result2);/*CON3201*/
            RetVal = (USHORT)DPDM_ERROR;
            goto Error_Return;
        }

/*      OFFSETOF(OutBuffer) = 0;                                      CON3201 */
        pDest = OutBuffer;

        /**************************************************************/
        /* Now copy the entry for this printer type into the INI.     */
        /**************************************************************/
        for ( j = 0, pSource = DMIniEntry[PrinterType].Data;
                     j < DMIniEntry[PrinterType].EntrySize;
                     j++ )
        {
            *pDest++ = *pSource++;
        }

        /**************************************************************/
        /* Add a null terminator.  Make sure the actual entry length  */
        /* is used, not the length of the allocated segment.          */
        /**************************************************************/
        *pDest++ = ';';
        *pDest++ = '\0';
        IniSize = (USHORT)((ULONG)pDest - (ULONG)OutBuffer);

        TRACE6(TFUNC, "INI entry size", &IniSize, 1);

        /***************************************************************/
        /* Set up the Version.                          PD00208        */
        /***************************************************************/
        prdu_strcpy( VersionBuf, OS2_INI_VERSION );
        *(VersionBuf + 3) = ';';
        *(VersionBuf + 4) = '\0';

        /**************************************************************/
        /* Write data back into OS2.INI, only if uFlags is one.       */
        /**************************************************************/
        prdm_PM_DD_Write( InitialPrinterName,
                          KeyWord,
                          "DRIVERDATA",
                          OutBuffer,
                          IniSize);

        prdm_PM_DD_Write( InitialPrinterName,
                          KeyWord,
                          "VERSION",
                          VersionBuf,
                          (USHORT)5);

        /**************************************************************/
        /* If data has changed for the download, card or code page    */
        /* data or the code page reload flag has been set for the     */
        /* svaed printer type...                                      */
        /**************************************************************/
        if ( DMIniEntry[pDMSettings->PrinterType].DataChange )
        {
            TRACE8(TFUNC, "Look for printer", FNULL, 0);

            /**********************************************************/
            /* Find the entry for the state data for this printer     */
            /**********************************************************/
            for( lplpPrinterData  =
                              /* (lpPrtDataEntry far*)&PrinterStateData; */
                                 (lpPrtDataEntry *)&PrinterStateData;/*CON3201*/
                 (*lplpPrinterData != FNULL);
              /* lplpPrinterData = (lpPrtDataEntry far*) */
                 lplpPrinterData = (lpPrtDataEntry *)      /* CON3201 */
                               &( ((*lplpPrinterData)->PrtNextEntry )) )
            {
                if ( !prdu_strcmpN( InitialPrinterName,
                              (*lplpPrinterData)->LPName, 32) )
                {
                    /**************************************************/
                    /* Found printer - update the data change flag in */
                    /* the printer entry.                             */
                    /**************************************************/
                    (*lplpPrinterData)->DataChange =
                        DMIniEntry[pDMSettings->PrinterType].DataChange;
                    break;
                }
            }
        }


        /**************************************************************/
        /* Update our DriverData with values from DMSettings.  Note   */
        /* that DriverData will not have been touched while           */
        /* processing the Current Options Dialog Box.                 */
        /**************************************************************/

        /**************************************************************/
        /* First all the fields that are common to the old 42XX       */
        /* driver.                                                    */
        /**************************************************************/
        pDMDrivData->PrinterType   = pDMSettings->PrinterType;
        pDMDrivData->Resolution    = pDMSettings->Resolution;
        pDMDrivData->Orientation   = pDMSettings->Orientation;
        pDMDrivData->NumberOfForms = 1;
        pDMDrivData->FormNumber1   = pDMSettings->SelectedForm;
        pDMDrivData->FormNumber2   = pDMSettings->SelectedForm;
        prdu_strcpyN( (PBYTE) pDMDrivData->PrinterName,
                      (PBYTE) InitialPrinterName, 32);

        /**************************************************************/
        /* Now the new fields defined for versions 200 to 203.  Note  */
        /* DuplexEnabled is not used.                                 */
        /**************************************************************/
        pDMDrivData->DriverType    = DRIVER_TYPE;
        pDMDrivData->DLoadSysFonts = pDMSettings->DownSysFonts;
        pDMDrivData->SimDup        = pDMSettings->SimDup;
        pDMDrivData->Index     = DMData.DfltFontInfo.Info.Index;
        pDMDrivData->CodePageNo    = DMData.DfltFontInfo.Info.CodePageNo;
        prdu_strcpy( (PBYTE) pDMDrivData->CardName,
                     (PBYTE) DMData.DfltFontInfo.CardName );

        /**************************************************************/
        /* Now the new fields defined for versions 204 upwards ..     */
        /* Use the same value for form1 as form2.                     */
        /**************************************************************/
        pFormInfo1 = prdm_FindFormInfo( (ULONG)pDMSettings->SelectedForm );

        prdu_strcpy( (PBYTE) pDMDrivData->FormInfo1.FormName,
                     (PBYTE) pFormInfo1->FormName );

        pDMDrivData->FormInfo1.FormType  = pFormInfo1->FormType;
        pDMDrivData->FormInfo1.FormUnits = pFormInfo1->FormUnits;

        prdu_strcpy( (PBYTE) pDMDrivData->FormInfo2.FormName,
                     (PBYTE) pFormInfo1->FormName );

        pDMDrivData->FormInfo2.FormType  = pFormInfo1->FormType;
        pDMDrivData->FormInfo2.FormUnits = pFormInfo1->FormUnits;

        /**********************************************************************/
        /*  PD00136... added in version 207                                   */
        /**********************************************************************/
        pDMDrivData->DisableOutlineFonts = pDMSettings->DisableOutlineFonts;

        /**********************************************************************/
        /*  PD00137                                                           */
        /**********************************************************************/
        pDMDrivData->DfltFontPointSz = pDMSettings->DfltFontPointSz;

        /**********************************************************************/
        /*  PD00587 : added new resolution field.                             */
        /**********************************************************************/
        pDMDrivData->Resolution2   = pDMSettings->Resolution;

        /**********************************************************************/
        /*  PD00651 : added new MachineType field.                            */
        /**********************************************************************/
        pDMDrivData->MachineType   = pDMSettings->MachineType;

        /**********************************************************************/
        /* PD00769 : Set PrinterPatterns flag in driver data                  */
        /**********************************************************************/
        pDMDrivData->PrinterPatterns = pDMSettings->PrinterPatterns;

        /**********************************************************************/
        /*  600DPI : added new resolution field.                              */
        /**********************************************************************/
        pDMDrivData->Resolution3   = pDMSettings->Resolution;

    }
    /*.. if ( (uFlags == 0x01)  && (Result) ) ........................*/


    /******************************************************************/
    /* Update the driver data if uFlags is 2 or the user has          */
    /* ENTERed out of a dialog box.  If the user has CANCELed out of  */
    /* a box the driver data is NOT updated.                          */
    /******************************************************************/
    if ( (uFlags == 0x02) || Result )
    {
       /***********************************************************************/
       /*  PD00620 : Clear out the passed in driver data before writing out   */
       /*  the changes, as garbage could have been passed in.                 */
       /***********************************************************************/
       prdu_memset((PBYTE)DriverData->abGeneralData, 0, sizeof(DMDriverStruc));
       prdu_memset((PBYTE)DriverData->szDeviceName, 0, 32);

       if (!DriverDataConvert)
       {
           DriverData->cb = sizeof(DRIVDATA) + sizeof(DMDriverStruc) - 1;
           DriverData->lVersion = ulIniVersion;

           prdu_strcpy( (PBYTE) DriverData->szDeviceName,
                         (PBYTE) (KeyWord+8));                   /* PD00620   */

           /**************************************************************/
           /* First all the fields that are common to the old 42XX       */
           /* driver.                                                    */
           /**************************************************************/
           pGenData->PrinterType   = pDMDrivData->PrinterType;
           pGenData->Resolution    = pDMDrivData->Resolution;
           pGenData->Orientation   = pDMDrivData->Orientation;
           pGenData->NumberOfForms = pDMDrivData->NumberOfForms;
           pGenData->FormNumber1   = pDMDrivData->FormNumber1;
           pGenData->FormNumber2   = pDMDrivData->FormNumber2;

           if (LPNameNull && DriverDataLPNameNull)
           {
               /**********************************************************/
               /* Search name zero if default used                       */
               /**********************************************************/
               pGenData->PrinterName[0] = '\0';
           }
           else
           {
               /**********************************************************/
               /* Use value found in the INI                             */
               /**********************************************************/
               prdu_strcpyN( pGenData->PrinterName, SearchName, 32 );
           }

           /**************************************************************/
           /* Now the new fields defined for versions 200 to 203.  Note  */
           /* DuplexEnabled is not used.                                 */
           /**************************************************************/
           pGenData->DriverType    = DRIVER_TYPE;
           pGenData->DLoadSysFonts = pDMDrivData->DLoadSysFonts;
           pGenData->SimDup        = pDMDrivData->SimDup;
           pGenData->DuplexEnabled = pDMDrivData->DuplexEnabled;
           pGenData->Type          = pDMDrivData->Type;
           pGenData->Index         = pDMDrivData->Index;
           pGenData->CodePageNo    = pDMDrivData->CodePageNo;
           prdu_strcpy( (PBYTE) pGenData->CardName,
                        (PBYTE) pDMDrivData->CardName );

           /**************************************************************/
           /* Now the new fields defined for versions 204 upwards ..     */
           /* Use the same value for form1 as form2.                     */
           /**************************************************************/
           /*******************************************************************/
           /*  PD00615 : Copy the form name out with '*'s not country         */
           /*  dependent decimal places.                                      */
           /*******************************************************************/
           for ( i = 0; pDMDrivData->FormInfo1.FormName[i] != '\0'; i++ )
           {
                pGenData->FormInfo1.FormName[i] =
                   (pDMDrivData->FormInfo1.FormName[i] == DMData.DecimalPoint) ?
                   ALT_POINT : pDMDrivData->FormInfo1.FormName[i] ;
           }

           pGenData->FormInfo1.FormType  = pDMDrivData->FormInfo1.FormType;
           pGenData->FormInfo1.FormUnits = pDMDrivData->FormInfo1.FormUnits;

           /*******************************************************************/
           /*  PD00615 : Copy the form name out with '*'s not country         */
           /*  dependent decimal places.                                      */
           /*******************************************************************/
           for ( i = 0; pDMDrivData->FormInfo2.FormName[i] != '\0'; i++ )
           {
                pGenData->FormInfo2.FormName[i] =
                   (pDMDrivData->FormInfo2.FormName[i] == DMData.DecimalPoint) ?
                   ALT_POINT : pDMDrivData->FormInfo2.FormName[i] ;
           }

           pGenData->FormInfo2.FormType  = pDMDrivData->FormInfo2.FormType;
           pGenData->FormInfo2.FormUnits = pDMDrivData->FormInfo2.FormUnits;

           /**********************************************************************/
           /*  PD00136... added in version 207                                   */
           /**********************************************************************/
           pGenData->DisableOutlineFonts = pDMDrivData->DisableOutlineFonts;
           pGenData->DfltFontPointSz = pDMDrivData->DfltFontPointSz;

           /*******************************************************************/
           /*  PD00587 : added new resolution field for 360x360               */
           /*******************************************************************/
           pGenData->Resolution2   = pDMDrivData->Resolution2;

           /*******************************************************************/
           /*  PD00665,651 : added new MachineType field for Nile/Tiber       */
           /*******************************************************************/
           pGenData->MachineType   = pDMDrivData->MachineType;

           /*******************************************************************/
           /* PD00769 :  New field added in version 310                       */
           /*******************************************************************/
           pGenData->PrinterPatterns  = pDMDrivData->PrinterPatterns;

           /*******************************************************************/
           /*  600DPI : added new resolution field for 360x360                */
           /*******************************************************************/
           pGenData->Resolution3   = pDMDrivData->Resolution3;

       }
       else
       {
          if (DriverData->cb >= sizeof(DRIVDATA)+sizeof(DMDriverStruc)-1)
          {

             DriverData->lVersion = ulIniVersion;

             prdu_memcpy( (PBYTE) DriverData->abGeneralData,
                          (PBYTE) pDMDrivData,
                          sizeof(DMDriverStruc) );

             /*****************************************************************/
             /*  PD00615 : Copy the form names out with '*'s not country      */
             /*  dependent decimal places and pad rest of field with NULLs.   */
             /*****************************************************************/
             pTemp = (pDMDriverStruc) DriverData->abGeneralData;

             for ( i = 0; pDMDrivData->FormInfo1.FormName[i] != '\0'; i++ )
             {
                  pTemp->FormInfo1.FormName[i] =
                     (pDMDrivData->FormInfo1.FormName[i] == DMData.DecimalPoint) ?
                     ALT_POINT : pDMDrivData->FormInfo1.FormName[i] ;
             }

             for ( i = 0; pDMDrivData->FormInfo2.FormName[i] != '\0'; i++ )
             {
                  pTemp->FormInfo2.FormName[i] =
                   (pDMDrivData->FormInfo2.FormName[i] == DMData.DecimalPoint) ?
                      ALT_POINT : pDMDrivData->FormInfo2.FormName[i] ;
             }

             if (NullPrinterName)
             {
                *(DriverData->abGeneralData + 24) = 0;
             }

             prdu_strcpy( (PBYTE) DriverData->szDeviceName,
                          (PBYTE) DeviceName);

          }
          else if ( ( DriverData->cb >= 246 ) &&
               ( DriverData->cb <= sizeof(DRIVDATA)+sizeof(DMDriverStruc)-1 ) )

          /********************************************************************/
          /* We can write out most of the fields.                             */
          /********************************************************************/
          {
             DriverData->lVersion = ulIniVersion;
             /*****************************************************************/
             /* PD00769 : Don't copy more than requesters buffer size         */
             /*****************************************************************/
             prdu_memcpy( (PBYTE) DriverData->abGeneralData,
                          (PBYTE) pDMDrivData,
                          (USHORT)(DriverData->cb - sizeof(DRIVDATA) + 1) );

             /*****************************************************************/
             /*  PD00615 : Copy the form names out with '*'s not country      */
             /*  dependent decimal places.                                    */
             /*****************************************************************/
             pTemp = (pDMDriverStruc) DriverData->abGeneralData;

             for ( i = 0; pDMDrivData->FormInfo1.FormName[i] != '\0'; i++ )
             {
                  pTemp->FormInfo1.FormName[i] =
                     (pDMDrivData->FormInfo1.FormName[i] == DMData.DecimalPoint) ?
                     ALT_POINT : pDMDrivData->FormInfo1.FormName[i] ;
             }

             for ( i = 0; pDMDrivData->FormInfo2.FormName[i] != '\0'; i++ )
             {
                  pTemp->FormInfo2.FormName[i] =
                   (pDMDrivData->FormInfo2.FormName[i] == DMData.DecimalPoint) ?
                      ALT_POINT : pDMDrivData->FormInfo2.FormName[i] ;
             }

             if (NullPrinterName)
             {
                *(DriverData->abGeneralData + 24) = 0;
             }

             prdu_strcpy( (PBYTE) DriverData->szDeviceName,
                          (PBYTE) DeviceName);

          }
          else
          {
             OldDriverStructure = (PULONG) DriverData->abGeneralData;
             *OldDriverStructure++ = pDMDrivData->PrinterType;
             *OldDriverStructure++ = pDMDrivData->Resolution;
             *OldDriverStructure++ = pDMDrivData->Orientation;
             *OldDriverStructure++ = pDMDrivData->NumberOfForms;
             *OldDriverStructure++ = pDMDrivData->FormNumber1;
             *OldDriverStructure++ = pDMDrivData->FormNumber2;
             OldPrinterName = DriverData->abGeneralData + 24;
             prdu_strcpyN(OldPrinterName, SearchName, 32 );

             prdu_strcpy( (PBYTE) DriverData->szDeviceName,
                          (PBYTE) DeviceName);
          }
       }
    }

Error_Return:
    /******************************************************************/
    /* Ensure the cursor is reset to its original shape.              */
    /******************************************************************/
    Result = WinSetPointer( HWND_DESKTOP,
                            (HPOINTER)DMData.CursorHandle );

    /******************************************************************/
    /* Free all the memory which may have been allocated during this  */
    /* call.  This is where we come after an error before exiting.    */
    /*                                                                */
    /******************************************************************/
    if ( DataStart )
     /* SSFREESEG(SELECTOROF(DataStart)); */
        SSFREEMEM( DataStart );                            /* CON3201 */
    if ( OutBuffer )
     /* SSFREESEG(SELECTOROF(OutBuffer)); */
        SSFREEMEM( OutBuffer );                            /* CON3201 */

    if (DriverDataConvert)
    {
    /* SSFREESEG(SELECTOROF(pGenData)); */
       SSFREEMEM( pGenData );                              /* CON3201 */
    }

    prdm_FreeDMDataSegments();

    for ( i = 0; i < NO_OF_PRINTERS; i++ )
    {
        if ( DMIniEntry[i].Data )
         /* SSFREESEG(SELECTOROF(DMIniEntry[i].Data)); */
            SSFREEMEM( DMIniEntry[i].Data );               /* CON3201 */
    }

    /******************************************************************/
    /* Ok .. that's it.                                               */
    /******************************************************************/
    return (RetVal);
}
#undef TFUNC


#ifdef OMIT_OLD_CODE
/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdm_ReadIniString                                     */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   RETURNS:     ERROR_NEG   - error                                 */
/*                ERROR_ZERO  - no data found                         */
/*                other       - pointer to return                     */
/*                                                                    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function reads an entry in the os2.ini file and returns     */
/*   a pointer to a buffer containing the data. If the pointer is     */
/*   NULL no entry was found; if it is -1 an error occurred.          */
/*   The calling function is responsible for freeing memory           */
/*   allocated for the data, if the function succeeds                 */
/*                                                                    */
/**********************************************************************/
/*PBYTE pascal far prdm_ReadIniString( AppName, */
/*                                     KeyName) */

PSZ      AppName;        /*    PM_SPOOLER_ .... */
PSZ      KeyName;        /*                     */

{
#define TFUNC "prdm_ReadIniFle"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    USHORT         Result;
    PBYTE          Buffer;
    USHORT         Size;
    SHORT          RetLength;
/*  PFN            pPrfQueryProfSz;         CON3201 */
/*  PFN            pPrfQueryProfileString;  CON3201 */
    HMODULE        ModuleHandle;
    USHORT         DosResult;
    BOOL           ModuleOK;

    /******************************************************************/
    /* Need to worry about 1.1 and 1.2                                */
    /******************************************************************/
/* CON3201 - comment out for now at least
**  ModuleOK = DosLoadModule( FNULL, 0, "PMSHAPI", &ModuleHandle);
**
**  if ( ModuleOK == DOS_OK )
**  {
**      /**************************************************************/
**      /* Now try and get the address of Prf..                       */
**      /**************************************************************/
**      DosResult = DosGetProcAddr( ModuleHandle,
**                                  "PRFQUERYPROFILESIZE",
**                                  &pPrfQueryProfSz);
**      TRACE4(TFUNC, "DosGetProcAddr Res", &DosResult, 1);
**
**      if (DosResult == DOS_OK)
**      {
**          /**********************************************************/
**          /* 1.2: Can now make the call                             */
**          /**********************************************************/
**          if ( !pPrfQueryProfSz( HINI_SYSTEMPROFILE,
**                                 AppName,
**                                 KeyName,
**                                 (PULONG)&Size) )
**          {
**              goto ERROR_RETURN;
**          }
**      }
**      else
**      {
**          /**********************************************************/
**          /* 1.1: Now make the call                                 */
**          /**********************************************************/
**          if ( WinQueryProfileSize( hab,
**                                    AppName,
**                                    KeyName,
**                                    &Size) )
**          {
**              goto ERROR_RETURN;
**          }
**      }
**  }
*/
/* CON3201 - I pulled this out of the above statements                        */
/*  if ( !pPrfQueryProfSz( HINI_SYSTEMPROFILE,                        CON3201 */
    if ( !PrfQueryProfileSize( HINI_SYSTEMPROFILE,
                               AppName,
                                KeyName,
                               (PULONG)&Size) )
    {
        goto ERROR_RETURN;
    }
    else
    {
        /**************************************************************/
        /* Should never go through this code  (error logged by Dos-   */
        /* LoadModule???                                              */
        /**************************************************************/
        goto ERROR_RETURN;
    }

    if (Size)
    {
        /**************************************************************/
        /* There is an entry for this driver in the INI file, so      */
        /* allocate a some memory for it                              */
        /**************************************************************/
     /* Result = SSALLOCSEG (Size, &SELECTOROF(Buffer), 0); */
        Result = SafeSSALLOCMEM (&Buffer, Size, 0);            /* CON3201 */

        if (Result != DOS_OK)
        {
         /* Ring3LOGDOSERR(TFUNC, "SSALLOCSEG Fail", &Result, 1, Result); */
            Ring3LOGDOSERR(TFUNC, "SSALLOCMEM Fail", &Result, 1, Result);/*CON3201*/
            goto ERROR_RETURN;
        }

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

        /**************************************************************/
        /* Read the OS2.INI data into the buffer.                     */
        /**************************************************************/
//      if ( ModuleOK == DOS_OK )
//      {
//          /**********************************************************/
//          /* Now try and get the address of Prf..                   */
//          /**********************************************************/
//          DosResult = DosGetProcAddr( ModuleHandle,
//                                      "PRFQUERYPROFILESTRING",
//                                      &pPrfQueryProfileString);
//          TRACE4(TFUNC, "DosGetProcAddr Res", &DosResult, 1);
//
//          if (DosResult == DOS_OK)
//          {
//              /******************************************************/
//              /* 1.2: Can now make the call. Returns the number of  */
//              /* bytes written. Because we have always queried the  */
//              /* length this will always equal the size specified   */
//              /* so no need to check it.                            */
//              /******************************************************/
//              RetLength = pPrfQueryProfileString(
//                                    HINI_SYSTEMPROFILE,
//                                    AppName,
//                                    KeyName,
//                                    FNULL,
//                                    (PVOID)Buffer,
//                                    (PULONG)&Size);
//          }
//          else
//          {
//              /******************************************************/
//              /* 1.1: Can now make the call                         */
//              /******************************************************/
//              if ( WinQueryProfileData( hab,
//                                        AppName,
//                                        KeyName,
//                                        (PVOID)Buffer,
//                                        (PUSHORT)&Size) != OK )
//              {
//               /* SSFREESEG(SELECTOROF(Buffer)); */
//                  SSFREEMEM( Buffer );                   /* CON3201 */
//                  goto ERROR_RETURN;
//              }
//          }
//      }
//      else
//      {
//          /**********************************************************/
//          /* Should never go through this code                      */
//          /**********************************************************/
//          goto ERROR_RETURN;
//      }
        RetLength = PrfQueryProfileString(
                              HINI_SYSTEMPROFILE,
                                  AppName,
                                  KeyName,
                                  FNULL,
                                  (PVOID)Buffer,
                                  (PULONG)&Size);

        /**************************************************************/
        /* Good return - information found                            */
        /**************************************************************/
        return(Buffer);

    }   // .... if (Size)
    else
    {
        /**************************************************************/
        /* OK return - no information found                           */
        /**************************************************************/
        return((PBYTE)(ULONG)ERROR_ZERO);
    }

    /******************************************************************/
    /*     return - error occurred                                    */
    /******************************************************************/
Ring3LOGERROR_RETURN:

ERROR_RETURN:
    return((PBYTE)(ULONG)ERROR_NEG);

}

#undef TFUNC
#endif

#ifdef OMIT_OLD_CODE

/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdm_MatchDescription                                  */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PSZ       PrinterName   - Logical printer name                   */
/*                                                                    */
/*   RETURN    ERROR_NEG     - error                                  */
/*             PrinterType   - constant value for printer type        */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   Given a pointer to a logical printer name, return the equivalent */
/*   Printer Type index based on the printer description for that     */
/*   logical printer name stored under the PM_SPOOLER_DD_DESC app     */
/*   name.                                                            */
/*                                                                    */
/**********************************************************************/
/*SHORT pascal prdm_MatchDescription( pszPrinterName ) */

PSZ         pszPrinterName;

{
#define TFUNC "prdm_MatchDescription"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    PBYTE        pDeviceDesc;  // pointer to device description
    SHORT        PrinterType;
    SHORT        i;
    CHAR         Prntr_Name_Buf[MAX_PRNTR_NAME];

    /******************************************************************/
    /* Query ini file for the printer description relating to the     */
    /* target logical printer name. Assume that string is returned    */
    /* null terminated????                                            */
    /******************************************************************/
    pDeviceDesc = prdm_ReadIniString( (PSZ)"PM_SPOOLER_PRINTER_DESCR",
                                      pszPrinterName);

    if ((pDeviceDesc == (PBYTE)ERROR_NEG) ||
        (pDeviceDesc == (PBYTE)ERROR_ZERO))
    {
        /**************************************************************/
        /* An error occurred in accessing the INI file or there was   */
        /* no information for this logical printer name. In either    */
        /* case just use the default printer type.                    */
        /**************************************************************/
        return (DEFAULT_PRINTER);
    }
    else
    {
        /**************************************************************/
        /* Now have the device description string for the logical     */
        /* printer name. This is of the form IBM 4201 Proprinter III  */
        /* on LPT1 and must be compared with the driver description   */
        /* string.                                                    */
        /*                                                            */
        /* Workaround. Need to scan the list backwards or whenever an */
        /* IBM 4201 Proprinter xxx is selected it will always match   */
        /* in IBM 4201 Proprinter. This way the longest description   */
        /* is compared against first.                                 */
        /**************************************************************/
        PrinterType = DEFAULT_PRINTER;

        for (i=NO_OF_PRINTERS; i; i--)
        {
            /**********************************************************/
            /* description string from the INI file can be edited by  */
            /* the User therefore may be smaller, if it is then there */
            /* is no point in even trying to match.                   */
            /**********************************************************/

            WinLoadString( hab,
                           DMData.HModule,
                           IDS_FIRST_PRINTER + i-1,
                           MAX_PRNTR_NAME,
                           (PSZ)Prntr_Name_Buf );


            /******************************************************/
            /* Now compare strings. The full DVT description      */
            /* string must be present in the INI string, but the  */
            /* extra text is ignored.                             */
            /******************************************************/
            if ( !prdu_strcmp(
                          pDeviceDesc,
                          Prntr_Name_Buf))
            {
                PrinterType = i-1;
                break;
            }

        }

        return (PrinterType);
    }
}
#undef TFUNC
#endif
