Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1565 lines
41 KiB

/*++
Copyright (c) 1996-1997 Microsoft Corporation
Module Name:
psutil.c
Abstract:
PostScript utility functions
BInitDriverDefaultDevmode
BMergeDriverDevmode
VCopyUnicodeStringToAnsi
PGetAndConvertOldVersionFormTrayTable
BSaveAsOldVersionFormTrayTable
Environment:
Windows NT printer drivers
Revision History:
12/03/97 -fengy-
Added VUpdatePrivatePrinterData to split fixed fields in PrinterData
into Keyword/Value pairs in Registry.
04/17/97 -davidx-
Provide OEM plugins access to driver private devmode settings.
02/04/97 -davidx-
Devmode changes to support OEM plugins.
10/02/96 -davidx-
Implement BPSMergeDevmode.
09/26/96 -davidx-
Created it.
--*/
#include "lib.h"
#include "ppd.h"
#include "pslib.h"
#include "oemutil.h"
//
// Information about PostScript driver private devmode
//
CONST DRIVER_DEVMODE_INFO gDriverDMInfo =
{
PSDRIVER_VERSION, sizeof(PSDRVEXTRA),
PSDRIVER_VERSION_500, sizeof(PSDRVEXTRA500),
PSDRIVER_VERSION_400, sizeof(PSDRVEXTRA400),
PSDRIVER_VERSION_351, sizeof(PSDRVEXTRA351),
};
CONST DWORD gdwDriverDMSignature = PSDEVMODE_SIGNATURE;
CONST WORD gwDriverVersion = PSDRIVER_VERSION;
static VOID
VInitNewPrivateFields(
PRAWBINARYDATA pRawData,
PUIINFO pUIInfo,
PPSDRVEXTRA pdmPrivate,
BOOL bInitAllFields
)
/*++
Routine Description:
Intialize the new private devmode fields for PS 5.0
Arguments:
pUIInfo - Points to a UIINFO structure
pRawData - Points to raw binary printer description data
pdmPrivate - Points to the private devmode fields to be initialized
bInitAllFields - Whether to initialize all new private fields or
initialize the options array only
Return Value:
NONE
--*/
{
if (bInitAllFields)
{
pdmPrivate->wReserved1 = 0;
pdmPrivate->wSize = sizeof(PSDRVEXTRA);
pdmPrivate->fxScrFreq = 0;
pdmPrivate->fxScrAngle = 0;
pdmPrivate->iDialect = SPEED;
pdmPrivate->iTTDLFmt = TT_DEFAULT;
pdmPrivate->bReversePrint = FALSE;
pdmPrivate->iLayout = ONE_UP;
pdmPrivate->iPSLevel = pUIInfo->dwLangLevel;
pdmPrivate->wOEMExtra = 0;
pdmPrivate->wVer = PSDRVEXTRA_VERSION;
pdmPrivate->dwReserved2 = 0;
ZeroMemory(pdmPrivate->dwReserved3, sizeof(pdmPrivate->dwReserved3));
}
InitDefaultOptions(pRawData,
pdmPrivate->aOptions,
MAX_PRINTER_OPTIONS,
MODE_DOCUMENT_STICKY);
pdmPrivate->dwOptions = pRawData->dwDocumentFeatures;
pdmPrivate->dwChecksum32 = pRawData->dwChecksum32;
}
BOOL
BInitDriverDefaultDevmode(
OUT PDEVMODE pdmOut,
IN LPCTSTR ptstrPrinterName,
IN PUIINFO pUIInfo,
IN PRAWBINARYDATA pRawData,
IN BOOL bMetric
)
/*++
Routine Description:
Return the driver default devmode
Arguments:
pdmOut - Points to the output devmode to be initialized
ptstrPrinterName - Specifies the name of the printer
pUIInfo - Points to a UIINFO structure
pRawData - Points to raw binary printer description data
bMetric - Whether the system is running in metric mode
Return Value:
TRUE if successful, FALSE if there is an error
Note:
This function should initialize both public devmode fields
and driver private devmode fields. It's also assumed that
output buffer has already been zero initialized by the caller.
--*/
{
PPSDRVEXTRA pdmPrivate;
PFEATURE pFeature;
PPPDDATA pPpdData;
//
// Initialize public devmode fields
//
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
ASSERT(pPpdData != NULL);
pdmOut->dmDriverVersion = PSDRIVER_VERSION;
pdmOut->dmSpecVersion = DM_SPECVERSION;
pdmOut->dmSize = sizeof(DEVMODE);
pdmOut->dmDriverExtra = sizeof(PSDRVEXTRA);
pdmOut->dmFields = DM_ORIENTATION |
DM_SCALE |
DM_COPIES |
DM_PRINTQUALITY |
DM_YRESOLUTION |
DM_TTOPTION |
#ifndef WINNT_40
DM_NUP |
#endif
DM_COLOR |
DM_DEFAULTSOURCE;
pdmOut->dmOrientation = DMORIENT_PORTRAIT;
pdmOut->dmDuplex = DMDUP_SIMPLEX;
pdmOut->dmCollate = DMCOLLATE_FALSE;
pdmOut->dmMediaType = DMMEDIA_STANDARD;
pdmOut->dmTTOption = DMTT_SUBDEV;
pdmOut->dmColor = DMCOLOR_MONOCHROME;
pdmOut->dmDefaultSource = DMBIN_FORMSOURCE;
pdmOut->dmScale = 100;
pdmOut->dmCopies = 1;
pdmOut->dmPrintQuality =
pdmOut->dmYResolution = DEFAULT_RESOLUTION;
#ifndef WINNT_40
pdmOut->dmNup = DMNUP_SYSTEM;
#endif
if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_RESOLUTION))
{
PRESOLUTION pRes;
//
// Use the default resolution specified in the PPD file
//
if (pRes = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex))
{
pdmOut->dmPrintQuality = (short)pRes->iXdpi;
pdmOut->dmYResolution = (short)pRes->iYdpi;
}
}
if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_DUPLEX))
{
PDUPLEX pDuplex;
//
// Use the default duplex option specified in the PPD file
//
pdmOut->dmFields |= DM_DUPLEX;
if (pDuplex = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex))
pdmOut->dmDuplex = (SHORT) pDuplex->dwDuplexID;
}
#ifdef WINNT_40
if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_COLLATE))
{
PCOLLATE pCollate;
pdmOut->dmFields |= DM_COLLATE;
if (pCollate = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex))
pdmOut->dmCollate = (SHORT) pCollate->dwCollateID;
}
#else // !WINNT_40
pdmOut->dmFields |= DM_COLLATE;
pdmOut->dmCollate = DMCOLLATE_TRUE;
#endif // !WINNT_40
if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_MEDIATYPE))
{
//
// Use the default media type specified in the PPD file
//
pdmOut->dmFields |= DM_MEDIATYPE;
if (pFeature->dwDefaultOptIndex != OPTION_INDEX_ANY)
pdmOut->dmMediaType = DMMEDIA_USER + pFeature->dwDefaultOptIndex;
}
//
// Adobe wants to preserve the color information even for b/w printers.
// So for both b/w and color printers, turn color on by default for Adobe.
//
#ifndef ADOBE
if (IS_COLOR_DEVICE(pUIInfo))
{
#endif // !ADOBE
//
// Turn color on by default
//
pdmOut->dmColor = DMCOLOR_COLOR;
pdmOut->dmFields |= DM_COLOR;
#ifndef ADOBE
}
#endif // !ADOBE
//
// We always set ICM off. The spooler will turn it on at install time
// if there are color profiles installed with this printer
//
pdmOut->dmICMMethod = DMICMMETHOD_NONE;
pdmOut->dmICMIntent = DMICM_CONTRAST;
#ifndef WINNT_40
#ifndef ADOBE
if (IS_COLOR_DEVICE(pUIInfo))
{
#endif // !ADOBE
pdmOut->dmFields |= (DM_ICMMETHOD | DM_ICMINTENT);
#ifndef ADOBE
}
#endif // !ADOBE
#endif // !WINNT_40
//
// dmDeviceName field will be filled elsewhere.
// Use an arbitrary default value if the input parameter is NULL.
//
CopyString(pdmOut->dmDeviceName,
ptstrPrinterName ? ptstrPrinterName : TEXT("PostScript"),
CCHDEVICENAME);
//
// Initialize form-related fields
//
VDefaultDevmodeFormFields(pUIInfo, pdmOut, bMetric);
//
// Private devmode fields
//
pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmOut);
pdmPrivate->dwSignature = PSDEVMODE_SIGNATURE;
pdmPrivate->coloradj = gDefaultHTColorAdjustment;
#ifndef WINNT_40
pdmPrivate->dwFlags = PSDEVMODE_METAFILE_SPOOL;
#endif
if (pPpdData->dwFlags & PPDFLAG_PRINTPSERROR)
pdmPrivate->dwFlags |= PSDEVMODE_EHANDLER;
if (pUIInfo->dwLangLevel > 1)
pdmPrivate->dwFlags |= PSDEVMODE_COMPRESSBMP;
#ifndef KERNEL_MODE
//
// Set up some private devmode flag bits for compatibility
// with previous versions of the driver.
//
pdmPrivate->dwFlags |= PSDEVMODE_CTRLD_AFTER;
if (GetACP() == 1252)
pdmPrivate->dwFlags |= (PSDEVMODE_FONTSUBST|PSDEVMODE_ENUMPRINTERFONTS);
#endif
//
// Intialize the new private devmode fields for PS 5.0
//
VInitNewPrivateFields(pRawData, pUIInfo, pdmPrivate, TRUE);
if (SUPPORT_CUSTOMSIZE(pUIInfo))
{
VFillDefaultCustomPageSizeData(pRawData, &pdmPrivate->csdata, bMetric);
}
else
{
ZeroMemory(&pdmPrivate->csdata, sizeof(pdmPrivate->csdata));
pdmPrivate->csdata.dwX = pdmOut->dmPaperWidth * DEVMODE_PAPER_UNIT;
pdmPrivate->csdata.dwY = pdmOut->dmPaperLength * DEVMODE_PAPER_UNIT;
}
return TRUE;
}
BOOL
BMergeDriverDevmode(
IN OUT PDEVMODE pdmOut,
IN PUIINFO pUIInfo,
IN PRAWBINARYDATA pRawData,
IN PDEVMODE pdmIn
)
/*++
Routine Description:
Merge the input devmode with an existing devmode.
Arguments:
pdmOut - Points to a valid output devmode
pUIInfo - Points to a UIINFO structure
pRawData - Points to raw binary printer description data
pdmIn - Points to the input devmode
Return Value:
TRUE if successful, FALSE if there is a fatal error
Note:
This function should take care of both public devmode fields
and driver private devmode fields. It can assume the input
devmode has already been convert to the current size.
--*/
{
PPSDRVEXTRA pdmPrivateIn, pdmPrivateOut;
PFEATURE pFeature;
PPPDDATA pPpdData;
ASSERT(pdmOut != NULL &&
pdmOut->dmSize == sizeof(DEVMODE) &&
pdmOut->dmDriverExtra >= sizeof(PSDRVEXTRA) &&
pdmIn != NULL &&
pdmIn->dmSize == sizeof(DEVMODE) &&
pdmIn->dmDriverExtra >= sizeof(PSDRVEXTRA));
pdmPrivateIn = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmIn);
pdmPrivateOut = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmOut);
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
ASSERT(pPpdData != NULL);
//
// Merge the public devmode fields
//
#ifndef WINNT_40
if ( (pdmIn->dmFields & DM_NUP) &&
(pdmIn->dmNup == DMNUP_SYSTEM ||
pdmIn->dmNup == DMNUP_ONEUP))
{
pdmOut->dmNup = pdmIn->dmNup;
pdmOut->dmFields |= DM_NUP;
}
#endif // #ifndef WINNT_40
if (pdmIn->dmFields & DM_DEFAULTSOURCE &&
((pdmIn->dmDefaultSource >= DMBIN_FIRST &&
pdmIn->dmDefaultSource <= DMBIN_LAST) ||
pdmIn->dmDefaultSource >= DMBIN_USER))
{
pdmOut->dmFields |= DM_DEFAULTSOURCE;
pdmOut->dmDefaultSource = pdmIn->dmDefaultSource;
}
if ((pdmIn->dmFields & DM_ORIENTATION) &&
(pdmIn->dmOrientation == DMORIENT_PORTRAIT ||
pdmIn->dmOrientation == DMORIENT_LANDSCAPE))
{
pdmOut->dmFields |= DM_ORIENTATION;
pdmOut->dmOrientation = pdmIn->dmOrientation;
}
//
// If both DM_PAPERLENGTH and DM_PAPERWIDTH are set, copy
// dmPaperLength and dmPaperWidth fields. If DM_PAPERSIZE
// is set, copy dmPaperSize field. Otherwise, if DM_FORMNAME
// is set, copy dmFormName field.
//
if ((pdmIn->dmFields & DM_PAPERWIDTH) &&
(pdmIn->dmFields & DM_PAPERLENGTH) &&
(pdmIn->dmPaperWidth > 0) &&
(pdmIn->dmPaperLength > 0))
{
pdmOut->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
pdmOut->dmFields &= ~(DM_PAPERSIZE | DM_FORMNAME);
pdmOut->dmPaperWidth = pdmIn->dmPaperWidth;
pdmOut->dmPaperLength = pdmIn->dmPaperLength;
}
else if (pdmIn->dmFields & DM_PAPERSIZE)
{
if ((pdmIn->dmPaperSize != DMPAPER_CUSTOMSIZE) ||
SUPPORT_CUSTOMSIZE(pUIInfo) &&
SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData))
{
pdmOut->dmFields |= DM_PAPERSIZE;
pdmOut->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH | DM_FORMNAME);
pdmOut->dmPaperSize = pdmIn->dmPaperSize;
}
}
else if (pdmIn->dmFields & DM_FORMNAME)
{
pdmOut->dmFields |= DM_FORMNAME;
pdmOut->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH | DM_PAPERSIZE);
CopyString(pdmOut->dmFormName, pdmIn->dmFormName, CCHFORMNAME);
}
if ((pdmIn->dmFields & DM_SCALE) &&
(pdmIn->dmScale >= MIN_SCALE) &&
(pdmIn->dmScale <= MAX_SCALE))
{
pdmOut->dmFields |= DM_SCALE;
pdmOut->dmScale = pdmIn->dmScale;
}
if ((pdmIn->dmFields & DM_COPIES) &&
(pdmIn->dmCopies >= 1) &&
(pdmIn->dmCopies <= (SHORT) pUIInfo->dwMaxCopies))
{
pdmOut->dmFields |= DM_COPIES;
pdmOut->dmCopies = pdmIn->dmCopies;
}
if ((pdmIn->dmFields & DM_DUPLEX) &&
(GET_PREDEFINED_FEATURE(pUIInfo, GID_DUPLEX) != NULL) &&
(pdmIn->dmDuplex == DMDUP_SIMPLEX ||
pdmIn->dmDuplex == DMDUP_HORIZONTAL ||
pdmIn->dmDuplex == DMDUP_VERTICAL))
{
pdmOut->dmFields |= DM_DUPLEX;
pdmOut->dmDuplex = pdmIn->dmDuplex;
}
if ((pdmIn->dmFields & DM_COLLATE) &&
#ifdef WINNT_40
GET_PREDEFINED_FEATURE(pUIInfo, GID_COLLATE) != NULL &&
#endif
(pdmIn->dmCollate == DMCOLLATE_TRUE ||
pdmIn->dmCollate == DMCOLLATE_FALSE))
{
pdmOut->dmFields |= DM_COLLATE;
pdmOut->dmCollate = pdmIn->dmCollate;
}
if ((pdmIn->dmFields & DM_TTOPTION) &&
(pdmIn->dmTTOption == DMTT_BITMAP ||
pdmIn->dmTTOption == DMTT_DOWNLOAD ||
pdmIn->dmTTOption == DMTT_SUBDEV))
{
pdmOut->dmFields |= DM_TTOPTION;
pdmOut->dmTTOption = (pdmIn->dmTTOption == DMTT_SUBDEV) ? DMTT_SUBDEV : DMTT_DOWNLOAD;
}
//
// Merge color and ICM fields.
//
#ifndef ADOBE
if (IS_COLOR_DEVICE(pUIInfo))
{
#endif // !ADOBE
if ((pdmIn->dmFields & DM_COLOR) &&
(pdmIn->dmColor == DMCOLOR_COLOR ||
pdmIn->dmColor == DMCOLOR_MONOCHROME))
{
pdmOut->dmFields |= DM_COLOR;
pdmOut->dmColor = pdmIn->dmColor;
}
#ifndef WINNT_40
if ((pdmIn->dmFields & DM_ICMMETHOD) &&
(pdmIn->dmICMMethod == DMICMMETHOD_NONE ||
pdmIn->dmICMMethod == DMICMMETHOD_SYSTEM ||
pdmIn->dmICMMethod == DMICMMETHOD_DRIVER ||
pdmIn->dmICMMethod == DMICMMETHOD_DEVICE))
{
pdmOut->dmFields |= DM_ICMMETHOD;
pdmOut->dmICMMethod = pdmIn->dmICMMethod;
}
if ((pdmIn->dmFields & DM_ICMINTENT) &&
(pdmIn->dmICMIntent == DMICM_SATURATE ||
pdmIn->dmICMIntent == DMICM_CONTRAST ||
pdmIn->dmICMIntent == DMICM_COLORIMETRIC ||
pdmIn->dmICMIntent == DMICM_ABS_COLORIMETRIC))
{
pdmOut->dmFields |= DM_ICMINTENT;
pdmOut->dmICMIntent = pdmIn->dmICMIntent;
}
#endif // !WINNT_40
#ifndef ADOBE
}
#endif // !ADOBE
//
// Resolution
//
if ((pdmIn->dmFields & (DM_PRINTQUALITY|DM_YRESOLUTION)) &&
(pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_RESOLUTION)))
{
PRESOLUTION pRes;
DWORD dwIndex;
INT iXdpi, iYdpi;
switch (pdmIn->dmFields & (DM_PRINTQUALITY|DM_YRESOLUTION))
{
case DM_PRINTQUALITY:
iXdpi = iYdpi = pdmIn->dmPrintQuality;
break;
case DM_YRESOLUTION:
iXdpi = iYdpi = pdmIn->dmYResolution;
break;
default:
iXdpi = pdmIn->dmPrintQuality;
iYdpi = pdmIn->dmYResolution;
break;
}
dwIndex = MapToDeviceOptIndex(pUIInfo->pInfoHeader,
GID_RESOLUTION,
iXdpi,
iYdpi,
NULL);
if (pRes = PGetIndexedOption(pUIInfo, pFeature, dwIndex))
{
pdmOut->dmFields |= (DM_PRINTQUALITY|DM_YRESOLUTION);
pdmOut->dmPrintQuality = (short)pRes->iXdpi;
pdmOut->dmYResolution = (short)pRes->iYdpi;
}
}
//
// Media type
//
if ((pdmIn->dmFields & DM_MEDIATYPE) &&
(pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_MEDIATYPE)) &&
(pdmIn->dmMediaType == DMMEDIA_STANDARD ||
pdmIn->dmMediaType == DMMEDIA_TRANSPARENCY ||
pdmIn->dmMediaType == DMMEDIA_GLOSSY ||
((pdmIn->dmMediaType >= DMMEDIA_USER) &&
(pdmIn->dmMediaType < DMMEDIA_USER + pFeature->Options.dwCount))))
{
pdmOut->dmFields |= DM_MEDIATYPE;
pdmOut->dmMediaType = pdmIn->dmMediaType;
}
//
// Merge the private devmode fields
//
if (pdmPrivateIn->dwSignature == PSDEVMODE_SIGNATURE)
{
CopyMemory(pdmPrivateOut, pdmPrivateIn, sizeof(PSDRVEXTRA));
if (pdmPrivateOut->dwChecksum32 != pRawData->dwChecksum32)
{
WARNING(("PSCRIPT5: Devmode checksum mismatch.\n"));
//
// Intialize the new private devmode fields for PS 5.0.
// If wReserved1 field is not 0, then the devmode is of
// a previous version. In that case, we should initialize
// all new private fields instead of just the options array.
//
VInitNewPrivateFields(pRawData,
pUIInfo,
pdmPrivateOut,
pdmPrivateOut->wReserved1 != 0);
//
// Convert PS4 feature/option selections to PS4 format
//
if (pdmPrivateIn->wReserved1 == pPpdData->dwNt4Checksum)
{
VConvertOptSelectArray(pRawData,
pdmPrivateOut->aOptions,
MAX_PRINTER_OPTIONS,
((PSDRVEXTRA400 *) pdmPrivateIn)->aubOptions,
64,
MODE_DOCUMENT_STICKY);
}
}
if (pdmPrivateOut->iPSLevel == 0 ||
pdmPrivateOut->iPSLevel > (INT) pUIInfo->dwLangLevel)
{
pdmPrivateOut->iPSLevel = pUIInfo->dwLangLevel;
}
if (pdmPrivateOut->iTTDLFmt == TYPE_42 && pUIInfo->dwTTRasterizer != TTRAS_TYPE42)
pdmPrivateOut->iTTDLFmt = TT_DEFAULT;
if (IS_COLOR_DEVICE(pUIInfo))
{
pdmPrivateOut->dwFlags &= ~PSDEVMODE_NEG;
}
}
//
// If custom page size is supported, make sure the custom page
// size parameters are valid.
//
if (SUPPORT_CUSTOMSIZE(pUIInfo))
(VOID) BValidateCustomPageSizeData(pRawData, &pdmPrivateOut->csdata);
return TRUE;
}
BOOL
BValidateDevmodeCustomPageSizeFields(
PRAWBINARYDATA pRawData,
PUIINFO pUIInfo,
PDEVMODE pdm,
PRECTL prclImageArea
)
/*++
Routine Description:
Check if the devmode form fields are specifying PostScript custom page size
Arguments:
pRawData - Points to raw printer description data
pUIInfo - Points to UIINFO structure
pdm - Points to input devmode
prclImageArea - Returns imageable area of the custom page size
Return Value:
TRUE if the devmode specifies PostScript custom page size
FALSE otherwise
--*/
{
PPPDDATA pPpdData;
PPSDRVEXTRA pdmPrivate;
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
ASSERT(pPpdData != NULL);
if ((pdm->dmFields & DM_PAPERSIZE) &&
pdm->dmPaperSize == DMPAPER_CUSTOMSIZE &&
SUPPORT_CUSTOMSIZE(pUIInfo) &&
SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData))
{
pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
pdm->dmFields &= ~(DM_PAPERWIDTH|DM_PAPERLENGTH|DM_FORMNAME);
pdm->dmPaperWidth = (SHORT) (pdmPrivate->csdata.dwX / DEVMODE_PAPER_UNIT);
pdm->dmPaperLength = (SHORT) (pdmPrivate->csdata.dwY / DEVMODE_PAPER_UNIT);
ZeroMemory(pdm->dmFormName, sizeof(pdm->dmFormName));
if (prclImageArea)
{
prclImageArea->left =
prclImageArea->top = 0;
prclImageArea->right = pdmPrivate->csdata.dwX;
prclImageArea->bottom = pdmPrivate->csdata.dwY;
}
return TRUE;
}
return FALSE;
}
VOID
VCopyUnicodeStringToAnsi(
PSTR pstr,
PCWSTR pwstr,
INT iMaxChars
)
/*++
Routine Description:
Convert an ANSI string to a UNICODE string (using the current ANSI codepage)
Arguments:
pstr - Pointer to buffer for holding ANSI string
pwstr - Pointer to Unicode string
iMaxChars - Maximum number of ANSI characters to copy
Return Value:
NONE
Note:
If iMaxChars is 0 or negative, we assume the caller has provided
an ANSI buffer that's sufficiently large to do the conversion.
--*/
{
INT iLen = wcslen(pwstr) + 1;
if (iMaxChars <= 0)
iMaxChars = iLen;
#ifdef KERNEL_MODE
(VOID) EngUnicodeToMultiByteN(pstr, iMaxChars, NULL, (PWSTR) pwstr, iLen*sizeof(WCHAR));
#else // !KERNEL_MODE
(VOID) WideCharToMultiByte(CP_ACP, 0, pwstr, iLen, pstr, iMaxChars, NULL, NULL);
#endif
pstr[iMaxChars - 1] = NUL;
}
FORM_TRAY_TABLE
PGetAndConvertOldVersionFormTrayTable(
IN HANDLE hPrinter,
OUT PDWORD pdwSize
)
/*++
Routine Description:
Retrieve the old form-to-tray assignment table from registry and convert
it to the new format for the caller.
Arguments:
hPrinter - Handle to the printer object
pdwSize - Returns the form-to-tray assignment table size
Return Value:
Pointer to form-to-tray assignment table read from the registry
NULL if there is an error
--*/
{
PTSTR ptstrNewTable;
PTSTR ptstrOld, ptstrEnd, ptstrNew, ptstrSave;
DWORD dwTableSize, dwNewTableSize;
FORM_TRAY_TABLE pFormTrayTable;
//
// Retrieve the form-to-tray assignment information from registry
//
pFormTrayTable = PvGetPrinterDataBinary(hPrinter,
REGVAL_TRAY_FORM_SIZE_PS40,
REGVAL_TRAY_FORM_TABLE_PS40,
&dwTableSize);
if (pFormTrayTable == NULL)
return NULL;
//
// Simple validation to make sure the information is valid
// Old format contains the table size as the first field in table
//
if (dwTableSize != *pFormTrayTable)
{
ERR(("Corrupted form-to-tray assignment table!\n"));
SetLastError(ERROR_INVALID_DATA);
MemFree(pFormTrayTable);
return NULL;
}
//
// Convert the old format form-to-tray assignment table to new format
// OLD NEW
// Tray Name Tray Name
// Form Name Form Name
// Printer Form
// IsDefaultTray
//
//
// The first WCHAR hold the size of the table
//
dwTableSize -= sizeof(WCHAR);
ptstrOld = pFormTrayTable + 1;
ptstrEnd = ptstrOld + (dwTableSize / sizeof(WCHAR) - 1);
//
// Figuring out the size of new table, the last entry in the table
// is always a NUL so add the count for it here first
//
dwNewTableSize = 1;
while (ptstrOld < ptstrEnd && *ptstrOld != NUL)
{
ptstrSave = ptstrOld;
ptstrOld += _tcslen(ptstrOld) + 1;
ptstrOld += _tcslen(ptstrOld) + 1;
//
// New format contain only TrayName and FormName
//
dwNewTableSize += (DWORD)(ptstrOld - ptstrSave);
//
// Skip printer form and IsDefaultTray flag
//
ptstrOld += _tcslen(ptstrOld) + 2;
}
dwNewTableSize *= sizeof(WCHAR);
if ((ptstrOld != ptstrEnd) ||
(*ptstrOld != NUL) ||
(ptstrNewTable = MemAlloc(dwNewTableSize)) == NULL)
{
ERR(( "Couldn't convert form-to-tray assignment table.\n"));
MemFree(pFormTrayTable);
return NULL;
}
//
// The first WCHAR contains the table size
//
ptstrOld = pFormTrayTable + 1;
ptstrNew = ptstrNewTable;
while (*ptstrOld != NUL)
{
//
// Copy slot name, form name
//
ptstrSave = ptstrOld;
ptstrOld += _tcslen(ptstrOld) + 1;
ptstrOld += _tcslen(ptstrOld) + 1;
CopyMemory(ptstrNew, ptstrSave, (ptstrOld - ptstrSave) * sizeof(WCHAR));
ptstrNew += (ptstrOld - ptstrSave);
//
// skip printer form and IsDefaultTray flag
//
ptstrOld += _tcslen(ptstrOld) + 2;
}
//
// The last WCHAR is a NUL-terminator
//
*ptstrNew = NUL;
if (pdwSize)
*pdwSize = dwNewTableSize;
MemFree(pFormTrayTable);
ASSERT(BVerifyMultiSZPair(ptstrNewTable, dwNewTableSize));
return(ptstrNewTable);
}
#ifndef KERNEL_MODE
BOOL
BSaveAsOldVersionFormTrayTable(
IN HANDLE hPrinter,
IN FORM_TRAY_TABLE pFormTrayTable,
IN DWORD dwSize
)
/*++
Routine Description:
Save form-to-tray assignment table in NT 4.0 compatible format
Arguments:
hPrinter - Handle to the current printer
pFormTrayTable - Points to new format form-tray table
dwSize - Size of form-tray table to be saved, in bytes
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dwOldTableSize;
PTSTR ptstrNew, ptstrOld, ptstrOldTable;
BOOL bResult;
//
// Find out how much memory to allocate for old format table
// Old format table has size as its very first character
//
ASSERT((dwSize % sizeof(TCHAR)) == 0 && dwSize >= sizeof(TCHAR));
dwOldTableSize = dwSize + sizeof(WCHAR);
ptstrNew = pFormTrayTable;
while (*ptstrNew != NUL)
{
//
// Skip tray name and form name
//
ptstrNew += _tcslen(ptstrNew) + 1;
ptstrNew += _tcslen(ptstrNew) + 1;
//
// Old format has two extra characters per entry
// one for the empty PrinterForm field
// another for IsDefaultTray flag
//
dwOldTableSize += 2 * sizeof(TCHAR);
}
if ((ptstrOldTable = MemAlloc(dwOldTableSize)) == NULL)
{
ERR(("Memory allocation failed\n"));
return FALSE;
}
//
// Convert new format table to old format
// Be careful about the IsDefaultTray flag
//
ptstrNew = pFormTrayTable;
ptstrOld = ptstrOldTable;
*ptstrOld++ = (TCHAR) dwOldTableSize;
while (*ptstrNew != NUL)
{
//
// Copy slot name and form name
//
FINDFORMTRAY FindData;
DWORD dwCount;
PTSTR ptstrTrayName, ptstrFormName;
ptstrTrayName = ptstrNew;
ptstrNew += _tcslen(ptstrNew) + 1;
ptstrFormName = ptstrNew;
ptstrNew += _tcslen(ptstrNew) + 1;
CopyMemory(ptstrOld, ptstrTrayName, (ptstrNew - ptstrTrayName) * sizeof(TCHAR));
ptstrOld += (ptstrNew - ptstrTrayName);
//
// Set PrinterForm field to NUL
//
*ptstrOld++ = NUL;
//
// Set IsDefaultTray flag appropriately
//
dwCount = 0;
RESET_FINDFORMTRAY(pFormTrayTable, &FindData);
while (BSearchFormTrayTable(pFormTrayTable, NULL, ptstrFormName, &FindData))
dwCount++;
*ptstrOld++ = (dwCount == 1) ? TRUE : FALSE;
}
//
// The last character is a NUL-terminator
//
*ptstrOld = NUL;
bResult = BSetPrinterDataBinary(
hPrinter,
REGVAL_TRAY_FORM_SIZE_PS40,
REGVAL_TRAY_FORM_TABLE_PS40,
ptstrOldTable,
dwOldTableSize);
MemFree(ptstrOldTable);
return bResult;
}
#endif // !KERNEL_MODE
BOOL
BGetDevmodeSettingForOEM(
IN PDEVMODE pdm,
IN DWORD dwIndex,
OUT PVOID pOutput,
IN DWORD cbSize,
OUT PDWORD pcbNeeded
)
/*++
Routine Description:
Function to provide OEM plugins access to driver private devmode settings
Arguments:
pdm - Points to the devmode to be access
dwIndex - Predefined index to specify which devmode the caller is interested in
pOutput - Points to output buffer
cbSize - Size of output buffer
pcbNeeded - Returns the expected size of output buffer
Return Value:
TRUE if successful, FALSE if there is an error
--*/
#define MAPPSDEVMODEFIELD(index, field) \
{ index, offsetof(PSDRVEXTRA, field), sizeof(pdmPrivate->field) }
{
PPSDRVEXTRA pdmPrivate;
INT i;
static const struct {
DWORD dwIndex;
DWORD dwOffset;
DWORD dwSize;
} aIndexMap[] = {
MAPPSDEVMODEFIELD(OEMGDS_PSDM_FLAGS, dwFlags),
MAPPSDEVMODEFIELD(OEMGDS_PSDM_DIALECT, iDialect),
MAPPSDEVMODEFIELD(OEMGDS_PSDM_TTDLFMT, iTTDLFmt),
MAPPSDEVMODEFIELD(OEMGDS_PSDM_NUP, iLayout),
MAPPSDEVMODEFIELD(OEMGDS_PSDM_PSLEVEL, iPSLevel),
MAPPSDEVMODEFIELD(OEMGDS_PSDM_CUSTOMSIZE, csdata),
{ 0, 0, 0 }
};
pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
i = 0;
while (aIndexMap[i].dwSize != 0)
{
if (aIndexMap[i].dwIndex == dwIndex)
{
*pcbNeeded = aIndexMap[i].dwSize;
if (cbSize < aIndexMap[i].dwSize || pOutput == NULL)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
CopyMemory(pOutput, (PBYTE) pdmPrivate + aIndexMap[i].dwOffset, aIndexMap[i].dwSize);
return TRUE;
}
i++;
}
WARNING(("Unknown pscript devmode index: %d\n", dwIndex));
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
BOOL
BConvertPrinterPropertiesData(
IN HANDLE hPrinter,
IN PRAWBINARYDATA pRawData,
OUT PPRINTERDATA pPrinterData,
IN PVOID pvSrcData,
IN DWORD dwSrcSize
)
/*++
Routine Description:
Convert an older or newer version PRINTERDATA structure to current version
Arguments:
hPrinter - Handle to the current printer
pRawData - Points to raw printer description data
pPrinterData - Points to destination buffer
pvSrcData - Points to source data to be converted
dwSrcSize - Size of the source data in bytes
Return Value:
TRUE if conversion was successful, FALSE otherwise
Note:
This function is called after the library function has already
done a generic conversion.
--*/
{
PPS4_PRINTERDATA pSrc = pvSrcData;
PPPDDATA pPpdData;
//
// Check if the source PRINTERDATA was from NT4 PS driver
//
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
ASSERT(pPpdData != NULL);
if (dwSrcSize != sizeof(PS4_PRINTERDATA) ||
dwSrcSize != pSrc->wSize ||
pSrc->wDriverVersion != PSDRIVER_VERSION_400 ||
pSrc->wChecksum != pPpdData->dwNt4Checksum)
{
return FALSE;
}
//
// Convert PS4 feature/option selections to PS4 format
//
VConvertOptSelectArray(pRawData,
pPrinterData->aOptions,
MAX_PRINTER_OPTIONS,
pSrc->options,
64,
MODE_PRINTER_STICKY);
return TRUE;
}
VOID
VUpdatePrivatePrinterData(
IN HANDLE hPrinter,
IN OUT PPRINTERDATA pPrinterData,
IN DWORD dwMode,
IN PUIINFO pUIInfo,
IN POPTSELECT pCombineOptions
)
/*++
Routine Description:
Update the Registry with the keyword/value pairs
of PRINTERDATA's fixed fields.
Arguments:
hPrinter - Handle to the current printer
pPrinterData - Points to PRINTERDATA
dwMode - MODE_READ/MODE_WRITE
Return Value:
None
--*/
{
DWORD dwValue, dwMinFreeMem;
#ifdef KERNEL_MODE
ASSERT(dwMode == MODE_READ);
#endif
//
// read/write PRINTERDATA fields from/to registry
//
if (dwMode == MODE_READ)
{
if (BGetPrinterDataDWord(hPrinter, REGVAL_FREEMEM, &dwValue))
{
//
// REGVAL_FREEMEM is in unit of Kbyte, we need to convert it to byte.
// Also make sure the value is not less than the minimum value we required.
//
dwMinFreeMem = pUIInfo->dwLangLevel < 2 ? MIN_FREEMEM_L1: MIN_FREEMEM_L2;
pPrinterData->dwFreeMem = max(dwValue * KBYTES, dwMinFreeMem);
}
if (BGetPrinterDataDWord(hPrinter, REGVAL_JOBTIMEOUT, &dwValue))
{
pPrinterData->dwJobTimeout = dwValue;
}
if (BGetPrinterDataDWord(hPrinter, REGVAL_PROTOCOL, &dwValue))
{
pPrinterData->wProtocol = (WORD)dwValue;
if (pPrinterData->wProtocol != PROTOCOL_ASCII &&
pPrinterData->wProtocol != PROTOCOL_BCP &&
pPrinterData->wProtocol != PROTOCOL_TBCP &&
pPrinterData->wProtocol != PROTOCOL_BINARY)
{
pPrinterData->wProtocol = PROTOCOL_ASCII;
}
}
}
#ifndef KERNEL_MODE
else
{
ASSERT(dwMode == MODE_WRITE);
//
// Remember to convert byte to Kbyte for REGVAL_FREEMEM
//
(VOID) BSetPrinterDataDWord(hPrinter, REGVAL_FREEMEM, pPrinterData->dwFreeMem / KBYTES);
(VOID) BSetPrinterDataDWord(hPrinter, REGVAL_JOBTIMEOUT, pPrinterData->dwJobTimeout);
(VOID) BSetPrinterDataDWord(hPrinter, REGVAL_PROTOCOL, (DWORD)pPrinterData->wProtocol);
}
#endif // !KERNEL_MODE
}
VOID
VDefaultDevmodeFormFields(
PUIINFO pUIInfo,
PDEVMODE pDevmode,
BOOL bMetric
)
/*++
Routine Description:
Initialized the form-related devmode fields with their default values
Arguments:
pUIInfo - Points for UIINFO
pDevmode - Points to the DEVMODE whose form-related fields are to be initialized
bMetric - Specifies whether the system is running in metric mode
Return Value:
NONE
--*/
{
ASSERT(pUIInfo);
if (!(bMetric && (pUIInfo->dwFlags & FLAG_A4_SIZE_EXISTS)) &&
!(!bMetric && (pUIInfo->dwFlags & FLAG_LETTER_SIZE_EXISTS)))
{
PFEATURE pFeature;
PPAGESIZE pPageSize;
PCWSTR pDisplayName;
//
// A4 or Letter not available. Use the printer's default paper size.
//
if ((pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE)) &&
(pPageSize = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex)) &&
(pDisplayName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pPageSize->GenericOption.loDisplayName)))
{
CopyString(pDevmode->dmFormName, pDisplayName, CCHFORMNAME);
pDevmode->dmPaperSize = (short)(pPageSize->dwPaperSizeID);
pDevmode->dmPaperWidth = (short)(pPageSize->szPaperSize.cx / DEVMODE_PAPER_UNIT);
pDevmode->dmPaperLength = (short)(pPageSize->szPaperSize.cy / DEVMODE_PAPER_UNIT);
//
// PPD parser always assigns custom paper size values to dwPaperSizeID (see ppdparse.c), including for
// standard page sizes, so we need to use dmPaperSize/dmPaperWidth in devmode instead of dmPaperSize.
//
pDevmode->dmFields |= (DM_FORMNAME | DM_PAPERWIDTH | DM_PAPERLENGTH);
pDevmode->dmFields &= ~DM_PAPERSIZE;
//
// return when we succeeded, otherwise we will fall into the default A4 or Letter case
//
return;
}
else
{
ERR(("Failed to get default paper size from PPD\n"));
}
}
if (bMetric)
{
CopyString(pDevmode->dmFormName, A4_FORMNAME, CCHFORMNAME);
pDevmode->dmPaperSize = DMPAPER_A4;
pDevmode->dmPaperWidth = 2100; // 210mm measured in 0.1mm units
pDevmode->dmPaperLength = 2970; // 297mm
}
else
{
CopyString(pDevmode->dmFormName, LETTER_FORMNAME, CCHFORMNAME);
pDevmode->dmPaperSize = DMPAPER_LETTER;
pDevmode->dmPaperWidth = 2159; // 8.5"
pDevmode->dmPaperLength = 2794; // 11"
}
pDevmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
pDevmode->dmFields |= (DM_PAPERSIZE | DM_FORMNAME);
}
#if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
typedef struct _VMERRMSGIDTBL
{
LANGID lgid; // Language ID
DWORD resid; // VM error handler resource ID
}
VMERRMSGIDTBL, *PVMERRMSGIDTBL;
VMERRMSGIDTBL VMErrMsgIDTbl[] =
{
// Lang. ID Res. ID
{ LANG_CHINESE, 0 }, // Chinense: use sub table below
{ LANG_DANISH, PSPROC_vmerr_Danish_ps }, // Danish Adobe bug#342407
{ LANG_DUTCH, PSPROC_vmerr_Dutch_ps }, // Dutch
{ LANG_FINNISH, PSPROC_vmerr_Finnish_ps }, // Finnish Adobe bug#342407
{ LANG_FRENCH, PSPROC_vmerr_French_ps }, // French
{ LANG_GERMAN, PSPROC_vmerr_German_ps }, // German
{ LANG_ITALIAN, PSPROC_vmerr_Italian_ps }, // Italian
{ LANG_JAPANESE, PSPROC_vmerr_Japanese_ps }, // Japanese
{ LANG_KOREAN, PSPROC_vmerr_Korean_ps }, // Korean
{ LANG_NORWEGIAN, PSPROC_vmerr_Norwegian_ps }, // Norwegian Adobe bug#342407
{ LANG_PORTUGUESE, PSPROC_vmerr_Portuguese_ps }, // Portuguese
{ LANG_SPANISH, PSPROC_vmerr_Spanish_ps }, // Spanish
{ LANG_SWEDISH, PSPROC_vmerr_Swedish_ps }, // Swedish
{ 0, 0 } // Stopper. Don't remove this.
};
VMERRMSGIDTBL VMErrMsgIDTbl2[] =
{
// Sub lang. ID Res. ID
{ SUBLANG_CHINESE_TRADITIONAL, PSPROC_vmerr_TraditionalChinese_ps }, // Taiwan
{ SUBLANG_CHINESE_SIMPLIFIED, PSPROC_vmerr_SimplifiedChinese_ps }, // PRC
{ SUBLANG_CHINESE_HONGKONG, PSPROC_vmerr_TraditionalChinese_ps }, // Hong Kong
{ SUBLANG_CHINESE_SINGAPORE, PSPROC_vmerr_SimplifiedChinese_ps }, // Singapore
{ 0, 0 } // Stopper. Don't remove this.
};
DWORD
DWGetVMErrorMessageID(
VOID
)
/*++
Routine Description:
Get the VM Error message ID calculated from the current user's locale.
Arguments:
None
Return Value:
The VM Error message ID.
--*/
{
LANGID lgid;
WORD wPrim, wSub;
DWORD dwVMErrorMessageID;
PVMERRMSGIDTBL pTbl, pTbl2;
dwVMErrorMessageID = 0;
lgid = GetSystemDefaultLangID();
wPrim = PRIMARYLANGID(lgid);
for (pTbl = VMErrMsgIDTbl; pTbl->lgid && !dwVMErrorMessageID; pTbl++)
{
if (pTbl->lgid == wPrim)
{
if (pTbl->resid)
{
dwVMErrorMessageID = pTbl->resid;
break;
}
else
{
wSub = SUBLANGID(lgid);
for (pTbl2 = VMErrMsgIDTbl2; pTbl2->lgid; pTbl2++)
{
if (pTbl2->lgid == wSub)
{
dwVMErrorMessageID = pTbl2->resid;
break;
}
}
}
}
}
return dwVMErrorMessageID;
}
#endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)