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.
 
 
 
 
 
 

3801 lines
98 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
All rights reserved.
Module Name:
getsetop.c
Abstract:
PostScript helper functions for OEM plugins
HGetOptions
Author:
Feng Yue (fengy)
8/24/2000 fengy Completed with support of both PPD and driver features.
8/1/2000 fengy Created it with function framework.
--*/
#include "lib.h"
#include "ppd.h"
#include "pslib.h"
//
// PS driver's helper functions for OEM plugins
//
//
// synthesized PS driver features
//
const CHAR kstrPSFAddEuro[] = "%AddEuro";
const CHAR kstrPSFCtrlDAfter[] = "%CtrlDAfter";
const CHAR kstrPSFCtrlDBefore[] = "%CtrlDBefore";
const CHAR kstrPSFCustomPS[] = "%CustomPageSize";
const CHAR kstrPSFTrueGrayG[] = "%GraphicsTrueGray";
const CHAR kstrPSFJobTimeout[] = "%JobTimeout";
const CHAR kstrPSFMaxBitmap[] = "%MaxFontSizeAsBitmap";
const CHAR kstrPSFEMF[] = "%MetafileSpooling";
const CHAR kstrPSFMinOutline[] = "%MinFontSizeAsOutline";
const CHAR kstrPSFMirroring[] = "%Mirroring";
const CHAR kstrPSFNegative[] = "%Negative";
const CHAR kstrPSFPageOrder[] = "%PageOrder";
const CHAR kstrPSFNup[] = "%PagePerSheet";
const CHAR kstrPSFErrHandler[] = "%PSErrorHandler";
const CHAR kstrPSFPSMemory[] = "%PSMemory";
const CHAR kstrPSFOrientation[] = "%Orientation";
const CHAR kstrPSFOutFormat[] = "%OutputFormat";
const CHAR kstrPSFOutProtocol[] = "%OutputProtocol";
const CHAR kstrPSFOutPSLevel[] = "%OutputPSLevel";
const CHAR kstrPSFTrueGrayT[] = "%TextTrueGray";
const CHAR kstrPSFTTFormat[] = "%TTDownloadFormat";
const CHAR kstrPSFWaitTimeout[] = "%WaitTimeout";
//
// commonly used keyword strings
//
const CHAR kstrKwdTrue[] = "True";
const CHAR kstrKwdFalse[] = "False";
#define MAX_WORD_VALUE 0x7fff
#define MAX_DWORD_VALUE 0x7fffffff
#define RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode) \
if ((dwMode) == PSFPROC_ENUMOPTION_MODE) \
{ \
SetLastError(ERROR_NOT_SUPPORTED); \
return FALSE; \
}
/*++
Routine Name:
BOutputFeatureOption
Routine Description:
output one pair of feature keyword and option keyword names
Arguments:
pszFeature - feature keyword name
pszOption - option keyword name
pmszOutBuf - pointer to output data buffer
cbRemain - remaining output data buffer size in bytes
pcbNeeded - buffer size in bytes needed to output the keyword pair
Return Value:
TRUE if succeeds
FALSE if output data buffer size is not big enough
Last Error:
ERROR_INSUFFICIENT_BUFFER if FALSE is returned
--*/
BOOL
BOutputFeatureOption(
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded
)
{
DWORD cbFeatureSize, cbOptionSize;
ASSERT(pszFeature && pszOption);
cbFeatureSize = strlen(pszFeature) + 1;
cbOptionSize = strlen(pszOption) + 1;
if (pcbNeeded)
{
*pcbNeeded = cbFeatureSize + cbOptionSize;
}
if (!pmszOutBuf || cbRemain < (INT)(cbFeatureSize + cbOptionSize))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
CopyMemory(pmszOutBuf, pszFeature, cbFeatureSize);
pmszOutBuf += cbFeatureSize;
CopyMemory(pmszOutBuf, pszOption, cbOptionSize);
return TRUE;
}
/*++
Routine Name:
BReadBooleanOption
Routine Description:
return boolean value specified by the option keyword name
Arguments:
pszOption - option keyword name
pbValue - pointer to the variable to store returned boolean value
Return Value:
TRUE if the read operation succeeds
FALSE otherwise
Last Error:
None
--*/
BOOL
BReadBooleanOption(
IN PCSTR pszOption,
OUT PBOOL pbValue
)
{
BOOL bReadOK = TRUE;
ASSERT(pszOption && pbValue);
if (strcmp(pszOption, kstrKwdTrue) == EQUAL_STRING)
{
*pbValue = TRUE;
}
else if (strcmp(pszOption, kstrKwdFalse) == EQUAL_STRING)
{
*pbValue = FALSE;
}
else
{
bReadOK = FALSE;
}
return bReadOK;
}
/*++
Routine Name:
BGetSetBoolFlag
Routine Description:
get or set a feature's boolean setting
Arguments:
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pdwValue - pointer to DWORD data that stores the feature's setting
dwFlagBit - flag bit value to indicate the feature's setting is TRUE
bValid - TRUE if get/set on the feature's setting is supported. FALSE otherwise.
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the boolean setting
bSetMode - TRUE for set operation, FALSE for get operation
Return Value:
TRUE if the get or set operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER (set only) if FALSE is returned because set operation
is not supported, or set operation found invalid argument
ERROR_INSUFFICIENT_BUFFER (get only) see BOutputFeatureOption
--*/
BOOL
BGetSetBoolFlag(
IN PCSTR pszFeature,
IN PCSTR pszOption,
IN PDWORD pdwValue,
IN DWORD dwFlagBit,
IN BOOL bValid,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN BOOL bSetMode
)
{
BOOL bFlagSet;
ASSERT(pdwValue);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
if (!bValid ||
!BReadBooleanOption(pszOption, &bFlagSet))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (bFlagSet)
{
*pdwValue |= dwFlagBit;
}
else
{
*pdwValue &= ~dwFlagBit;
}
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
if (bValid && (*pdwValue & dwFlagBit))
{
bFlagSet = TRUE;
}
else
{
bFlagSet = FALSE;
}
return BOutputFeatureOption(pszFeature,
bFlagSet ? kstrKwdTrue : kstrKwdFalse,
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BReadUnsignedInt
Routine Description:
return unsigned integer value specified in the input data buffer
Arguments:
pcstrArgument - pointer to the input data buffer, where UINT value(s) are
represented as string of digit characters
bSingleArgument - TRUE if only one UINT should be read from the input data
FALSE if multiple UINTs can be read from the input data
pdwValue - pointer to the variable to store returned unsigned integer value
Return Value:
NULL read failed due to invalid characters in the digit string
non-NULL read succeeds. The new pointer position in the input data buffer
after one UINT is read will be returned.
Last Error:
None
--*/
PCSTR
PReadUnsignedInt(
IN PCSTR pcstrArgument,
IN BOOL bSingleArgument,
OUT PDWORD pdwValue
)
{
DWORD dwTemp = 0;
ASSERT(pcstrArgument && pdwValue);
//
// skip any preceding white spaces
//
while (*pcstrArgument == ' ' || *pcstrArgument == '\t')
{
pcstrArgument++;
}
//
// the first non-white space character must be a digit
//
if (!(*pcstrArgument >= '0' && *pcstrArgument <= '9'))
{
ERR(("first non-white space character is not a digit\n"));
return NULL;
}
//
// read in the digits
//
while (*pcstrArgument >= '0' && *pcstrArgument <= '9')
{
dwTemp = dwTemp * 10 + *pcstrArgument - '0';
pcstrArgument++;
}
if (bSingleArgument)
{
//
// any remaing characters must be white spaces
//
while (*pcstrArgument)
{
if (*pcstrArgument != ' ' && *pcstrArgument != '\t')
{
ERR(("character after digits is not white space\n"));
return NULL;
}
pcstrArgument++;
}
}
else
{
//
// skip any remaining white spaces
//
while (*pcstrArgument == ' ' || *pcstrArgument == '\t')
{
pcstrArgument++;
}
}
*pdwValue = dwTemp;
return pcstrArgument;
}
/*++
Routine Name:
BGetSetUnsignedInt
Routine Description:
get or set a feature's unsigned integer setting
Arguments:
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pdwValue - pointer to DWORD data that stores the feature's setting
dwMaxVal - maximum valid UINT value for the feature's setting
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the UINT setting
bSetMode - TRUE for set operation, FALSE for get operation
Return Value:
TRUE if the get or set operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER (set only) if set operation failed because of
invalid character(s) in the digit character string
ERROR_INSUFFICIENT_BUFFER (get only) see BOutputFeatureOption
--*/
BOOL
BGetSetUnsignedInt(
IN PCSTR pszFeature,
IN PCSTR pszOption,
IN OUT PDWORD pdwValue,
IN DWORD dwMaxVal,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN BOOL bSetMode
)
{
ASSERT(pdwValue);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
DWORD dwTemp;
if (!PReadUnsignedInt(pszOption, TRUE, &dwTemp) ||
dwTemp > dwMaxVal)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*pdwValue = dwTemp;
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
CHAR pszValue[16];
_ultoa(*pdwValue, pszValue, 10);
return BOutputFeatureOption(pszFeature,
pszValue,
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BPSFProc_AddEuro
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_AddEuro(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
BOOL bValid, bResult;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
//
bValid = pUIInfo->dwLangLevel >= 2;
bResult = BGetSetBoolFlag(pszFeature,
pszOption,
&(pPrinterData->dwFlags),
PFLAGS_ADD_EURO,
bValid,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode && bResult)
{
pPrinterData->dwFlags |= PFLAGS_EURO_SET;
}
#endif // !KERNEL_MODE
return bResult;
}
/*++
Routine Name:
BPSFProc_CtrlDA
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_CtrlDA(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
//
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pPrinterData->dwFlags),
PFLAGS_CTRLD_AFTER,
TRUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_CtrlDB
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_CtrlDB(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
//
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pPrinterData->dwFlags),
PFLAGS_CTRLD_BEFORE,
TRUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_CustomPS
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER if get/set of the feature setting is not supported,
or set operation found invalid arguments
ERROR_INSUFFICIENT_BUFFER (get only) if output data buffer size is not big enough
--*/
BOOL
BPSFProc_CustomPS(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
typedef struct _PSF_CUSTOMFEED_ENTRY {
PCSTR pszFeedName; // feed direction name
DWORD dwFeedDirection; // feed direction code
} PSF_CUSTOMFEED_ENTRY, *PPSF_CUSTOMFEED_ENTRY;
static const PSF_CUSTOMFEED_ENTRY kPSF_CustomFeedTable[] =
{
{"LongEdge", LONGEDGEFIRST},
{"ShortEdge", SHORTEDGEFIRST},
{"LongEdgeFlip", LONGEDGEFIRST_FLIPPED},
{"ShortEdgeFlip", SHORTEDGEFIRST_FLIPPED},
{NULL, 0},
};
PPSF_CUSTOMFEED_ENTRY pEntry, pMatchEntry;
PPSDRVEXTRA pdmPrivate;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
//
// This feature is supported when the printer supports custom
// page size AND current custom page size is currently selected
//
// For reason of following check, refer to BPackItemFormName in
// docprop.c and BDisplayPSCustomPageSizeDialog in custsize.c.
//
if (!SUPPORT_CUSTOMSIZE(pUIInfo) ||
!SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData) ||
pdm->dmPaperSize != DMPAPER_CUSTOMSIZE)
{
ERR(("custom size not supported/selected: dmPaperSize=%d, mode=%d\n", pdm->dmPaperSize, bSetMode));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pMatchEntry = NULL;
pEntry = (PPSF_CUSTOMFEED_ENTRY)&(kPSF_CustomFeedTable[0]);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
PCSTR pcstrArgument = pszOption;
CUSTOMSIZEDATA csdata;
BOOL bResult;
if ((pcstrArgument = PReadUnsignedInt(pcstrArgument,
FALSE,
&(csdata.dwX))) &&
(pcstrArgument = PReadUnsignedInt(pcstrArgument,
FALSE,
&(csdata.dwY))) &&
(pcstrArgument = PReadUnsignedInt(pcstrArgument,
FALSE,
&(csdata.dwWidthOffset))) &&
(pcstrArgument = PReadUnsignedInt(pcstrArgument,
FALSE,
&(csdata.dwHeightOffset))))
{
while (pEntry->pszFeedName)
{
if ((*pcstrArgument == *(pEntry->pszFeedName)) &&
(strcmp(pcstrArgument, pEntry->pszFeedName) == EQUAL_STRING))
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
if (!pMatchEntry)
{
//
// unrecognized feed direction name
//
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// All arguments are recognized. Save into private devmode and do validation.
//
pdmPrivate->csdata.wFeedDirection = (WORD)pMatchEntry->dwFeedDirection;
pdmPrivate->csdata.dwX = POINT_TO_MICRON(csdata.dwX);
pdmPrivate->csdata.dwY = POINT_TO_MICRON(csdata.dwY);
pdmPrivate->csdata.dwWidthOffset = POINT_TO_MICRON(csdata.dwWidthOffset);
pdmPrivate->csdata.dwHeightOffset = POINT_TO_MICRON(csdata.dwHeightOffset);
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
bResult = BValidateCustomPageSizeData((PRAWBINARYDATA)(pUIInfo->pInfoHeader),
&(pdmPrivate->csdata));
if (!bResult)
{
VERBOSE(("Set: custom page size input arguments are adjusted\n"));
}
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
DWORD cbFeatureSize, cbNeeded, cbFeedNameSize;
INT iIndex;
ASSERT(pszFeature);
cbNeeded = 0;
//
// frist output the feature keyword
//
cbFeatureSize = strlen(pszFeature) + 1;
if (pmszOutBuf && (cbRemain >= (INT)cbFeatureSize))
{
CopyMemory(pmszOutBuf, pszFeature, cbFeatureSize);
pmszOutBuf += cbFeatureSize;
}
cbRemain -= cbFeatureSize;
cbNeeded += cbFeatureSize;
//
// then output the 4 custom page size parameters
//
for (iIndex = 0; iIndex < 4; iIndex++)
{
DWORD dwValue, cbValueSize;
CHAR pszValue[16];
switch (iIndex)
{
case 0:
{
dwValue = pdmPrivate->csdata.dwX;
break;
}
case 1:
{
dwValue = pdmPrivate->csdata.dwY;
break;
}
case 2:
{
dwValue = pdmPrivate->csdata.dwWidthOffset;
break;
}
case 3:
{
dwValue = pdmPrivate->csdata.dwWidthOffset;
break;
}
default:
{
RIP(("hit bad iIndex %d\n", iIndex));
break;
}
}
dwValue = MICRON_TO_POINT(dwValue);
_ultoa(dwValue, pszValue, 10);
cbValueSize = strlen(pszValue) + 1;
if (pmszOutBuf && (cbRemain >= (INT)cbValueSize))
{
//
// output the decimal value string
//
CopyMemory(pmszOutBuf, pszValue, cbValueSize);
//
// replace NUL with space as the separator between decimal value strings
//
pmszOutBuf += cbValueSize - 1;
*pmszOutBuf = ' ';
pmszOutBuf++;
}
cbRemain -= cbValueSize;
cbNeeded += cbValueSize;
}
//
// lastly output the feed direction name
//
while (pEntry->pszFeedName)
{
if (pdmPrivate->csdata.wFeedDirection == pEntry->dwFeedDirection)
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
if (!pMatchEntry)
{
RIP(("unknown wFeedDirection %d\n", pdmPrivate->csdata.wFeedDirection));
pMatchEntry = (PPSF_CUSTOMFEED_ENTRY)&(kPSF_CustomFeedTable[0]);
}
cbFeedNameSize = strlen(pMatchEntry->pszFeedName) + 1;
if (pmszOutBuf && (cbRemain >= (INT)cbFeedNameSize))
{
CopyMemory(pmszOutBuf, pMatchEntry->pszFeedName, cbFeedNameSize);
pmszOutBuf += cbFeedNameSize;
}
cbRemain -= cbFeedNameSize;
cbNeeded += cbFeedNameSize;
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
//
// check if output buffer is big enough for all of the 5 parameters
//
if (!pmszOutBuf || cbRemain < 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
}
/*++
Routine Name:
BPSFProc_TrueGrayG
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_TrueGrayG(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
//
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pPrinterData->dwFlags),
PFLAGS_TRUE_GRAY_GRAPH,
TRUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_JobTimeout
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
--*/
BOOL
BPSFProc_JobTimeout(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to VUnpackPrinterPropertiesItems in prnprop.c
// and _BPackPrinterOptions in ps.c
//
return BGetSetUnsignedInt(pszFeature,
pszOption,
&(pPrinterData->dwJobTimeout),
MAX_DWORD_VALUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_MaxBitmap
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
--*/
BOOL
BPSFProc_MaxBitmap(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
DWORD dwValue;
BOOL bResult;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
//
dwValue = pPrinterData->wMaxbitmapPPEM;
bResult = BGetSetUnsignedInt(pszFeature,
pszOption,
&dwValue,
MAX_WORD_VALUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode && bResult)
{
pPrinterData->wMaxbitmapPPEM = (WORD)dwValue;
}
#endif // !KERNEL_MODE
return bResult;
}
/*++
Routine Name:
BPSFProc_EMF
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER if get/set of the feature setting is not supported,
or set operation found invalid arguments
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_EMF(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
PPSDRVEXTRA pdmPrivate;
BOOL bResult;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
//
// refer to BPackItemEmfFeatures and VUnpackDocumentPropertiesItems
//
// We assume spooler EMF is enabled if reverse printing is supported.
// (refer to PFillUiData for how it sets pUiData->bEMFSpooling)
//
//
// On Win2K+, this feature is not supported if spooler EMF is disabled.
// On NT4, spooler doesn't support the EMF capability query, so we
// always support our driver's EMF on/off feature.
//
#ifndef WINNT_40
{
BOOL bEMFSpooling;
VGetSpoolerEmfCaps(hPrinter, NULL, &bEMFSpooling, 0, NULL);
if (!bEMFSpooling)
{
ERR(("%s not supported when spooler EMF is disabled, mode=%d", pszFeature, bSetMode));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
}
#endif // !WINNT_40
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pdmPrivate->dwFlags),
PSDEVMODE_METAFILE_SPOOL,
TRUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_MinOutline
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
--*/
BOOL
BPSFProc_MinOutline(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
DWORD dwValue;
BOOL bResult;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
//
dwValue = pPrinterData->wMinoutlinePPEM;
bResult = BGetSetUnsignedInt(pszFeature,
pszOption,
&dwValue,
MAX_WORD_VALUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode && bResult)
{
pPrinterData->wMinoutlinePPEM = (WORD)dwValue;
}
#endif // !KERNEL_MODE
return bResult;
}
/*++
Routine Name:
BPSFProc_Mirroring
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_Mirroring(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
PPSDRVEXTRA pdmPrivate;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
//
// refer to _BPackDocumentOptions and _VUnpackDocumentOptions in ps.c
//
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pdmPrivate->dwFlags),
PSDEVMODE_MIRROR,
TRUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_Negative
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_Negative(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
PPSDRVEXTRA pdmPrivate;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
//
// refer to _BPackDocumentOptions and _VUnpackDocumentOptions in ps.c
//
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pdmPrivate->dwFlags),
PSDEVMODE_NEG,
!IS_COLOR_DEVICE(pUIInfo),
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_PageOrder
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER if get/set of the feature setting is not supported,
or set operation found invalid argument
ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
enum or get operation
--*/
BOOL
BPSFProc_PageOrder(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
static const CHAR pstrPageOrder[][16] =
{
"FrontToBack",
"BackToFront",
};
PPSDRVEXTRA pdmPrivate;
INT iIndex;
BOOL bReversePrint;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
//
// option enumeration handling
//
if (dwMode == PSFPROC_ENUMOPTION_MODE)
{
DWORD cbNeeded = 0;
for (iIndex = 0; iIndex < 2; iIndex++)
{
DWORD cbOptionNameSize;
cbOptionNameSize = strlen(pstrPageOrder[iIndex]) + 1;
if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
{
CopyMemory(pmszOutBuf, pstrPageOrder[iIndex], cbOptionNameSize);
pmszOutBuf += cbOptionNameSize;
}
cbRemain -= cbOptionNameSize;
cbNeeded += cbOptionNameSize;
}
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
if (!pmszOutBuf || cbRemain < 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
//
// option get/set handling
//
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
VGetSpoolerEmfCaps(hPrinter, NULL, &bReversePrint, 0, NULL);
if (!bReversePrint)
{
ERR(("%s not supported when spooler EMF is disabled, mode=%d", pszFeature, bSetMode));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
for (iIndex = 0; iIndex < 2; iIndex++)
{
if ((*pszOption == pstrPageOrder[iIndex][0]) &&
(strcmp(pszOption, pstrPageOrder[iIndex]) == EQUAL_STRING))
{
break;
}
}
if (iIndex >= 2)
{
//
// unrecognized page order name
//
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// refer to VUnpackDocumentPropertiesItems
//
pdmPrivate->bReversePrint = iIndex != 0;
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
INT iSelection;
//
// refer to BPackItemEmfFeatures
//
iSelection = pdmPrivate->bReversePrint ? 1 : 0;
return BOutputFeatureOption(pszFeature,
pstrPageOrder[iSelection],
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BPSFProc_Nup
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
enum or get operation
--*/
BOOL
BPSFProc_Nup(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
typedef struct _PSF_NUP_ENTRY {
PCSTR pszNupName; // Nup name
LAYOUT iLayout; // Nup code
} PSF_NUP_ENTRY, *PPSF_NUP_ENTRY;
static const PSF_NUP_ENTRY kPSF_NupTable[] =
{
"1", ONE_UP,
"2", TWO_UP,
"4", FOUR_UP,
"6", SIX_UP,
"9", NINE_UP,
"16", SIXTEEN_UP,
"Booklet", BOOKLET_UP,
NULL, 0,
};
PPSF_NUP_ENTRY pEntry, pMatchEntry;
PPSDRVEXTRA pdmPrivate;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
pMatchEntry = NULL;
pEntry = (PPSF_NUP_ENTRY)&(kPSF_NupTable[0]);
//
// option enumeration handling
//
if (dwMode == PSFPROC_ENUMOPTION_MODE)
{
BOOL bEMFSpooling;
DWORD cbNeeded = 0;
VGetSpoolerEmfCaps(hPrinter, NULL, &bEMFSpooling, 0, NULL);
while (pEntry->pszNupName)
{
//
// Booklet is not supported on NT4 and only supported when
// spooler EMF is enabled on Win2K+.
//
if ((pEntry->iLayout != BOOKLET_UP) ||
bEMFSpooling)
{
DWORD cbOptionNameSize;
cbOptionNameSize = strlen(pEntry->pszNupName) + 1;
if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
{
CopyMemory(pmszOutBuf, pEntry->pszNupName, cbOptionNameSize);
pmszOutBuf += cbOptionNameSize;
}
cbRemain -= cbOptionNameSize;
cbNeeded += cbOptionNameSize;
}
pEntry++;
}
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
if (!pmszOutBuf || cbRemain < 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
//
// option get/set handling
//
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
while (pEntry->pszNupName)
{
if ((*pszOption == *(pEntry->pszNupName)) &&
(strcmp(pszOption, pEntry->pszNupName) == EQUAL_STRING))
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// refer to VUnpackDocumentPropertiesItems
//
if (!pMatchEntry)
{
//
// unrecognized Nup name
//
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pdmPrivate->iLayout = pMatchEntry->iLayout;
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
while (pEntry->pszNupName)
{
if (pdmPrivate->iLayout == pEntry->iLayout)
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// If no match, default to 1-up.
//
if (!pMatchEntry)
{
RIP(("unknown iLayout value: %d\n", pdmPrivate->iLayout));
pMatchEntry = (PPSF_NUP_ENTRY)&(kPSF_NupTable[0]);
}
//
// refer to BPackItemEmfFeatures
//
return BOutputFeatureOption(pszFeature,
pMatchEntry->pszNupName,
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BPSFProc_PSErrHandler
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_PSErrHandler(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
PPSDRVEXTRA pdmPrivate;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
//
// refer to _BPackDocumentOptions and _VUnpackDocumentOptions in ps.c
//
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pdmPrivate->dwFlags),
PSDEVMODE_EHANDLER,
TRUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_PSMemory
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
--*/
BOOL
BPSFProc_PSMemory(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
DWORD dwFreeMem;
BOOL bResult;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _BPackPrinterOptions in ps.c and
// VUnpackPrinterPropertiesItems in prnprop.c
//
dwFreeMem = pPrinterData->dwFreeMem / KBYTES;
bResult = BGetSetUnsignedInt(pszFeature,
pszOption,
&dwFreeMem,
MAX_DWORD_VALUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bResult && bSetMode)
{
DWORD dwMinimum;
//
// Make sure the PS memory is not set below the minimum required.
// (refer to _BPackPrinterOptions in ps.c)
//
dwMinimum = (pUIInfo->dwLangLevel <= 1 ? MIN_FREEMEM_L1 : MIN_FREEMEM_L2) / KBYTES;
pPrinterData->dwFreeMem = max(dwFreeMem, dwMinimum) * KBYTES;
}
#endif // !KERNEL_MODE
return bResult;
}
/*++
Routine Name:
BPSFProc_Orientation
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
enum or get operation
--*/
BOOL
BPSFProc_Orientation(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
static const CHAR pstrOrient[][32] =
{
"Portrait",
"Landscape",
"RotatedLandscape",
};
PPSDRVEXTRA pdmPrivate;
INT iIndex;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
//
// option enumeration handling
//
if (dwMode == PSFPROC_ENUMOPTION_MODE)
{
DWORD cbNeeded = 0;
for (iIndex = 0; iIndex <= 2; iIndex++)
{
DWORD cbOptionNameSize;
cbOptionNameSize = strlen(pstrOrient[iIndex]) + 1;
if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
{
CopyMemory(pmszOutBuf, pstrOrient[iIndex], cbOptionNameSize);
pmszOutBuf += cbOptionNameSize;
}
cbRemain -= cbOptionNameSize;
cbNeeded += cbOptionNameSize;
}
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
if (!pmszOutBuf || cbRemain < 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
//
// option get/set handling
//
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
for (iIndex = 0; iIndex <= 2; iIndex++)
{
if ((*pszOption == pstrOrient[iIndex][0]) &&
(strcmp(pszOption, pstrOrient[iIndex]) == EQUAL_STRING))
{
break;
}
}
if (iIndex > 2)
{
//
// unrecognized orientation name
//
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// refer to _VUnpackDocumentOptions in ps.c
//
pdm->dmFields |= DM_ORIENTATION;
pdm->dmOrientation = (iIndex == 0) ? DMORIENT_PORTRAIT :
DMORIENT_LANDSCAPE;
if (iIndex != 2)
pdmPrivate->dwFlags &= ~PSDEVMODE_LSROTATE;
else
pdmPrivate->dwFlags |= PSDEVMODE_LSROTATE;
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
INT iSelection;
//
// refer to _BPackOrientationItem in ps.c
//
if ((pdm->dmFields & DM_ORIENTATION) &&
(pdm->dmOrientation == DMORIENT_LANDSCAPE))
{
iSelection = pdmPrivate->dwFlags & PSDEVMODE_LSROTATE ? 2 : 1;
}
else
iSelection = 0;
return BOutputFeatureOption(pszFeature,
pstrOrient[iSelection],
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BPSFProc_OutFormat
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
enum or get operation
--*/
BOOL
BPSFProc_OutFormat(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
typedef struct _PSF_OUTFORMAT_ENTRY {
PCSTR pszFormatName; // output format name
DIALECT iDialect; // output format code
} PSF_OUTFORMAT_ENTRY, *PPSF_OUTFORMAT_ENTRY;
static const PSF_OUTFORMAT_ENTRY kPSF_OutFormatTable[] =
{
{"Speed", SPEED},
{"Portability", PORTABILITY},
{"EPS", EPS},
{"Archive", ARCHIVE},
{NULL, 0},
};
PPSF_OUTFORMAT_ENTRY pEntry, pMatchEntry;
PPSDRVEXTRA pdmPrivate;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
pMatchEntry = NULL;
pEntry = (PPSF_OUTFORMAT_ENTRY)&(kPSF_OutFormatTable[0]);
//
// option enumeration handling
//
if (dwMode == PSFPROC_ENUMOPTION_MODE)
{
DWORD cbNeeded = 0;
while (pEntry->pszFormatName)
{
DWORD cbOptionNameSize;
cbOptionNameSize = strlen(pEntry->pszFormatName) + 1;
if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
{
CopyMemory(pmszOutBuf, pEntry->pszFormatName, cbOptionNameSize);
pmszOutBuf += cbOptionNameSize;
}
cbRemain -= cbOptionNameSize;
cbNeeded += cbOptionNameSize;
pEntry++;
}
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
if (!pmszOutBuf || cbRemain < 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
//
// option get/set handling
//
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
while (pEntry->pszFormatName)
{
if ((*pszOption == *(pEntry->pszFormatName)) &&
(strcmp(pszOption, pEntry->pszFormatName) == EQUAL_STRING))
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// refer to _VUnpackDocumentOptions in ps.c
//
if (!pMatchEntry)
{
//
// unrecognized output format name
//
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pdmPrivate->iDialect = pMatchEntry->iDialect;
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
while (pEntry->pszFormatName)
{
if (pdmPrivate->iDialect == pEntry->iDialect)
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// If no match, default to SPEED.
//
if (!pMatchEntry)
{
RIP(("unknown iDialect value: %d\n", pdmPrivate->iDialect));
pMatchEntry = (PPSF_OUTFORMAT_ENTRY)&(kPSF_OutFormatTable[0]);
}
//
// refer to BPackItemPSOutputOption in ps.c
//
return BOutputFeatureOption(pszFeature,
pMatchEntry->pszFormatName,
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BPSFProc_Protocol
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
enum or get operation
--*/
BOOL
BPSFProc_Protocol(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
typedef struct _PSF_PROTOCOL_ENTRY {
PCSTR pszProtocolName; // output protocol name
DWORD dwProtocol; // output protocol code
} PSF_PROTOCOL_ENTRY, *PPSF_PROTOCOL_ENTRY;
static const PSF_PROTOCOL_ENTRY kPSF_ProtocolTable[] =
{
{"ASCII", PROTOCOL_ASCII},
{"BCP", PROTOCOL_BCP},
{"TBCP", PROTOCOL_TBCP},
{"Binary", PROTOCOL_BINARY},
{NULL, 0},
};
PPSF_PROTOCOL_ENTRY pEntry, pMatchEntry;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
pMatchEntry = NULL;
pEntry = (PPSF_PROTOCOL_ENTRY)&(kPSF_ProtocolTable[0]);
//
// option enumeration handling
//
if (dwMode == PSFPROC_ENUMOPTION_MODE)
{
DWORD cbNeeded = 0;
while (pEntry->pszProtocolName)
{
//
// ASCII is always supported.
//
if ((pEntry->dwProtocol == PROTOCOL_ASCII) ||
(pUIInfo->dwProtocols & pEntry->dwProtocol))
{
DWORD cbOptionNameSize;
cbOptionNameSize = strlen(pEntry->pszProtocolName) + 1;
if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
{
CopyMemory(pmszOutBuf, pEntry->pszProtocolName, cbOptionNameSize);
pmszOutBuf += cbOptionNameSize;
}
cbRemain -= cbOptionNameSize;
cbNeeded += cbOptionNameSize;
}
pEntry++;
}
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
if (!pmszOutBuf || cbRemain < 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
//
// option get/set handling
//
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
while (pEntry->pszProtocolName)
{
if ((*pszOption == *(pEntry->pszProtocolName)) &&
(strcmp(pszOption, pEntry->pszProtocolName) == EQUAL_STRING))
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// refer to _VUnpackDriverPrnPropItem in ps.c
//
if (!pMatchEntry ||
(pMatchEntry->dwProtocol != PROTOCOL_ASCII &&
!(pUIInfo->dwProtocols & pMatchEntry->dwProtocol)))
{
//
// Either unrecognized protocol name, or the protocol is not supported.
// (ASCII is always supported.)
//
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pPrinterData->wProtocol = (WORD)pMatchEntry->dwProtocol;
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
while (pEntry->pszProtocolName)
{
if (pPrinterData->wProtocol == (WORD)pEntry->dwProtocol)
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// If no match or matched protocol is not supported, default to PROTOCOL_ASCII.
//
if (!pMatchEntry)
{
RIP(("unknown wProtocol value: %d\n", pPrinterData->wProtocol));
pMatchEntry = (PPSF_PROTOCOL_ENTRY)&(kPSF_ProtocolTable[0]);
}
//
// refer to BPackPSProtocolItem in ps.c
//
if (pMatchEntry->dwProtocol != PROTOCOL_ASCII &&
!(pUIInfo->dwProtocols & pMatchEntry->dwProtocol))
{
ERR(("unsupported wProtocol value: %d\n", pPrinterData->wProtocol));
pMatchEntry = (PPSF_PROTOCOL_ENTRY)&(kPSF_ProtocolTable[0]);
}
return BOutputFeatureOption(pszFeature,
pMatchEntry->pszProtocolName,
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BPSFProc_PSLevel
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER if PSLevel is set to a negative value,
or see BGetSetUnsignedInt
ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
--*/
BOOL
BPSFProc_PSLevel(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
PPSDRVEXTRA pdmPrivate;
DWORD dwPSLevel;
BOOL bResult;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
//
// refer to _VUnpackDocumentOptions and BPackItemPSLevel in ps.c
//
dwPSLevel = (DWORD)pdmPrivate->iPSLevel;
bResult = BGetSetUnsignedInt(pszFeature,
pszOption,
&dwPSLevel,
pUIInfo->dwLangLevel,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bResult && bSetMode)
{
//
// set output PS level to 0 is not allowed
//
if (dwPSLevel > 0)
{
pdmPrivate->iPSLevel = (INT)dwPSLevel;
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
bResult = FALSE;
}
}
#endif // !KERNEL_MODE
return bResult;
}
/*++
Routine Name:
BPSFProc_TrueGrayT
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
--*/
BOOL
BPSFProc_TrueGrayT(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
//
return BGetSetBoolFlag(pszFeature,
pszOption,
&(pPrinterData->dwFlags),
PFLAGS_TRUE_GRAY_TEXT,
TRUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
/*++
Routine Name:
BPSFProc_TTFormat
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
enum or get operation
--*/
BOOL
BPSFProc_TTFormat(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
typedef struct _PSF_TTFORMAT_ENTRY {
PCSTR pszTTFmtName; // TT download format name
TTDLFMT iTTDLFmt; // TT download format enum code
} PSF_TTFORMAT_ENTRY, *PPSF_TTFORMAT_ENTRY;
static const PSF_TTFORMAT_ENTRY kPSF_TTFormatTable[] =
{
{"Automatic", TT_DEFAULT},
{"Outline", TYPE_1},
{"Bitmap", TYPE_3},
{"NativeTrueType", TYPE_42},
{NULL, 0},
};
PPSF_TTFORMAT_ENTRY pEntry, pMatchEntry;
PPSDRVEXTRA pdmPrivate;
BOOL bSupportType42;
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
bSupportType42 = pUIInfo->dwTTRasterizer == TTRAS_TYPE42;
pMatchEntry = NULL;
pEntry = (PPSF_TTFORMAT_ENTRY)&(kPSF_TTFormatTable[0]);
//
// option enumeration handling
//
if (dwMode == PSFPROC_ENUMOPTION_MODE)
{
DWORD cbNeeded = 0;
while (pEntry->pszTTFmtName)
{
if ((pEntry->iTTDLFmt != TYPE_42) ||
bSupportType42)
{
DWORD cbOptionNameSize;
cbOptionNameSize = strlen(pEntry->pszTTFmtName) + 1;
if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
{
CopyMemory(pmszOutBuf, pEntry->pszTTFmtName, cbOptionNameSize);
pmszOutBuf += cbOptionNameSize;
}
cbRemain -= cbOptionNameSize;
cbNeeded += cbOptionNameSize;
}
pEntry++;
}
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
if (!pmszOutBuf || cbRemain < 0)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
//
// option get/set handling
//
ASSERT(pdm);
pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
#ifndef KERNEL_MODE
//
// set is only supported for UI plugins
//
if (bSetMode)
{
while (pEntry->pszTTFmtName)
{
if ((*pszOption == *(pEntry->pszTTFmtName)) &&
(strcmp(pszOption, pEntry->pszTTFmtName) == EQUAL_STRING))
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// refer to _VUnpackDocumentOptions in ps.c
//
if (!pMatchEntry ||
(!bSupportType42 && pMatchEntry->iTTDLFmt == TYPE_42))
{
//
// Either unrecognized TTFormat name, or the TTFormat is not supported.
//
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pdmPrivate->iTTDLFmt = pMatchEntry->iTTDLFmt;
return TRUE;
}
#else
ASSERT(bSetMode == FALSE);
#endif // !KERNEL_MODE
//
// get is supported for both UI and render plugins
//
{
while (pEntry->pszTTFmtName)
{
if (pdmPrivate->iTTDLFmt == pEntry->iTTDLFmt)
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// If no match or matched format is not supported, default to Automatic format.
//
if (!pMatchEntry)
{
RIP(("unknown TTFormat value: %d\n", pdmPrivate->iTTDLFmt));
pMatchEntry = (PPSF_TTFORMAT_ENTRY)&(kPSF_TTFormatTable[0]);
}
//
// refer to BPackItemTTDownloadFormat in ps.c
//
if (!bSupportType42 && pMatchEntry->iTTDLFmt == TYPE_42)
{
ERR(("unsupported TTFormat value: %d\n", pdmPrivate->iTTDLFmt));
pMatchEntry = (PPSF_TTFORMAT_ENTRY)&(kPSF_TTFormatTable[0]);
}
return BOutputFeatureOption(pszFeature,
pMatchEntry->pszTTFmtName,
pmszOutBuf,
cbRemain,
pcbNeeded);
}
}
/*++
Routine Name:
BPSFProc_WaitTimeout
Routine Description:
%-feature enum/get/set operation handler
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
pPpdData - pointer to driver's PPDDATA structure
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
pszFeature - feature keyword name
pszOption - (set only) option keyword name
pmszOutBuf - (get only) pointer to output data buffer
cbRemain - (get only) remaining output data buffer size in bytes
pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
dwMode - indicate one of three operations: enum, get, set
Return Value:
TRUE if the requested operation succeeds
FALSE otherwise
Last Error:
ERROR_NOT_SUPPORTED unsupported enum operation is requested
ERROR_INVALID_PARAMETER
ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
--*/
BOOL
BPSFProc_WaitTimeout(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo,
IN PPPDDATA pPpdData,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN PCSTR pszFeature,
IN PCSTR pszOption,
OUT PSTR pmszOutBuf,
IN INT cbRemain,
OUT PDWORD pcbNeeded,
IN DWORD dwMode
)
{
BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
//
// refer to VUnpackPrinterPropertiesItems in prnprop.c
// and _BPackPrinterOptions in ps.c
//
return BGetSetUnsignedInt(pszFeature,
pszOption,
&(pPrinterData->dwWaitTimeout),
MAX_DWORD_VALUE,
pmszOutBuf,
cbRemain,
pcbNeeded,
bSetMode);
}
//
// Note: for pfnPSProc handlers whose bPrinterSticky is TRUE,
// the PDEVMODE will be NULL (see PFillUiData), so you should NOT
// access PDEVMODE.
//
const PSFEATURE_ENTRY kPSFeatureTable[] =
{
//
// pszPSFeatureName bPrinterSticky bEnumerableOptions bBooleanOptions pfnPSProc
//
{kstrPSFAddEuro, TRUE, TRUE, TRUE, BPSFProc_AddEuro},
{kstrPSFCtrlDAfter, TRUE, TRUE, TRUE, BPSFProc_CtrlDA},
{kstrPSFCtrlDBefore, TRUE, TRUE, TRUE, BPSFProc_CtrlDB},
{kstrPSFCustomPS, FALSE, FALSE, FALSE, BPSFProc_CustomPS},
{kstrPSFTrueGrayG, TRUE, TRUE, TRUE, BPSFProc_TrueGrayG},
{kstrPSFJobTimeout, TRUE, FALSE, FALSE, BPSFProc_JobTimeout},
{kstrPSFMaxBitmap, TRUE, FALSE, FALSE, BPSFProc_MaxBitmap},
{kstrPSFEMF, FALSE, TRUE, TRUE, BPSFProc_EMF},
{kstrPSFMinOutline, TRUE, FALSE, FALSE, BPSFProc_MinOutline},
{kstrPSFMirroring, FALSE, TRUE, TRUE, BPSFProc_Mirroring},
{kstrPSFNegative, FALSE, TRUE, TRUE, BPSFProc_Negative},
{kstrPSFPageOrder, FALSE, TRUE, FALSE, BPSFProc_PageOrder},
{kstrPSFNup, FALSE, TRUE, FALSE, BPSFProc_Nup},
{kstrPSFErrHandler, FALSE, TRUE, TRUE, BPSFProc_PSErrHandler},
{kstrPSFPSMemory, TRUE, FALSE, FALSE, BPSFProc_PSMemory},
{kstrPSFOrientation, FALSE, TRUE, FALSE, BPSFProc_Orientation},
{kstrPSFOutFormat, FALSE, TRUE, FALSE, BPSFProc_OutFormat},
{kstrPSFOutProtocol, TRUE, TRUE, FALSE, BPSFProc_Protocol},
{kstrPSFOutPSLevel, FALSE, FALSE, FALSE, BPSFProc_PSLevel},
{kstrPSFTrueGrayT, TRUE, TRUE, TRUE, BPSFProc_TrueGrayT},
{kstrPSFTTFormat, FALSE, TRUE, FALSE, BPSFProc_TTFormat},
{kstrPSFWaitTimeout, TRUE, FALSE, FALSE, BPSFProc_WaitTimeout},
{NULL, FALSE, FALSE, FALSE, NULL},
};
/*++
Routine Name:
PComposeFullFeatureList
Routine Description:
Allocate a buffer and fill the buffer with the full keyword list
of supported features.
Caller is responsible to free the buffer.
Arguments:
hPrinter - printer handle
pUIInfo - pointer to driver's UIINFO structure
Return Value:
NULL if failed to allocate and correctly fill the buffer
non-NULL succeeds. Pointer to the buffer containing full keyword list
of supported features will be returned.
Last Error:
None
--*/
PSTR
PComposeFullFeatureList(
IN HANDLE hPrinter,
IN PUIINFO pUIInfo
)
{
PSTR pmszFeatureList, pmszRet = NULL;
DWORD cbNeeded = 0;
HRESULT hr;
hr = HEnumFeaturesOrOptions(hPrinter,
pUIInfo->pInfoHeader,
0,
NULL,
NULL,
0,
&cbNeeded);
if (hr != E_OUTOFMEMORY || cbNeeded == 0)
{
ERR(("HEnumFeaturesOrOptions failed. hr=%X\n", hr));
goto exit;
}
if ((pmszFeatureList = MemAlloc(cbNeeded)) == NULL)
{
ERR(("memory allocation failed.\n"));
goto exit;
}
hr = HEnumFeaturesOrOptions(hPrinter,
pUIInfo->pInfoHeader,
0,
NULL,
pmszFeatureList,
cbNeeded,
&cbNeeded);
if (FAILED(hr))
{
ERR(("HEnumFeaturesOrOptions failed. hr=%X\n", hr));
MemFree(pmszFeatureList);
goto exit;
}
//
// Succeeded
//
pmszRet = pmszFeatureList;
exit:
return pmszRet;
}
/*++
Routine Name:
BValidMultiSZString
Routine Description:
validate if a given ASCII string is in MULTI_SZ format
Arguments:
pmszString - the input ASCII string that needs validation
cbSize - size in bytes of the input ASCII string
bCheckPairs - TRUE if need to validate the MULTI_SZ
string contains pairs. FALSE otherwise.
Return Value:
TRUE if the input ASCII string is in valid MULTI_SZ format
FALSE if it's not
Last Error:
None
--*/
BOOL
BValidMultiSZString(
IN PCSTR pmszString,
IN DWORD cbSize,
IN BOOL bCheckPairs
)
{
PCSTR pszEnd;
INT cTokens = 0;
if (!pmszString || !cbSize)
{
return FALSE;
}
pszEnd = pmszString + cbSize - 1;
while (*pmszString && pmszString <= pszEnd)
{
while (*pmszString && pmszString <= pszEnd)
{
pmszString++;
}
if (pmszString > pszEnd)
{
ERR(("Missing single token's NUL terminator!\n"));
return FALSE;
}
cTokens++;
pmszString++;
}
if (pmszString > pszEnd)
{
ERR(("Missing MULTI_SZ string's last NUL terminator!\n"));
return FALSE;
}
if (!bCheckPairs)
{
return TRUE;
}
else
{
return (cTokens % 2) ? FALSE : TRUE;
}
}
/*++
Routine Name:
HGetOptions
Routine Description:
get the current setting for a specified feature
For UI plugin's GetOptions call during DrvDocumentPropertySheets, or for
render plugins's GetOptions call, both doc-sticky and printer-sticky features
are supported.
For UI plugin's GetOptions call during DrvDevicePropertySheets, only
printer-sticky features are supported.
Arguments:
hPrinter - printer handle
pInfoHeader - pointer to driver's INFOHEADER structure
pOptionsArray - pointer to driver's combined option array
pdm - pointer to public DEVMODE
pPrinterData - pointer to driver's PRINTERDATA structure
dwFlags - flags for the get operation
pmszFeaturesRequested - MULTI_SZ ASCII string containing feature keyword names
cbin - size in bytes of the pmszFeaturesRequested string
pmszFeatureOptionBuf - pointer to output data buffer to store feature settings
cbSize - size in bytes of pmszFeatureOptionBuf buffer
pcbNeeded - buffer size in bytes needed to output the feature settings
bPrinterSticky - TRUE if we are in printer-sticky mode, FALSE if we are in
doc-sticky mode
Return Value:
S_OK if the get operation succeeds
E_INVALIDARG if input pmszFeaturesRequested is not in valid MULTI_SZ format
E_OUTOFMEMORY if output data buffer size is not big enough
E_FAIL if other internal failures are encountered
Last Error:
None
--*/
HRESULT
HGetOptions(
IN HANDLE hPrinter,
IN PINFOHEADER pInfoHeader,
IN POPTSELECT pOptionsArray,
IN PDEVMODE pdm,
IN PPRINTERDATA pPrinterData,
IN DWORD dwFlags,
IN PCSTR pmszFeaturesRequested,
IN DWORD cbIn,
OUT PSTR pmszFeatureOptionBuf,
IN DWORD cbSize,
OUT PDWORD pcbNeeded,
IN BOOL bPrinterSticky
)
{
PUIINFO pUIInfo;
PPPDDATA pPpdData;
HRESULT hr;
PSTR pmszFeatureList = NULL, pCurrentOut;
PCSTR pszFeature;
DWORD cbNeeded;
INT cbRemain;
pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHeader);
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER(pInfoHeader);
ASSERT(pUIInfo != NULL && pUIInfo->dwSize == sizeof(UIINFO));
ASSERT(pPpdData != NULL && pPpdData->dwSizeOfStruct == sizeof(PPDDATA));
if (pUIInfo == NULL || pPpdData == NULL)
{
hr = E_FAIL;
goto exit;
}
if (!pmszFeaturesRequested)
{
//
// client is asking for settings of all features.
//
if (!(pmszFeatureList = PComposeFullFeatureList(hPrinter, pUIInfo)))
{
hr = E_FAIL;
goto exit;
}
pszFeature = pmszFeatureList;
}
else
{
//
// client provided its specific feature list.
//
// We need to verify the MULTI_SZ input buffer first.
//
if (!BValidMultiSZString(pmszFeaturesRequested, cbIn, FALSE))
{
ERR(("Get: invalid MULTI_SZ input param\n"));
hr = E_INVALIDARG;
goto exit;
}
pszFeature = pmszFeaturesRequested;
}
pCurrentOut = pmszFeatureOptionBuf;
cbNeeded = 0;
cbRemain = (INT)cbSize;
while (*pszFeature)
{
DWORD cbFeatureKeySize;
cbFeatureKeySize = strlen(pszFeature) + 1;
if (*pszFeature == PSFEATURE_PREFIX)
{
PPSFEATURE_ENTRY pEntry, pMatchEntry;
//
// synthesized PS driver feature
//
pMatchEntry = NULL;
pEntry = (PPSFEATURE_ENTRY)(&kPSFeatureTable[0]);
while (pEntry->pszPSFeatureName)
{
if ((*pszFeature == *(pEntry->pszPSFeatureName)) &&
(strcmp(pszFeature, pEntry->pszPSFeatureName) == EQUAL_STRING))
{
pMatchEntry = pEntry;
break;
}
pEntry++;
}
//
// Both doc-sticky and printer-sticky features are supported in DOC_STICKY_MODE,
// but only printer-sticky features are supported in PRINTER_STICKY_MODE.
// (refer to comments in HEnumConstrainedOptions)
//
if (!pMatchEntry ||
(bPrinterSticky && !pMatchEntry->bPrinterSticky))
{
VERBOSE(("Get: invalid or mode-mismatched feature %s\n", pszFeature));
goto next_feature;
}
if (pMatchEntry->pfnPSProc)
{
DWORD cbPSFSize = 0;
BOOL bResult;
bResult = (pMatchEntry->pfnPSProc)(hPrinter,
pUIInfo,
pPpdData,
pdm,
pPrinterData,
pszFeature,
NULL,
pCurrentOut,
cbRemain,
&cbPSFSize,
PSFPROC_GETOPTION_MODE);
if (bResult)
{
//
// If the handler succeeded, it should have filled in the output buffer
// with correct content and return the size of buffer consumption in cbPSFSize.
//
pCurrentOut += cbPSFSize;
}
else
{
//
// If the handler failed because of insufficent output buffer, it should return
// the needed buffer size in cbPSFSize.
//
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
ERR(("Get: %%-feature handler failed on %s\n", pszFeature));
}
}
cbRemain -= cbPSFSize;
cbNeeded += cbPSFSize;
}
}
else
{
PFEATURE pFeature;
POPTION pOption;
PSTR pszOption;
DWORD dwFeatureIndex, cbOptionKeySize;
//
// PPD *OpenUI feature
//
pFeature = PGetNamedFeature(pUIInfo, pszFeature, &dwFeatureIndex);
//
// Both doc-sticky and printer-sticky features are supported in DOC_STICKY_MODE,
// but only printer-sticky features are supported in PRINTER_STICKY_MODE.
// (refer to comments in HEnumConstrainedOptions)
//
if (!pFeature ||
(bPrinterSticky && pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY))
{
VERBOSE(("Get: invalid or mode-mismatched feature %s\n", pszFeature));
goto next_feature;
}
//
// Skip GID_LEADINGEDGE, GID_USEHWMARGINS. They are not real PPD *OpenUI features.
//
if (pFeature->dwFeatureID == GID_LEADINGEDGE ||
pFeature->dwFeatureID == GID_USEHWMARGINS)
{
VERBOSE(("Get: skip feature %s\n", pszFeature));
goto next_feature;
}
pOption = PGetIndexedOption(pUIInfo, pFeature, pOptionsArray[dwFeatureIndex].ubCurOptIndex);
if (!pOption)
{
WARNING(("Get: invalid option selection for feature %s\n", pszFeature));
goto next_feature;
}
pszOption = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName);
ASSERT(pszOption);
cbOptionKeySize = strlen(pszOption) + 1;
//
// We don't support pick-many yet.
//
ASSERT(pOptionsArray[dwFeatureIndex].ubNext == NULL_OPTSELECT);
//
// At this point, we found a valid setting for the feature.
//
if (pCurrentOut && (cbRemain >= (INT)(cbFeatureKeySize + cbOptionKeySize)))
{
CopyMemory(pCurrentOut, pszFeature, cbFeatureKeySize);
pCurrentOut += cbFeatureKeySize;
CopyMemory(pCurrentOut, pszOption, cbOptionKeySize);
pCurrentOut += cbOptionKeySize;
}
cbRemain -= (cbFeatureKeySize + cbOptionKeySize);
cbNeeded += cbFeatureKeySize + cbOptionKeySize;
}
next_feature:
pszFeature += cbFeatureKeySize;
}
//
// remember the last NUL terminator for the MULTI_SZ output string
//
cbRemain--;
cbNeeded++;
if (pcbNeeded)
{
*pcbNeeded = cbNeeded;
}
if (!pCurrentOut || cbRemain < 0)
{
hr = E_OUTOFMEMORY;
goto exit;
}
*pCurrentOut = NUL;
hr = S_OK;
exit:
MemFree(pmszFeatureList);
return hr;
}