|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
prnprop.c
Abstract:
This file handles the PrinterProperties and DrvDevicePropertySheets spooler API
Environment:
Win32 subsystem, DriverUI module, user mode
Revision History:
02/13/97 -davidx- Implement OEM plugin support.
02/10/97 -davidx- Consistent handling of common printer info.
02/04/97 -davidx- Reorganize driver UI to separate ps and uni DLLs.
07/17/96 -amandan- Created it.
--*/
#include "precomp.h"
//
// Local functions prototypes
//
CPSUICALLBACK cpcbPrinterPropertyCallback(PCPSUICBPARAM); LONG LPrnPropApplyNow(PUIDATA, PCPSUICBPARAM, BOOL); LONG LPrnPropSelChange(PUIDATA, PCPSUICBPARAM);
LONG DrvDevicePropertySheets( PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam )
/*++
Routine Description:
This function adds the Device Property Page to the property sheets.
This function performs the following operations:
REASON_INIT- fills PCOMPROPSHEETUI with printer UI items calls compstui to add the page.
REASON_GET_INFO_HEADER - fills out PROPSHEETUI_INFO.
REASON_SET_RESULT - saves printerdata settings in registry buffer.
REASON_DESTROY - Cleans up.
Arguments:
pSUIInfo - pointer to PPROPSHEETUI_INFO lParam - varies depending on the reason this function is called
Return Value:
> 0 success <= 0 for failure
--*/
{ PDEVICEPROPERTYHEADER pDPHdr; PCOMPROPSHEETUI pCompstui; PUIDATA pUiData; LONG lResult, lRet; BOOL bResult = FALSE;
//
// Validate input parameters
//
if (!pPSUIInfo || !(pDPHdr = (PDEVICEPROPERTYHEADER) pPSUIInfo->lParamInit)) { RIP(("DrvDevicePropertySheet: invalid parameter\n")); return -1; }
//
// Create a UIDATA structure if necessary
//
if (pPSUIInfo->Reason == PROPSHEETUI_REASON_INIT) { pUiData = PFillUiData(pDPHdr->hPrinter, pDPHdr->pszPrinterName, NULL, MODE_PRINTER_STICKY); } else pUiData = (PUIDATA)pPSUIInfo->UserData;
//
// Validate pUiData
//
if (pUiData == NULL) { ERR(("UIDATA is NULL\n")); return -1; }
ASSERT(VALIDUIDATA(pUiData));
//
// Handle various cases for which this function might be called
//
switch (pPSUIInfo->Reason) { case PROPSHEETUI_REASON_INIT:
//
// Allocate memory and partially fill out various data
// structures required to call common UI routine.
//
pUiData->bPermission = ((pDPHdr->Flags & DPS_NOPERMISSION) == 0);
#ifdef PSCRIPT
FOREACH_OEMPLUGIN_LOOP((&(pUiData->ci)))
if (HAS_COM_INTERFACE(pOemEntry)) { HRESULT hr;
hr = HComOEMHideStandardUI(pOemEntry, OEMCUIP_PRNPROP);
//
// In the case when multiple plugins are chained, it doesn't
// make sense for one plugin to hide standard UI when another
// one still wants to use the standard UI. So as long as one
// plugin returns S_OK here, we will hide the standard UI.
//
if (bResult = SUCCEEDED(hr)) break; }
END_OEMPLUGIN_LOOP
#endif // PSCRIPT
if (bResult) { //
// Set the flag to indicate plugin is hiding our standard
// device property sheet UI.
//
pUiData->dwHideFlags |= HIDEFLAG_HIDE_STD_PRNPROP;
pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet; pUiData->hComPropSheet = pPSUIInfo->hComPropSheet;
if (BAddOemPluginPages(pUiData, pDPHdr->Flags)) { pPSUIInfo->UserData = (ULONG_PTR) pUiData; pPSUIInfo->Result = CPSUI_CANCEL; lRet = 1; break; } } else if (pCompstui = PPrepareDataForCommonUI(pUiData, CPSUI_PDLGPAGE_PRINTERPROP)) { pCompstui->pfnCallBack = cpcbPrinterPropertyCallback; pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet; pUiData->hComPropSheet = pPSUIInfo->hComPropSheet; pUiData->pCompstui = pCompstui;
//
// Show which items are constrained
//
VPropShowConstraints(pUiData, MODE_PRINTER_STICKY);
//
// Update the current selection of tray items based on
// the form-to-tray assignment table.
//
VSetupFormTrayAssignments(pUiData);
//
// Call common UI library to add our pages
//
if (pUiData->pfnComPropSheet(pUiData->hComPropSheet, CPSFUNC_ADD_PCOMPROPSHEETUI, (LPARAM) pCompstui, (LPARAM) &lResult) && BAddOemPluginPages(pUiData, pDPHdr->Flags)) { pPSUIInfo->UserData = (ULONG_PTR) pUiData; pPSUIInfo->Result = CPSUI_CANCEL;
lRet = 1; break; } }
//
// Clean up in the case of error
//
ERR(("Failed to initialize property sheets\n")); VFreeUiData(pUiData); return -1;
case PROPSHEETUI_REASON_GET_INFO_HEADER: { PPROPSHEETUI_INFO_HEADER pPSUIHdr; DWORD dwIcon;
pPSUIHdr = (PPROPSHEETUI_INFO_HEADER) lParam; pPSUIHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW; pPSUIHdr->pTitle = pUiData->ci.pPrinterName; pPSUIHdr->hInst = ghInstance;
//
// Use the Icon specified in the binary data as
// the printer icon.
//
dwIcon = pUiData->ci.pUIInfo->loPrinterIcon;
if (dwIcon && (pPSUIHdr->IconID = HLoadIconFromResourceDLL(&pUiData->ci, dwIcon))) pPSUIHdr->Flags |= PSUIHDRF_USEHICON; else pPSUIHdr->IconID = _DwGetPrinterIconID(); } lRet = 1; break;
case PROPSHEETUI_REASON_SET_RESULT:
{ PSETRESULT_INFO pSRInfo = (PSETRESULT_INFO) lParam; PCOMMONINFO pci = (PCOMMONINFO)pUiData;
//
// CPSUICB_REASON_APPLYNOW may not have been called. If so, we need
// to perform tasks that are usually done by CPSUICB_REASON_APPLYNOW
// case in our callback function cpcbPrinterPropertyCallback.
//
if ((pSRInfo->Result == CPSUI_OK) && !(pci->dwFlags & FLAG_APPLYNOW_CALLED)) { OPTSELECT OldCombinedOptions[MAX_COMBINED_OPTIONS];
//
// Save a copy the pre-resolve option array
//
CopyMemory(OldCombinedOptions, pci->pCombinedOptions, MAX_COMBINED_OPTIONS * sizeof(OPTSELECT));
//
// Call the parsers to resolve any remaining conflicts.
//
ResolveUIConflicts(pci->pRawData, pci->pCombinedOptions, MAX_COMBINED_OPTIONS, MODE_PRINTER_STICKY);
//
// Update the OPTITEM list to match the updated options array
//
VUpdateOptItemList(pUiData, OldCombinedOptions, pci->pCombinedOptions);
(VOID)LPrnPropApplyNow(pUiData, NULL, TRUE); }
pPSUIInfo->Result = pSRInfo->Result; }
lRet = 1; break;
case PROPSHEETUI_REASON_DESTROY:
//
// Clean up
//
VFreeUiData(pUiData); lRet = 1;
break;
default:
return -1; }
return lRet; }
CPSUICALLBACK cpcbPrinterPropertyCallback( IN PCPSUICBPARAM pCallbackParam )
/*++
Routine Description:
Callback function provided to common UI DLL for handling printer properties dialog.
Arguments:
pCallbackParam - Pointer to CPSUICBPARAM structure
Return Value:
CPSUICB_ACTION_NONE - no action needed CPSUICB_ACTION_OPTIF_CHANGED - items changed and should be refreshed
--*/
{ PUIDATA pUiData = (PUIDATA) pCallbackParam->UserData; LONG lRet = CPSUICB_ACTION_NONE;
ASSERT(VALIDUIDATA(pUiData)); pUiData->hDlg = pCallbackParam->hDlg;
//
// If user has no permission to change anything, then
// simply return without taking any action.
//
if (!HASPERMISSION(pUiData) && (pCallbackParam->Reason != CPSUICB_REASON_ABOUT)) return CPSUICB_ACTION_NONE;
switch (pCallbackParam->Reason) { case CPSUICB_REASON_SEL_CHANGED: case CPSUICB_REASON_ECB_CHANGED:
lRet = LPrnPropSelChange(pUiData, pCallbackParam); break;
case CPSUICB_REASON_ITEMS_REVERTED:
{ POPTITEM pOptItem; DWORD dwOptItem;
//
// This callback reason is used when user changed items
// and decided to revert changes from the parent item in
// the treeview. The callback funciton is called after
// all revertable items are reverted to its original.
// Only deal with installable feature at this point
//
dwOptItem = pUiData->dwFeatureItem; pOptItem = pUiData->pFeatureItems;
for ( ; dwOptItem--; pOptItem++) VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
//
// Show which items are constrained
//
VPropShowConstraints(pUiData, MODE_PRINTER_STICKY); }
lRet = CPSUICB_ACTION_REINIT_ITEMS; break;
case CPSUICB_REASON_APPLYNOW:
pUiData->ci.dwFlags |= FLAG_APPLYNOW_CALLED;
lRet = LPrnPropApplyNow(pUiData, pCallbackParam, FALSE); break;
case CPSUICB_REASON_ABOUT:
DialogBoxParam(ghInstance, MAKEINTRESOURCE(IDD_ABOUT), pUiData->hDlg, _AboutDlgProc, (LPARAM) pUiData); break;
#ifdef UNIDRV
case CPSUICB_REASON_PUSHBUTTON:
//
// Call the font installer
//
if (GETUSERDATAITEM(pCallbackParam->pCurItem->UserData) == SOFTFONT_SETTINGS_ITEM) { BOOL bUseOurDlgProc = TRUE; OEMFONTINSTPARAM fip; PFN_OEMFontInstallerDlgProc pDlgProc = NULL;
memset(&fip, 0, sizeof(OEMFONTINSTPARAM)); fip.cbSize = sizeof(OEMFONTINSTPARAM); fip.hPrinter = pUiData->ci.hPrinter; fip.hModule = ghInstance; fip.hHeap = pUiData->ci.hHeap; if (HASPERMISSION(pUiData)) fip.dwFlags = FG_CANCHANGE;
FOREACH_OEMPLUGIN_LOOP(&pUiData->ci)
if (HAS_COM_INTERFACE(pOemEntry)) {
if (HComOEMFontInstallerDlgProc(pOemEntry, NULL, 0, 0, (LPARAM)&fip) != E_NOTIMPL) { HComOEMFontInstallerDlgProc(pOemEntry, pUiData->hDlg, 0, 0, (LPARAM)&fip); bUseOurDlgProc = FALSE; break; } } else { pDlgProc = GET_OEM_ENTRYPOINT(pOemEntry, OEMFontInstallerDlgProc);
if (pDlgProc) { (pDlgProc)(pUiData->hDlg, 0, 0, (LPARAM)&fip); bUseOurDlgProc = FALSE; break; } }
END_OEMPLUGIN_LOOP
if (bUseOurDlgProc) { DialogBoxParam(ghInstance, MAKEINTRESOURCE(FONTINST), pUiData->hDlg, FontInstProc, (LPARAM)(&fip)); } }
break;
#endif // UNIDRV
default:
lRet = CPSUICB_ACTION_NONE; break; }
return LInvokeOemPluginCallbacks(pUiData, pCallbackParam, lRet); }
LONG LPrnPropSelChange( IN PUIDATA pUiData, IN PCPSUICBPARAM pCallbackParam ) /*++
Routine Description:
Handle the case where user changes the current selection of an item
Arguments:
pUiData - Pointer to our UIDATA structure pCallbackParam - Callback parameter passed to us by common UI
Return Value:
CPSUICB_ACTION_NONE - no action needed CPSUICB_ACTION_OPTIF_CHANGED - items changed and should be refreshed
--*/
{ POPTITEM pCurItem = pCallbackParam->pCurItem; PFEATURE pFeature;
if (! IS_DRIVER_OPTITEM(pUiData, pCurItem)) return CPSUICB_ACTION_NONE;
if (ISPRINTERFEATUREITEM(pCurItem->UserData)) { //
// Deal with generic printer features only here
// All generic features have pFeature stored in UserData
//
pFeature = (PFEATURE) GETUSERDATAITEM(pCurItem->UserData);
//
// Update the pOptionsArray with the new selection
//
VUpdateOptionsArrayWithSelection(pUiData, pCurItem);
//
// PostScript specific hack to manually associate *InstalledMemory
// printer feature with "Available PostScript Memory" option.
//
#ifdef PSCRIPT
if (pFeature->dwFeatureID == GID_MEMOPTION) { POPTITEM pVMOptItem; PMEMOPTION pMemOption;
if ((pVMOptItem = PFindOptItem(pUiData, PRINTER_VM_ITEM)) && (pMemOption = PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, pCurItem->Sel))) { PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData;
pVMOptItem->Flags |= OPTIF_CHANGED; pVMOptItem->Sel = pMemOption->dwFreeMem / KBYTES;
pPrinterData->dwFreeMem = pMemOption->dwFreeMem; pUiData->ci.dwFlags &= ~FLAG_USER_CHANGED_FREEMEM; } }
#endif // PSCRIPT
//
// Update the display and show which items are constrained
//
VPropShowConstraints(pUiData, MODE_PRINTER_STICKY); return CPSUICB_ACTION_REINIT_ITEMS; }
#ifdef PSCRIPT
if (GETUSERDATAITEM(pCurItem->UserData) == PRINTER_VM_ITEM) { //
// remember the fact that current value of "Available PostScript Memory" is entered by user
//
pUiData->ci.dwFlags |= FLAG_USER_CHANGED_FREEMEM; }
#endif // PSCRIPT
return CPSUICB_ACTION_NONE; }
VOID VUnpackPrinterPropertiesItems( IN OUT PUIDATA pUiData )
/*++
Routine Description:
Unpack printer properties treeview items
Arguments:
pUiData - Pointer to our UIDATA structure
Return Value:
NONE
Note:
Only save the settings from driver built-in features, the generic features selection are saved in PrnPropSelChange directly to pUiData->pOptionsArray (in addition to formtray assignemtn and printer vm)
--*/
{ PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData; POPTITEM pOptItem = pUiData->pDrvOptItem; DWORD dwOptItem = pUiData->dwDrvOptItem;
for ( ; dwOptItem > 0; dwOptItem--, pOptItem++) { switch (GETUSERDATAITEM(pOptItem->UserData)) { case JOB_TIMEOUT_ITEM:
pPrinterData->dwJobTimeout = pOptItem->Sel; break;
case WAIT_TIMEOUT_ITEM:
pPrinterData->dwWaitTimeout = pOptItem->Sel; break;
case IGNORE_DEVFONT_ITEM:
if (pOptItem->Sel == 0) pPrinterData->dwFlags &= ~PFLAGS_IGNORE_DEVFONT; else pPrinterData->dwFlags |= PFLAGS_IGNORE_DEVFONT; break;
case PAGE_PROTECT_ITEM: { VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
} break;
default:
_VUnpackDriverPrnPropItem(pUiData, pOptItem); break; } } }
LONG LPrnPropApplyNow( PUIDATA pUiData, PCPSUICBPARAM pCallbackParam, BOOL bFromSetResult )
/*++
Routine Description:
Handle the case where user clicks OK to exit the dialog Need to save the printer sticky options in pUiData->pOptionsArray to printerdata.aOptions
Arguments:
pUiData - Pointer to our UIDATA structure pCallbackParam - Callback parameter passed to us by common UI bFromSetResult - TRUE if called from PROPSHEETUI_REASON_SET_RESULT, FALSE otherwise.
Return Value:
CPSUICB_ACTION_NONE - dismiss the dialog CPSUICB_ACTION_NO_APPLY_EXIT - don't dismiss the dialog
--*/
{ PCOMMONINFO pci; BOOL bResult = TRUE;
if (!bFromSetResult) { ASSERT(pCallbackParam);
//
// Check if there are still any unresolved constraints left?
//
if (((pUiData->ci.dwFlags & FLAG_PLUGIN_CHANGED_OPTITEM) || BOptItemSelectionsChanged(pUiData->pDrvOptItem, pUiData->dwDrvOptItem)) && ICheckConstraintsDlg(pUiData, pUiData->pFeatureItems, pUiData->dwFeatureItem, TRUE) == CONFLICT_CANCEL) { //
// Conflicts found and user clicked CANCEL to
// go back to the dialog without dismissing it.
//
return CPSUICB_ACTION_NO_APPLY_EXIT; } }
//
// Unpack printer properties treeview items
//
VUnpackPrinterPropertiesItems(pUiData);
//
// Save form-to-tray assignment table
// Save font substitution table
// Save any driver-specific properties
//
if (! BUnpackItemFormTrayTable(pUiData)) { ERR(("BUnpackItemFormTrayTable failed\n")); bResult = FALSE; }
if (! BUnpackItemFontSubstTable(pUiData)) { ERR(("BUnpackItemFontSubstTable failed\n")); bResult = FALSE; }
if (! _BUnpackPrinterOptions(pUiData)) { ERR(("_BUnpackPrinterOptions failed\n")); bResult = FALSE; }
//
// Separate the printer sticky options from the combined option array
// and save it to printerdata.aOptions
//
pci = (PCOMMONINFO) pUiData;
SeparateOptionArray( pci->pRawData, pci->pCombinedOptions, pci->pPrinterData->aOptions, MAX_PRINTER_OPTIONS, MODE_PRINTER_STICKY);
if (!BSavePrinterProperties(pci->hPrinter, pci->pRawData, pci->pPrinterData, sizeof(PRINTERDATA))) { ERR(("BSavePrinterProperties failed\n")); bResult = FALSE; }
#ifndef WINNT_40
VNotifyDSOfUpdate(pci->hPrinter);
#endif // !WINNT_40
if (!bFromSetResult) { //
// DCR: Should we display an error message if there is
// an error while saving the printer-sticky properties?
//
pCallbackParam->Result = CPSUI_OK; return CPSUICB_ACTION_ITEMS_APPLIED; } else { return 1; } }
BOOL BPackPrinterPropertyItems( IN OUT PUIDATA pUiData )
/*++
Routine Description:
Pack printer property information into treeview items.
Arguments:
pUiData - Points to UIDATA structure
Return Value:
TRUE if successful, FALSE if there is an error.
--*/
{ return BPackItemFormTrayTable(pUiData) && _BPackFontSubstItems(pUiData) && _BPackPrinterOptions(pUiData) && BPackItemGenericOptions(pUiData) && BPackOemPluginItems(pUiData); }
|