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.
506 lines
15 KiB
506 lines
15 KiB
/******************************** MODULE HEADER ****************************
|
|
* devcaps.c
|
|
* Implements the DrvDeviceCapabilities function - returns information
|
|
* about the printers capabilities.
|
|
*
|
|
*
|
|
* Copyright (C) 1993, Microsoft Corporation.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "rasuipch.h"
|
|
#pragma hdrstop("rasuipch.h")
|
|
#define GLOBAL_MACS
|
|
#include "gblmac.h"
|
|
#undef GLOBAL_MACS
|
|
|
|
/*
|
|
* The following sizes are copied from the Win 3.1 driver. They do not
|
|
* appear to be defined in any public place, although it looks like
|
|
* they should be.
|
|
*/
|
|
|
|
#define CCHBINNAME 24 /* Characters allowed for bin names */
|
|
#define CCHDEVNAME 64 /* Driver file name limits */
|
|
#define CDEPENDENTFILES 3 /* # of dependent files. */
|
|
#define CCHPAPERNAME 64 /* Max length of paper size names */
|
|
|
|
|
|
/*
|
|
* A couple of macros to turn master units into 0.1mm units - the
|
|
* value needed for some of these calls.
|
|
*/
|
|
|
|
#define MAST01mmX(xx) (((xx) * 254 + pdh->ptMaster.x / 2) / pdh->ptMaster.x)
|
|
#define MAST01mmY(yy) (((yy) * 254 + pdh->ptMaster.y / 2) / pdh->ptMaster.y)
|
|
|
|
|
|
|
|
/*
|
|
* Useful external variables that we use.
|
|
*/
|
|
|
|
extern HANDLE hHeap; /* For all our memory wants */
|
|
|
|
/*
|
|
* Local function prototypes.
|
|
*/
|
|
|
|
void
|
|
vGetBinNames(
|
|
int iCount,
|
|
short *psIndex,
|
|
WCHAR *pwchOut, /* Where the output is created */
|
|
PRASDDUIINFO pRasdduiInfo /* Rasddui UI data */
|
|
);
|
|
|
|
|
|
/******************************* Function Header *****************************
|
|
* DrvDeviceCapabilities
|
|
* Called by an application wanting to find out what this particular
|
|
* printer is able to do.
|
|
*
|
|
* RETURNS:
|
|
* -1 on error, else depends upon information requested.
|
|
*
|
|
* HISTORY:
|
|
* 15:09 on Tue 13 Apr 1993 -by- Lindsay Harris [lindsayh]
|
|
* First version, borrowed from Win 3.1
|
|
*
|
|
*****************************************************************************/
|
|
|
|
DWORD
|
|
DrvDeviceCapabilities( hPrinter, pDeviceName, iDevCap, pvOutput, pDMIn )
|
|
HANDLE hPrinter; /* Access to registry via spooler */
|
|
PWSTR pDeviceName; /* Particular printer model name */
|
|
WORD iDevCap; /* Capability required */
|
|
void *pvOutput; /* Output area (for some) */
|
|
DEVMODE *pDMIn; /* DEVMODE defining mode of operation etc */
|
|
{
|
|
|
|
|
|
int iI; /* Classic loop index */
|
|
int iCount; /* Count the number of items */
|
|
short *psIndex; /* For scanning arrays of offsets */
|
|
|
|
DWORD dwRet; /* Return value */
|
|
|
|
PRINTER_INFO PI; /* To set things up */
|
|
POINTw ptwSize; /* Win 3.1 POINT structure (2 shorts) */
|
|
|
|
EXTDEVMODE edm; /* Working copy of DEVMODE + */
|
|
EXTDEVMODE *pEDM; /* Access to the above, or what's passed in */
|
|
|
|
DOWNLOADINFO *pDLI; /* Check for download capabilities */
|
|
PAGECONTROL *pPageCtrl; /* Number of copies info */
|
|
PAPERSIZE *pSize;
|
|
long lTmp;
|
|
PRASDDUIINFO pRasdduiInfo = NULL; /* Common UI Data */
|
|
DWORD OEMResult = GDI_ERROR;
|
|
|
|
TRY
|
|
|
|
/*
|
|
* Note that the output area is one of many kinds, depending upon the
|
|
* type of information requested. To make the code cleaner, here
|
|
* are some macros to define different flavours of output area.
|
|
*/
|
|
|
|
#define psOutput ((short *)pvOutput)
|
|
#define pbOutput ((BYTE *)pvOutput)
|
|
#define pptOutput ((POINT *)pvOutput)
|
|
#define pdwOutput ((DWORD *)pvOutput)
|
|
#define pwchOutput ((WCHAR *)pvOutput)
|
|
|
|
/* Allocate the global data structure */
|
|
if (!(pRasdduiInfo = pGetUIInfo(hPrinter, pDMIn, ePrinter, eNoChange, eNoHelp)))
|
|
{
|
|
RASUIDBGP(DEBUG_ERROR,("Rasddui!DrvDeviceCapabilities: Allocation failed; pRasdduiInfo is NULL\n") );
|
|
return (DWORD)-1;
|
|
}
|
|
pEDM = pRasdduiInfo->pEDM;
|
|
|
|
//undefined the macro fGeneral to stop compilation error.
|
|
#if defined(fGeneral)
|
|
#undef fGeneral
|
|
#endif
|
|
|
|
/*
|
|
* Red tape is all processed, so now determine the information
|
|
* that the user requested!
|
|
*/
|
|
|
|
dwRet = (DWORD)-1; /* Default error return */
|
|
|
|
|
|
/* Call the OEM.
|
|
*/
|
|
OEMResult = OEMDrvDeviceCapabilities(pRasdduiInfo, hPrinter, pDeviceName, iDevCap, pvOutput, pDMIn);
|
|
|
|
/* DC_FIELDS. If the result is GDI_ERROR, null it out so the OR below has no effect.
|
|
*/
|
|
if (iDevCap == DC_FIELDS) {
|
|
if (OEMResult == GDI_ERROR) {
|
|
OEMResult = 0;
|
|
}
|
|
}
|
|
|
|
/* Not DC_FIELDS. Accept a good return and leave.
|
|
*/
|
|
else {
|
|
if (OEMResult != GDI_ERROR) {
|
|
dwRet = OEMResult;
|
|
LEAVE;
|
|
}
|
|
}
|
|
|
|
|
|
// initialize psize , we need to check fGeneral bit
|
|
pSize = GetTableInfo( pdh, HE_PAPERSIZE, pEDM );
|
|
|
|
switch( iDevCap )
|
|
{
|
|
case DC_FIELDS:
|
|
dwRet = (DWORD)pEDM->dm.dmFields | OEMResult;
|
|
break;
|
|
|
|
case DC_DUPLEX:
|
|
// return 1 if the printer is capable of duplex printing.
|
|
// Otherwise, return 0.
|
|
dwRet = (DWORD)(pEDM->dm.dmFields & DM_DUPLEX ? TRUE : FALSE);
|
|
break;
|
|
|
|
case DC_SIZE:
|
|
// return the size of DEVMODE structure.
|
|
dwRet = (DWORD)pEDM->dm.dmSize;
|
|
break;
|
|
|
|
case DC_EXTRA:
|
|
// return the size of DRIVEREXTRA structure.
|
|
dwRet = (DWORD)pEDM->dm.dmDriverExtra;
|
|
break;
|
|
|
|
case DC_VERSION:
|
|
dwRet = (DWORD)pEDM->dm.dmSpecVersion;
|
|
break;
|
|
|
|
case DC_DRIVER:
|
|
dwRet = (DWORD)pEDM->dm.dmDriverVersion;
|
|
break;
|
|
|
|
case DC_BINS: /* Paper bin IDs */
|
|
case DC_BINNAMES: /* Paper bin IDs and names */
|
|
|
|
psIndex = (short *)((BYTE *)pdh + pdh->loHeap +
|
|
pModel->rgoi[ MD_OI_PAPERSOURCE ]);
|
|
|
|
// count the # of items in the list.
|
|
for( iCount = 0; psIndex[iCount] != 0; iCount++ )
|
|
;
|
|
|
|
if( pvOutput )
|
|
{
|
|
/*
|
|
* An output area address, so put the data in there.
|
|
*/
|
|
|
|
switch( iDevCap )
|
|
{
|
|
case DC_BINS:
|
|
//Add the Form source as the first source; This psedo source
|
|
//maps to The Print Manager Setting for the forms for a
|
|
//given printer.
|
|
*psOutput++ = DMBIN_FORMSOURCE;
|
|
for( iI = 0; iI < iCount; iI++, ++psIndex )
|
|
{
|
|
PAPERSOURCE *pPS;
|
|
|
|
pPS = GetTableInfoIndex( pdh, HE_PAPERSOURCE,
|
|
*psIndex - 1 );
|
|
*psOutput++ = pPS->sPaperSourceID;
|
|
}
|
|
break;
|
|
|
|
case DC_BINNAMES:
|
|
vGetBinNames( iCount, psIndex, pvOutput,pRasdduiInfo );
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//Add a psedo source for every printer which will map to
|
|
//Printmanager setting for the Forms. So the driver report
|
|
//one extra source.
|
|
dwRet = (DWORD)iCount+1;
|
|
break;
|
|
|
|
case DC_PAPERS: /* Available forms by index numner */
|
|
case DC_PAPERNAMES: /* Paper sizes by name, order as DC_PAPERS */
|
|
case DC_PAPERSIZE: /* Paper sizes in units of 0.1mm */
|
|
dwRet = 0;
|
|
for( iI = 0; pFD[ iI ].pFI; iI++ )
|
|
{
|
|
/*
|
|
* Check that this form is suitable with this printer.
|
|
* This happens if ANY bit in dwSource is set.
|
|
*/
|
|
|
|
|
|
if( pFD[ iI ].dwSource )
|
|
{
|
|
/* Valid data, so up the count & copy the name (if needed) */
|
|
|
|
++dwRet; /* One more to return */
|
|
|
|
if( pvOutput )
|
|
{
|
|
/* Output is desired too! */
|
|
|
|
switch( iDevCap )
|
|
{
|
|
case DC_PAPERS:
|
|
*psOutput++ = iI + 1; /* These are 1 based */
|
|
break;
|
|
|
|
|
|
case DC_PAPERNAMES:
|
|
wcsncpy( pwchOutput, pFD[ iI ].pFI->pName, CCHPAPERNAME );
|
|
pwchOutput += CCHPAPERNAME;
|
|
break;
|
|
|
|
case DC_PAPERSIZE:
|
|
|
|
/* Convert from Master Units to 0.1mm */
|
|
pptOutput->x = MAST01mmX( pFD[ iI ].pFI->Size.cx );
|
|
pptOutput->y = MAST01mmY( pFD[ iI ].pFI->Size.cy );
|
|
|
|
// We need to consider PS_ROTATE bit in here
|
|
// Fixes a problem when printing on envelopes
|
|
|
|
if( pSize->fGeneral & PS_ROTATE )
|
|
{
|
|
lTmp = pptOutput->x;
|
|
pptOutput->x = pptOutput->y;
|
|
pptOutput->y = lTmp;
|
|
}
|
|
|
|
pptOutput++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case DC_MINEXTENT: /* Return minimum paper size allowed */
|
|
case DC_MAXEXTENT: /* Ditto, but maximum paper size */
|
|
|
|
if( iDevCap == DC_MINEXTENT )
|
|
{
|
|
ptwSize = pModel->ptMin; /* Minimum size, master units */
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Maximum size: there are several minor points to consider,
|
|
* namely that there is a no limit value that we turn into
|
|
* something else.
|
|
*/
|
|
|
|
ptwSize.x = pModel->sMaxPhysWidth; /* No question */
|
|
ptwSize.y = pModel->ptMax.y;
|
|
if( ptwSize.y == NOT_USED )
|
|
ptwSize.y = 0x7fff; /* Win 3.1 compatability */
|
|
}
|
|
dwRet = MAKELONG( MAST01mmX( ptwSize.x ), MAST01mmY( ptwSize.y ) );
|
|
break;
|
|
|
|
case DC_ENUMRESOLUTIONS:
|
|
/*
|
|
* Return the list of resolutions supported by the device.
|
|
* Each resolution is represented by a pair of DWORD's for
|
|
* the X and Y values respectively.
|
|
* If pvOutput is null, simply return the # of resolution supported.
|
|
*/
|
|
|
|
psIndex = (short *)((BYTE *)pdh + pdh->loHeap +
|
|
pModel->rgoi[ MD_OI_RESOLUTION ]);
|
|
|
|
/*
|
|
* Scan through the array of resolutions available for this
|
|
* printer. If there is an output area, then copy the results
|
|
* there as we go.
|
|
*/
|
|
|
|
for( iI = 0; psIndex[ iI ]; iI++ )
|
|
{
|
|
|
|
if( pvOutput )
|
|
{
|
|
/* Copy the numbers to the output area */
|
|
RESOLUTION *pRes;
|
|
|
|
pRes = GetTableInfoIndex( pdh, HE_RESOLUTION, psIndex[ iI ] - 1 );
|
|
|
|
*pdwOutput++ = (DWORD) ((pdh->ptMaster.x /
|
|
pRes->ptTextScale.x) >> pRes->ptScaleFac.x);
|
|
*pdwOutput++ = (DWORD) ((pdh->ptMaster.y /
|
|
pRes->ptTextScale.y) >> pRes->ptScaleFac.y);
|
|
}
|
|
|
|
}
|
|
dwRet = (DWORD)iI;
|
|
|
|
break;
|
|
|
|
|
|
case DC_FILEDEPENDENCIES:
|
|
#if 0
|
|
if (pvOutput)
|
|
{
|
|
lstrcpy(pvOutput, (LPSTR)szUnidrv);
|
|
pvOutput += CCHDEVNAME;
|
|
lstrcpy(pvOutput, (LPSTR)szDMColor);
|
|
pvOutput += CCHDEVNAME;
|
|
lstrcpy(pvOutput, (LPSTR)szUnihelp);
|
|
}
|
|
dwRet = (DWORD) CDEPENDENTFILES;
|
|
#else
|
|
dwRet = 0;
|
|
if( pwchOutput )
|
|
*pwchOutput = (WCHAR)0;
|
|
#endif
|
|
break;
|
|
|
|
case DC_TRUETYPE: /* What can we do with TrueType */
|
|
|
|
if( !(pEDM->dm.dmFields & DM_TTOPTION) )
|
|
{
|
|
// TrueType fonts are not available
|
|
dwRet = (DWORD) 0;
|
|
break;
|
|
}
|
|
|
|
|
|
#if defined( DCTT_DOWNLOAD ) || defined( DCTT_BITMAP )
|
|
pDLI = GetTableInfo( pdh, HE_DOWNLOADINFO, pEDM );
|
|
if (pDLI && pDLI->cbBitmapFontDescriptor == sizeof( SF_HEADER ) &&
|
|
!(pModel->fGeneral & MD_SERIAL) )
|
|
{
|
|
dwRet = (DWORD) (DCTT_BITMAP | DCTT_DOWNLOAD);
|
|
}
|
|
else
|
|
dwRet = (DWORD) DCTT_BITMAP;
|
|
#else
|
|
pDLI; /* Stop warning */
|
|
dwRet = 0;
|
|
#endif
|
|
|
|
break;
|
|
|
|
case DC_ORIENTATION:
|
|
// return the position of landscape relative (couterclock-wise)
|
|
// to portrait. "0" means no landscape orientation available.
|
|
// "90" is what seen on PCL page printers, and "270" is for
|
|
// dot-matirx printers.
|
|
|
|
|
|
if( pModel->fGeneral & MD_LANDSCAPE_RT90 )
|
|
dwRet = 90;
|
|
else
|
|
dwRet = 270;
|
|
break;
|
|
|
|
case DC_COPIES: /* Maximum number of copies we can print */
|
|
|
|
pPageCtrl = GetTableInfo( pdh, HE_PAGECONTROL, pEDM );
|
|
|
|
if( pPageCtrl )
|
|
dwRet = (DWORD)pPageCtrl->sMaxCopyCount;
|
|
else
|
|
dwRet = 1;
|
|
break;
|
|
|
|
#if 0
|
|
/* !!!LindsayH - what the hell is DC_BINADJUST??? */
|
|
case DC_BINADJUST:
|
|
{
|
|
PAPERSOURCE *pSrc;
|
|
|
|
pSrc = GetTableInfo( pdh, HE_PAPERSOURCE, pEDM );
|
|
if (pSrc->sBinAdjust >= DCBA_FIRST && pSrc->sBinAdjust <= DCBA_LAST)
|
|
dwRet = (DWORD) pSrc->sBinAdjust;
|
|
else
|
|
dwRet = (DWORD) -1;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
ENDTRY
|
|
|
|
FINALLY
|
|
vReleaseUIInfo(&pRasdduiInfo);
|
|
ENDFINALLY
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
|
|
/*************************** Function Header *********************************
|
|
* vGetBinNames
|
|
* Fills in the output area to contain the names of paper sources. These
|
|
* are returned as Unicode strings.
|
|
*
|
|
* RETURNS:
|
|
* Nothing.
|
|
*
|
|
* HISTORY:
|
|
* 10:53 on Wed 14 Apr 1993 -by- Lindsay Harris [lindsayh]
|
|
* Mark I, based on Win 3.1 code.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void
|
|
vGetBinNames(
|
|
int iCount,
|
|
short *psIndex,
|
|
WCHAR *pwchOut, /* Where the output is created */
|
|
PRASDDUIINFO pRasdduiInfo /* Rasddui UI data */
|
|
)
|
|
{
|
|
int iI; /* Loop index */
|
|
int iID; /* The paper source ID, turned into name */
|
|
|
|
PAPERSOURCE *pSource; /* To reference the data as we go along */
|
|
|
|
|
|
//Set first name of the source pseduo source which maps to
|
|
//Printman forms setting.
|
|
LoadStringW( hModule, SRC_FORMSOURCE, pwchOut, CCHBINNAME );
|
|
pwchOut += CCHBINNAME; /* Skip over this one */
|
|
|
|
for( iI = 0; iI < iCount && *psIndex; iI++, ++psIndex )
|
|
{
|
|
pSource = GetTableInfoIndex( pdh, HE_PAPERSOURCE, *psIndex - 1 );
|
|
iID = pSource->sPaperSourceID;
|
|
|
|
if( iID <= DMBIN_USER )
|
|
{
|
|
/* Standard name that we have */
|
|
LoadStringW( hModule, iID + SOURCE, pwchOut, CCHBINNAME );
|
|
}
|
|
else
|
|
{
|
|
/* Minidriver defined form name */
|
|
iLoadStringW( &WinResData, iID, pwchOut, CCHBINNAME);
|
|
}
|
|
|
|
pwchOut += CCHBINNAME; /* Skip over this one */
|
|
}
|
|
|
|
return;
|
|
}
|