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.

833 lines
21 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. prnprop.c
  5. Abstract:
  6. This file handles the PrinterProperties and
  7. DrvDevicePropertySheets spooler API
  8. Environment:
  9. Win32 subsystem, DriverUI module, user mode
  10. Revision History:
  11. 02/13/97 -davidx-
  12. Implement OEM plugin support.
  13. 02/10/97 -davidx-
  14. Consistent handling of common printer info.
  15. 02/04/97 -davidx-
  16. Reorganize driver UI to separate ps and uni DLLs.
  17. 07/17/96 -amandan-
  18. Created it.
  19. --*/
  20. #include "precomp.h"
  21. //
  22. // Local functions prototypes
  23. //
  24. CPSUICALLBACK cpcbPrinterPropertyCallback(PCPSUICBPARAM);
  25. LONG LPrnPropApplyNow(PUIDATA, PCPSUICBPARAM, BOOL);
  26. LONG LPrnPropSelChange(PUIDATA, PCPSUICBPARAM);
  27. LONG
  28. DrvDevicePropertySheets(
  29. PPROPSHEETUI_INFO pPSUIInfo,
  30. LPARAM lParam
  31. )
  32. /*++
  33. Routine Description:
  34. This function adds the Device Property Page to the
  35. property sheets.
  36. This function performs the following operations:
  37. REASON_INIT- fills PCOMPROPSHEETUI with printer UI items
  38. calls compstui to add the page.
  39. REASON_GET_INFO_HEADER - fills out PROPSHEETUI_INFO.
  40. REASON_SET_RESULT - saves printerdata settings in registry buffer.
  41. REASON_DESTROY - Cleans up.
  42. Arguments:
  43. pSUIInfo - pointer to PPROPSHEETUI_INFO
  44. lParam - varies depending on the reason this function is called
  45. Return Value:
  46. > 0 success <= 0 for failure
  47. --*/
  48. {
  49. PDEVICEPROPERTYHEADER pDPHdr;
  50. PCOMPROPSHEETUI pCompstui;
  51. PUIDATA pUiData;
  52. LONG lResult, lRet;
  53. BOOL bResult = FALSE;
  54. //
  55. // Validate input parameters
  56. //
  57. if (!pPSUIInfo || !(pDPHdr = (PDEVICEPROPERTYHEADER) pPSUIInfo->lParamInit))
  58. {
  59. RIP(("DrvDevicePropertySheet: invalid parameter\n"));
  60. return -1;
  61. }
  62. //
  63. // Create a UIDATA structure if necessary
  64. //
  65. if (pPSUIInfo->Reason == PROPSHEETUI_REASON_INIT)
  66. {
  67. pUiData = PFillUiData(pDPHdr->hPrinter,
  68. pDPHdr->pszPrinterName,
  69. NULL,
  70. MODE_PRINTER_STICKY);
  71. }
  72. else
  73. pUiData = (PUIDATA)pPSUIInfo->UserData;
  74. //
  75. // Validate pUiData
  76. //
  77. if (pUiData == NULL)
  78. {
  79. ERR(("UIDATA is NULL\n"));
  80. return -1;
  81. }
  82. ASSERT(VALIDUIDATA(pUiData));
  83. //
  84. // Handle various cases for which this function might be called
  85. //
  86. switch (pPSUIInfo->Reason)
  87. {
  88. case PROPSHEETUI_REASON_INIT:
  89. //
  90. // Allocate memory and partially fill out various data
  91. // structures required to call common UI routine.
  92. //
  93. pUiData->bPermission = ((pDPHdr->Flags & DPS_NOPERMISSION) == 0);
  94. #ifdef PSCRIPT
  95. FOREACH_OEMPLUGIN_LOOP((&(pUiData->ci)))
  96. if (HAS_COM_INTERFACE(pOemEntry))
  97. {
  98. HRESULT hr;
  99. hr = HComOEMHideStandardUI(pOemEntry,
  100. OEMCUIP_PRNPROP);
  101. //
  102. // In the case when multiple plugins are chained, it doesn't
  103. // make sense for one plugin to hide standard UI when another
  104. // one still wants to use the standard UI. So as long as one
  105. // plugin returns S_OK here, we will hide the standard UI.
  106. //
  107. if (bResult = SUCCEEDED(hr))
  108. break;
  109. }
  110. END_OEMPLUGIN_LOOP
  111. #endif // PSCRIPT
  112. if (bResult)
  113. {
  114. //
  115. // Set the flag to indicate plugin is hiding our standard
  116. // device property sheet UI.
  117. //
  118. pUiData->dwHideFlags |= HIDEFLAG_HIDE_STD_PRNPROP;
  119. pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet;
  120. pUiData->hComPropSheet = pPSUIInfo->hComPropSheet;
  121. if (BAddOemPluginPages(pUiData, pDPHdr->Flags))
  122. {
  123. pPSUIInfo->UserData = (ULONG_PTR) pUiData;
  124. pPSUIInfo->Result = CPSUI_CANCEL;
  125. lRet = 1;
  126. break;
  127. }
  128. }
  129. else if (pCompstui = PPrepareDataForCommonUI(pUiData, CPSUI_PDLGPAGE_PRINTERPROP))
  130. {
  131. pCompstui->pfnCallBack = cpcbPrinterPropertyCallback;
  132. pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet;
  133. pUiData->hComPropSheet = pPSUIInfo->hComPropSheet;
  134. pUiData->pCompstui = pCompstui;
  135. //
  136. // Show which items are constrained
  137. //
  138. VPropShowConstraints(pUiData, MODE_PRINTER_STICKY);
  139. //
  140. // Update the current selection of tray items based on
  141. // the form-to-tray assignment table.
  142. //
  143. VSetupFormTrayAssignments(pUiData);
  144. //
  145. // Call common UI library to add our pages
  146. //
  147. if (pUiData->pfnComPropSheet(pUiData->hComPropSheet,
  148. CPSFUNC_ADD_PCOMPROPSHEETUI,
  149. (LPARAM) pCompstui,
  150. (LPARAM) &lResult) &&
  151. BAddOemPluginPages(pUiData, pDPHdr->Flags))
  152. {
  153. pPSUIInfo->UserData = (ULONG_PTR) pUiData;
  154. pPSUIInfo->Result = CPSUI_CANCEL;
  155. lRet = 1;
  156. break;
  157. }
  158. }
  159. //
  160. // Clean up in the case of error
  161. //
  162. ERR(("Failed to initialize property sheets\n"));
  163. VFreeUiData(pUiData);
  164. return -1;
  165. case PROPSHEETUI_REASON_GET_INFO_HEADER:
  166. {
  167. PPROPSHEETUI_INFO_HEADER pPSUIHdr;
  168. DWORD dwIcon;
  169. pPSUIHdr = (PPROPSHEETUI_INFO_HEADER) lParam;
  170. pPSUIHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW;
  171. pPSUIHdr->pTitle = pUiData->ci.pPrinterName;
  172. pPSUIHdr->hInst = ghInstance;
  173. //
  174. // Use the Icon specified in the binary data as
  175. // the printer icon.
  176. //
  177. dwIcon = pUiData->ci.pUIInfo->loPrinterIcon;
  178. if (dwIcon && (pPSUIHdr->IconID = HLoadIconFromResourceDLL(&pUiData->ci, dwIcon)))
  179. pPSUIHdr->Flags |= PSUIHDRF_USEHICON;
  180. else
  181. pPSUIHdr->IconID = _DwGetPrinterIconID();
  182. }
  183. lRet = 1;
  184. break;
  185. case PROPSHEETUI_REASON_SET_RESULT:
  186. {
  187. PSETRESULT_INFO pSRInfo = (PSETRESULT_INFO) lParam;
  188. PCOMMONINFO pci = (PCOMMONINFO)pUiData;
  189. //
  190. // CPSUICB_REASON_APPLYNOW may not have been called. If so, we need
  191. // to perform tasks that are usually done by CPSUICB_REASON_APPLYNOW
  192. // case in our callback function cpcbPrinterPropertyCallback.
  193. //
  194. if ((pSRInfo->Result == CPSUI_OK) &&
  195. !(pci->dwFlags & FLAG_APPLYNOW_CALLED))
  196. {
  197. OPTSELECT OldCombinedOptions[MAX_COMBINED_OPTIONS];
  198. //
  199. // Save a copy the pre-resolve option array
  200. //
  201. CopyMemory(OldCombinedOptions,
  202. pci->pCombinedOptions,
  203. MAX_COMBINED_OPTIONS * sizeof(OPTSELECT));
  204. //
  205. // Call the parsers to resolve any remaining conflicts.
  206. //
  207. ResolveUIConflicts(pci->pRawData,
  208. pci->pCombinedOptions,
  209. MAX_COMBINED_OPTIONS,
  210. MODE_PRINTER_STICKY);
  211. //
  212. // Update the OPTITEM list to match the updated options array
  213. //
  214. VUpdateOptItemList(pUiData, OldCombinedOptions, pci->pCombinedOptions);
  215. (VOID)LPrnPropApplyNow(pUiData, NULL, TRUE);
  216. }
  217. pPSUIInfo->Result = pSRInfo->Result;
  218. }
  219. lRet = 1;
  220. break;
  221. case PROPSHEETUI_REASON_DESTROY:
  222. //
  223. // Clean up
  224. //
  225. VFreeUiData(pUiData);
  226. lRet = 1;
  227. break;
  228. default:
  229. return -1;
  230. }
  231. return lRet;
  232. }
  233. CPSUICALLBACK
  234. cpcbPrinterPropertyCallback(
  235. IN PCPSUICBPARAM pCallbackParam
  236. )
  237. /*++
  238. Routine Description:
  239. Callback function provided to common UI DLL for handling
  240. printer properties dialog.
  241. Arguments:
  242. pCallbackParam - Pointer to CPSUICBPARAM structure
  243. Return Value:
  244. CPSUICB_ACTION_NONE - no action needed
  245. CPSUICB_ACTION_OPTIF_CHANGED - items changed and should be refreshed
  246. --*/
  247. {
  248. PUIDATA pUiData = (PUIDATA) pCallbackParam->UserData;
  249. LONG lRet = CPSUICB_ACTION_NONE;
  250. ASSERT(VALIDUIDATA(pUiData));
  251. pUiData->hDlg = pCallbackParam->hDlg;
  252. //
  253. // If user has no permission to change anything, then
  254. // simply return without taking any action.
  255. //
  256. if (!HASPERMISSION(pUiData) && (pCallbackParam->Reason != CPSUICB_REASON_ABOUT))
  257. return CPSUICB_ACTION_NONE;
  258. switch (pCallbackParam->Reason)
  259. {
  260. case CPSUICB_REASON_SEL_CHANGED:
  261. case CPSUICB_REASON_ECB_CHANGED:
  262. lRet = LPrnPropSelChange(pUiData, pCallbackParam);
  263. break;
  264. case CPSUICB_REASON_ITEMS_REVERTED:
  265. {
  266. POPTITEM pOptItem;
  267. DWORD dwOptItem;
  268. //
  269. // This callback reason is used when user changed items
  270. // and decided to revert changes from the parent item in
  271. // the treeview. The callback funciton is called after
  272. // all revertable items are reverted to its original.
  273. // Only deal with installable feature at this point
  274. //
  275. dwOptItem = pUiData->dwFeatureItem;
  276. pOptItem = pUiData->pFeatureItems;
  277. for ( ; dwOptItem--; pOptItem++)
  278. VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
  279. //
  280. // Show which items are constrained
  281. //
  282. VPropShowConstraints(pUiData, MODE_PRINTER_STICKY);
  283. }
  284. lRet = CPSUICB_ACTION_REINIT_ITEMS;
  285. break;
  286. case CPSUICB_REASON_APPLYNOW:
  287. pUiData->ci.dwFlags |= FLAG_APPLYNOW_CALLED;
  288. lRet = LPrnPropApplyNow(pUiData, pCallbackParam, FALSE);
  289. break;
  290. case CPSUICB_REASON_ABOUT:
  291. DialogBoxParam(ghInstance,
  292. MAKEINTRESOURCE(IDD_ABOUT),
  293. pUiData->hDlg,
  294. _AboutDlgProc,
  295. (LPARAM) pUiData);
  296. break;
  297. #ifdef UNIDRV
  298. case CPSUICB_REASON_PUSHBUTTON:
  299. //
  300. // Call the font installer
  301. //
  302. if (GETUSERDATAITEM(pCallbackParam->pCurItem->UserData) == SOFTFONT_SETTINGS_ITEM)
  303. {
  304. BOOL bUseOurDlgProc = TRUE;
  305. OEMFONTINSTPARAM fip;
  306. PFN_OEMFontInstallerDlgProc pDlgProc = NULL;
  307. memset(&fip, 0, sizeof(OEMFONTINSTPARAM));
  308. fip.cbSize = sizeof(OEMFONTINSTPARAM);
  309. fip.hPrinter = pUiData->ci.hPrinter;
  310. fip.hModule = ghInstance;
  311. fip.hHeap = pUiData->ci.hHeap;
  312. if (HASPERMISSION(pUiData))
  313. fip.dwFlags = FG_CANCHANGE;
  314. FOREACH_OEMPLUGIN_LOOP(&pUiData->ci)
  315. if (HAS_COM_INTERFACE(pOemEntry))
  316. {
  317. if (HComOEMFontInstallerDlgProc(pOemEntry,
  318. NULL,
  319. 0,
  320. 0,
  321. (LPARAM)&fip) != E_NOTIMPL)
  322. {
  323. HComOEMFontInstallerDlgProc(pOemEntry,
  324. pUiData->hDlg,
  325. 0,
  326. 0,
  327. (LPARAM)&fip);
  328. bUseOurDlgProc = FALSE;
  329. break;
  330. }
  331. }
  332. else
  333. {
  334. pDlgProc = GET_OEM_ENTRYPOINT(pOemEntry, OEMFontInstallerDlgProc);
  335. if (pDlgProc)
  336. {
  337. (pDlgProc)(pUiData->hDlg, 0, 0, (LPARAM)&fip);
  338. bUseOurDlgProc = FALSE;
  339. break;
  340. }
  341. }
  342. END_OEMPLUGIN_LOOP
  343. if (bUseOurDlgProc)
  344. {
  345. DialogBoxParam(ghInstance,
  346. MAKEINTRESOURCE(FONTINST),
  347. pUiData->hDlg,
  348. FontInstProc,
  349. (LPARAM)(&fip));
  350. }
  351. }
  352. break;
  353. #endif // UNIDRV
  354. default:
  355. lRet = CPSUICB_ACTION_NONE;
  356. break;
  357. }
  358. return LInvokeOemPluginCallbacks(pUiData, pCallbackParam, lRet);
  359. }
  360. LONG
  361. LPrnPropSelChange(
  362. IN PUIDATA pUiData,
  363. IN PCPSUICBPARAM pCallbackParam
  364. )
  365. /*++
  366. Routine Description:
  367. Handle the case where user changes the current selection of an item
  368. Arguments:
  369. pUiData - Pointer to our UIDATA structure
  370. pCallbackParam - Callback parameter passed to us by common UI
  371. Return Value:
  372. CPSUICB_ACTION_NONE - no action needed
  373. CPSUICB_ACTION_OPTIF_CHANGED - items changed and should be refreshed
  374. --*/
  375. {
  376. POPTITEM pCurItem = pCallbackParam->pCurItem;
  377. PFEATURE pFeature;
  378. if (! IS_DRIVER_OPTITEM(pUiData, pCurItem))
  379. return CPSUICB_ACTION_NONE;
  380. if (ISPRINTERFEATUREITEM(pCurItem->UserData))
  381. {
  382. //
  383. // Deal with generic printer features only here
  384. // All generic features have pFeature stored in UserData
  385. //
  386. pFeature = (PFEATURE) GETUSERDATAITEM(pCurItem->UserData);
  387. //
  388. // Update the pOptionsArray with the new selection
  389. //
  390. VUpdateOptionsArrayWithSelection(pUiData, pCurItem);
  391. //
  392. // PostScript specific hack to manually associate *InstalledMemory
  393. // printer feature with "Available PostScript Memory" option.
  394. //
  395. #ifdef PSCRIPT
  396. if (pFeature->dwFeatureID == GID_MEMOPTION)
  397. {
  398. POPTITEM pVMOptItem;
  399. PMEMOPTION pMemOption;
  400. if ((pVMOptItem = PFindOptItem(pUiData, PRINTER_VM_ITEM)) &&
  401. (pMemOption = PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, pCurItem->Sel)))
  402. {
  403. PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData;
  404. pVMOptItem->Flags |= OPTIF_CHANGED;
  405. pVMOptItem->Sel = pMemOption->dwFreeMem / KBYTES;
  406. pPrinterData->dwFreeMem = pMemOption->dwFreeMem;
  407. pUiData->ci.dwFlags &= ~FLAG_USER_CHANGED_FREEMEM;
  408. }
  409. }
  410. #endif // PSCRIPT
  411. //
  412. // Update the display and show which items are constrained
  413. //
  414. VPropShowConstraints(pUiData, MODE_PRINTER_STICKY);
  415. return CPSUICB_ACTION_REINIT_ITEMS;
  416. }
  417. #ifdef PSCRIPT
  418. if (GETUSERDATAITEM(pCurItem->UserData) == PRINTER_VM_ITEM)
  419. {
  420. //
  421. // remember the fact that current value of "Available PostScript Memory" is entered by user
  422. //
  423. pUiData->ci.dwFlags |= FLAG_USER_CHANGED_FREEMEM;
  424. }
  425. #endif // PSCRIPT
  426. return CPSUICB_ACTION_NONE;
  427. }
  428. VOID
  429. VUnpackPrinterPropertiesItems(
  430. IN OUT PUIDATA pUiData
  431. )
  432. /*++
  433. Routine Description:
  434. Unpack printer properties treeview items
  435. Arguments:
  436. pUiData - Pointer to our UIDATA structure
  437. Return Value:
  438. NONE
  439. Note:
  440. Only save the settings from driver built-in features, the
  441. generic features selection are saved in PrnPropSelChange directly
  442. to pUiData->pOptionsArray (in addition to formtray assignemtn and
  443. printer vm)
  444. --*/
  445. {
  446. PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData;
  447. POPTITEM pOptItem = pUiData->pDrvOptItem;
  448. DWORD dwOptItem = pUiData->dwDrvOptItem;
  449. for ( ; dwOptItem > 0; dwOptItem--, pOptItem++)
  450. {
  451. switch (GETUSERDATAITEM(pOptItem->UserData))
  452. {
  453. case JOB_TIMEOUT_ITEM:
  454. pPrinterData->dwJobTimeout = pOptItem->Sel;
  455. break;
  456. case WAIT_TIMEOUT_ITEM:
  457. pPrinterData->dwWaitTimeout = pOptItem->Sel;
  458. break;
  459. case IGNORE_DEVFONT_ITEM:
  460. if (pOptItem->Sel == 0)
  461. pPrinterData->dwFlags &= ~PFLAGS_IGNORE_DEVFONT;
  462. else
  463. pPrinterData->dwFlags |= PFLAGS_IGNORE_DEVFONT;
  464. break;
  465. case PAGE_PROTECT_ITEM:
  466. {
  467. VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
  468. }
  469. break;
  470. default:
  471. _VUnpackDriverPrnPropItem(pUiData, pOptItem);
  472. break;
  473. }
  474. }
  475. }
  476. LONG
  477. LPrnPropApplyNow(
  478. PUIDATA pUiData,
  479. PCPSUICBPARAM pCallbackParam,
  480. BOOL bFromSetResult
  481. )
  482. /*++
  483. Routine Description:
  484. Handle the case where user clicks OK to exit the dialog
  485. Need to save the printer sticky options in pUiData->pOptionsArray
  486. to printerdata.aOptions
  487. Arguments:
  488. pUiData - Pointer to our UIDATA structure
  489. pCallbackParam - Callback parameter passed to us by common UI
  490. bFromSetResult - TRUE if called from PROPSHEETUI_REASON_SET_RESULT, FALSE otherwise.
  491. Return Value:
  492. CPSUICB_ACTION_NONE - dismiss the dialog
  493. CPSUICB_ACTION_NO_APPLY_EXIT - don't dismiss the dialog
  494. --*/
  495. {
  496. PCOMMONINFO pci;
  497. BOOL bResult = TRUE;
  498. if (!bFromSetResult)
  499. {
  500. ASSERT(pCallbackParam);
  501. //
  502. // Check if there are still any unresolved constraints left?
  503. //
  504. if (((pUiData->ci.dwFlags & FLAG_PLUGIN_CHANGED_OPTITEM) ||
  505. BOptItemSelectionsChanged(pUiData->pDrvOptItem, pUiData->dwDrvOptItem)) &&
  506. ICheckConstraintsDlg(pUiData,
  507. pUiData->pFeatureItems,
  508. pUiData->dwFeatureItem,
  509. TRUE) == CONFLICT_CANCEL)
  510. {
  511. //
  512. // Conflicts found and user clicked CANCEL to
  513. // go back to the dialog without dismissing it.
  514. //
  515. return CPSUICB_ACTION_NO_APPLY_EXIT;
  516. }
  517. }
  518. //
  519. // Unpack printer properties treeview items
  520. //
  521. VUnpackPrinterPropertiesItems(pUiData);
  522. //
  523. // Save form-to-tray assignment table
  524. // Save font substitution table
  525. // Save any driver-specific properties
  526. //
  527. if (! BUnpackItemFormTrayTable(pUiData))
  528. {
  529. ERR(("BUnpackItemFormTrayTable failed\n"));
  530. bResult = FALSE;
  531. }
  532. if (! BUnpackItemFontSubstTable(pUiData))
  533. {
  534. ERR(("BUnpackItemFontSubstTable failed\n"));
  535. bResult = FALSE;
  536. }
  537. if (! _BUnpackPrinterOptions(pUiData))
  538. {
  539. ERR(("_BUnpackPrinterOptions failed\n"));
  540. bResult = FALSE;
  541. }
  542. //
  543. // Separate the printer sticky options from the combined option array
  544. // and save it to printerdata.aOptions
  545. //
  546. pci = (PCOMMONINFO) pUiData;
  547. SeparateOptionArray(
  548. pci->pRawData,
  549. pci->pCombinedOptions,
  550. pci->pPrinterData->aOptions,
  551. MAX_PRINTER_OPTIONS,
  552. MODE_PRINTER_STICKY);
  553. if (!BSavePrinterProperties(pci->hPrinter, pci->pRawData,
  554. pci->pPrinterData, sizeof(PRINTERDATA)))
  555. {
  556. ERR(("BSavePrinterProperties failed\n"));
  557. bResult = FALSE;
  558. }
  559. #ifndef WINNT_40
  560. VNotifyDSOfUpdate(pci->hPrinter);
  561. #endif // !WINNT_40
  562. if (!bFromSetResult)
  563. {
  564. //
  565. // DCR: Should we display an error message if there is
  566. // an error while saving the printer-sticky properties?
  567. //
  568. pCallbackParam->Result = CPSUI_OK;
  569. return CPSUICB_ACTION_ITEMS_APPLIED;
  570. }
  571. else
  572. {
  573. return 1;
  574. }
  575. }
  576. BOOL
  577. BPackPrinterPropertyItems(
  578. IN OUT PUIDATA pUiData
  579. )
  580. /*++
  581. Routine Description:
  582. Pack printer property information into treeview items.
  583. Arguments:
  584. pUiData - Points to UIDATA structure
  585. Return Value:
  586. TRUE if successful, FALSE if there is an error.
  587. --*/
  588. {
  589. return
  590. BPackItemFormTrayTable(pUiData) &&
  591. _BPackFontSubstItems(pUiData) &&
  592. _BPackPrinterOptions(pUiData) &&
  593. BPackItemGenericOptions(pUiData) &&
  594. BPackOemPluginItems(pUiData);
  595. }