|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
quryprnt.c
Abstract:
This file handles the DrvQueryPrintEx spooler API
Environment:
Win32 subsystem, DriverUI module, user mode
Revision History:
02/13/97 -davidx- Implement OEM plugin support.
02/08/97 -davidx- Rewrote it to use common data management functions.
02/04/97 -davidx- Reorganize driver UI to separate ps and uni DLLs.
07/17/96 -amandan- Created it.
--*/
#include "precomp.h"
//
// Forward declaration of local functions
//
BOOL BFormatDQPMessage(PDEVQUERYPRINT_INFO, INT, ...); BOOL BQueryPrintDevmode(PDEVQUERYPRINT_INFO, PCOMMONINFO); BOOL BQueryPrintForm(PDEVQUERYPRINT_INFO, PCOMMONINFO);
BOOL DevQueryPrintEx( PDEVQUERYPRINT_INFO pDQPInfo )
/*++
Routine Description:
This function checks whether the job can be printed with DEVMODE passed in. This function will use the following criterias to determine whether the job is printable: - get basic printer information - verify input devmode - verify resolution is supported - verify there is no conflicts between printer feature selections - verify form-to-tray assignment
Arguments:
pDQPInfo - Points to a DEVQUERYPRINT_INFO structure
Return Value:
TRUE if the job can be printed with the given DEVMODE, otherwise FALSE
--*/
{ PCOMMONINFO pci; BOOL bResult;
if (pDQPInfo == NULL || pDQPInfo->hPrinter == NULL) return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_PARAM);
if (pDQPInfo->pDevMode == NULL) return TRUE;
if ((pci = PLoadCommonInfo(pDQPInfo->hPrinter, NULL, 0)) == NULL) return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_COMMONINFO);
bResult = BQueryPrintDevmode(pDQPInfo, pci) && BQueryPrintForm(pDQPInfo, pci);
if (bResult) { PFN_OEMDevQueryPrintEx pfnOEMDevQueryPrintEx;
//
// call OEMDevQueryPrintEx entrypoint for each plugin,
// or until one of them returns FALSE.
//
FOREACH_OEMPLUGIN_LOOP(pci)
if (HAS_COM_INTERFACE(pOemEntry)) { HRESULT hr;
hr = HComOEMDevQueryPrintEx(pOemEntry, &pci->oemuiobj, pDQPInfo, pci->pdm, pOemEntry->pOEMDM); if (hr == E_NOTIMPL) continue;
if (!(bResult = SUCCEEDED(hr))) break;
} else { if ((pfnOEMDevQueryPrintEx = GET_OEM_ENTRYPOINT(pOemEntry, OEMDevQueryPrintEx)) && !pfnOEMDevQueryPrintEx(&pci->oemuiobj, pDQPInfo, pci->pdm, pOemEntry->pOEMDM)) { ERR(("OEMDevQueryPrintEx failed for '%ws': %d\n", CURRENT_OEM_MODULE_NAME(pOemEntry), GetLastError()));
bResult = FALSE; break; } }
END_OEMPLUGIN_LOOP }
VFreeCommonInfo(pci); return bResult; }
BOOL BFormatDQPMessage( PDEVQUERYPRINT_INFO pDQPInfo, INT iMsgResId, ... )
/*++
Routine Description:
Format DevQueryPrintEx error message
Arguments:
pDQPInfo - Points to a DEVQUERYPRINT_INFO structure iMsgResId - Error message format specifier (string resource ID)
Return Value:
FALSE
--*/
#define MAX_FORMAT_STRING 256
#define MAX_DQP_MESSAGE 512
{ TCHAR awchFormat[MAX_FORMAT_STRING]; TCHAR awchMessage[MAX_DQP_MESSAGE]; INT iLength = 0; va_list arglist;
//
// Load the format specifier string resource
// and use swprintf to format the error message
//
va_start(arglist, iMsgResId);
if (! LoadString(ghInstance, iMsgResId, awchFormat, MAX_FORMAT_STRING)) awchFormat[0] = NUL;
if (SUCCEEDED(StringCchVPrintfW(awchMessage, CCHOF(awchMessage), awchFormat, arglist))) { iLength = wcslen(awchMessage); }
if (iLength <= 0) { StringCchCopyW(awchMessage, CCHOF(awchMessage), L"Error"); iLength = wcslen(awchMessage); }
va_end(arglist);
//
// Copy the error message string to DQPInfo
//
iLength += 1; pDQPInfo->cchNeeded = iLength;
if (iLength > (INT) pDQPInfo->cchErrorStr) iLength = pDQPInfo->cchErrorStr;
if (pDQPInfo->pszErrorStr && iLength) CopyString(pDQPInfo->pszErrorStr, awchMessage, iLength);
return FALSE; }
BOOL BQueryPrintDevmode( PDEVQUERYPRINT_INFO pDQPInfo, PCOMMONINFO pci )
/*++
Routine Description:
Validate devmode information
Arguments:
pDQPInfo - Points to a DEVQUERYPRINT_INFO structure pci - Points to basic printer info
Return Value:
TRUE if successful, FALSE if the job should be held
--*/
{ INT iRealizedRes, iResX, iResY; PFEATURE pFeature; DWORD dwFeatureIndex, dwOptionIndexOld, dwOptionIndexNew; BOOL bUpdateFormField;
//
// Validate input devmode
// Get printer-sticky properties
// Merge doc- and printer-sticky printer feature selections
// Fix up combined options array with public devmode info
//
if (! BFillCommonInfoDevmode(pci, NULL, pDQPInfo->pDevMode)) return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_DEVMODE);
if (! BFillCommonInfoPrinterData(pci)) return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_PRINTERDATA);
if (! BCombineCommonInfoOptionsArray(pci)) return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_MEMORY);
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); return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_DEVMODE); }
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pci->pUIInfo, pFeature); dwOptionIndexOld = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
if (! ResolveUIConflicts( pci->pRawData, pci->pCombinedOptions, MAX_COMBINED_OPTIONS, MODE_DOCANDPRINTER_STICKY|DONT_RESOLVE_CONFLICT)) { return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_OPTSELECT); }
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)) return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_COMMONINFO);
//
// Check if the requested resolution is supported
//
iRealizedRes = max(pci->pdm->dmPrintQuality, pci->pdm->dmYResolution); iResX = iResY = 0;
//
// Kludze, there are some cases where apps set dmPrintQuality/dmYResolution
// to be one of the DMRES values. We skip the checking for resolution
// since Unidrv/Pscript will map them to one of the valid resolution options
// at print time
//
if (pDQPInfo->pDevMode->dmFields & DM_PRINTQUALITY) { iResX = pDQPInfo->pDevMode->dmPrintQuality;
if (iResX <= DMRES_DRAFT) return TRUE; }
if (pDQPInfo->pDevMode->dmFields & DM_YRESOLUTION) { iResY = pDQPInfo->pDevMode->dmYResolution;
if (iResY <= DMRES_DRAFT) return TRUE; }
if (max(iResX, iResY) != iRealizedRes) return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_RESOLUTION);
return TRUE; }
BOOL BQueryPrintForm( PDEVQUERYPRINT_INFO pDQPInfo, PCOMMONINFO pci )
/*++
Routine Description:
Check if the requested form and/or tray is available
Arguments:
pDQPInfo - Points to a DEVQUERYPRINT_INFO structure pci - Points to basic printer info
Return Value:
TRUE if successful, FALSE if the job should be held
--*/
{ PUIINFO pUIInfo; PFEATURE pFeature; PPAGESIZE pPageSize; PWSTR pwstrTrayName; FORM_TRAY_TABLE pFormTrayTable; FINDFORMTRAY FindData; WCHAR awchTrayName[CCHBINNAME]; DWORD dwFeatureIndex, dwOptionIndex; BOOL bResult = FALSE;
//
// Skip it if form name is not specified
//
if ((pci->pdm->dmFields & DM_FORMNAME) == 0 || pci->pdm->dmFormName[0] == NUL) { return TRUE; }
pUIInfo = pci->pUIInfo;
if ((pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE)) == NULL) { ASSERT(FALSE); return TRUE; }
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature); dwOptionIndex = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
if ((pPageSize = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex)) == NULL) { ASSERT(FALSE); return TRUE; }
//
// For custom page size option, we have left the devmode form fields unchanged.
// See function VOptionToDevmodeFields().
//
//
// We've only shown user forms supported by custom page size in Form-to-Tray table.
//
if (pPageSize->dwPaperSizeID == DMPAPER_USER || pPageSize->dwPaperSizeID == DMPAPER_CUSTOMSIZE) { FORM_INFO_1 *pForm;
//
// We already verified the dmFormName field at the beginning.
//
if (pForm = MyGetForm(pci->hPrinter, pci->pdm->dmFormName, 1)) { //
// Built-in and printer forms supported by custom page size option won't show
// up in either PageSize list or Form-to-Tray assignment table. So we only
// continue to check the From-to-Tray assignment table for user forms supported
// by custom page size option. See function BFormSupportedOnPrinter().
//
if (pForm->Flags != FORM_USER) { MemFree(pForm); return TRUE; }
MemFree(pForm); } }
//
// Get the specified tray name, if any
//
pwstrTrayName = NULL;
if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_INPUTSLOT)) { PINPUTSLOT pInputSlot;
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature); dwOptionIndex = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
if ((pInputSlot = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex)) && (pInputSlot->dwPaperSourceID != DMBIN_FORMSOURCE) && LOAD_STRING_OPTION_NAME(pci, pInputSlot, awchTrayName, CCHBINNAME)) { pwstrTrayName = awchTrayName; } }
//
// Find out if the requested form/tray pair is
// listed in the form-to-tray assignment table.
//
if (pFormTrayTable = PGetFormTrayTable(pci->hPrinter, NULL)) { RESET_FINDFORMTRAY(pFormTrayTable, &FindData);
bResult = BSearchFormTrayTable(pFormTrayTable, pwstrTrayName, pci->pdm->dmFormName, &FindData); MemFree(pFormTrayTable); }
if (! bResult) { if (pwstrTrayName != NULL) { return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_FORMTRAY, pci->pdm->dmFormName, pwstrTrayName); } else { return BFormatDQPMessage(pDQPInfo, IDS_DQPERR_FORMTRAY_ANY, pci->pdm->dmFormName); } }
return TRUE; }
|