mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1107 lines
37 KiB
1107 lines
37 KiB
/******************************* Module Header ******************************
|
|
* devmode.c
|
|
* Functions used to check/get/default the EXTDEVMODE structure
|
|
* that is used to characterise the driver.
|
|
*
|
|
* HISTORY:
|
|
* 13:32 on Wed 01 May 1991 -by- Lindsay Harris [lindsayh]
|
|
* Functions moved from udenable.c; set up reasonable defaults.
|
|
*
|
|
* Copyright (C) 1991 - 1993, Microsoft Corporation
|
|
*
|
|
***************************************************************************/
|
|
|
|
|
|
#include <stddef.h>
|
|
#include <windows.h>
|
|
#include <winddi.h> /* EngGetPrinterData() */
|
|
|
|
#include <winres.h>
|
|
#include <libproto.h>
|
|
|
|
#include "win30def.h"
|
|
#include "udmindrv.h"
|
|
#include "udpfm.h"
|
|
#include "uddevice.h"
|
|
#include "udresrc.h"
|
|
#include "pdev.h"
|
|
#include <memory.h>
|
|
#include <string.h>
|
|
#include <winspool.h>
|
|
#include "stretch.h"
|
|
#include "udrender.h"
|
|
#include "udfnprot.h"
|
|
#include "regkeys.h"
|
|
#include <udproto.h>
|
|
#include <dm.h>
|
|
|
|
#include "rasdd.h"
|
|
#include "oem.h"
|
|
|
|
|
|
/* Private functions */
|
|
|
|
static BOOL bGetEDM( PDEV *, int iModel, MODELDATA*, PEDM );
|
|
|
|
|
|
BOOL bRegGetEDM( PDEV *, EXTDEVMODE *, HANDLE, DATAHDR *, MODELDATA *, INT );
|
|
void vSetPaperDetails( PDEV *, EXTDEVMODE * );
|
|
|
|
//Robmat, function added for WDL release Aug 1995
|
|
void vSetTextonlyCTT( PDEV *, signed short );
|
|
|
|
#if DBG
|
|
|
|
/* Debugging Flags */
|
|
|
|
#define DEBUG_VSETPAPERDETAILS 0x0001
|
|
#define DEBUG_VSETPAPERSIZE 0x0002
|
|
#define DEBUG_DEVMODE_TRACE_PP 0x0004
|
|
#define DEBUG_DEVMODE_ERROR 0x0008
|
|
#define DEBUG_DEFAULT 0x0000
|
|
|
|
void vPrintPaperSource(char *,char *,WORD);
|
|
|
|
#define GLOBAL_DEBUG_RASDD_DEVMODE_FLAGS gwDebugDevmode
|
|
|
|
/* Set to DEBUG_DEVMODE_ERROR after debugging */
|
|
//WORD GLOBAL_DEBUG_RASDD_DEVMODE_FLAGS = DEBUG_DEVMODE_TRACE_PP | DEBUG_DEVMODE_ERROR ;
|
|
|
|
WORD GLOBAL_DEBUG_RASDD_DEVMODE_FLAGS = DEBUG_DEVMODE_ERROR ;
|
|
#endif
|
|
|
|
/* Debugging Macrocs */
|
|
|
|
#if DBG
|
|
#define RASDDBGP(DbgType,Msg) \
|
|
if( GLOBAL_DEBUG_RASDD_DEVMODE_FLAGS & (DbgType) ) DbgPrint Msg
|
|
|
|
#else
|
|
#define RASDDBGP(DbgType,Msg)
|
|
#endif
|
|
|
|
|
|
|
|
/***************************** Function Header ****************************
|
|
* pGenerateEDM
|
|
* Amalgamate the various data sources to generate an ExtDevMode
|
|
* that reflects what is required for this printer/job.
|
|
*
|
|
* Uses library routine to construct from supplied devmode, then
|
|
* merges in private registry settings.
|
|
*
|
|
* RETURNS:
|
|
* Nothing, but fills in first PEDM.
|
|
*
|
|
* HISTORY:
|
|
* 14:29 on Thu 30 Apr 1992 -by- Lindsay Harris [lindsayh]
|
|
* Always set the paper size/source details.
|
|
*
|
|
* 14:55 on Fri 28 Jun 1991 -by- Lindsay Harris [lindsayh]
|
|
* Created now that pieces are fitting together
|
|
*
|
|
**************************************************************************/
|
|
|
|
PEDM
|
|
pGenerateEDM( pPDev, iModel, pEDMIn )
|
|
PDEV *pPDev; /* Printer name, etc */
|
|
int iModel; /* model number */
|
|
EXTDEVMODE *pEDMIn; /* Supplied by user, may be 0 or invalid */
|
|
{
|
|
PEDM pEDMOut = 0; /* Devmode to return */
|
|
PEDM pEDMRegistry = 0; /* Devmode constructed from registry */
|
|
DATAHDR *pDH = 0;
|
|
MODELDATA* pModel = 0;
|
|
HANDLE hModule = 0;
|
|
|
|
TRY
|
|
/* Use lib routine to build known good devmode from input.
|
|
*/
|
|
pDH = (DATAHDR*) pPDev->pGPCData;
|
|
pModel = GetTableInfoIndex( pDH, HE_MODELDATA, iModel);
|
|
hModule = ((WINRESDATA *) pPDev->pvWinResData)->uh.hMOD;
|
|
|
|
pEDMOut = (PEDM) pLibConstructDevModeFromSource(0 /* hHeap */,
|
|
pPDev->hPrinter,
|
|
pPDev->pstrModel,
|
|
iModel,
|
|
pModel->fGeneral,
|
|
pDH,
|
|
hModule,
|
|
OEMDEVMODEFN(pPDev),
|
|
(PDEVMODE) pEDMIn);
|
|
|
|
if (!pEDMOut) {
|
|
LEAVE;
|
|
}
|
|
|
|
/* Construct devmode from the registry. Copy devmode registry crossover stuff, including memory,
|
|
* flags, and font cartridge information.
|
|
*/
|
|
if (bGetEDM( pPDev, iModel, pModel, pEDMRegistry = pLibGetHardDefaultEDM(0 /* hHeap */,
|
|
pPDev->hPrinter, pPDev->pstrModel, iModel, pModel->fGeneral, pDH, hModule,
|
|
OEMDEVMODEFN(pPDev)))) {
|
|
|
|
int i;
|
|
|
|
pEDMOut->dx.dmMemory = pEDMRegistry->dx.dmMemory;
|
|
pEDMOut->dx.sFlags |= pEDMRegistry->dx.sFlags;
|
|
pEDMOut->dx.dmNumCarts = pEDMRegistry->dx.dmNumCarts;
|
|
for ( i = 0; i < pEDMRegistry->dx.dmNumCarts; i++ ) {
|
|
pEDMOut->dx.rgFontCarts[i] = pEDMRegistry->dx.rgFontCarts[i];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Also need to set the DRIVEREXTRA fields that match
|
|
* the specified FORM.
|
|
*/
|
|
vSetPaperDetails( pPDev, pEDMOut );
|
|
|
|
/*
|
|
* Set the resolution information to whatever the user requested,
|
|
* and using whatever method they prefer.
|
|
*/
|
|
vSetEDMRes( pEDMOut, ((UD_PDEV *)pPDev->pUDPDev)->pdh );
|
|
|
|
// Robmat, added for WDL release
|
|
// If the minidriver is a textonly driver we set the CTT by
|
|
// calling the vSetTextonlyCTT function
|
|
if (pDH->fTechnology == GPC_TECH_TTY)
|
|
vSetTextonlyCTT( pPDev, pEDMOut->dx.sCTT );
|
|
|
|
ENDTRY
|
|
|
|
FINALLY
|
|
if (pEDMRegistry) {
|
|
LibFree(pEDMRegistry);
|
|
}
|
|
ENDFINALLY
|
|
|
|
return(pEDMOut);
|
|
}
|
|
|
|
|
|
/******************************** Function Header ****************************
|
|
* bGetEDM
|
|
* Try to read the EXTDEVMODE data for this printer. If it cannot
|
|
* be found, set the default values.
|
|
*
|
|
* RETURNS:
|
|
* Nothing
|
|
*
|
|
* HISTORY:
|
|
* 14:34 on Wed 25 Mar 1992 -by- Lindsay Harris [lindsayh]
|
|
* Update to use registry - Ha!
|
|
*
|
|
* 16:01 on Fri 28 Jun 1991 -by- Lindsay Harris [lindsayh]
|
|
* Rewrite: use the printers.ini file (with SteveCat).
|
|
*
|
|
* 14:19 on Wed 01 May 1991 -by- Lindsay Harris [lindsayh]
|
|
* First version to set sensible defaults.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static BOOL
|
|
bGetEDM( pPDev, iModel, pModel, pEDM )
|
|
PDEV *pPDev;
|
|
int iModel;
|
|
MODELDATA *pModel;
|
|
PEDM pEDM;
|
|
{
|
|
DATAHDR *pDH; /* Limit information etc */
|
|
BOOL bReturn = FALSE;
|
|
|
|
/* pEDM comes in intialized to a good default devmode. No need
|
|
* to reinitialize.
|
|
*/
|
|
|
|
/*
|
|
* Match the model name (passed in at EnablePDEV time) to the data
|
|
* in the minidriver files. We have been careful to make sure that
|
|
* all the information required is available to us by the time we
|
|
* reach here.
|
|
*/
|
|
pDH = pPDev->pGPCData;
|
|
|
|
/*
|
|
* Get this printer's data from the registry, and see how good it is.
|
|
*/
|
|
if( bRegGetEDM( pPDev, pEDM, pPDev->hheap, pDH, pModel, iModel ) &&
|
|
bValidateDX( &pEDM->dx, pDH, iModel, TRUE ) )
|
|
{
|
|
|
|
#if DBG
|
|
int iI;
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("rasdd!bGetEDM: value of EDM.dx.dmMemory is %d \n",pEDM->dx.dmMemory) );
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("rasdd!bGetEDM: value of EDM.dx.sFlags is 0x%x \n",pEDM->dx.sFlags) );
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("rasdd!bGetEDM: value of EDM.dx.dmNumCarts is %d \n",pEDM->dx.dmNumCarts) );
|
|
for( iI = 0; iI < pEDM->dx.dmNumCarts; iI++ )
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("rasdd!bGetEDM: value of EDM.dx.rgFontCarts[%d] is %d \n",iI,
|
|
pEDM->dx.rgFontCarts[iI]) );
|
|
#endif
|
|
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
return(bReturn);
|
|
}
|
|
|
|
/************************** Function Header ******************************
|
|
* bRegGetEDM
|
|
* Get the DRIVEREXTRA data from the registry. Performs conversion
|
|
* from ASCII to binary, and does first order verification.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, FALSE being no data or unacceptable data.
|
|
*
|
|
* HISTORY:
|
|
* 22:00 on Sun 26 Mar 1995 -by- Ganesh Pandey [ganeshp]
|
|
* Added support for new registry keys
|
|
* 15:01 on Wed 25 Mar 1992 -by- Lindsay Harris [lindsayh]
|
|
* Start.
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
bRegGetEDM( pPDev, pEDM, hHeap, pdh, pModel, iModelNum )
|
|
PDEV *pPDev; /* Need for access to data */
|
|
EXTDEVMODE *pEDM; /* Area to fill in */
|
|
HANDLE hHeap; /* Heap Handle */
|
|
DATAHDR *pdh; /* Minidriver DataHeader entry pointer */
|
|
MODELDATA *pModel; /* Minidriver ModelData pointer */
|
|
INT iModelNum ; /* Model Number */
|
|
{
|
|
|
|
ULONG ul; /* Needs an address to pass to spooler */
|
|
DWORD dwType;
|
|
PFONTCARTMAP pFontCartMap = NULL; /* Font Cart Mapping Table */
|
|
INT NumAllCartridges = 0;/* Number of all Cartridges */
|
|
HANDLE hPrinter; /* Handle for access to printer data */
|
|
BOOL bRet = TRUE; /* Return Value */
|
|
WINRESDATA *pWinResData; /* Minidriver resource data access struct */
|
|
|
|
hPrinter = pPDev->hPrinter ;
|
|
pWinResData = (WINRESDATA *)pPDev->pvWinResData;
|
|
|
|
if ( bNewkeys(hPrinter) )
|
|
{
|
|
|
|
/* pEDM comes in intialized to good default data. No need to
|
|
* to reinitialize. Continue on and grab memory, font cartridge and
|
|
* flag data.
|
|
*/
|
|
|
|
/* bBuildFontCartTable allocates the FontCart Table. Caller should deallocate
|
|
* the pointer
|
|
*/
|
|
if ( !bBuildFontCartTable ( hHeap, &pFontCartMap, &NumAllCartridges,
|
|
pdh, pModel, pWinResData) )
|
|
{
|
|
if ( pFontCartMap )
|
|
{
|
|
HeapFree(hHeap, 0,pFontCartMap);
|
|
pFontCartMap = NULL;
|
|
}
|
|
if (NumAllCartridges)
|
|
{
|
|
#if DBG
|
|
DbgPrint("Rasdd!bRegGetEDM:Can't build FONTCARTMAP table, pFontCartMap is 0x%x !!\n",pFontCartMap?pFontCartMap:NULL);
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
/* Read Memory, Rasdd Flags and Font Carts, vDexDefault has been already
|
|
* Called in bGetEDM.
|
|
*/
|
|
|
|
if ( (bRet = ( bRegReadMemory(hPrinter, pEDM, pdh,pModel ) &&
|
|
bRegReadRasddFlags(hPrinter, pEDM) &&
|
|
bRegReadFontCarts(hPrinter, pEDM,hHeap,NumAllCartridges,
|
|
pFontCartMap) )))
|
|
;
|
|
|
|
/* Free the FontCartMap Buffer */
|
|
if ( pFontCartMap )
|
|
{
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasddui!bRegGetEDM: Freeing pFontCartMap = 0x%x\n",pFontCartMap?pFontCartMap:NULL));
|
|
HeapFree(hHeap, 0,pFontCartMap);
|
|
pFontCartMap = NULL;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ul = sizeof( EXTDEVMODE ); /* Memory size we have */
|
|
if( GetPrinterData( pPDev->hPrinter, PP_MAIN, &dwType,
|
|
(BYTE *)pEDM, sizeof( EXTDEVMODE ), &ul ) ||
|
|
ul < (ULONG)sizeof( EXTDEVMODE ) || pEDM->dx.sVer != DXF_VER )
|
|
{
|
|
return FALSE; /* No good: 0 means AOK return */
|
|
}
|
|
|
|
}
|
|
/*
|
|
* Is this data any good? Basically check on the version. The
|
|
* caller is presumed to do more serious checking.
|
|
*/
|
|
|
|
|
|
return ( bRet && (pEDM->dx.sVer == DXF_VER) ) ;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Some macros to make life easier for form matching.
|
|
*/
|
|
|
|
#define XTOMASTER( xx ) ((xx) = ((xx) * pdh->ptMaster.x + 12700) / 25400)
|
|
#define YTOMASTER( yy ) ((yy) = ((yy) * pdh->ptMaster.y + 12700) / 25400)
|
|
|
|
#define EQUAL( a, b ) (((a) - (b) < 10) && ((a) - (b) > -10))
|
|
|
|
/***************************** Function Header ******************************
|
|
* vSetPaperDetails
|
|
* Set the DRIVEREXTRA.rgindex[ HE_PAPERSIZE ] & ...[ HE_PAPERSOURCE ]
|
|
* fields from the EXTDEVMODE structure passed to us.
|
|
*
|
|
* RETURNS:
|
|
* Nothing
|
|
*
|
|
* HISTORY:
|
|
* 11:27 on Mon 05 Apr 1993 -by- Lindsay Harris [lindsayh]
|
|
* Handle the old cases: DM_PAPERSIZE or specific width/length.
|
|
*
|
|
* 14:29 on Thu 30 Apr 1992 -by- Lindsay Harris [lindsayh]
|
|
* Complete: now sets paper source data according to registry forms data
|
|
*
|
|
* 14:10 on Thu 09 Apr 1992 -by- Lindsay Harris [lindsayh]
|
|
* First version, now that functionality exists to use it.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void
|
|
vSetPaperDetails( pPDev, pEDM )
|
|
PDEV *pPDev; /* Access to spooler via engine */
|
|
EXTDEVMODE *pEDM; /* Forms details */
|
|
{
|
|
|
|
/*
|
|
* We are NOT called unless the dmPaperSize field is legitimate,
|
|
* as defined by the dmField value.
|
|
*/
|
|
|
|
short *ps; /* Scanning the PAPERSIZES */
|
|
short sUser; /* User defined form index, if applicable */
|
|
DWORD dw;
|
|
WCHAR *pbName; /* Fudge name for spooler */
|
|
int iI; /* Loop index */
|
|
|
|
FORM_INFO_1 *pFI1; /* Which one of the following to use */
|
|
FORM_INFO_1 *pFIBase = NULL;/* Address of allocated storage */
|
|
DATAHDR *pdh; /* GPC data base */
|
|
MODELDATA *pMD; /* MODELDATA for this printer */
|
|
PAPERSIZE *pPS; /* PAPERSIZE information */
|
|
DWORD dwType;
|
|
WCHAR * pwchHeapPtr = NULL ; /* Heap Pointer for TrayForm buffer,
|
|
Needed for Freeing */
|
|
|
|
HANDLE hHeap = NULL ; /* Heap Handle */
|
|
|
|
|
|
|
|
#if DBG
|
|
if (gwDebugDevmode & DEBUG_VSETPAPERDETAILS)
|
|
if (pEDM->dm.dmFields & DM_DEFAULTSOURCE)
|
|
{
|
|
DbgPrint("\nRasdd!vSetPaperDetails:DM_DEFAULTSOURCE Set, \n");
|
|
DbgPrint("Source in pEDM->dm.dmDefaultSource is ");
|
|
switch(pEDM->dm.dmDefaultSource)
|
|
{
|
|
case DMBIN_UPPER:
|
|
DbgPrint("DMBIN_UPPER\n");
|
|
break;
|
|
case DMBIN_LOWER:
|
|
DbgPrint("DMBIN_LOWER\n");
|
|
break;
|
|
case DMBIN_MIDDLE:
|
|
DbgPrint("DMBIN_MIDDLE\n");
|
|
break;
|
|
case DMBIN_MANUAL:
|
|
DbgPrint("DMBIN_MANUAL\n");
|
|
break;
|
|
case DMBIN_ENVELOPE:
|
|
DbgPrint("DMBIN_ENVELOPE\n");
|
|
break;
|
|
case DMBIN_ENVMANUAL:
|
|
DbgPrint("DMBIN_ENVMANUAL\n");
|
|
break;
|
|
case DMBIN_AUTO:
|
|
DbgPrint("DMBIN_AUTO\n");
|
|
break;
|
|
case DMBIN_TRACTOR:
|
|
DbgPrint("DMBIN_TRACTOR\n");
|
|
break;
|
|
case DMBIN_SMALLFMT:
|
|
DbgPrint("DMBIN_SMALLFMT\n");
|
|
break;
|
|
case DMBIN_LARGEFMT:
|
|
DbgPrint("DMBIN_LARGEFMT\n");
|
|
break;
|
|
case DMBIN_LARGECAPACITY:
|
|
DbgPrint("DMBIN_LARGECAPACITY\n");
|
|
break;
|
|
case DMBIN_CASSETTE:
|
|
DbgPrint("DMBIN_CASSETTE\n");
|
|
break;
|
|
case DMBIN_FORMSOURCE:
|
|
DbgPrint("DMBIN_FORMSOURCE\n");
|
|
break;
|
|
case DMBIN_USER:
|
|
DbgPrint("DMBIN_USER\n");
|
|
break;
|
|
|
|
default:
|
|
if (pEDM->dm.dmDefaultSource > DMBIN_USER)
|
|
{
|
|
DbgPrint("Driver Defined PaperSource,\n");
|
|
DbgPrint("\t\tValue of Index is %d\n",
|
|
pEDM->dm.dmDefaultSource);
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("Not a Valid one,Value of ");
|
|
DbgPrint("Index is %d\n",
|
|
pEDM->dm.dmDefaultSource);
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
DbgPrint("RASDD!vSetPaperDetails:DM_DEFAULTSOURCE Not Set, Value of dmFields is %x\n",pEDM->dm.dmFields);
|
|
#endif
|
|
|
|
#if DBG
|
|
if ( gwDebugDevmode & DEBUG_VSETPAPERSIZE)
|
|
{
|
|
if( pEDM->dm.dmFields & DM_PAPERSIZE )
|
|
{
|
|
DbgPrint("\nRasdd!vSetPaperDetails1:dmFields & DM_PAPERSIZE SET \n");
|
|
if (pEDM->dm.dmPaperSize == DMPAPER_USER)
|
|
{
|
|
DbgPrint("Rasdd!vSetPaperDetails1:dmPaperSize==DMPAPER_USER\n");
|
|
if ( pEDM->dm.dmFields & DM_PAPERLENGTH )
|
|
{
|
|
DbgPrint("Rasdd!vSetPaperDetails1:dmFields & DM_PAPERLENGTH SET \n");
|
|
DbgPrint("Rasdd!vSetPaperDetails1: dmPaperLength is %d\n",pEDM->dm.dmPaperLength);
|
|
}
|
|
if ( pEDM->dm.dmFields & DM_PAPERWIDTH )
|
|
{
|
|
DbgPrint("Rasdd!vSetPaperDetails1:dmFields & DM_PAPERWIDTH SET \n");
|
|
DbgPrint("Rasdd!vSetPaperDetails1: dmPaperWidth is %d\n",pEDM->dm.dmPaperWidth);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("Rasdd!vSetPaperDetails1: dmPaperSize is %d\n",pEDM->dm.dmPaperSize);
|
|
}
|
|
}
|
|
|
|
if ( pEDM->dm.dmFields & DM_PAPERLENGTH )
|
|
{
|
|
DbgPrint("\nRasdd!vSetPaperDetails1: dmFields & DM_PAPERLENGTH SET \n");
|
|
DbgPrint("Rasdd!vSetPaperDetails1: dmPaperLength is %d\n",pEDM->dm.dmPaperLength);
|
|
}
|
|
|
|
if ( pEDM->dm.dmFields & DM_PAPERWIDTH )
|
|
{
|
|
DbgPrint("Rasdd!vSetPaperDetails1: dmFields & DM_PAPERWIDTH SET \n");
|
|
DbgPrint("Rasdd!vSetPaperDetails1: dmPaperWidth is %d\n",pEDM->dm.dmPaperWidth);
|
|
|
|
}
|
|
DbgPrint("Rasdd!vSetPaperDetails1: dmFields is %x\n",pEDM->dm.dmFields);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* The spooler gives us the size of the form given it's name. Once
|
|
* we have the size, we can convert it to the relevant paper size
|
|
* structure, and we can also select the correct paper source.
|
|
*/
|
|
|
|
/*
|
|
* There are several variations on how to pick a size. In order
|
|
* of importance, if the DM_FORMNAME bit is set, use the form name
|
|
* contained in the DEVMODE. If not set, look at the DM_PAPERSIZE
|
|
* bit, which gives us an index into the paper size data returned
|
|
* from the spooler. Otherwise, look at the paper length and width,
|
|
* and use those values. If no good, then select the current default.
|
|
*/
|
|
|
|
if( (pEDM->dm.dmFields & (DM_FORMNAME | DM_PAPERSIZE)) == 0 &&
|
|
(pEDM->dm.dmFields & (DM_PAPERLENGTH | DM_PAPERWIDTH) !=
|
|
(DM_PAPERLENGTH | DM_PAPERWIDTH)) )
|
|
{
|
|
return; /* None specified, so leave as default */
|
|
}
|
|
|
|
|
|
|
|
dw = 0; /* Storage size: non allocated yet! */
|
|
|
|
/*
|
|
* NOTE that the sequence of steps here is deliberate. We use the
|
|
* form name IFF there is no other information about the size. This
|
|
* is because old apps will not know about the form name field, and
|
|
* so will not use it. But they will change the papersize field,
|
|
* meaning we may have a DEVMODE with form name and paper size that
|
|
* disagree. (This is because we supply a default DEVMODE with
|
|
* all the fields set, while the app changes only those it knows).
|
|
*/
|
|
|
|
if ( (pEDM->dm.dmFields & DM_FORMNAME)
|
|
&& (!(pEDM->dm.dmFields & (DM_PAPERSIZE |
|
|
DM_PAPERLENGTH |
|
|
DM_PAPERWIDTH))) ){
|
|
|
|
/* An explicit form name - ask the spooler for it's details! */
|
|
pbName = pEDM->dm.dmFormName;
|
|
|
|
GetForm( pPDev->hPrinter, pbName, 1, NULL, 0, &dw );
|
|
if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
#if DBG
|
|
DbgPrint( "Rasdd!vSetPaperDetails: GetForm returns error %ld\n",
|
|
GetLastError() );
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
pFIBase = pFI1 = (FORM_INFO_1 *)HeapAlloc( pPDev->hheap, 0, dw );
|
|
|
|
if( pFI1 == NULL )
|
|
return; /* SHOULD NOT HAPPEN */
|
|
|
|
if( !GetForm( pPDev->hPrinter, pbName, 1, (BYTE *)pFI1, dw, &dw ) )
|
|
{
|
|
/* Didn't get the form, so match to printer's paper sizes */
|
|
|
|
return; /* Use the default, hope for the best! */
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Either a form index OR a size is specified. In either case,
|
|
* we ask the spooler for the list of forms, and match on what
|
|
* is available.
|
|
*/
|
|
|
|
DWORD cReturned; /* Number of forms returned */
|
|
|
|
|
|
if( !EnumForms( pPDev->hPrinter, 1, NULL, 0, &dw, &cReturned ) )
|
|
{
|
|
if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
if( pFIBase = (FORM_INFO_1 *)HeapAlloc( pPDev->hheap, 0, dw ) )
|
|
{
|
|
if( !EnumForms( pPDev->hPrinter, 1, (BYTE *)pFIBase,
|
|
dw, &dw, &cReturned ) )
|
|
{
|
|
HeapFree( pPDev->hheap, 0, (LPSTR)pFIBase );
|
|
|
|
return; /* Not much we can do here */
|
|
}
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
else
|
|
return; /* SHOULD NEVER HAPPEN!! */
|
|
|
|
|
|
/*
|
|
* All is well, so now look at what we have. If the DM_PAPERSIZE
|
|
* field is set, then simply index the data we have from the
|
|
* spooler, otherwise look through it for a matching form size.
|
|
*/
|
|
|
|
if( pEDM->dm.dmFields & DM_PAPERSIZE )
|
|
{
|
|
/* Use the index to check! */
|
|
|
|
iI = pEDM->dm.dmPaperSize - DMPAPER_FIRST;
|
|
|
|
if( iI < 0 || iI >= (int)cReturned )
|
|
{
|
|
/* Out of range, so use the default */
|
|
|
|
HeapFree( pPDev->hheap, 0, (LPSTR)pFIBase );
|
|
|
|
return;
|
|
}
|
|
|
|
pFI1 = pFIBase + iI; /* Used later to find numbers */
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Scan, looking for a match on sizes */
|
|
|
|
for( pFI1 = pFIBase, iI = 0; iI < (int)cReturned; ++iI, ++pFI1 )
|
|
{
|
|
|
|
|
|
#define DM_MATCH( dm, sp ) ((((sp) + 50) / 100 - dm) < 15 && (((sp) + 50) / 100 - dm) > -15)
|
|
/* Convert to our units */
|
|
|
|
if( DM_MATCH( pEDM->dm.dmPaperWidth, pFI1->Size.cx ) &&
|
|
DM_MATCH( pEDM->dm.dmPaperLength, pFI1->Size.cy ) )
|
|
{
|
|
/* Found it, so off we go */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( iI >= (int)cReturned )
|
|
{
|
|
HeapFree( pPDev->hheap, 0, (LPSTR)pFIBase );
|
|
return; /* No match, so use default */
|
|
}
|
|
}
|
|
|
|
pbName = pFI1->pName;
|
|
}
|
|
|
|
|
|
/*
|
|
* To do some of the forms operations, we need the MODELDATA structure
|
|
* for this printer. This allows us to convert the spooler form sizes
|
|
* (units of 1e-6 metres) to the master units that our data contains.
|
|
* Then we can plough on regardless.
|
|
*/
|
|
|
|
pdh = pPDev->pGPCData;
|
|
|
|
if( !(pMD = GetTableInfo( pdh, HE_MODELDATA, pEDM )) )
|
|
{
|
|
HeapFree( pPDev->hheap, 0, (LPSTR)pFI1 );
|
|
|
|
return; /* Use whatever we have */
|
|
}
|
|
|
|
/*
|
|
* Set the width values into the DEVMODE, in case a user defined form
|
|
* is required for this size.
|
|
*/
|
|
|
|
pEDM->dm.dmPaperWidth = (pFI1->Size.cx + 50) / 100;
|
|
pEDM->dm.dmPaperLength = (pFI1->Size.cy + 50) / 100;
|
|
|
|
|
|
/* Convert to our units */
|
|
XTOMASTER( pFI1->Size.cx );
|
|
YTOMASTER( pFI1->Size.cy );
|
|
|
|
/* Got the form, so match to printer's paper sizes */
|
|
|
|
|
|
ps = (short *)((BYTE *)pdh + pdh->loHeap +
|
|
pMD->rgoi[ MD_OI_PAPERSIZE ] );
|
|
|
|
|
|
|
|
/* Assign the first value, in case we do not find a match */
|
|
pEDM->dx.rgindex[ HE_PAPERSIZE ] = (short)(*ps - 1);
|
|
sUser = -1; /* Illegal value */
|
|
|
|
for( ; *ps; ++ps )
|
|
{
|
|
pPS = GetTableInfoIndex( pdh, HE_PAPERSIZE, *ps - 1 );
|
|
if( pPS == NULL )
|
|
continue; /* SHOULD NOT HAPPEN */
|
|
|
|
/* If this size matches, then use it! */
|
|
if( EQUAL( pFI1->Size.cx, pPS->ptSize.x ) &&
|
|
EQUAL( pFI1->Size.cy, pPS->ptSize.y ) )
|
|
{
|
|
/* Bingo: save this in DRIVEREXTRA! */
|
|
pEDM->dx.rgindex[ HE_PAPERSIZE ] = (short)(*ps - 1);
|
|
|
|
#if DBG
|
|
if ( gwDebugDevmode & DEBUG_VSETPAPERSIZE)
|
|
{
|
|
DbgPrint("\nRasdd!vSetPaperDetails:Standard PaperSize Match\n");
|
|
DbgPrint("Rasdd!vSetPaperDetails: Setting Standard ");
|
|
DbgPrint("form,Name is %ws\n", pFI1->pName);
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
|
|
if( pPS->sPaperSizeID == DMPAPER_USER )
|
|
{
|
|
/* User defined forms have size limits and that's that. */
|
|
if( pFI1->Size.cx >= pMD->ptMin.x &&
|
|
pFI1->Size.cy >= pMD->ptMin.y &&
|
|
pFI1->Size.cx <= pMD->ptMax.x &&
|
|
((pMD->ptMax.y == -1 )?TRUE:pFI1->Size.cy
|
|
<= pMD->ptMax.y) )
|
|
{
|
|
/* Remember this in case there is no other match */
|
|
sUser = *ps - 1;
|
|
|
|
#if DBG
|
|
if ( gwDebugDevmode & DEBUG_VSETPAPERSIZE)
|
|
{
|
|
DbgPrint("Rasdd!vSetPaperDetails: Setting user defined ");
|
|
DbgPrint("form,Name is %ws\n", pFI1->pName);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
if( *ps == 0 )
|
|
{
|
|
/*
|
|
* If sUser is >= 0, then set the user defined form!
|
|
*/
|
|
|
|
if( sUser >= 0 )
|
|
{
|
|
pEDM->dx.rgindex[ HE_PAPERSIZE ] = sUser;
|
|
|
|
/* MUST also set the paper size fields in the DEVMODE for later */
|
|
}
|
|
#if DBG
|
|
else
|
|
DbgPrint( "Rasdd!vSetPaperDetails: form '%ws' has no size match\n",
|
|
pbName );
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Now need to find the corresponding source. The data is
|
|
* stored in the registry, and the digit on the end of the
|
|
* entry name is an index into the array of data in the GPC heap.
|
|
*/
|
|
|
|
ps = (short *)((BYTE *)pdh + pdh->loHeap +
|
|
pMD->rgoi[ MD_OI_PAPERSOURCE ] );
|
|
|
|
/* Assign the first value as default, in case the match fails */
|
|
pEDM->dx.rgindex[ HE_PAPERSOURCE ] = *ps - 1;
|
|
|
|
//Try using User preferred Source
|
|
if ((pEDM->dm.dmFields & DM_DEFAULTSOURCE) &&
|
|
(pEDM->dm.dmDefaultSource != DMBIN_FORMSOURCE) )
|
|
{
|
|
PPAPERSOURCE pPaperSource;
|
|
|
|
//Try going through the mindriver papersource list, and find the
|
|
//papersource whose id mathches with dmDefaultSource
|
|
for( ; *ps; ++ps )
|
|
{
|
|
// Subtract one to make the value 0 based
|
|
pPaperSource = GetTableInfoIndex( pdh, HE_PAPERSOURCE,*ps - 1);
|
|
|
|
#if DBG
|
|
vPrintPaperSource("vSetPaperDetails","pPaperSource",
|
|
pPaperSource->sPaperSourceID);
|
|
#endif
|
|
|
|
//Found the match
|
|
if (pPaperSource->sPaperSourceID == pEDM->dm.dmDefaultSource)
|
|
{
|
|
pEDM->dx.rgindex[ HE_PAPERSOURCE ] = *ps - 1;
|
|
|
|
#if DBG
|
|
vPrintPaperSource("vSetPaperDetails",
|
|
"pEDM->dx.rgindex[HE_PAPERSOURCE]",
|
|
pPaperSource->sPaperSourceID);
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else //Use Forms
|
|
{
|
|
|
|
WCHAR awchFormName[ MAXFORMNAMELEN ]; /* Form Name */
|
|
WCHAR awchTrayName[ MAXPAPSRCNAMELEN ]; /* Local Buffer for Tray name */
|
|
WCHAR awchSelectStr[ MAXSELSTRLEN ] ; /* Select String */
|
|
WCHAR awchRegName[ 64 ];
|
|
ULONG ul;
|
|
int iRemBuffSize = 0 ; /* Used size of the Buffer */
|
|
WCHAR * pwchBuffPtr = NULL ; /* Current buffer Pointer */
|
|
DWORD dwErrCode = 0; /* Error Code from GetPrinterData */
|
|
HANDLE hPrinter = NULL; /* Printer Handle */
|
|
DWORD cbNeeded; /* Extra parameter to GetPrinterData */
|
|
|
|
hPrinter = pPDev->hPrinter; /* Printer Handle */
|
|
hHeap = pPDev->hheap ;
|
|
|
|
if ( bNewkeys(hPrinter) )
|
|
{
|
|
dwType = REG_MULTI_SZ;
|
|
|
|
if( ( dwErrCode = GetPrinterData( hPrinter, PP_TRAYFORMTABLE,
|
|
&dwType, (BYTE *)pwchBuffPtr,
|
|
0, &cbNeeded ) )
|
|
!= ERROR_SUCCESS )
|
|
{
|
|
|
|
if( (dwErrCode != ERROR_INSUFFICIENT_BUFFER) &&
|
|
(dwErrCode != ERROR_MORE_DATA) )
|
|
{
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_ERROR,( "Rasdd!vSetPaperDetails:GetPrinterData(Trayforms First Call) fails: errcode = %ld\n",dwErrCode) );
|
|
|
|
SetLastError(dwErrCode);
|
|
goto ErrorHandler ;
|
|
}
|
|
else if(!(pwchHeapPtr = pwchBuffPtr = (WCHAR *)HeapAlloc( hHeap, HEAP_ZERO_MEMORY, cbNeeded )) )
|
|
{
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_ERROR,("Rasdd!vSetPaperDetails:HeapAlloc(Trayforms) failed\n") );
|
|
goto ErrorHandler ;
|
|
}
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("\nRasdd!vSetPaperDetails:Size of buffer needed = %d\n",cbNeeded));
|
|
|
|
if( ( dwErrCode = GetPrinterData( hPrinter, PP_TRAYFORMTABLE, &dwType, (BYTE *)pwchBuffPtr,
|
|
cbNeeded, &cbNeeded ) ) != ERROR_SUCCESS )
|
|
{
|
|
RASDDBGP(DEBUG_DEVMODE_ERROR,( "Rasdd!vSetPaperDetails:GetPrinterData(Trayforms Second Call) fails: errcode = %ld\n",dwErrCode));
|
|
|
|
SetLastError(dwErrCode);
|
|
goto ErrorHandler ;
|
|
}
|
|
|
|
}
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasdd!vSetPaperDetails:Size of buffer read = %d\n",cbNeeded));
|
|
|
|
/* iRemBuffSize is number of WCHAR */
|
|
iRemBuffSize = cbNeeded / sizeof(WCHAR);
|
|
|
|
for( iI = 0; *ps; ++iI, ++ps )
|
|
{
|
|
|
|
ZeroMemory(awchFormName,sizeof(awchFormName) );
|
|
ZeroMemory(awchTrayName,sizeof(awchTrayName) );
|
|
ZeroMemory(awchSelectStr,sizeof(awchSelectStr) );
|
|
|
|
if( iRemBuffSize)
|
|
{
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("\nRasdd!vSetPaperDetails:PaperSrcName in buffer = %ws\n",pwchBuffPtr));
|
|
vGetFromBuffer(awchTrayName,&pwchBuffPtr,&iRemBuffSize);
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasdd!vSetPaperDetails:Retrieved PaperSrcName = %ws\n",awchTrayName));
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasdd!vSetPaperDetails:FormName in buffer = %ws\n",pwchBuffPtr));
|
|
vGetFromBuffer(awchFormName,&pwchBuffPtr,&iRemBuffSize);
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasdd!vSetPaperDetails:Retrieved FormName = %ws\n",awchFormName));
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasdd!vSetPaperDetails:Select string in buffer = %ws\n",pwchBuffPtr));
|
|
vGetFromBuffer(awchSelectStr,&pwchBuffPtr,&iRemBuffSize);
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasdd!vSetPaperDetails:Retrieved Select String is %ws\n",awchSelectStr));
|
|
|
|
}
|
|
else
|
|
{
|
|
RASDDBGP(DEBUG_DEVMODE_ERROR,("Rasdd!vSetPaperDatails: Unexpected End of TrayFormTable, Using default papersrc\n"));
|
|
continue;
|
|
}
|
|
|
|
/* Got a name, so scan the forms data for this one. */
|
|
|
|
/* If the names match, BINGO, we have a source too! */
|
|
if( wcscmp( awchFormName, pbName ) == 0 )
|
|
{
|
|
/* Got it! */
|
|
pEDM->dx.rgindex[ HE_PAPERSOURCE ] = *ps - 1;
|
|
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("Rasdd!vSetPaperDetails:Using forms to set PaperSource,\n"));
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("\t\tMinidriver PaperSource index is %d\n",*ps));
|
|
RASDDBGP(DEBUG_DEVMODE_TRACE_PP,("\t\tMinidriver PaperSource Name is %ws\n",awchTrayName));
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwType = REG_SZ; /* String data for form names */
|
|
/* Old Registry Keys */
|
|
for( iI = 0; *ps; ++iI, ++ps )
|
|
{
|
|
iDrvPrintfW( awchRegName, PP_PAP_SRC, iI );
|
|
if( !GetPrinterData( pPDev->hPrinter, awchRegName, &dwType,
|
|
(BYTE *)awchFormName, sizeof( awchFormName ), &ul ) )
|
|
{
|
|
/* If the names match, BINGO, we have a source too! */
|
|
if( wcscmp( awchFormName, pbName ) == 0 )
|
|
{
|
|
/* Got it! */
|
|
pEDM->dx.rgindex[ HE_PAPERSOURCE ] = *ps - 1;
|
|
|
|
#if DBG
|
|
if (gwDebugDevmode & DEBUG_VSETPAPERDETAILS)
|
|
{
|
|
DbgPrint("Rasdd!vSetPaperDetails:Using forms to set PaperSource,\n");
|
|
DbgPrint("\t\tMinidriver PaperSource index is %d\n",*ps);
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
}
|
|
#if DBG
|
|
else
|
|
DbgPrint( "Rasdd!vSetPaperDetails: GetPrinterData( %ws ) fails\n", awchRegName );
|
|
#endif
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if( *ps == 0 )
|
|
DbgPrint( "Rasdd!vSetPaperDetails: form '%ws' not installed\n", pbName );
|
|
#endif
|
|
|
|
ErrorHandler:
|
|
/* Free The Form Database */
|
|
if(pFIBase)
|
|
{
|
|
HeapFree( pPDev->hheap, 0, (LPSTR)pFIBase );
|
|
pFIBase = NULL;
|
|
}
|
|
|
|
/* Free the TrayBin Buffer */
|
|
if( pwchHeapPtr )
|
|
{
|
|
HeapFree( hHeap, 0, (LPSTR)pwchHeapPtr );
|
|
pwchHeapPtr = NULL;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#if DBG
|
|
void vPrintPaperSource(pcCalledFrom,pcDataTypeName,wPaperSource)
|
|
char * pcCalledFrom;
|
|
char * pcDataTypeName;
|
|
WORD wPaperSource;
|
|
{
|
|
|
|
if (gwDebugDevmode & DEBUG_VSETPAPERDETAILS)
|
|
{
|
|
//DbgPrint("RASDD!vSetPaperDetails:DM_DEFAULTSOURCE Set in EDM.dx, \n");
|
|
DbgPrint("Rasdd!%s: ",pcCalledFrom);
|
|
DbgPrint("Source in %s is ",pcDataTypeName);
|
|
switch(wPaperSource)
|
|
{
|
|
case DMBIN_UPPER:
|
|
DbgPrint("DMBIN_UPPER\n");
|
|
break;
|
|
case DMBIN_LOWER:
|
|
DbgPrint("DMBIN_LOWER\n");
|
|
break;
|
|
case DMBIN_MIDDLE:
|
|
DbgPrint("DMBIN_MIDDLE\n");
|
|
break;
|
|
case DMBIN_MANUAL:
|
|
DbgPrint("DMBIN_MANUAL\n");
|
|
break;
|
|
case DMBIN_ENVELOPE:
|
|
DbgPrint("DMBIN_ENVELOPE\n");
|
|
break;
|
|
case DMBIN_ENVMANUAL:
|
|
DbgPrint("DMBIN_ENVMANUAL\n");
|
|
break;
|
|
case DMBIN_AUTO:
|
|
DbgPrint("DMBIN_AUTO\n");
|
|
break;
|
|
case DMBIN_TRACTOR:
|
|
DbgPrint("DMBIN_TRACTOR\n");
|
|
break;
|
|
case DMBIN_SMALLFMT:
|
|
DbgPrint("DMBIN_SMALLFMT\n");
|
|
break;
|
|
case DMBIN_LARGEFMT:
|
|
DbgPrint("DMBIN_LARGEFMT\n");
|
|
break;
|
|
case DMBIN_LARGECAPACITY:
|
|
DbgPrint("DMBIN_LARGECAPACITY\n");
|
|
break;
|
|
case DMBIN_CASSETTE:
|
|
DbgPrint("DMBIN_CASSETTE\n");
|
|
break;
|
|
case DMBIN_FORMSOURCE:
|
|
DbgPrint("DMBIN_FORMSOURCE\n");
|
|
break;
|
|
case DMBIN_USER:
|
|
DbgPrint("DMBIN_USER\n");
|
|
break;
|
|
default:
|
|
if (wPaperSource > DMBIN_USER)
|
|
{
|
|
DbgPrint("Driver Defined PaperSource,\n");
|
|
DbgPrint("\t\tValue of Index is %d\n", wPaperSource);
|
|
}
|
|
else
|
|
DbgPrint("Not a Valid one,Value of PaperSource is %d\n",
|
|
wPaperSource);
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
//DbgPrint("RASDD!vSetPaperDetails:DM_DEFAULTSOURCE Not Set, Value of dmFields is %x\n",pEDM->dm.dmFields);
|
|
}
|
|
#endif
|
|
|
|
/************************* Function Header *********************************
|
|
* vSetTextonlyCTT
|
|
* Check in the registry for our CTT index, If this index differs
|
|
* from the MODELDATA's sDefaultCTT so we will replace the MODELDATA
|
|
* value with the value we have got from the registry.
|
|
* If the registry contains a zero for CTT we do nothing so the
|
|
* drivers default CTT from MODELDATA is used.
|
|
*
|
|
* RETURNS:
|
|
* nothing
|
|
*
|
|
* HISTORY:
|
|
* 10:00 on Fri 04 Jun 1995 -by- Robert Matysek [Robmat]
|
|
* First incarnation.
|
|
*
|
|
***************************************************************************/
|
|
|
|
void
|
|
vSetTextonlyCTT( pPDev, iCTT )
|
|
PDEV *pPDev; /* Printer name, etc */
|
|
signed short iCTT; /* CTT value, valid are 0, -1, -2, -3 */
|
|
{
|
|
|
|
if ( iCTT != 0 )
|
|
((UD_PDEV*)(pPDev->pUDPDev))->sDefCTT = iCTT;
|
|
}
|
|
|