1656 lines
37 KiB
C
1656 lines
37 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
driverui.c
|
||
|
||
Abstract:
|
||
|
||
This file contains utility functions for the UI and the
|
||
interface to the parser.
|
||
|
||
Environment:
|
||
|
||
Win32 subsystem, DriverUI module, user mode
|
||
|
||
Revision History:
|
||
|
||
02/09/97 -davidx-
|
||
Rewrote it to consistently handle common printer info
|
||
and to clean up parser interface code.
|
||
|
||
02/04/97 -davidx-
|
||
Reorganize driver UI to separate ps and uni DLLs.
|
||
|
||
07/17/96 -amandan-
|
||
Created it.
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
|
||
HANDLE HCreateHeapForCI();
|
||
|
||
|
||
PCOMMONINFO
|
||
PLoadCommonInfo(
|
||
HANDLE hPrinter,
|
||
PTSTR pPrinterName,
|
||
DWORD dwFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Load basic information needed by the driver UI such as:
|
||
printer driver info level 2
|
||
load raw printer description data
|
||
printer description data instance based on default settings
|
||
get information about OEM plugins
|
||
load OEM UI modules
|
||
|
||
Arguments:
|
||
|
||
hPrinter - Handle to the current printer
|
||
pPrinterName - Points to the current printer name
|
||
dwFlags - One of the following combinations:
|
||
0
|
||
FLAG_ALLOCATE_UIDATA
|
||
FLAG_OPENPRINTER_NORMAL [ | FLAG_OPEN_CONDITIONAL ]
|
||
FLAG_OPENPRINTER_ADMIN [ | FLAG_INIT_PRINTER ]
|
||
FLAG_OPENPRINTER_ADMIN [ | FLAG_PROCESS_INIFILE ]
|
||
|
||
Return Value:
|
||
|
||
Pointer to an allocated COMMONINFO structure if successful
|
||
NULL if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
static PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL, PRINTER_ALL_ACCESS };
|
||
PCOMMONINFO pci;
|
||
DWORD dwSize;
|
||
|
||
//
|
||
// Allocate memory for a COMMONINFO structure
|
||
//
|
||
|
||
dwSize = (dwFlags & FLAG_ALLOCATE_UIDATA) ? sizeof(UIDATA) : sizeof(COMMONINFO);
|
||
|
||
if (! (pci = MemAllocZ(dwSize)) ||
|
||
! (pci->pPrinterName = DuplicateString(pPrinterName ? pPrinterName : TEXT("NULL"))))
|
||
{
|
||
ERR(("Memory allocation failed\n"));
|
||
VFreeCommonInfo(pci);
|
||
return NULL;
|
||
}
|
||
|
||
pci->pvStartSign = pci;
|
||
pci->dwFlags = dwFlags;
|
||
|
||
//
|
||
// Check if we should open a handle to the current printer
|
||
//
|
||
|
||
if (dwFlags & (FLAG_OPENPRINTER_NORMAL | FLAG_OPENPRINTER_ADMIN))
|
||
{
|
||
ASSERT(hPrinter == NULL && pPrinterName != NULL);
|
||
|
||
//
|
||
// Open a printer handle with the specified access right
|
||
//
|
||
|
||
if (! OpenPrinter(pPrinterName,
|
||
&hPrinter,
|
||
(dwFlags & FLAG_OPENPRINTER_ADMIN) ? &PrinterDefaults : NULL))
|
||
{
|
||
ERR(("OpenPrinter failed for '%ws': %d\n", pPrinterName, GetLastError()));
|
||
VFreeCommonInfo(pci);
|
||
return NULL;
|
||
}
|
||
|
||
pci->hPrinter = hPrinter;
|
||
}
|
||
else
|
||
{
|
||
ASSERT(hPrinter != NULL);
|
||
pci->hPrinter = hPrinter;
|
||
}
|
||
|
||
//
|
||
// If the caller requires that the printer to be initialized,
|
||
// check to make sure it is. If not, return error.
|
||
//
|
||
|
||
if (dwFlags & FLAG_OPEN_CONDITIONAL)
|
||
{
|
||
PPRINTER_INFO_2 pPrinterInfo2;
|
||
DWORD dwInitData;
|
||
|
||
//
|
||
// NOTE: We're really like to use level 4 here. But due to bug in the
|
||
// spooler, GetPrinter level 4 doesn't work for printer connections.
|
||
//
|
||
|
||
dwInitData = gwDriverVersion;
|
||
|
||
#ifdef WINNT_40
|
||
//
|
||
// Hack around spooler bug where DrvConvertDevmode is called before
|
||
// DrvPrinterEvent.Initialzed is called.
|
||
//
|
||
if (!BGetPrinterDataDWord(hPrinter, REGVAL_PRINTER_INITED, &dwInitData))
|
||
DrvPrinterEvent(pPrinterName, PRINTER_EVENT_INITIALIZE, 0, 0);
|
||
#endif
|
||
|
||
if ((pPrinterInfo2 = MyGetPrinter(hPrinter, 2)) == NULL ||
|
||
(pPrinterInfo2->pServerName == NULL) &&
|
||
!BGetPrinterDataDWord(hPrinter, REGVAL_PRINTER_INITED, &dwInitData))
|
||
{
|
||
dwInitData = 0;
|
||
}
|
||
|
||
MemFree(pPrinterInfo2);
|
||
|
||
if (dwInitData != gwDriverVersion)
|
||
{
|
||
TERSE(("Printer not fully initialized yet: %d\n", GetLastError()));
|
||
VFreeCommonInfo(pci);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Get information about the printer driver
|
||
//
|
||
|
||
if ((pci->pDriverInfo3 = MyGetPrinterDriver(hPrinter, NULL, 3)) == NULL)
|
||
{
|
||
ERR(("Cannot get printer driver info: %d\n", GetLastError()));
|
||
VFreeCommonInfo(pci);
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// If FLAG_INIT_PRINTER is set, we should initialize the printer here.
|
||
//
|
||
|
||
if (dwFlags & (FLAG_INIT_PRINTER | FLAG_PROCESS_INIFILE))
|
||
{
|
||
//
|
||
// Parse OEM plugin configuration file and
|
||
// save the resulting info into registry
|
||
//
|
||
|
||
if (!BProcessPrinterIniFile(hPrinter, pci->pDriverInfo3, NULL,
|
||
(dwFlags & FLAG_UPGRADE_PRINTER) ? FLAG_INIPROCESS_UPGRADE : 0))
|
||
{
|
||
VERBOSE(("BProcessPrinterIniFile failed\n"));
|
||
}
|
||
|
||
//
|
||
// If printer was successfully initialized and caller is not asking to process
|
||
// ini file only, save a flag in the registry to indicate the fact.
|
||
//
|
||
|
||
if (dwFlags & FLAG_INIT_PRINTER)
|
||
{
|
||
(VOID) BSetPrinterDataDWord(hPrinter, REGVAL_PRINTER_INITED, gwDriverVersion);
|
||
}
|
||
}
|
||
|
||
//
|
||
// fix 317359. In case some part of the driver has changed refresh the .bpd
|
||
// to update driver-language-specific strings in the .bpd. "Manual Feed" is
|
||
// written by the parser and therefore the .bpd depends on the language the
|
||
// parser was localized for. Checking the language would have to be done every time
|
||
// something is printed, therefore we just delete the .bpd, then the it gets reparsed
|
||
// always has the same language as the driver.
|
||
//
|
||
#ifdef PSCRIPT
|
||
if (dwFlags & FLAG_REFRESH_PARSED_DATA)
|
||
{
|
||
DeleteRawBinaryData(pci->pDriverInfo3->pDataFile);
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Load raw binary printer description data, and
|
||
// Get a printer description data instance using the default settings
|
||
//
|
||
// Notice that this is done inside a critical section (because
|
||
// GPD parsers has lots of globals).
|
||
//
|
||
|
||
// ENTER_CRITICAL_SECTION();
|
||
|
||
pci->pRawData = LoadRawBinaryData(pci->pDriverInfo3->pDataFile);
|
||
|
||
if (pci->pRawData)
|
||
pci->pInfoHeader = InitBinaryData(pci->pRawData, NULL, NULL);
|
||
|
||
if (pci->pInfoHeader)
|
||
pci->pUIInfo = OFFSET_TO_POINTER(pci->pInfoHeader, pci->pInfoHeader->loUIInfoOffset);
|
||
|
||
// LEAVE_CRITICAL_SECTION();
|
||
|
||
if (!pci->pRawData || !pci->pInfoHeader || !pci->pUIInfo)
|
||
{
|
||
ERR(("Cannot load printer description data: %d\n", GetLastError()));
|
||
VFreeCommonInfo(pci);
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Get information about OEM plugins and load them
|
||
//
|
||
|
||
if (! (pci->pOemPlugins = PGetOemPluginInfo(hPrinter,
|
||
pci->pDriverInfo3->pConfigFile,
|
||
pci->pDriverInfo3)) ||
|
||
! BLoadOEMPluginModules(pci->pOemPlugins))
|
||
{
|
||
ERR(("Cannot load OEM plugins: %d\n", GetLastError()));
|
||
VFreeCommonInfo(pci);
|
||
return NULL;
|
||
}
|
||
|
||
pci->oemuiobj.cbSize = sizeof(OEMUIOBJ);
|
||
pci->oemuiobj.pOemUIProcs = (POEMUIPROCS) &OemUIHelperFuncs;
|
||
pci->pOemPlugins->pdriverobj = &pci->oemuiobj;
|
||
return pci;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
VFreeCommonInfo(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Release common information used by the driver UI
|
||
|
||
Arguments:
|
||
|
||
pci - Common driver information to be released
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
if (pci == NULL)
|
||
return;
|
||
|
||
//
|
||
// Unload OEM UI modules and free OEM plugin info
|
||
//
|
||
|
||
if (pci->pOemPlugins)
|
||
VFreeOemPluginInfo(pci->pOemPlugins);
|
||
|
||
//
|
||
// Unload raw binary printer description data
|
||
// and/or any printer description data instance
|
||
//
|
||
|
||
if (pci->pInfoHeader)
|
||
FreeBinaryData(pci->pInfoHeader);
|
||
|
||
if (pci->pRawData)
|
||
UnloadRawBinaryData(pci->pRawData);
|
||
|
||
//
|
||
// Close the printer handle if it was opened by us
|
||
//
|
||
|
||
if ((pci->dwFlags & (FLAG_OPENPRINTER_NORMAL|FLAG_OPENPRINTER_ADMIN)) &&
|
||
(pci->hPrinter != NULL))
|
||
{
|
||
ClosePrinter(pci->hPrinter);
|
||
}
|
||
|
||
#ifdef UNIDRV
|
||
if (pci->pWinResData)
|
||
{
|
||
VWinResClose(pci->pWinResData);
|
||
MemFree(pci->pWinResData);
|
||
}
|
||
#endif
|
||
|
||
if (pci->hHeap)
|
||
HeapDestroy(pci->hHeap);
|
||
|
||
MemFree(pci->pSplForms);
|
||
MemFree(pci->pCombinedOptions);
|
||
MemFree(pci->pPrinterData);
|
||
MemFree(pci->pPrinterName);
|
||
MemFree(pci->pDriverInfo3);
|
||
MemFree(pci->pdm);
|
||
MemFree(pci);
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BFillCommonInfoDevmode(
|
||
PCOMMONINFO pci,
|
||
PDEVMODE pdmPrinter,
|
||
PDEVMODE pdmInput
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Populate the devmode fields in the COMMONINFO structure.
|
||
start out with the driver default devmode, and
|
||
merge it with the printer default devmode, and
|
||
merge it with the input devmode
|
||
|
||
Arguments:
|
||
|
||
pci - Points to a COMMONINFO structure
|
||
pdmPrinter - Points to printer default devmode
|
||
pdmInput - Points to input devmode
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
Note:
|
||
|
||
pdmPrinter and/or pdmInput can be NULL.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Start with driver default devmode
|
||
//
|
||
|
||
ASSERT(pci->pdm == NULL);
|
||
|
||
pci->pdm = PGetDefaultDevmodeWithOemPlugins(
|
||
pci->pPrinterName,
|
||
pci->pUIInfo,
|
||
pci->pRawData,
|
||
IsMetricCountry(),
|
||
pci->pOemPlugins,
|
||
pci->hPrinter);
|
||
|
||
//
|
||
// Merge with printer default and input devmode
|
||
//
|
||
|
||
if (! pci->pdm ||
|
||
! BValidateAndMergeDevmodeWithOemPlugins(
|
||
pci->pdm,
|
||
pci->pUIInfo,
|
||
pci->pRawData,
|
||
pdmPrinter,
|
||
pci->pOemPlugins,
|
||
pci->hPrinter) ||
|
||
! BValidateAndMergeDevmodeWithOemPlugins(
|
||
pci->pdm,
|
||
pci->pUIInfo,
|
||
pci->pRawData,
|
||
pdmInput,
|
||
pci->pOemPlugins,
|
||
pci->hPrinter))
|
||
{
|
||
ERR(("Cannot process devmode information: %d\n", GetLastError()));
|
||
return FALSE;
|
||
}
|
||
|
||
pci->pdmPrivate = (PDRIVEREXTRA) GET_DRIVER_PRIVATE_DEVMODE(pci->pdm);
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BFillCommonInfoPrinterData(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Populate the printer-sticky property data field
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
ASSERT(pci->pPrinterData == NULL);
|
||
|
||
if (pci->pPrinterData = MemAllocZ(sizeof(PRINTERDATA)))
|
||
return BGetPrinterProperties(pci->hPrinter, pci->pRawData, pci->pPrinterData);
|
||
|
||
ERR(("Memory allocation failed\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BCombineCommonInfoOptionsArray(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Combined document-sticky feature selections and printer-sticky
|
||
feature selection into a single options array
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTSELECT pDocOptions, pPrinterOptions;
|
||
|
||
#ifdef UNIDRV
|
||
|
||
OPTSELECT DocOptions[MAX_PRINTER_OPTIONS];
|
||
OPTSELECT PrinterOptions[MAX_PRINTER_OPTIONS];
|
||
|
||
#endif
|
||
|
||
//
|
||
// Allocate enough memory for the combined options array
|
||
//
|
||
|
||
pci->pCombinedOptions = MemAllocZ(sizeof(OPTSELECT) * MAX_COMBINED_OPTIONS);
|
||
|
||
if (pci->pCombinedOptions == NULL)
|
||
{
|
||
ERR(("Memory allocation failed\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pDocOptions = pci->pdm ? PGetDevmodeOptionsArray(pci->pdm) : NULL;
|
||
pPrinterOptions = pci->pPrinterData ? pci->pPrinterData->aOptions : NULL;
|
||
|
||
#ifdef UNIDRV
|
||
|
||
//
|
||
// GPD parser doesn't follow the current parser interface spec.
|
||
// It AVs if either doc- or printer-sticky options array is NULL.
|
||
// So we have to call it first to get appropriate default options first.
|
||
//
|
||
|
||
if (pDocOptions == NULL)
|
||
{
|
||
if (! InitDefaultOptions(pci->pRawData,
|
||
DocOptions,
|
||
MAX_PRINTER_OPTIONS,
|
||
MODE_DOCUMENT_STICKY))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
pDocOptions = DocOptions;
|
||
}
|
||
|
||
if (pPrinterOptions == NULL)
|
||
{
|
||
if (! InitDefaultOptions(pci->pRawData,
|
||
PrinterOptions,
|
||
MAX_PRINTER_OPTIONS,
|
||
MODE_PRINTER_STICKY))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
pPrinterOptions = PrinterOptions;
|
||
}
|
||
|
||
#endif // UNIDRV
|
||
|
||
return CombineOptionArray(pci->pRawData,
|
||
pci->pCombinedOptions,
|
||
MAX_COMBINED_OPTIONS,
|
||
pDocOptions,
|
||
pPrinterOptions);
|
||
}
|
||
|
||
|
||
VOID
|
||
VFixOptionsArrayWithPaperSizeID(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
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
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PFEATURE pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_PAGESIZE);
|
||
BOOL abEnabledOptions[MAX_PRINTER_OPTIONS];
|
||
PDWORD pdwPaperIndex = (PDWORD)&abEnabledOptions;
|
||
DWORD dwCount, dwOptionIndex, i;
|
||
WCHAR awchBuf[CCHPAPERNAME];
|
||
|
||
|
||
if (pFeature == NULL)
|
||
return;
|
||
|
||
dwCount = MapToDeviceOptIndex(pci->pInfoHeader,
|
||
GID_PAGESIZE,
|
||
pci->pdm->dmPaperWidth * DEVMODE_PAPER_UNIT,
|
||
pci->pdm->dmPaperLength * DEVMODE_PAPER_UNIT,
|
||
pdwPaperIndex);
|
||
if (dwCount == 0 )
|
||
return;
|
||
|
||
if (dwCount > 1 )
|
||
{
|
||
PPAGESIZE pPageSize;
|
||
|
||
for (i = 0; i < dwCount; i++)
|
||
{
|
||
if (pPageSize = (PPAGESIZE)PGetIndexedOption(pci->pUIInfo, pFeature, pdwPaperIndex[i]))
|
||
{
|
||
if ((LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, awchBuf, CCHPAPERNAME)) &&
|
||
(_wcsicmp(pci->pdm->dmFormName, awchBuf) == EQUAL_STRING) )
|
||
{
|
||
dwOptionIndex = pdwPaperIndex[i];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (i >= dwCount)
|
||
dwOptionIndex = pdwPaperIndex[0];
|
||
|
||
}
|
||
else
|
||
dwOptionIndex = pdwPaperIndex[0];
|
||
|
||
ZeroMemory(abEnabledOptions, sizeof(abEnabledOptions));
|
||
abEnabledOptions[dwOptionIndex] = TRUE;
|
||
ReconstructOptionArray(pci->pRawData,
|
||
pci->pCombinedOptions,
|
||
MAX_COMBINED_OPTIONS,
|
||
GET_INDEX_FROM_FEATURE(pci->pUIInfo, pFeature),
|
||
abEnabledOptions);
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
VFixOptionsArrayWithDevmode(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Fix up combined options array with information from public devmode fields
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Mapping table from public devmode fields to GID indices
|
||
// We assume that GID_COLORMODE corresponds to DM_COLR
|
||
//
|
||
|
||
static CONST struct _DMFIELDS_GID_MAPPING {
|
||
DWORD dwGid;
|
||
DWORD dwMask;
|
||
} DMFieldsGIDMapping[] = {
|
||
{ GID_RESOLUTION, DM_PRINTQUALITY|DM_YRESOLUTION },
|
||
{ GID_PAGESIZE, DM_FORMNAME|DM_PAPERSIZE|DM_PAPERWIDTH|DM_PAPERLENGTH },
|
||
{ GID_DUPLEX, DM_DUPLEX },
|
||
{ GID_INPUTSLOT, DM_DEFAULTSOURCE },
|
||
{ GID_MEDIATYPE, DM_MEDIATYPE },
|
||
{ GID_ORIENTATION, DM_ORIENTATION },
|
||
{ GID_COLLATE, DM_COLLATE },
|
||
{ GID_COLORMODE, DM_COLOR },
|
||
};
|
||
|
||
INT iIndex;
|
||
BOOL bConflict;
|
||
|
||
//
|
||
// Validate form-related devmode fields
|
||
//
|
||
|
||
if (pci->pSplForms == NULL)
|
||
pci->pSplForms = MyEnumForms(pci->hPrinter, 1, &pci->dwSplForms);
|
||
|
||
if (! BValidateDevmodeCustomPageSizeFields(
|
||
pci->pRawData,
|
||
pci->pUIInfo,
|
||
pci->pdm,
|
||
NULL) &&
|
||
! BValidateDevmodeFormFields(
|
||
pci->hPrinter,
|
||
pci->pdm,
|
||
NULL,
|
||
pci->pSplForms,
|
||
pci->dwSplForms))
|
||
{
|
||
VDefaultDevmodeFormFields(pci->pUIInfo, pci->pdm, IsMetricCountry());
|
||
}
|
||
|
||
//
|
||
// Fix up options array with information from public devmode fields
|
||
//
|
||
|
||
iIndex = sizeof(DMFieldsGIDMapping) / sizeof(struct _DMFIELDS_GID_MAPPING);
|
||
|
||
while (iIndex-- > 0)
|
||
{
|
||
if (pci->pdm->dmFields & DMFieldsGIDMapping[iIndex].dwMask)
|
||
{
|
||
#if UNIDRV
|
||
if (DMFieldsGIDMapping[iIndex].dwGid == GID_PAGESIZE)
|
||
{
|
||
VFixOptionsArrayWithPaperSizeID(pci);
|
||
}
|
||
else
|
||
#endif
|
||
{
|
||
(VOID) ChangeOptionsViaID(pci->pInfoHeader,
|
||
pci->pCombinedOptions,
|
||
DMFieldsGIDMapping[iIndex].dwGid,
|
||
pci->pdm);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BUpdateUIInfo(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get an updated printer description data instance using the combined options array
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
PINFOHEADER pInfoHeader;
|
||
|
||
//
|
||
// Get an updated instance of printer description data
|
||
//
|
||
|
||
pInfoHeader = UpdateBinaryData(pci->pRawData,
|
||
pci->pInfoHeader,
|
||
pci->pCombinedOptions);
|
||
|
||
|
||
if (pInfoHeader == NULL)
|
||
{
|
||
ERR(("UpdateBinaryData failed\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Reset various points in COMMONINFO structure
|
||
//
|
||
|
||
pci->pInfoHeader = pInfoHeader;
|
||
pci->pUIInfo = OFFSET_TO_POINTER(pInfoHeader, pInfoHeader->loUIInfoOffset);
|
||
ASSERT(pci->pUIInfo != NULL);
|
||
|
||
return (pci->pUIInfo != NULL);
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BPrepareForLoadingResource(
|
||
PCOMMONINFO pci,
|
||
BOOL bNeedHeap
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Make sure a heap is created and the resource DLL has been loaded
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
bNeedHeap - Whether memory heap is necessary
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL bResult = FALSE;
|
||
|
||
//
|
||
// Create the memory heap if necessary
|
||
//
|
||
|
||
if ( bNeedHeap &&
|
||
! pci->hHeap &&
|
||
! (pci->hHeap = HCreateHeapForCI()))
|
||
{
|
||
return bResult;
|
||
}
|
||
|
||
#ifdef UNIDRV
|
||
|
||
if (pci->pWinResData)
|
||
{
|
||
bResult = TRUE;
|
||
}
|
||
else
|
||
{
|
||
if ((pci->pWinResData = MemAllocZ(sizeof(WINRESDATA))) &&
|
||
(BInitWinResData(pci->pWinResData,
|
||
pci->pDriverInfo3->pDriverPath,
|
||
pci->pUIInfo)))
|
||
bResult = TRUE;
|
||
}
|
||
|
||
#endif
|
||
|
||
return bResult;
|
||
}
|
||
|
||
|
||
|
||
#ifndef PSCRIPT
|
||
|
||
PWSTR
|
||
PGetReadOnlyDisplayName(
|
||
PCOMMONINFO pci,
|
||
PTRREF loOffset
|
||
)
|
||
|
||
/*++
|
||
|
||
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 free the returned pointer. The memory
|
||
will go away when the binary printer description data is unloaded
|
||
or when the driver's heap is destroyed.
|
||
|
||
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
|
||
|
||
--*/
|
||
|
||
{
|
||
if (loOffset & GET_RESOURCE_FROM_DLL)
|
||
{
|
||
//
|
||
// loOffset specifies a string resource ID
|
||
// in the resource DLL
|
||
//
|
||
|
||
WCHAR wchbuf[MAX_DISPLAY_NAME];
|
||
INT iLength;
|
||
PWSTR pwstr;
|
||
HANDLE hResDll;
|
||
DWORD dwResID = loOffset & ~GET_RESOURCE_FROM_DLL;
|
||
|
||
//
|
||
// First ensure the resource DLL has been loaded
|
||
// and a heap has already been created
|
||
//
|
||
|
||
if (! BPrepareForLoadingResource(pci, TRUE))
|
||
return NULL;
|
||
|
||
//
|
||
// Load string resource into a temporary buffer
|
||
// and allocate enough memory to hold the string
|
||
//
|
||
|
||
iLength = ILOADSTRING(pci, dwResID, wchbuf, MAX_DISPLAY_NAME);
|
||
|
||
pwstr = HEAPALLOC(pci->hHeap, (iLength+1) * sizeof(WCHAR));
|
||
|
||
if (pwstr == NULL)
|
||
{
|
||
ERR(("Memory allocation failed\n"));
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Copy the string to allocated memory and
|
||
// return a pointer to it.
|
||
//
|
||
|
||
CopyMemory(pwstr, wchbuf, iLength*sizeof(WCHAR));
|
||
return pwstr;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// loOffset is a byte offset from the beginning of
|
||
// the resource data block
|
||
//
|
||
|
||
return OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, loOffset);
|
||
}
|
||
}
|
||
|
||
#endif // !PSCRIPT
|
||
|
||
|
||
|
||
BOOL
|
||
BLoadDisplayNameString(
|
||
PCOMMONINFO pci,
|
||
PTRREF loOffset,
|
||
PWSTR pwstrBuf,
|
||
INT iMaxChars
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is similar to PGetReadOnlyDisplayName
|
||
but the caller must provide the buffer for loading the string.
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
loOffset - Display name string offset
|
||
pwstrBuf - Points to buffer for storing loaded display name string
|
||
iMaxChars - Size of output buffer in characters
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
ASSERT(pwstrBuf && iMaxChars > 0);
|
||
pwstrBuf[0] = NUL;
|
||
|
||
if (loOffset & GET_RESOURCE_FROM_DLL)
|
||
{
|
||
//
|
||
// loOffset specifies a string resource ID
|
||
// in the resource DLL
|
||
//
|
||
|
||
INT iLength;
|
||
HANDLE hResDll;
|
||
DWORD dwResID = loOffset & ~GET_RESOURCE_FROM_DLL;
|
||
|
||
//
|
||
// First ensure the resource DLL has been loaded
|
||
//
|
||
|
||
if (! BPrepareForLoadingResource(pci, FALSE))
|
||
return FALSE;
|
||
|
||
//
|
||
// Load string resource into the output buffer
|
||
// and allocate enough memory to hold the string
|
||
//
|
||
|
||
iLength = ILOADSTRING(pci, dwResID, pwstrBuf, (WORD)iMaxChars);
|
||
|
||
return (iLength > 0);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// loOffset is a byte offset from the beginning of
|
||
// the resource data block
|
||
//
|
||
|
||
PWSTR pwstr;
|
||
|
||
pwstr = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, loOffset);
|
||
|
||
if (pwstr == NULL)
|
||
return FALSE;
|
||
|
||
CopyString(pwstrBuf, pwstr, iMaxChars);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
BOOL
|
||
BLoadPageSizeNameString(
|
||
PCOMMONINFO pci,
|
||
PTRREF loOffset,
|
||
PWSTR pwstrBuf,
|
||
INT iMaxChars,
|
||
INT iStdId
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is similar to PGetReadOnlyDisplayName
|
||
but the caller must provide the buffer for loading the string.
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
loOffset - Display name string offset
|
||
pwstrBuf - Points to buffer for storing loaded display name string
|
||
iMaxChars - Size of output buffer in characters
|
||
iStdId - Predefined standard ID for page size, e.g. DMPAPER_XXX
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ASSERT(pwstrBuf && iMaxChars > 0);
|
||
pwstrBuf[0] = NUL;
|
||
|
||
if (loOffset == USE_SYSTEM_NAME)
|
||
{
|
||
PFORM_INFO_1 pForm;
|
||
INT iIndex = iStdId - DMPAPER_FIRST;
|
||
|
||
//
|
||
// iIndex is zero based.
|
||
//
|
||
|
||
if (pci->pSplForms == NULL ||
|
||
(INT)pci->dwSplForms <= iIndex)
|
||
{
|
||
WARNING(("BLoadPageSizeName, use std name, pSplForms is NULL \n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pForm = pci->pSplForms + iIndex;
|
||
CopyString(pwstrBuf, pForm->pName, iMaxChars);
|
||
return (TRUE);
|
||
|
||
}
|
||
else
|
||
return (BLoadDisplayNameString(pci, loOffset, pwstrBuf, iMaxChars));
|
||
}
|
||
|
||
|
||
ULONG_PTR
|
||
HLoadIconFromResourceDLL(
|
||
PCOMMONINFO pci,
|
||
DWORD dwIconID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Load icon resource from the resource DLL
|
||
|
||
Arguments:
|
||
|
||
pci - Points to common printer info
|
||
dwIconID - Specifies ID of the icon to be loaded
|
||
|
||
Return Value:
|
||
|
||
Handle to the specified icon resource
|
||
0 if the specified icon cannot be loaded
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// First ensure the resource DLL has been loaded
|
||
//
|
||
#ifdef UNIDRV
|
||
|
||
RES_ELEM ResElem;
|
||
ULONG_PTR pRes;
|
||
|
||
if (! BPrepareForLoadingResource(pci, FALSE))
|
||
return 0;
|
||
|
||
if (BGetWinRes(pci->pWinResData, (PQUALNAMEEX)&dwIconID, (INT)((ULONG_PTR)RT_ICON), &ResElem))
|
||
return ((ULONG_PTR)(ResElem.pvResData));
|
||
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
PUIDATA
|
||
PFillUiData(
|
||
HANDLE hPrinter,
|
||
PTSTR pPrinterName,
|
||
PDEVMODE pdmInput,
|
||
INT iMode
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called by DrvDocumentPropertySheets and
|
||
DrvPrinterPropertySheets. It allocates and initializes
|
||
a UIDATA structure that's used to display property pages.
|
||
|
||
Arguments:
|
||
|
||
hPrinter - Handle to the current printer
|
||
pPrinterName - Name of the current printer
|
||
pdmInput - Input devmode
|
||
iMode - Identify the caller:
|
||
MODE_DOCUMENT_STICKY - called from DrvDocumentPropertySheets
|
||
MODE_PRINTER_STICY - called from DrvPrinterPropertySheets
|
||
|
||
Return Value:
|
||
|
||
Pointer to a UIDATA structure, NULL if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
PUIDATA pUiData;
|
||
PCOMMONINFO pci;
|
||
BOOL bNupOption;
|
||
PFEATURE pFeature;
|
||
DWORD dwFeatureIndex, dwOptionIndexOld, dwOptionIndexNew;
|
||
BOOL bUpdateFormField;
|
||
|
||
//
|
||
// Allocate UIDATA structure and load common information
|
||
//
|
||
|
||
pUiData = (PUIDATA) PLoadCommonInfo(hPrinter, pPrinterName, FLAG_ALLOCATE_UIDATA);
|
||
|
||
if (pUiData == NULL)
|
||
goto fill_uidata_err;
|
||
|
||
pUiData->pvEndSign = pUiData;
|
||
pUiData->iMode = iMode;
|
||
pci = &pUiData->ci;
|
||
|
||
//
|
||
// Create a memory heap
|
||
//
|
||
|
||
if ((pci->hHeap = HCreateHeapForCI()) == NULL)
|
||
goto fill_uidata_err;
|
||
|
||
//
|
||
// Get printer-sticky property data
|
||
//
|
||
|
||
if (! BFillCommonInfoPrinterData(pci))
|
||
goto fill_uidata_err;
|
||
|
||
//
|
||
// If called from DrvDocumentPropertySheets, then process
|
||
// devmode information: driver default + printer default + input devmode
|
||
//
|
||
|
||
if (iMode == MODE_DOCUMENT_STICKY)
|
||
{
|
||
PPRINTER_INFO_2 pPrinterInfo2;
|
||
|
||
if (! (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)) ||
|
||
! BFillCommonInfoDevmode(pci, pPrinterInfo2->pDevMode, pdmInput))
|
||
{
|
||
MemFree(pPrinterInfo2);
|
||
goto fill_uidata_err;
|
||
}
|
||
|
||
MemFree(pPrinterInfo2);
|
||
}
|
||
|
||
//
|
||
// Merge doc-sticky and printer-sticky option selections
|
||
//
|
||
|
||
if (! BCombineCommonInfoOptionsArray(pci))
|
||
goto fill_uidata_err;
|
||
|
||
//
|
||
// If called from DrvDocumentPropertySheets,
|
||
// fix up combined options with public devmode information
|
||
//
|
||
|
||
if (iMode == MODE_DOCUMENT_STICKY)
|
||
{
|
||
VFixOptionsArrayWithDevmode(pci);
|
||
|
||
//
|
||
// Remember the paper size option parser picked to support the devmode form
|
||
//
|
||
|
||
if ((pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_PAGESIZE)) == NULL)
|
||
{
|
||
ASSERT(FALSE);
|
||
goto fill_uidata_err;
|
||
}
|
||
|
||
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pci->pUIInfo, pFeature);
|
||
dwOptionIndexOld = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
|
||
}
|
||
|
||
VGetSpoolerEmfCaps(pci->hPrinter, &bNupOption, &pUiData->bEMFSpooling, 0, NULL);
|
||
|
||
//
|
||
// Resolve any conflicts between printer feature selections,
|
||
// and get an updated printer description data instance
|
||
// using the combined options array.
|
||
//
|
||
|
||
(VOID) ResolveUIConflicts(pci->pRawData,
|
||
pci->pCombinedOptions,
|
||
MAX_COMBINED_OPTIONS,
|
||
iMode == MODE_PRINTER_STICKY ?
|
||
iMode :
|
||
MODE_DOCANDPRINTER_STICKY);
|
||
|
||
if (iMode == MODE_DOCUMENT_STICKY)
|
||
{
|
||
dwOptionIndexNew = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
|
||
|
||
bUpdateFormField = FALSE;
|
||
|
||
if (dwOptionIndexNew != dwOptionIndexOld)
|
||
{
|
||
//
|
||
// Constraint resolving has changed page size selection, so we need
|
||
// to update devmode's form fields.
|
||
//
|
||
|
||
bUpdateFormField = TRUE;
|
||
}
|
||
else
|
||
{
|
||
FORM_INFO_1 *pForm = NULL;
|
||
|
||
//
|
||
// Unless the form requested by devmode is not supported on the printer,
|
||
// we still want to show the original form name in upcoming doc-setting UI.
|
||
// For example, if input devmode requested "Legal", parser maps it to option
|
||
// "OEM Legal", but both "Legal" and "OEM Legal" will be shown as supported
|
||
// forms on the printer, then we should still show "Legal" instead of "OEM Legal"
|
||
// in UI's PageSize list. However, if input devmode requestd "8.5 x 12", which
|
||
// won't be shown as a supportd form and it's mapped to "OEM Legal", then we should
|
||
// show "OEM Legal".
|
||
//
|
||
|
||
//
|
||
// pdm->dmFormName won't have a valid form name for custom page size (see
|
||
// BValidateDevmodeFormFields()). VOptionsToDevmodeFields() knows to handle that.
|
||
//
|
||
|
||
if ((pci->pdm->dmFields & DM_FORMNAME) &&
|
||
(pForm = MyGetForm(pci->hPrinter, pci->pdm->dmFormName, 1)) &&
|
||
!BFormSupportedOnPrinter(pci, pForm, &dwOptionIndexNew))
|
||
{
|
||
bUpdateFormField = TRUE;
|
||
}
|
||
|
||
MemFree(pForm);
|
||
}
|
||
|
||
VOptionsToDevmodeFields(pci, bUpdateFormField);
|
||
}
|
||
|
||
if (BUpdateUIInfo(pci))
|
||
{
|
||
//
|
||
// Set the flag to indicate we are within the property sheet session. This flag will
|
||
// be used by new helper function interface to determine whether the helper function
|
||
// is available or not.
|
||
//
|
||
|
||
pci->dwFlags |= FLAG_PROPSHEET_SESSION;
|
||
|
||
return pUiData;
|
||
}
|
||
|
||
|
||
fill_uidata_err:
|
||
|
||
ERR(("PFillUiData failed: %d\n", GetLastError()));
|
||
VFreeUiData(pUiData);
|
||
return NULL;
|
||
}
|
||
|
||
|
||
|
||
PTSTR
|
||
PtstrDuplicateStringFromHeap(
|
||
IN PTSTR ptstrSrc,
|
||
IN HANDLE hHeap
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Duplicate a Unicode string
|
||
|
||
Arguments:
|
||
|
||
pwstrUnicodeString - Pointer to the input Unicode string
|
||
hHeap - Handle to a heap from which to allocate memory
|
||
|
||
Return Value:
|
||
|
||
Pointer to the resulting Unicode string
|
||
NULL if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
PTSTR ptstrDest;
|
||
INT iSize;
|
||
|
||
if (ptstrSrc == NULL)
|
||
return NULL;
|
||
|
||
iSize = SIZE_OF_STRING(ptstrSrc);
|
||
|
||
if (ptstrDest = HEAPALLOC(hHeap, iSize))
|
||
CopyMemory(ptstrDest, ptstrSrc, iSize);
|
||
else
|
||
ERR(("Couldn't duplicate string: %ws\n", ptstrSrc));
|
||
|
||
return ptstrDest;
|
||
}
|
||
|
||
|
||
|
||
POPTITEM
|
||
PFindOptItemWithKeyword(
|
||
IN PUIDATA pUiData,
|
||
IN PCSTR pKeywordName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Find the OPTITEM with UserData's pKeywordName matching given keyword name
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
pKeywordName - Specifies the keyword name needs to be matched
|
||
|
||
Return Value:
|
||
|
||
Pointer to the specified OPTITEM, NULL if no such item is found
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwCount;
|
||
POPTITEM pOptItem;
|
||
|
||
ASSERT(VALIDUIDATA(pUiData));
|
||
|
||
pOptItem = pUiData->pDrvOptItem;
|
||
dwCount = pUiData->dwDrvOptItem;
|
||
|
||
while (dwCount--)
|
||
{
|
||
if (((PUSERDATA)pOptItem->UserData)->pKeyWordName != NULL &&
|
||
strcmp(((PUSERDATA)pOptItem->UserData)->pKeyWordName, pKeywordName) == EQUAL_STRING)
|
||
return pOptItem;
|
||
|
||
pOptItem++;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
|
||
|
||
POPTITEM
|
||
PFindOptItemWithUserData(
|
||
IN PUIDATA pUiData,
|
||
IN DWORD UserData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Find the OPTITEM containing the specified UserData value
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
UserData - Specifies the interested UserData value
|
||
|
||
Return Value:
|
||
|
||
Pointer to the specified OPTITEM, NULL if no such item is found
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwCount;
|
||
POPTITEM pOptItem;
|
||
|
||
ASSERT(VALIDUIDATA(pUiData));
|
||
|
||
pOptItem = pUiData->pDrvOptItem;
|
||
dwCount = pUiData->dwDrvOptItem;
|
||
|
||
while (dwCount--)
|
||
{
|
||
if (GETUSERDATAITEM(pOptItem->UserData) == UserData)
|
||
return pOptItem;
|
||
|
||
pOptItem++;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
#ifndef WINNT_40
|
||
|
||
VOID
|
||
VNotifyDSOfUpdate(
|
||
IN HANDLE hPrinter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Call SetPrinter to notify the DS of the update of driver attribute
|
||
|
||
Arguments:
|
||
|
||
hPrinter - Handle to the current printer
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
{
|
||
|
||
PRINTER_INFO_7 PrinterInfo7;
|
||
|
||
ZeroMemory(&PrinterInfo7, sizeof(PrinterInfo7));
|
||
PrinterInfo7.dwAction = DSPRINT_UPDATE;
|
||
|
||
//
|
||
// Comments from spooler DS developer:
|
||
//
|
||
// In the beginning, SetPrinter did not fail with ERROR_IO_PENDING.
|
||
// Then it was modified and would occasionally fail with this error.
|
||
// Finally, for performance reasons, it was modified again and now
|
||
// almost always fails with this error (there are situations where
|
||
// it will succeed).
|
||
//
|
||
|
||
if (!SetPrinter(hPrinter, 7, (PBYTE) &PrinterInfo7, 0) &&
|
||
(GetLastError() != ERROR_IO_PENDING))
|
||
{
|
||
WARNING(("Couldn't publish printer info into DS\n"));
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
HANDLE HCreateHeapForCI()
|
||
{
|
||
HANDLE hHeap;
|
||
|
||
if(!(hHeap = HeapCreate(0, 8192, 0)))
|
||
{
|
||
ERR(("CreateHeap failed: %d\n", GetLastError()));
|
||
}
|
||
|
||
return hHeap;
|
||
}
|
||
|
||
|
||
#ifndef WINNT_40
|
||
BOOL
|
||
DrvQueryColorProfile(
|
||
HANDLE hPrinter,
|
||
PDEVMODEW pdmSrc,
|
||
ULONG ulQueryMode,
|
||
VOID *pvProfileData,
|
||
ULONG *pcbProfileData,
|
||
FLONG *pflProfileData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Call the OEM to let them determine the default color profile.
|
||
|
||
Arguments:
|
||
|
||
hPrinter - Handle to printer
|
||
pdmSrc - Input devmode
|
||
ulQueryMode - query mode
|
||
pvProfileData - Buffer for profile data
|
||
pcbProfileData - Size of profile data buffer
|
||
pflProfileData - other profile info
|
||
|
||
Return Value:
|
||
|
||
TRUE for success and FALSE for failure
|
||
|
||
--*/
|
||
|
||
{
|
||
PFN_OEMQueryColorProfile pfnQueryColorProfile;
|
||
PCOMMONINFO pci;
|
||
BOOL bRc = FALSE;
|
||
|
||
|
||
if (! (pci = PLoadCommonInfo(hPrinter, NULL, 0)) ||
|
||
! BFillCommonInfoDevmode(pci, NULL, pdmSrc) ||
|
||
! BCombineCommonInfoOptionsArray(pci))
|
||
{
|
||
WARNING(("Could not get PCI in DrvQueryColorProfile\n"));
|
||
VFreeCommonInfo(pci);
|
||
return FALSE;
|
||
}
|
||
|
||
VFixOptionsArrayWithDevmode(pci);
|
||
|
||
(VOID) ResolveUIConflicts(pci->pRawData,
|
||
pci->pCombinedOptions,
|
||
MAX_COMBINED_OPTIONS,
|
||
MODE_DOCUMENT_STICKY);
|
||
|
||
VOptionsToDevmodeFields(pci, TRUE);
|
||
|
||
if (! BUpdateUIInfo(pci))
|
||
{
|
||
VFreeCommonInfo(pci);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// If OEM plugin returns a profile, give it back, otherwise return FALSE
|
||
//
|
||
|
||
FOREACH_OEMPLUGIN_LOOP(pci)
|
||
|
||
if (HAS_COM_INTERFACE(pOemEntry))
|
||
{
|
||
HRESULT hr;
|
||
|
||
hr = HComOEMQUeryColorProfile(pOemEntry,
|
||
hPrinter,
|
||
&pci->oemuiobj,
|
||
pci->pdm,
|
||
pOemEntry->pOEMDM,
|
||
ulQueryMode,
|
||
pvProfileData,
|
||
pcbProfileData,
|
||
pflProfileData
|
||
);
|
||
|
||
if (hr == E_NOTIMPL)
|
||
continue;
|
||
|
||
bRc = SUCCEEDED(hr);
|
||
}
|
||
else
|
||
{
|
||
pfnQueryColorProfile = GET_OEM_ENTRYPOINT(pOemEntry, OEMQueryColorProfile);
|
||
|
||
if (pfnQueryColorProfile)
|
||
{
|
||
bRc = (*pfnQueryColorProfile)(hPrinter,
|
||
&pci->oemuiobj,
|
||
pci->pdm,
|
||
pOemEntry->pOEMDM,
|
||
ulQueryMode,
|
||
pvProfileData,
|
||
pcbProfileData,
|
||
pflProfileData
|
||
);
|
||
}
|
||
}
|
||
|
||
if (bRc)
|
||
break;
|
||
|
||
END_OEMPLUGIN_LOOP
|
||
|
||
VFreeCommonInfo(pci);
|
||
|
||
return bRc;
|
||
}
|
||
|
||
#else // ifndef WINNT_40
|
||
BOOL
|
||
DrvQueryColorProfile(
|
||
HANDLE hPrinter,
|
||
PDEVMODEW pdmSrc,
|
||
ULONG ulQueryMode,
|
||
VOID *pvProfileData,
|
||
ULONG *pcbProfileData,
|
||
FLONG *pflProfileData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Call the OEM to let them determine the default color profile.
|
||
|
||
Arguments:
|
||
|
||
hPrinter - Handle to printer
|
||
pdmSrc - Input devmode
|
||
ulQueryMode - query mode
|
||
pvProfileData - Buffer for profile data
|
||
pcbProfileData - Size of profile data buffer
|
||
pflProfileData - other profile info
|
||
|
||
Return Value:
|
||
|
||
TRUE for success and FALSE for failure
|
||
|
||
--*/
|
||
|
||
{
|
||
return TRUE;
|
||
}
|
||
#endif // WINNT_40
|