Windows NT 4.0 source code leak
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

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