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.
562 lines
14 KiB
562 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
data.h
|
|
|
|
Abstract:
|
|
|
|
Interface to PPD/GPD parsers and deals with getting binary data.
|
|
|
|
Environment:
|
|
|
|
Windows NT Unidrv driver
|
|
|
|
Revision History:
|
|
|
|
10/15/96 -amandan-
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include "unidrv.h"
|
|
|
|
|
|
PGPDDRIVERINFO
|
|
PGetDefaultDriverInfo(
|
|
IN HANDLE hPrinter,
|
|
IN PRAWBINARYDATA pRawData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function just need to get default driverinfo
|
|
|
|
Arguments:
|
|
|
|
hPrinter - Handle to printer.
|
|
pRawData - Pointer to RAWBINARYDATA
|
|
|
|
Return Value:
|
|
|
|
Returns pUIInfo
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PINFOHEADER pInfoHeader;
|
|
|
|
//
|
|
// Set the current driver version
|
|
//
|
|
|
|
pInfoHeader = InitBinaryData(pRawData, NULL, NULL);
|
|
|
|
//
|
|
// Get GPDDRIVERINFO
|
|
//
|
|
|
|
if (pInfoHeader == NULL)
|
|
return NULL;
|
|
else
|
|
return(OFFSET_TO_POINTER(pInfoHeader, pInfoHeader->loDriverOffset));
|
|
|
|
}
|
|
|
|
|
|
|
|
PGPDDRIVERINFO
|
|
PGetUpdateDriverInfo (
|
|
IN PDEV * pPDev,
|
|
IN HANDLE hPrinter,
|
|
IN PINFOHEADER pInfoHeader,
|
|
IN POPTSELECT pOptionsArray,
|
|
IN PRAWBINARYDATA pRawData,
|
|
IN WORD wMaxOptions,
|
|
IN PDEVMODE pdmInput,
|
|
IN PPRINTERDATA pPrinterData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function calls the parser to get the updated INFOHEADER
|
|
for the binary data.
|
|
|
|
Arguments:
|
|
|
|
hPrinter Handle to printer
|
|
pOptionsArray pointer to optionsarray
|
|
pRawData Pointer to RAWBINARYDATA
|
|
wMaxOptions max count for optionsarray
|
|
pdmInput Pointer to input DEVMODE
|
|
pPrinterData Pointer to PRINTERDATA
|
|
|
|
Return Value:
|
|
|
|
PINFOHEADER , NULL if failure.
|
|
|
|
Note:
|
|
|
|
At this point the input devmode have been validated. And its option
|
|
array is either the default or its own valid array. Don't need to check
|
|
again in this function.
|
|
|
|
Once completed, this function should have filled out the pOptionsArray with
|
|
1. Combined array from PRINTERDATA and DEVMODE
|
|
2. Resolve UI Conflicts
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PUNIDRVEXTRA pdmPrivate;
|
|
POPTSELECT pDocOptions, pPrinterOptions;
|
|
RECTL rcFormImageArea;
|
|
OPTSELECT DocOptions[MAX_PRINTER_OPTIONS];
|
|
OPTSELECT PrinterOptions[MAX_PRINTER_OPTIONS];
|
|
|
|
|
|
//
|
|
// Check for PRINTERDATA.dwChecksum32, If matches with current binary data,
|
|
// Use it to combine PRINTERDATA.aOptions to combined array
|
|
//
|
|
|
|
pPrinterOptions = pPrinterData->dwChecksum32 == pRawData->dwChecksum32 ?
|
|
pPrinterData->aOptions : NULL;
|
|
|
|
if (pdmInput)
|
|
{
|
|
pdmPrivate = (PUNIDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmInput);
|
|
pDocOptions = pdmPrivate->aOptions;
|
|
}
|
|
else
|
|
pDocOptions = NULL;
|
|
|
|
//
|
|
// Combine the option arrays to pOptionsArray
|
|
// Note: pDocOptions and pPrinterOptions cannot be NULL when combining
|
|
// options array to get snapshot.
|
|
//
|
|
|
|
if (pDocOptions == NULL)
|
|
{
|
|
if (! InitDefaultOptions(pRawData,
|
|
DocOptions,
|
|
MAX_PRINTER_OPTIONS,
|
|
MODE_DOCUMENT_STICKY))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pDocOptions = DocOptions;
|
|
}
|
|
|
|
if (pPrinterOptions == NULL)
|
|
{
|
|
if (! InitDefaultOptions(pRawData,
|
|
PrinterOptions,
|
|
MAX_PRINTER_OPTIONS,
|
|
MODE_PRINTER_STICKY))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pPrinterOptions = PrinterOptions;
|
|
}
|
|
|
|
|
|
CombineOptionArray(pRawData, pOptionsArray, wMaxOptions, pDocOptions, pPrinterOptions);
|
|
|
|
if (! BMergeFormToTrayAssignments(pPDev))
|
|
{
|
|
ERR(("BMergeFormToTrayAssignments failed"));
|
|
}
|
|
|
|
//
|
|
// Resolve any UI conflicts.
|
|
//
|
|
|
|
if (!ResolveUIConflicts( pRawData,
|
|
pOptionsArray,
|
|
MAX_PRINTER_OPTIONS,
|
|
MODE_DOCANDPRINTER_STICKY))
|
|
{
|
|
VERBOSE(("Resolved conflicting printer feature selections.\n"));
|
|
}
|
|
|
|
//
|
|
// We are here means pOptionsArray is valid. Call parser to UpdateBinaryData
|
|
//
|
|
|
|
pInfoHeader = InitBinaryData(pRawData,
|
|
pInfoHeader,
|
|
pOptionsArray);
|
|
|
|
//
|
|
// Get GPDDRIVERINFO
|
|
//
|
|
|
|
if (pInfoHeader == NULL)
|
|
return NULL;
|
|
else
|
|
return(OFFSET_TO_POINTER(pInfoHeader, pInfoHeader->loDriverOffset));
|
|
|
|
}
|
|
|
|
VOID
|
|
VFixOptionsArray(
|
|
PDEV *pPDev,
|
|
PRECTL prcFormImageArea
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This functions is called to propagate public devmode settings
|
|
to the combined option array.
|
|
|
|
Arguments:
|
|
|
|
hPrinter Handle to printer
|
|
pInfoHeader Pointer to INFOHEADER
|
|
pOptionsArray Pointer to the options array
|
|
pdmInput Pointer to input devmode
|
|
bMetric Flag to indicate running in metric system
|
|
prcImageArea Returns the logical imageable area associated with the requested form
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Note:
|
|
|
|
--*/
|
|
|
|
{
|
|
WORD wGID, wOptID, wOption;
|
|
HANDLE hPrinter = pPDev->devobj.hPrinter ;
|
|
PINFOHEADER pInfoHeader = pPDev->pInfoHeader ;
|
|
POPTSELECT pOptionsArray = pPDev->pOptionsArray ;
|
|
PDEVMODE pdmInput = pPDev->pdm ;
|
|
BOOL bMetric = pPDev->PrinterData.dwFlags & PFLAGS_METRIC ;
|
|
|
|
//
|
|
// Validate the form-related fields in the input devmode and
|
|
// make sure they're consistent with each other.
|
|
//
|
|
|
|
if (BValidateDevmodeFormFields(hPrinter, pdmInput, prcFormImageArea, NULL, 0) == FALSE)
|
|
{
|
|
//
|
|
// If failed to validate the form fields, ask parser to
|
|
// use the default
|
|
//
|
|
|
|
VDefaultDevmodeFormFields(pPDev->pUIInfo, pdmInput, bMetric );
|
|
|
|
prcFormImageArea->top = prcFormImageArea->left = 0;
|
|
prcFormImageArea->right = pdmInput->dmPaperWidth * DEVMODE_PAPER_UNIT;
|
|
prcFormImageArea->bottom = pdmInput->dmPaperLength * DEVMODE_PAPER_UNIT;
|
|
|
|
|
|
}
|
|
|
|
for (wOption = 0; wOption < MAX_GID; wOption++)
|
|
{
|
|
switch(wOption)
|
|
{
|
|
|
|
case 0:
|
|
wGID = GID_PAGESIZE;
|
|
VFixOptionsArrayWithPaperSizeID(pPDev) ;
|
|
continue;
|
|
break;
|
|
|
|
case 1:
|
|
wGID = GID_DUPLEX;
|
|
break;
|
|
|
|
case 2:
|
|
wGID = GID_INPUTSLOT;
|
|
break;
|
|
|
|
case 3:
|
|
wGID = GID_MEDIATYPE;
|
|
break;
|
|
|
|
case 4:
|
|
wGID = GID_COLORMODE;
|
|
break;
|
|
|
|
case 5:
|
|
wGID = GID_COLLATE;
|
|
break;
|
|
|
|
case 6:
|
|
wGID = GID_RESOLUTION;
|
|
break;
|
|
|
|
case 7:
|
|
wGID = GID_ORIENTATION;
|
|
break;
|
|
|
|
default:
|
|
continue;
|
|
|
|
}
|
|
|
|
ChangeOptionsViaID(pInfoHeader, pOptionsArray, wGID, pdmInput);
|
|
|
|
}
|
|
}
|
|
|
|
PWSTR
|
|
PGetROnlyDisplayName(
|
|
PDEV *pPDev,
|
|
PTRREF loOffset,
|
|
PWSTR wstrBuf,
|
|
WORD wsize
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
revised capabilities:
|
|
caller must pass in a local buffer to
|
|
hold the string, the local buffer
|
|
shall be of fixed size say
|
|
WCHAR wchbuf[MAX_DISPLAY_NAME];
|
|
|
|
|
|
The return value shall be either the passed
|
|
in ptr or a ptr pointing directly to the buds
|
|
binary data.
|
|
|
|
Routine Description:
|
|
|
|
Get a read-only copy of a display name:
|
|
1) if the display name is in the binary printer description data,
|
|
then we simply return a pointer to that data.
|
|
2) otherwise, the display name is in the resource DLL.
|
|
we allocate memory out of the driver's heap and
|
|
load the string.
|
|
|
|
Caller should NOT attempt to free the returned pointer unless
|
|
that pointer is one he allocated.
|
|
|
|
Arguments:
|
|
|
|
pci - Points to basic printer info
|
|
loOffset - Display name string offset
|
|
|
|
Return Value:
|
|
|
|
Pointer to the requested display name string
|
|
NULL if there is an error or string not found in resource.dll
|
|
|
|
--*/
|
|
|
|
{
|
|
if (loOffset & GET_RESOURCE_FROM_DLL)
|
|
{
|
|
//
|
|
// loOffset specifies a string resource ID
|
|
// in the resource DLL
|
|
//
|
|
|
|
INT iLength;
|
|
|
|
//
|
|
// First ensure the resource DLL has been loaded
|
|
// and a heap has already been created
|
|
//
|
|
|
|
// nah, just look here!
|
|
|
|
// pPDev->WinResData.hModule ;
|
|
|
|
//
|
|
// Load string resource into a temporary buffer
|
|
// and allocate enough memory to hold the string
|
|
//
|
|
|
|
// #ifdef RCSTRINGSUPPORT
|
|
#if 0
|
|
|
|
if(((loOffset & ~GET_RESOURCE_FROM_DLL) >= RESERVED_STRINGID_START)
|
|
&& ((loOffset & ~GET_RESOURCE_FROM_DLL) <= RESERVED_STRINGID_END))
|
|
{
|
|
iLength = ILoadStringW( &pPDev->localWinResData,
|
|
(int)( loOffset & ~GET_RESOURCE_FROM_DLL),
|
|
wstrBuf, wsize );
|
|
}
|
|
else
|
|
#endif
|
|
|
|
{
|
|
iLength = ILoadStringW( &pPDev->WinResData,
|
|
(int)( loOffset & ~GET_RESOURCE_FROM_DLL),
|
|
wstrBuf, wsize );
|
|
}
|
|
|
|
|
|
|
|
|
|
if( iLength)
|
|
return (wstrBuf); // debug check that buffer is null terminated.
|
|
return(NULL); // no string was found!
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// loOffset is a byte offset from the beginning of
|
|
// the resource data block
|
|
//
|
|
|
|
return OFFSET_TO_POINTER(pPDev->pUIInfo->pubResourceData, loOffset);
|
|
// note wchbuf is ignored in this case.
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
VFixOptionsArrayWithPaperSizeID(
|
|
PDEV *pPDev
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fix up combined options array with paper size information from public devmode fields
|
|
|
|
Arguments:
|
|
|
|
pci - Points to basic printer info
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
|
|
function uses:
|
|
|
|
UImodule Render Module equiv
|
|
|
|
pci->pUIInfo pPDev->pUIInfo
|
|
pci->pInfoHeader pPDev->pInfoHeader
|
|
pci->pdm pPDev->pdm
|
|
pci->pRawData pPDev->pRawData
|
|
pci->pCombinedOptions pPDev->pOptionsArray
|
|
|
|
MapToDeviceOptIndex
|
|
PGetIndexedOption
|
|
PGetReadOnlyDisplayName
|
|
ReconstructOptionArray
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PFEATURE pFeature = GET_PREDEFINED_FEATURE(pPDev->pUIInfo, GID_PAGESIZE);
|
|
BOOL abEnabledOptions[MAX_PRINTER_OPTIONS];
|
|
PDWORD pdwPaperIndex = (PDWORD)abEnabledOptions;
|
|
DWORD dwCount, dwOptionIndex, i;
|
|
|
|
if (pFeature == NULL)
|
|
return;
|
|
|
|
dwCount = MapToDeviceOptIndex(pPDev->pInfoHeader,
|
|
GID_PAGESIZE,
|
|
pPDev->pdm->dmPaperWidth * DEVMODE_PAPER_UNIT,
|
|
pPDev->pdm->dmPaperLength * DEVMODE_PAPER_UNIT,
|
|
pdwPaperIndex);
|
|
if (dwCount == 0 )
|
|
return;
|
|
|
|
dwOptionIndex = pdwPaperIndex[0];
|
|
|
|
if (dwCount > 1 )
|
|
{
|
|
POPTION pOption;
|
|
PCWSTR pDisplayName;
|
|
WCHAR wchBuf[MAX_DISPLAY_NAME];
|
|
|
|
|
|
for (i = 0; i < dwCount; i++)
|
|
{
|
|
if (pOption = PGetIndexedOption(pPDev->pUIInfo, pFeature, pdwPaperIndex[i]))
|
|
{
|
|
if(pOption->loDisplayName == 0xffffffff) //use papername from EnumForms()
|
|
{
|
|
PFORM_INFO_1 pForms;
|
|
DWORD dwFormIndex ;
|
|
|
|
// temp hack!!! possibly needed for NT40 ?
|
|
|
|
// dwOptionIndex = pdwPaperIndex[i];
|
|
// break;
|
|
// end hack.
|
|
// ----- the fix ------ //
|
|
if (pPDev->pSplForms == NULL)
|
|
pPDev->pSplForms = MyEnumForms(pPDev->devobj.hPrinter, 1, &pPDev->dwSplForms);
|
|
|
|
if (pPDev->pSplForms == NULL)
|
|
{
|
|
// ERR(("No spooler forms.\n")); just a heads up.
|
|
// dwOptionIndex already set to safe default
|
|
break;
|
|
}
|
|
|
|
pForms = pPDev->pSplForms ;
|
|
dwFormIndex = ((PPAGESIZE)pOption)->dwPaperSizeID - 1 ;
|
|
|
|
|
|
if ( (dwFormIndex < pPDev->dwSplForms) &&
|
|
(pDisplayName = (pForms[dwFormIndex]).pName) &&
|
|
(_wcsicmp(pPDev->pdm->dmFormName, pDisplayName) == EQUAL_STRING) )
|
|
{
|
|
dwOptionIndex = pdwPaperIndex[i];
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if ( (pDisplayName = PGetROnlyDisplayName(pPDev, pOption->loDisplayName,
|
|
wchBuf, MAX_DISPLAY_NAME )) &&
|
|
(_wcsicmp(pPDev->pdm->dmFormName, pDisplayName) == EQUAL_STRING) )
|
|
{
|
|
dwOptionIndex = pdwPaperIndex[i];
|
|
break;
|
|
}
|
|
}
|
|
} // if name doesn't match we default to the first candidate.
|
|
}
|
|
|
|
ZeroMemory(abEnabledOptions, sizeof(abEnabledOptions));
|
|
abEnabledOptions[dwOptionIndex] = TRUE;
|
|
ReconstructOptionArray(pPDev->pRawData,
|
|
pPDev->pOptionsArray,
|
|
MAX_COMBINED_OPTIONS,
|
|
GET_INDEX_FROM_FEATURE(pPDev->pUIInfo, pFeature),
|
|
abEnabledOptions);
|
|
|
|
}
|
|
|
|
|