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.
 
 
 
 
 
 

1378 lines
38 KiB

/******************************* MODULE HEADER *******************************
* dm.c
*
* OEM devmode related functions.
*
*
* Copyright (C) 1996 Microsoft Corporation.
*
****************************************************************************/
#include <precomp.h>
#include <winres.h>
#include <windows.h>
#include <winspool.h>
#include <winddi.h>
#include <winddiui.h>
#include <libproto.h>
#include <udmindrv.h>
#include <udresrc.h>
#include <memory.h>
#include <udproto.h>
#include <oemdm.h>
#include "rasdd.h"
#include "dm.h"
#include "libedge.h"
/***************************** Function Header ****************************
* vScanOutBadDevModeValues
* This function checks for input Devmode Values and if they are
* bad, replaces them with default values.
*
* RETURNS:
* Check for the input value and if bad fills in the default value.
*
* HISTORY:
*
* 14:55 on Wed April 5th 1995 -by- Ganesh Pandey[ganeshp]
* Created
*
* 7/31/96 - Moved here from Rasdd. Jason Staczek
*
**************************************************************************/
void
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, wMDoiValue, wValue )
DATAHDR* pDH; /* GPC data */
int iModel; /* Printer model */
EXTDEVMODE *pEDMDefault; /* Default data */
EXTDEVMODE *pEDMIn; /* Suspect data to be repaired*/
WORD wMDoiValue; /* Minidriver index Value */
WORD wValue; /* Devmode Value to be tested */
{
MODELDATA *pModel; /* Minidriver ModelData pointer */
short *psInd; /* Index array in GPC heap */
BOOL bMatch = FALSE;
pModel = GetTableInfoIndex( pDH, HE_MODELDATA, iModel );
/* Scan out bad input devmode values */
psInd = (short *)((BYTE *)pDH + pDH->loHeap + pModel->rgoi[ wMDoiValue ]);
if(!*psInd) // Input value is not supported.
{
if ( pEDMIn->dx.rgindex[ wValue ] != -1 )
{
/*Paper Quality not supported */
pEDMIn->dx.rgindex[ wValue ] = -1;
}
}
else
{
for( ; *psInd; psInd++ )
{
/* The value in devmode is 0 based and the minidriver list is
* one base. One is added to make the value one based.
*/
if( (int)*psInd == ( pEDMIn->dx.rgindex[ wValue ] + 1 ) )
{
bMatch = TRUE;
break;
}
}
/* If the input devmode value is not one of the supported ones,
* set the value to default.
*/
if (!bMatch)
pEDMIn->dx.rgindex[ wValue ] = pEDMDefault->dx.rgindex[ wValue ];
}
}
/***************************** Function Header ****************************
* vReplaceBadDMValuesWithDefaults
*
* A wrapper around ScanOutBadDevmodeValues. This was pulled from
* rasdd\devmode.c. Checks and repairs a variety of GPC values.
*
* RETURNS:
*
* None
*
* HISTORY:
*
**************************************************************************/
void
vReplaceBadDMValuesWithDefaults(pDH, iModel, pEDMDefault, pEDMIn)
DATAHDR* pDH; /* GPC data */
int iModel; /* Printer model */
EXTDEVMODE *pEDMDefault; /* Default data */
EXTDEVMODE *pEDMIn; /* Suspect data to be repaired */
{
/* Scan Out Bad Resoulution and PaperQuality. pEDMOut has the default
* Values for HE_RESOLUTION & HE_PAPERQUALITY
*/
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_RESOLUTION, HE_RESOLUTION );
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_PAPERQUALITY,HE_PAPERQUALITY );
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_COLOR,HE_COLOR );
// added by DerryD, July 95 for WDL release
//
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_PAPERDEST,HE_PAPERDEST );
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_TEXTQUAL,HE_TEXTQUAL );
if (!(pDH->wVersion < GPC_VERSION3 ))
{
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_PRINTDENSITY,HE_PRINTDENSITY );
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_IMAGECONTROL,HE_IMAGECONTROL );
}
vScanOutBadDevModeValues(pDH, iModel, pEDMDefault, pEDMIn, MD_OI_COLOR,HE_COLOR );
}
/**************************** Function Header ********************************
* LibFree
*
* RETURNS:
* None.
*
*
* HISTORY:
*****************************************************************************/
#ifdef NTGDIKM
void
LibFree(
void* pmem)
{
LIBFREE(0, 0, pmem);
}
#else
void
LibFree(
HANDLE hHeap,
DWORD flags,
void* pmem)
{
LIBFREE(hHeap, flags, pmem);
}
#endif /* NTGDIKM */
/**************************** Function Header ********************************
* dwGetDMSize
*
* RETURNS:
* (DRIVEREXTRA*) Given a devmode, returns a pointer to driver extra
* portion.
*
* HISTORY:
*
*****************************************************************************/
DWORD
dwGetDMSize(
PDEVMODE pdm)
{
return(pdm ? pdm->dmSize + pdm->dmDriverExtra: 0);
}
/**************************** Function Header ********************************
* pGetDriverExtra
*
* RETURNS:
* (DRIVEREXTRA*) Given a devmode, returns a pointer to driver extra
* portion.
*
* HISTORY:
*
*****************************************************************************/
DRIVEREXTRA *
pGetDriverExtra(
PDEVMODE pdmDest)
{
return(pdmDest && pdmDest->dmDriverExtra != 0 ?
(DRIVEREXTRA*) ((PBYTE) pdmDest + pdmDest->dmSize) : 0);
}
/**************************** Function Header ********************************
* dwCurrentGetRasddExtraSize
*
* RETURNS:
* (DWORD) Size of Rasdd's devmode, excluding OEM's extra data.
*
* HISTORY:
*
*****************************************************************************/
DWORD
dwGetCurrentRasddExtraSize(
void)
{
return(sizeof(DRIVEREXTRA));
}
/**************************** Function Header ********************************
* dwGetRasddExtraSize
*
* RETURNS:
* (DWORD) Size of rasdd extra data in supplied devmode, excluding andy
* OEM extra data.
*
* HISTORY:
*
*****************************************************************************/
DWORD
dwGetRasddExtraSize(
PDEVMODE pdm)
{
DRIVEREXTRA* pDX = pGetDriverExtra(pdm);
DWORD dwSize = 0;
if (pDX) {
/* Must check version of driver extra. There was no dmSize field before
* MIN_ODM_DXF_VER. Sanity check this by making sure that dmDriverExtra
* is equal to what we think rasdd and oem extra is.
*/
if (pDX->sVer >= MIN_OEM_DXF_VER) {
if (pdm->dmDriverExtra == pDX->dmSize + pDX->dmOEMDriverExtra) {
dwSize = pDX->dmSize;
}
}
else {
dwSize = pdm->dmDriverExtra;
}
}
return(dwSize);
}
/**************************** Function Header ********************************
* pGetOEMExtra
*
* Given a DEVMODE, returns a pointer to the top of OEM extra data.
*
* RETURNS:
* (void*) Pointer to OEM portion of devmode.
*
* HISTORY:
*
*****************************************************************************/
PDMEXTRAHDR
pGetOEMExtra(
DEVMODE* pDM)
{
DRIVEREXTRA* pDX = pGetDriverExtra(pDM);
DWORD dwSize = dwGetRasddExtraSize(pDM);
PDMEXTRAHDR poem = 0;
if (pDX && dwSize && pDX->sVer >= MIN_OEM_DXF_VER && pDX->dmOEMDriverExtra != 0) {
poem = (PDMEXTRAHDR) ((PBYTE) pDX + (int) dwSize);
}
return(poem);
}
/**************************** Function Header ********************************
* dwGetOEMExtraDataSize
*
* Given a DEVMODE, returns the size of the OEM portion. Note that this
* is the size specified in the supplied DEVMODE, not the current size
* required by the OEM.
*
* RETURNS:
* (DWORD) Size.
*
* HISTORY:
*
*****************************************************************************/
DWORD
dwGetOEMExtraDataSize(
DEVMODE* pDM)
{
PDMEXTRAHDR poem = pGetOEMExtra(pDM);
if (poem) {
return(poem->dmSize);
}
return(0);
}
/**************************** Function Header ********************************
* dwLibGetDriverExtraSize
*
* RETURNS:
* (DWORD) Size of Rasdd's devmode, including OEM's extra data. This is
* the size of the current DEVMODE, and may generate a call to the OEM.
*
* HISTORY:
*
*****************************************************************************/
DWORD
dwLibGetDriverExtraSize(
HANDLE hPrinter,
PWSTR pwstrModel,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM)
{
return(dwGetCurrentRasddExtraSize() +
dwLibGetOEMDevmodeSize(hPrinter, pwstrModel, hModule, fnOEM));
}
/**************************** Function Header ********************************
* dwLibGetCurrentDevmodeSize
*
* RETURNS:
* (DWORD) Size of Rasdd's devmode, including OEM's extra data. This is
* the size of the current devmode, and may generate a call to the OEM.
*
* HISTORY:
*
*****************************************************************************/
DWORD
dwLibGetCurrentDevmodeSize(
HANDLE hPrinter,
PWSTR pwstrModel,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM)
{
return(sizeof(DEVMODE) +
dwLibGetDriverExtraSize(hPrinter, pwstrModel, hModule, fnOEM));
}
/**************************** Function Header ********************************
* dwLibGetOEMDevmodeSize
*
* RETURNS:
* (DWORD) Size of OEM's extra devmode data. This is the size of the
* current driver's OEM, not an existing devmode size.
*
* HISTORY:
*
*****************************************************************************/
DWORD
dwLibGetOEMDevmodeSize(
HANDLE hPrinter,
PWSTR pwstrModel,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM)
{
OEM_DEVMODEPARAM dmp = {0};
DWORD cbNeeded = 0;
TRY
dmp.cbSize = sizeof(OEM_DEVMODEPARAM);
dmp.fMode = OEMDM_SIZE;
dmp.hPrinter = hPrinter;
dmp.pPrinterModel = pwstrModel;
dmp.pcbNeeded = &cbNeeded;
dmp.hModule = hModule;
if (fnOEM == 0 || !(*fnOEM)(&dmp)) {
cbNeeded = 0;
}
ENDTRY
FINALLY
ENDFINALLY
return(cbNeeded);
}
/**************************** Function Header ********************************
* bLibValidateOEMDevmode
*
*
* RETURNS:
* (BOOL) TRUE if valid.
*
* HISTORY:
*
*****************************************************************************/
BOOL
bLibValidateOEMDevmode(
HANDLE hPrinter,
PWSTR pwstrModel,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM,
PDEVMODE pDM)
{
BOOL bOK = FALSE;
OEM_DEVMODEPARAM dmp = {0};
TRY
/* Valid if there isn't any.
*/
if (dwLibGetOEMDevmodeSize(hPrinter, pwstrModel, hModule, fnOEM) == 0) {
bOK = TRUE;
LEAVE;
}
dmp.cbSize = sizeof(OEM_DEVMODEPARAM);
dmp.fMode = OEMDM_VALIDATE;
dmp.hPrinter = hPrinter;
dmp.pPrinterModel = pwstrModel;
dmp.pPublicDMIn = pDM;
dmp.pOEMDMIn = (PVOID) pGetOEMExtra((PDEVMODE) pDM);
dmp.cbBufSize = dwGetOEMExtraDataSize((PDEVMODE) pDM);
dmp.hModule = hModule;
/* Call OEM.
*/
bOK = fnOEM && (*fnOEM)(&dmp);
ENDTRY
FINALLY
ENDFINALLY
return(bOK);
}
/**************************** Function Header ********************************
* bLibSetDefaultOEMExtra
*
* Gets devmode defaults from OEM. Assumes that pEDM is sufficiently
* large to hold extra data as reported by OEM.
*
* RETURNS:
* (void)
*
* HISTORY:
*
*****************************************************************************/
void
vLibSetDefaultOEMExtra(
HANDLE hPrinter,
PWSTR pwstrModel,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM,
EXTDEVMODE* pEDM)
{
OEM_DEVMODEPARAM dmp = {0};
DWORD cbNeeded = 0;
DWORD cbBufSize;
TRY
/* Get OEM size.
*/
cbBufSize = dwLibGetOEMDevmodeSize(hPrinter, pwstrModel, hModule, fnOEM);
/* Set dmDriverExtra in public devmode. This will include the size of OEM extra
* data if present.
*/
pEDM->dm.dmDriverExtra = (WORD) dwLibGetDriverExtraSize(hPrinter,
pwstrModel, hModule, fnOEM);
/* Set dmOEMDriverExtra in rasdd devmode.
*/
pEDM->dx.dmOEMDriverExtra = (WORD) cbBufSize;
/* If OEM has nothing, we're done.
*/
if (cbBufSize == 0) {
LEAVE;
}
dmp.cbSize = sizeof(OEM_DEVMODEPARAM);
dmp.fMode = OEMDM_DEFAULT;
dmp.hPrinter = hPrinter;
dmp.pPrinterModel = pwstrModel;
dmp.pPublicDMOut = (PDEVMODE) pEDM;
dmp.pOEMDMOut = pGetOEMExtra((PDEVMODE) pEDM);
dmp.cbBufSize = cbBufSize;
dmp.pcbNeeded = &cbNeeded;
dmp.hModule = hModule;
/* Call OEM.
*/
if (fnOEM) {
(*fnOEM)(&dmp);
}
ENDTRY
FINALLY
ENDFINALLY
return;
}
/**************************** Function Header ********************************
* bLibConvertOEMDevmode
*
* RETURNS:
* (BOOL) TRUE if OEM converts or if no OEM.
*
* HISTORY:
*
*****************************************************************************/
BOOL
bLibConvertOEMDevmode(
HANDLE hPrinter,
PWSTR pwstrModel,
PDEVMODE pdmIn,
PDEVMODE pdmOut,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM,
DWORD *pcbNeeded)
{
OEM_DEVMODEPARAM dmp = {0};
BOOL bReturn = TRUE;
TRY
if (fnOEM == 0) {
LEAVE;
}
dmp.cbSize = sizeof(OEM_DEVMODEPARAM);
dmp.fMode = OEMDM_CONVERT;
dmp.hPrinter = hPrinter;
dmp.pPrinterModel = pwstrModel;
dmp.pPublicDMIn = pdmIn;
dmp.pPublicDMOut = pdmOut;
dmp.pOEMDMIn = pGetOEMExtra(pdmIn);
dmp.pOEMDMOut = pGetOEMExtra(pdmOut);
dmp.cbBufSize = dwGetOEMExtraDataSize(pdmOut);
dmp.hModule = hModule;
dmp.pcbNeeded = pcbNeeded;
*dmp.pcbNeeded = dmp.cbBufSize;
/* Call OEM.
*/
bReturn = (*fnOEM)(&dmp);
if (!bReturn) {
/* If pOEMDMOut == 0, return success. OEM should never fail.
* They can examine pOEMDMIN and set public DM only.
*/
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && dmp.pOEMDMOut == 0) {
*pcbNeeded = 0;
bReturn = TRUE;
SetLastError(ERROR_SUCCESS);
}
}
ENDTRY
FINALLY
ENDFINALLY
return(bReturn);
}
/**************************** Function Header ********************************
* pLibGetHardDefaultEDM
*
* RETURNS:
* (PEXTDEVMODE) Pointer to complete hardcoded default EXTDEVMODE. The
* buffer must be freed by the caller.
*
* HISTORY:
*
*****************************************************************************/
EXTDEVMODE*
pLibGetHardDefaultEDM(
HANDLE hHeap,
HANDLE hPrinter,
PWSTR pwstrModel,
int iModelNum,
DWORD fGeneral,
DATAHDR* pDH,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM)
{
EXTDEVMODE * pEDM = 0;
MODELDATA* pModel = 0;
TRY
/* Allocate one. Freed when heap is destroyed in ReleaseUIInfo.
*/
pEDM = LIBALLOC(hHeap, HEAP_ZERO_MEMORY, dwLibGetCurrentDevmodeSize(hPrinter,
pwstrModel, hModule, fnOEM));
if (!pEDM) {
LEAVE;
}
/* Get hard defaults. Public, private and OEM.
*/
vSetDefaultDM(pEDM, pwstrModel, bIsUSA(hPrinter));
vDXDefault(&pEDM->dx, pDH, iModelNum);
vLibSetDefaultOEMExtra(hPrinter, pwstrModel, hModule, fnOEM, pEDM);
/* This transfers res info from private to public devmode.
*/
vSetResData(pEDM, pDH);
/* Limit capabilities based on current model flags.
*/
if (!(fGeneral & MD_DUPLEX)) {
pEDM->dm.dmFields &= ~DM_DUPLEX;
}
if (!(fGeneral & MD_COPIES)) {
pEDM->dm.dmFields &= ~DM_COPIES;
}
/* Set color. On by default, but turn it off if no data in GPC.
*/
pModel = GetTableInfoIndex( pDH, HE_MODELDATA, iModelNum);
if (!bDeviceIsColor(pDH, pModel)) {
pEDM->dm.dmFields &= ~DM_COLOR;
}
ENDTRY
FINALLY
ENDFINALLY
return(pEDM);
}
/**************************** Function Header ********************************
* bLibvalidatePrivateDM
*
* RETURNS:
* (BOOL) TRUE if Rasdd devmode doesn't validate.
*
* HISTORY:
*****************************************************************************/
BOOL
bLibValidatePrivateDM(
DEVMODE * pDM,
DATAHDR * pDH,
int iModel)
{
DRIVEREXTRA* pdx = pGetDriverExtra(pDM);
return(pdx != 0 && bValidateDX(pdx, pDH, iModel, FALSE));
}
/**************************** Function Header ********************************
* bConstructDevModeFromSource
*
* RETURNS:
* (PDEVMODE) A good current devmode constructed from input, printman
* devmode and hard defaults. User must free this.
*
* HISTORY:
*****************************************************************************/
PDEVMODE
pLibConstructDevModeFromSource(
HANDLE hHeap, /* heap for UI, 0 for kernel-mode */
HANDLE hPrinter, /* printer handle */
PWSTR pwstrModel, /* model name */
int iModelNum, /* model index */
DWORD fGeneral, /* fGeneral from MODELDATA */
DATAHDR* pDH, /* GPC data */
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM, /* OEM's DEVMODE entry point */
PDEVMODE pdmSrc) /* input devmode */
{
PEDM pHardDefaultDM = 0;
PEDM pHardDefaultDMCopy = 0;
PEDM pPrintManDM = 0;
PEDM pResult = 0;
TRY
/* Get hard default and printman devmodes. These both allocate and
* require us to free.
*/
pHardDefaultDM = pLibGetHardDefaultEDM(hHeap, hPrinter, pwstrModel,
iModelNum, fGeneral, pDH, hModule, fnOEM);
pPrintManDM = pLibGetPrintmanDevmode(hHeap, hPrinter);
if (!pHardDefaultDM) {
LEAVE;
}
/* Copy default before we do anything to it. We'll need it to scan out
* bad values later.
*/
pHardDefaultDMCopy = LIBALLOC(hHeap, 0, dwGetDMSize((PDEVMODE) pHardDefaultDM));
if (pHardDefaultDMCopy) {
CopyMemory(pHardDefaultDMCopy, pHardDefaultDM, dwGetDMSize((PDEVMODE) pHardDefaultDM));
}
/* Merge printman with default.
*/
if (!bLibValidateSetDevMode(hHeap, hPrinter, pwstrModel, iModelNum,
fGeneral, pDH, hModule, fnOEM, (PDEVMODE) pHardDefaultDM,
(PDEVMODE) pPrintManDM)) {
LEAVE;
}
/* Now merge result with input devmode.
*/
if (!bLibValidateSetDevMode(hHeap, hPrinter, pwstrModel, iModelNum,
fGeneral, pDH, hModule, fnOEM, (PDEVMODE) pHardDefaultDM, pdmSrc)) {
LEAVE;
}
/* Results have been copied in both steps to pHardDefaultDM.
*/
pResult = pHardDefaultDM;
/* Scan out any bad devmode values.
*/
if (pHardDefaultDMCopy) {
vReplaceBadDMValuesWithDefaults(pDH, iModelNum, pHardDefaultDMCopy, pResult);
LIBFREE(hHeap, 0, pHardDefaultDMCopy);
pHardDefaultDMCopy = 0;
}
ENDTRY
FINALLY
/* Clean up
*/
if (!pResult && pHardDefaultDM) {
LIBFREE(hHeap, 0, pHardDefaultDM);
pHardDefaultDM = 0;
}
if (pPrintManDM) {
LIBFREE(hHeap, 0, pPrintManDM);
pPrintManDM = 0;
}
ENDFINALLY
return((PDEVMODE) pResult);
}
/**************************** Function Header ********************************
* bLibValidateSetDevMode
*
* RETURNS:
* (BOOL) TRUE if new devmode can be constructed.
*
* HISTORY:
*****************************************************************************/
BOOL
bLibValidateSetDevMode(
HANDLE hHeap, /* heap for UI, 0 for kernel-mode */
HANDLE hPrinter, /* printer handle */
PWSTR pwstrModel, /* model name */
int iModelNum, /* model index */
DWORD fGeneral, /* fGeneral from MODELDATA */
DATAHDR* pDH, /* GPC data */
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM, /* OEM's DEVMODE entry point */
PDEVMODE pdmDest, /* output devmode */
PDEVMODE pdmSrc) /* input devmode */
/*++
Routine Description:
Verify the source devmode and merge it with destination devmode
1. Take unknown input devmode, known good output devmode.
2. Convert input devmode into temporary known good devmode.
3. Validate public portion of converted DM. If successful,
call vMergeDM into the output devmode.
4. Validate private portion of converted DM. If successful, copy
private portion of converted DM to output DM.
5. Validate OEM portion of converted DM. If successful, copy
OEM portion of converted DM to output DM.
Arguments:
pRasdduiInfo Pointer to UI info
pdmDest Pointer to destination devmode
pdmSrc Pointer to source devmode
Return Value:
TRUE if source devmode is valid and successfully merged
FALSE otherwise
Note:
pdmDest MUST point to a valid current EXTDEVMODE.
--*/
{
PDEVMODE pdm = 0;
PDEVMODE pdmTemp = 0;
DRIVEREXTRA* privDest = 0;
DRIVEREXTRA* privSrc = 0;
DMEXTRAHDR* oemDest = 0;
DMEXTRAHDR* oemSrc = 0;
DWORD dwOEMSize = 0;
DWORD cbNeeded = 0;
/* Assume success unless caller does not supply valid dest devmode.
*/
BOOL bRet = TRUE;
TRY
/* Verify pdmDest. It must contain a valid current devmode.
*/
if (!bValidateEDM((PEDM) pdmDest)) {
bRet = FALSE;
LEAVE;
}
/* If source is NULL, return OK if dest is present.
*/
if (pdmSrc == 0) {
bRet = (pdmDest != 0);
LEAVE;
}
/* Allocate temporary hard default devmode. Convert the input
* devmode into the temp.
*/
pdmTemp = (PDEVMODE) pLibGetHardDefaultEDM(hHeap, hPrinter, pwstrModel,
iModelNum, fGeneral, pDH, hModule, fnOEM);
if (!pdmTemp) {
LEAVE;
}
/* Save off size of current OEM devmode.
*/
dwOEMSize = dwGetOEMExtraDataSize(pdmTemp);
cbNeeded = dwGetDMSize(pdmTemp);
if (!LibDrvConvertDevMode(
0 /* pPrinterName */,
hHeap,
hPrinter,
pwstrModel,
iModelNum,
fGeneral,
pDH,
hModule,
fnOEM,
pdmSrc,
pdmTemp,
&cbNeeded,
CDM_CONVERT)) {
LEAVE;
}
/* Source (input) devmode is now converted into pdmTemp.
*/
pdmSrc = pdmTemp;
/* PUBLIC
*
* Validate public portion of source. If it's OK, merge it into
* destination.
*/
if (bValidateEDM((PEDM) pdmSrc)) {
vMergeDM(pdmDest, pdmSrc);
}
/* PRIVATE
*
* Validate private private portion. If it's OK, copy it into
* destination.
*/
if (!bLibValidatePrivateDM(pdmSrc, pDH, iModelNum)) {
LEAVE;
}
privDest = pGetDriverExtra(pdmDest);
privSrc = pGetDriverExtra(pdmSrc);
if (!privDest || !privSrc) {
LEAVE;
}
CopyMemory(privDest, privSrc, dwGetCurrentRasddExtraSize());
/* Now update size, including size of any OEM extra data
* hanging off the end of this default devmode.
*/
privDest->dmSize = (short) dwGetCurrentRasddExtraSize();
privDest->dmOEMDriverExtra = (short) dwOEMSize;
/* OEM
*
* Validate OEM and copy if OK. Note that if Rasdd's extra data is bad,
* we won't even look at the OEM data (caller will get default).
*/
if (!bLibValidateOEMDevmode(hPrinter, pwstrModel, hModule, fnOEM, pdmSrc)) {
LEAVE;
}
oemDest = pGetOEMExtra(pdmDest);
oemSrc = pGetOEMExtra(pdmSrc);
if (!oemDest || !oemSrc) {
LEAVE;
}
CopyMemory(oemDest, oemSrc, dwOEMSize);
/* Verify that dmDriverExtra and rasdd's OEMExtra have
* been set up properly.
*/
privDest->dmOEMDriverExtra = (short) dwOEMSize;
pdmDest->dmDriverExtra = privDest->dmOEMDriverExtra + privDest->dmSize;
ENDTRY
FINALLY
/* Finally, convert any new resolution information from public devmode to
* rasdd private.
*/
if (bRet) {
vSetEDMRes((PEDM) pdmDest, pDH);
}
/* Clean up.
*/
if (pdmTemp) {
LIBFREE(hHeap, 0, pdmTemp);
pdmTemp = 0;
}
ENDFINALLY
return(bRet);
}
/**************************** Function Header ********************************
* pLibGetPrintmanDevmode
*
* RETURNS:
* (EXTDEVMODE*) Newly allocated devmode from spooler.
*
* HISTORY:
*****************************************************************************/
EXTDEVMODE*
pLibGetPrintmanDevmode(
HANDLE hHeap,
HANDLE hPrinter)
{
DWORD dwBufSize = 0;
DWORD dwNeeded = 0;
PRINTER_INFO_2 *pPrinterInfo = 0;
EXTDEVMODE* pEDM = 0;
TRY
/* Get buffer size and allocate.
*/
GETPRINTER(hPrinter, 2, 0, 0, &dwNeeded);
pPrinterInfo = (PRINTER_INFO_2 *) LIBALLOC(hHeap, 0, dwNeeded);
if (!pPrinterInfo) {
LEAVE;
}
/* Now get data.
*/
if (!GETPRINTER(hPrinter, 2, (LPBYTE) pPrinterInfo, dwNeeded,
&dwNeeded)) {
LEAVE;
}
/* Allocate and copy.
*/
pEDM = pPrinterInfo->pDevMode ? (EXTDEVMODE*) LIBALLOC(hHeap,
0, dwGetDMSize(pPrinterInfo->pDevMode)) : 0;
if (pEDM) {
CopyMemory(pEDM, pPrinterInfo->pDevMode, dwGetDMSize(pPrinterInfo->pDevMode));
}
ENDTRY
FINALLY
if (pPrinterInfo) {
LIBFREE(hHeap, 0, pPrinterInfo);
pPrinterInfo = 0;
}
ENDFINALLY
return(pEDM);
}
/****************************************************************************
* pSaveAndStripOEM
*
* Copies the input devmode, with any OEM portion stripped off and
* adjusted for by resetting public dmDriverExtra and DRIVEREXTRA fields.
*
* RETURNS:
* (PDEVMODE) A copy of the input devmode. Returned copy must be freed
* by caller.
*
* HISTORY:
****************************************************************************/
PDEVMODE
pSaveAndStripOEM(
HANDLE hHeap,
PDEVMODE pdmIn)
{
PDEVMODE pdmStrippedCopy = 0;
/* Save a copy of the input devmode.
*/
if (pdmIn) {
pdmStrippedCopy = LIBALLOC(hHeap, 0, dwGetDMSize(pdmIn));
if (pdmStrippedCopy) {
CopyMemory(pdmStrippedCopy, pdmIn, dwGetDMSize(pdmIn));
}
}
/* Now chop off OEM portion by resetting public dmDriverExtra
* to size of rasdd extra only. Note that dwGetOEMExtraDataSize
* checks for non-zero input.
*/
if (dwGetOEMExtraDataSize(pdmStrippedCopy) != 0) {
DRIVEREXTRA *pExtra = 0;
if ((pExtra = pGetDriverExtra(pdmStrippedCopy)) != 0) {
pdmStrippedCopy->dmDriverExtra = (short) dwGetRasddExtraSize(pdmStrippedCopy);
pExtra->dmOEMDriverExtra = 0;
}
}
return(pdmStrippedCopy);
}
/**************************** Function Header ********************************
* LibDrvConvertDevMode
* Use by SetPrinter and GetPrinter to convert devmodes
*
* Arguments:
*
* pPrinterName - Points to printer name string
* pdmIn - Points to the input devmode
* pdmOut - Points to the output devmode buffer
* pcbNeeded - Specifies the size of output buffer on input
* On output, this is the size of output devmode
* fMode - Specifies what function to perform
*
* RETURN VALUE:
*
* TRUE if successful
* FALSE otherwise and an error code is logged
*
* HISTORY:
*
* 9:52:23 on 12/13/1995 -by- Ganesh Pandey [ganeshp]
* Created it.
*
*****************************************************************************/
BOOL
LibDrvConvertDevMode(
PWSTR pPrinterName,
HANDLE hHeap,
HANDLE hPrinter,
PWSTR pwstrModel,
int iModelNum,
DWORD flags,
DATAHDR* pdh,
HANDLE hModule, // OEM's module handle, GPC DLL for KM, UI DLL for UM.
OEM_DEVMODEFN fnOEM,
PDEVMODE pdmIn,
PDEVMODE pdmOut,
PLONG pcbNeeded,
DWORD fMode)
{
DEVMODE* pDefault = 0;
DWORD dwSize = 0;
DWORD dwOEMSize = 0;
DRIVEREXTRA *pdx;
PDEVMODE pdmStrippedInput = 0;
PDEVMODE pdmStrippedOutput = 0;
BOOL bReturn = FALSE;
DWORD dwBufSize = 0;
TRY
dwBufSize = *pcbNeeded;
/* Typical processing.
*/
switch (fMode) {
/* CDM_DRIVER_DEFAULT:
*
*
* From the DDK:
*
* If the input value of pcbNeeded specifies an output buffer of sufficient size,
* the driver should copy the current version of its default DEVMODE to pdmOut. Then,
* if pdmIn is not null, the driver should convert the input DEVMODE to its current
* DEVMODE version, merging the results in the buffer to which pdmOut points. If
* pcbNeeded does not point to a buffer of sufficient size, the driver should update
* pcbNeeded with the required buffer size, set the last error to ERROR_INSUFFICIENT_BUFFER,
* and return FALSE.
*
*
* If this is the case, we should be able to fill in pdmOut with hardcoded defaults, then
* call this routine again with fMode == CDM_CONVERT.
*/
case CDM_DRIVER_DEFAULT:
/* Get size of current devmode.
*/
dwSize = dwLibGetCurrentDevmodeSize(hPrinter, pwstrModel, hModule, fnOEM);
/* If output buffer's big enough, copy default.
*/
if (dwBufSize >= (int) dwSize) {
PDEVMODE pDefault = 0;
pDefault = (PDEVMODE) pLibGetHardDefaultEDM(
hHeap,
hPrinter,
pwstrModel,
iModelNum,
flags,
pdh,
hModule,
fnOEM);
if (pDefault) {
CopyMemory(pdmOut, pDefault, dwSize);
LIBFREE(hHeap, 0, pDefault);
pDefault = 0;
bReturn = TRUE;
}
}
/* Not big enough. Set error and size.
*/
else {
*pcbNeeded = dwSize;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
/* If pdmIn and successful so far, convert and merge into pdmOut.
* Call ourselves with fMode == CDM_CONVERT.
*/
if (bReturn == TRUE && pdmIn) {
bReturn = LibDrvConvertDevMode(pPrinterName, hHeap, hPrinter, pwstrModel, iModelNum, flags,
pdh, hModule, fnOEM, pdmIn, pdmOut, pcbNeeded, CDM_CONVERT);
}
break;
/* CDM_CONVERT
*
*
* From the DDK:
*
* The driver should determine that both pdmIn and pdmOut point to valid DEVMODEs that
* were previously returned by it. If either DEVMODE is not valid, the driver should set
* the last error to ERROR_INVALID_PARAMETER and return FALSE. Otherwise, the driver should
* convert the input DEVMODE to the output DEVMODE.
*/
case CDM_CONVERT:
/* The library routine should be able to take care of this if any OEM portion
* is first stripped off the input devmode.
*/
pdmStrippedInput = pSaveAndStripOEM(hHeap, pdmIn);
pdmStrippedOutput = pSaveAndStripOEM(hHeap, pdmOut);
/* Verify inputs.
*/
if (pdmStrippedInput == 0 || pdmStrippedOutput == 0) {
SetLastError(ERROR_INVALID_PARAMETER);
}
else if (ConvertDevmode(pdmStrippedInput, pdmStrippedOutput) > 0) {
bReturn = TRUE;
}
/* Now let OEM have a crack at it. Note that OEM gets the original, unstripped
* devmodes.
*/
if (bReturn == TRUE) {
bReturn = bLibConvertOEMDevmode(hPrinter, pwstrModel, pdmIn, pdmOut, hModule,
fnOEM, pcbNeeded);
/* If OEM failed, add its pcbNeeded to size of the rest of the
* devmode in pdmStrippedOutput.
*/
if (bReturn == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
*pcbNeeded += dwGetDMSize(pdmStrippedOutput);
}
}
/* If OEM was successful, reassemble both converted versions into pdmOut.
*/
if (bReturn == TRUE) {
/* If the output is new enough to have and OEM, tack it on.
*/
pdx = pGetDriverExtra(pdmStrippedOutput);
if (pdx && pdx->sVer >= MIN_OEM_DXF_VER) {
/* If we any OEM and we have enough room, do the copy.
*/
dwOEMSize = dwGetOEMExtraDataSize(pdmOut);
dwSize = dwGetDMSize(pdmStrippedOutput) + dwOEMSize;
if (dwBufSize >= (int) dwSize) {
if (dwOEMSize) {
/* Copy the results of OEM conversion in pdmOut to the tail end of the
* lib conversion in pdmStrippedOutput.
*/
DMEXTRAHDR *poem = pGetOEMExtra(pdmOut);
CopyMemory((char*) pdmStrippedOutput + dwGetDMSize(pdmStrippedOutput),
poem, dwOEMSize);
/* Now adjust dmDriverExtra and dwOEMDriverExtra.
*/
pdx->dmOEMDriverExtra = (short) dwOEMSize;
pdmStrippedOutput->dmDriverExtra += (short) dwOEMSize;
}
}
/* Not enough rooom to add OEM.
*/
else {
*pcbNeeded = dwSize;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bReturn = FALSE;
}
}
/* Finally copy pdmStrippedOutput to pdmOut. May or may not contain an OEM
* portion.
*/
if (bReturn == TRUE) {
if (dwBufSize >= (int) dwGetDMSize(pdmStrippedOutput)) {
CopyMemory(pdmOut, pdmStrippedOutput, dwGetDMSize(pdmStrippedOutput));
/* Record total size of output devmode.
*/
*pcbNeeded = dwGetDMSize(pdmOut);
}
else {
*pcbNeeded = dwSize;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
bReturn = FALSE;
}
}
}
/* One more check. Make sure driver extra validates to current version. If not,
* replace entire driver extra and any OEM extra with defaults.
*/
if (bReturn == TRUE && !bLibValidatePrivateDM(pdmOut, pdh, iModelNum)) {
/* Strip off entire DRIVEREXTRA leaving public only, then convert to
* current version.
*/
pdmIn->dmDriverExtra = 0;
bReturn = LibDrvConvertDevMode(pPrinterName, hHeap, hPrinter, pwstrModel, iModelNum,
flags, pdh, hModule, fnOEM, pdmIn, pdmOut, pcbNeeded, CDM_DRIVER_DEFAULT);
}
/* Clean up
*/
if (pdmStrippedInput) {
LIBFREE(hHeap, 0, pdmStrippedInput);
pdmStrippedInput = 0;
}
if (pdmStrippedOutput) {
LIBFREE(hHeap, 0, pdmStrippedOutput);
pdmStrippedOutput = 0;
}
break;
/* No 3.51 conversion in kernel mode.
*/
#ifndef NTGDIKM
/* CDM_CONVERT351
*
*
* From the DDK:
*
*
* If the input value of pcbNeeded specifies an output buffer of sufficient size, the
* driver should copy its NT Version 3.51 default DEVMODE to pdmOut. Then, if pdmIn is not
* null, the driver should convert the input DEVMODE to its NT 3.51 DEVMODE, merging the
* results in the buffer to which pdmOut points. If pcbNeeded does not point to a buffer of
* sufficient size, the driver should update pcbNeeded with the required buffer size, set
* the last error to ERROR_INSUFFICIENT_BUFFER, and return FALSE.
*/
case CDM_CONVERT351:
{
DRIVER_VERSION_INFO RasddDriverVersions;
/* Fill out driver versions.
*/
RasddDriverVersions.dmDriverVersion = DM_DRIVERVERSION;
RasddDriverVersions.dmDriverExtra = (short) dwGetCurrentRasddExtraSize();
RasddDriverVersions.dmDriverVersion351 = DM_DRIVERVERSION_351;
RasddDriverVersions.dmDriverExtra351 = sizeof(DRIVEREXTRA351);
/* The library routine should be able to take care of this if any OEM portion
* is first stripped off the input devmode.
*/
pdmStrippedInput = pSaveAndStripOEM(hHeap, pdmIn);
/* Let the library routine handle it. Don't check pdmStrippedInput -- the library
* routine will take care of it.
*/
if (CommonDrvConvertDevmode(pPrinterName, pdmStrippedInput, pdmOut,
pcbNeeded, fMode, &RasddDriverVersions) == CDM_RESULT_TRUE) {
bReturn = TRUE;
}
/* Now let OEM have a crack at it. Hand them old private, and let them set
* any public fields they need to. Note that OEM gets the original, unstripped
* devmode.
*/
if (bReturn == TRUE) {
bReturn = bLibConvertOEMDevmode(hPrinter, pwstrModel, pdmIn, pdmOut, hModule,
fnOEM, pcbNeeded);
}
/* Clean up
*/
if (pdmStrippedInput) {
LIBFREE(hHeap, 0, pdmStrippedInput);
pdmStrippedInput = 0;
}
}
break;
#endif /* NTGDIKM */
default:
break;
}
ENDTRY
FINALLY
ENDFINALLY
return(bReturn);
}