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.

826 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. psoemhlp.c
  6. Abstract:
  7. PostScript helper functions for OEM UI plugins
  8. HSetOptions
  9. Author:
  10. Feng Yue (fengy)
  11. 8/24/2000 fengy Completed with support of both PPD and driver features.
  12. 7/21/2000 fengy Created it with function framework.
  13. --*/
  14. #include "precomp.h"
  15. //
  16. // PS driver's helper functions for OEM UI plugins
  17. //
  18. /*++
  19. Routine Name:
  20. VUpdatePSF_EMFFeatures
  21. Routine Description:
  22. change EMF features' settings to make sure they are in sync with each other
  23. Arguments:
  24. pci - pointer to driver's COMMONINFO structure
  25. dwChangedItemID - ID to indicate which item has been changed
  26. Return Value:
  27. None
  28. Last Error:
  29. None
  30. --*/
  31. VOID
  32. VUpdatePSF_EMFFeatures(
  33. IN PCOMMONINFO pci,
  34. IN DWORD dwChangedItemID
  35. )
  36. {
  37. PDEVMODE pdm = pci->pdm;
  38. PPSDRVEXTRA pdmPrivate = pci->pdmPrivate;
  39. //
  40. // (refer to VUpdateEmfFeatureItems and VUnpackDocumentPropertiesItems)
  41. //
  42. if (!((PUIDATA)pci)->bEMFSpooling)
  43. {
  44. ERR(("VUpdatePSF_EMFFeatures: spooler EMF disabled\n"));
  45. return;
  46. }
  47. if (dwChangedItemID != METASPOOL_ITEM)
  48. {
  49. if (!ISSET_MFSPOOL_FLAG(pdmPrivate))
  50. {
  51. //
  52. // need to turn driver EMF on to support the EMF feature
  53. //
  54. if (dwChangedItemID == NUP_ITEM)
  55. {
  56. //
  57. // booklet
  58. //
  59. if (NUPOPTION(pdmPrivate) == BOOKLET_UP)
  60. {
  61. TERSE(("EMF turned on for BOOKLET_UP\n"));
  62. SET_MFSPOOL_FLAG(pdmPrivate);
  63. }
  64. }
  65. else if (dwChangedItemID == REVPRINT_ITEM)
  66. {
  67. BOOL bReversed = BGetPageOrderFlag(pci);
  68. //
  69. // reverse printing
  70. //
  71. if ((!REVPRINTOPTION(pdmPrivate) && bReversed) ||
  72. (REVPRINTOPTION(pdmPrivate) && !bReversed))
  73. {
  74. TERSE(("EMF turned on for reverse order\n"));
  75. SET_MFSPOOL_FLAG(pdmPrivate);
  76. }
  77. }
  78. else if (dwChangedItemID == COPIES_COLLATE_ITEM)
  79. {
  80. //
  81. // collate
  82. //
  83. if ((pdm->dmFields & DM_COLLATE) &&
  84. (pdm->dmCollate == DMCOLLATE_TRUE) &&
  85. !PRINTER_SUPPORTS_COLLATE(pci))
  86. {
  87. TERSE(("EMF turned on for collate\n"));
  88. SET_MFSPOOL_FLAG(pdmPrivate);
  89. }
  90. }
  91. else
  92. {
  93. RIP(("unknown dwChangedItemID: %d\n", dwChangedItemID));
  94. }
  95. }
  96. }
  97. else
  98. {
  99. //
  100. // driver EMF option has being changed
  101. //
  102. if (!ISSET_MFSPOOL_FLAG(pdmPrivate))
  103. {
  104. BOOL bReversed = BGetPageOrderFlag(pci);
  105. //
  106. // drier EMF option is turned off, need to handle several EMF features
  107. //
  108. // booklet
  109. //
  110. if (NUPOPTION(pdmPrivate) == BOOKLET_UP)
  111. {
  112. TERSE(("EMF off, so BOOKLET_UP to ONE_UP\n"));
  113. NUPOPTION(pdmPrivate) = ONE_UP;
  114. }
  115. //
  116. // collate
  117. //
  118. if ((pdm->dmFields & DM_COLLATE) &&
  119. (pdm->dmCollate == DMCOLLATE_TRUE) &&
  120. !PRINTER_SUPPORTS_COLLATE(pci))
  121. {
  122. TERSE(("EMF off, so collate off\n"));
  123. pdm->dmCollate = DMCOLLATE_FALSE;
  124. //
  125. // Update Collate feature option index
  126. //
  127. ChangeOptionsViaID(pci->pInfoHeader,
  128. pci->pCombinedOptions,
  129. GID_COLLATE,
  130. pdm);
  131. }
  132. //
  133. // reverse order printing
  134. //
  135. if ((!REVPRINTOPTION(pdmPrivate) && bReversed) ||
  136. (REVPRINTOPTION(pdmPrivate) && !bReversed))
  137. {
  138. TERSE(("EMF off, so reverse %d\n", bReversed));
  139. REVPRINTOPTION(pdmPrivate) = bReversed;
  140. }
  141. }
  142. }
  143. }
  144. /*++
  145. Routine Name:
  146. BUpdatePSF_RevPrintAndOutputOrder
  147. Routine Description:
  148. sync up settings between driver synthesized feature %PageOrder
  149. and PPD feature *OutputOrder to avoid spooler simulation
  150. Arguments:
  151. pci - pointer to driver's COMMONINFO structure
  152. dwChangedItemID - ID to indicate which item has been changed
  153. Return Value:
  154. TRUE if the sync up succeeds
  155. FALSE if there is no PPD feature "OutputOrder" or current
  156. setting for "OutputOrder" is invalid
  157. Last Error:
  158. None
  159. --*/
  160. BOOL
  161. BUpdatePSF_RevPrintAndOutputOrder(
  162. IN PCOMMONINFO pci,
  163. IN DWORD dwChangedItemID
  164. )
  165. {
  166. PUIINFO pUIInfo = pci->pUIInfo;
  167. PPPDDATA pPpdData;
  168. PFEATURE pFeature;
  169. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER(pci->pInfoHeader);
  170. ASSERT(pPpdData != NULL && pPpdData->dwSizeOfStruct == sizeof(PPDDATA));
  171. //
  172. // refer to VSyncRevPrintAndOutputOrder
  173. //
  174. if (pPpdData &&
  175. pPpdData->dwOutputOrderIndex != INVALID_FEATURE_INDEX &&
  176. (pFeature = PGetIndexedFeature(pUIInfo, pPpdData->dwOutputOrderIndex)))
  177. {
  178. INT iSelection;
  179. POPTION pOption;
  180. PCSTR pstrOptionName;
  181. BOOL bReverse;
  182. //
  183. // "OutputOrder" feature is available. We only recognize the 2 standard options
  184. // "Normal" and "Reverse".
  185. //
  186. iSelection = pci->pCombinedOptions[pPpdData->dwOutputOrderIndex].ubCurOptIndex;
  187. if (iSelection < 2 &&
  188. (pOption = PGetIndexedOption(pUIInfo, pFeature, iSelection)) &&
  189. (pstrOptionName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName)))
  190. {
  191. PPSDRVEXTRA pdmPrivate = pci->pdmPrivate;
  192. if (strcmp(pstrOptionName, "Reverse") == EQUAL_STRING)
  193. bReverse = TRUE;
  194. else
  195. bReverse = FALSE;
  196. if (dwChangedItemID == REVPRINT_ITEM)
  197. {
  198. //
  199. // reverse printing setting has just being changed. We should change
  200. // "OutputOrder" option if needed to match the requested output order.
  201. //
  202. if ((!REVPRINTOPTION(pdmPrivate) && bReverse) ||
  203. (REVPRINTOPTION(pdmPrivate) && !bReverse))
  204. {
  205. TERSE(("RevPrint change causes OutputOrder to be %d\n", 1 - iSelection));
  206. pci->pCombinedOptions[pPpdData->dwOutputOrderIndex].ubCurOptIndex = (BYTE)(1 - iSelection);
  207. }
  208. }
  209. else
  210. {
  211. //
  212. // output order setting has just being changed. We should change reverse
  213. // printing option to match the request output order.
  214. //
  215. TERSE(("OutputOrder change causes RevPrint to be %d\n", bReverse));
  216. REVPRINTOPTION(pdmPrivate) = bReverse;
  217. }
  218. //
  219. // sync between reverse print and output order succeeeded
  220. //
  221. return TRUE;
  222. }
  223. }
  224. //
  225. // sync between reverse print and output order failed
  226. //
  227. return FALSE;
  228. }
  229. /*++
  230. Routine Name:
  231. VUpdatePSF_BookletAndDuplex
  232. Routine Description:
  233. sync up settings between driver synthesized feature %PagePerSheet
  234. and PPD feature *Duplex
  235. Arguments:
  236. pci - pointer to driver's COMMONINFO structure
  237. dwChangedItemID - ID to indicate which item has been changed
  238. Return Value:
  239. None
  240. Last Error:
  241. None
  242. --*/
  243. VOID
  244. VUpdatePSF_BookletAndDuplex(
  245. IN PCOMMONINFO pci,
  246. IN DWORD dwChangedItemID
  247. )
  248. {
  249. PUIINFO pUIInfo = pci->pUIInfo;
  250. PFEATURE pDuplexFeature;
  251. //
  252. // refer to VUpdateBookletOption
  253. //
  254. if (pDuplexFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_DUPLEX))
  255. {
  256. PDUPLEX pDuplexOption;
  257. DWORD dwFeatureIndex, dwOptionIndex;
  258. PPSDRVEXTRA pdmPrivate = pci->pdmPrivate;
  259. dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pDuplexFeature);
  260. dwOptionIndex = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
  261. pDuplexOption = PGetIndexedOption(pUIInfo, pDuplexFeature, dwOptionIndex);
  262. if (pDuplexOption &&
  263. pDuplexOption->dwDuplexID == DMDUP_SIMPLEX &&
  264. NUPOPTION(pdmPrivate) == BOOKLET_UP)
  265. {
  266. ASSERT(((PUIDATA)pci)->bEMFSpooling);
  267. if (dwChangedItemID == NUP_ITEM)
  268. {
  269. DWORD cIndex;
  270. //
  271. // Booklet is enabled - turn duplex on
  272. //
  273. pDuplexOption = PGetIndexedOption(pUIInfo, pDuplexFeature, 0);
  274. for (cIndex = 0 ; cIndex < pDuplexFeature->Options.dwCount; cIndex++)
  275. {
  276. if (pDuplexOption->dwDuplexID != DMDUP_SIMPLEX)
  277. {
  278. TERSE(("Booklet change causes Duplex to be %d\n", cIndex));
  279. pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex = (BYTE)cIndex;
  280. break;
  281. }
  282. pDuplexOption++;
  283. }
  284. }
  285. else
  286. {
  287. ASSERT(dwChangedItemID == DUPLEX_ITEM);
  288. //
  289. // Duplex is turned off, so disable booklet and set to 2 up.
  290. //
  291. TERSE(("Simplex change causes Booklet to be 2up\n"));
  292. NUPOPTION(pdmPrivate) = TWO_UP;
  293. }
  294. }
  295. }
  296. }
  297. /*++
  298. Routine Name:
  299. HSetOptions
  300. Routine Description:
  301. set new driver settings for PPD features and driver synthesized features
  302. Arguments:
  303. poemuiobj - pointer to driver context object
  304. dwFlags - flags for the set operation
  305. pmszFeatureOptionBuf - MULTI_SZ ASCII string containing new settings'
  306. feature/option keyword pairs
  307. cbin - size in bytes of the pmszFeatureOptionBuf string
  308. pdwResult - pointer to the DWORD that will store the result of set operation
  309. Return Value:
  310. S_OK if the set operation succeeds
  311. E_INVALIDARG if input pmszFeatureOptionBuf is not in valid MULTI_SZ format,
  312. or flag for the set operation is not recognized
  313. E_FAIL if the set operation fails
  314. Last Error:
  315. None
  316. --*/
  317. HRESULT
  318. HSetOptions(
  319. IN POEMUIOBJ poemuiobj,
  320. IN DWORD dwFlags,
  321. IN PCSTR pmszFeatureOptionBuf,
  322. IN DWORD cbIn,
  323. OUT PDWORD pdwResult
  324. )
  325. {
  326. PCOMMONINFO pci = (PCOMMONINFO)poemuiobj;
  327. PDEVMODE pdm;
  328. PPSDRVEXTRA pdmPrivate;
  329. PUIINFO pUIInfo;
  330. PPPDDATA pPpdData;
  331. PCSTR pszFeature, pszOption;
  332. BOOL bPageSizeSet = FALSE, bPrinterSticky, bNoConflict;
  333. INT iMode;
  334. LAYOUT iOldLayout;
  335. //
  336. // do some validation on the input parameters
  337. //
  338. if (!BValidMultiSZString(pmszFeatureOptionBuf, cbIn, TRUE))
  339. {
  340. ERR(("Set: invalid MULTI_SZ input param\n"));
  341. return E_INVALIDARG;
  342. }
  343. if (!(dwFlags & SETOPTIONS_FLAG_RESOLVE_CONFLICT) &&
  344. !(dwFlags & SETOPTIONS_FLAG_KEEP_CONFLICT))
  345. {
  346. ERR(("Set: invalid dwFlags %d\n", dwFlags));
  347. return E_INVALIDARG;
  348. }
  349. pUIInfo = pci->pUIInfo;
  350. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER(pci->pInfoHeader);
  351. ASSERT(pPpdData != NULL && pPpdData->dwSizeOfStruct == sizeof(PPDDATA));
  352. if (pPpdData == NULL)
  353. {
  354. return E_FAIL;
  355. }
  356. pdm = pci->pdm;
  357. bPrinterSticky = ((PUIDATA)pci)->iMode == MODE_PRINTER_STICKY ? TRUE : FALSE;
  358. if (!bPrinterSticky)
  359. {
  360. ASSERT(pdm);
  361. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  362. iOldLayout = NUPOPTION(pdmPrivate);
  363. //
  364. // First we need to propagate devmode settings (in case
  365. // plugin has changed it) into option array.
  366. //
  367. // devmode is only valid in non printer-sticky mode. Refer to comments
  368. // in HEnumConstrainedOptions().
  369. //
  370. VFixOptionsArrayWithDevmode(pci);
  371. }
  372. //
  373. // Then set each feature specified by plugin.
  374. //
  375. pszFeature = pmszFeatureOptionBuf;
  376. while (*pszFeature)
  377. {
  378. DWORD cbFeatureKeySize, cbOptionKeySize;
  379. cbFeatureKeySize = strlen(pszFeature) + 1;
  380. pszOption = pszFeature + cbFeatureKeySize;
  381. cbOptionKeySize = strlen(pszOption) + 1;
  382. //
  383. // Feature or option setting string can't be empty.
  384. //
  385. if (cbFeatureKeySize == 1 || cbOptionKeySize == 1)
  386. {
  387. ERR(("Set: empty feature or option keyword\n"));
  388. goto next_feature;
  389. }
  390. if (*pszFeature == PSFEATURE_PREFIX)
  391. {
  392. PPSFEATURE_ENTRY pEntry, pMatchEntry;
  393. //
  394. // synthesized PS driver feature
  395. //
  396. pMatchEntry = NULL;
  397. pEntry = (PPSFEATURE_ENTRY)(&kPSFeatureTable[0]);
  398. while (pEntry->pszPSFeatureName)
  399. {
  400. if ((*pszFeature == *(pEntry->pszPSFeatureName)) &&
  401. (strcmp(pszFeature, pEntry->pszPSFeatureName) == EQUAL_STRING))
  402. {
  403. pMatchEntry = pEntry;
  404. break;
  405. }
  406. pEntry++;
  407. }
  408. //
  409. // See comments in HEnumConstrainedOptions for following stickiness mode check.
  410. //
  411. if (!pMatchEntry ||
  412. (bPrinterSticky && !pMatchEntry->bPrinterSticky) ||
  413. (!bPrinterSticky && pMatchEntry->bPrinterSticky))
  414. {
  415. VERBOSE(("Set: invalid or mode-mismatched feature %s\n", pszFeature));
  416. goto next_feature;
  417. }
  418. if (pMatchEntry->pfnPSProc)
  419. {
  420. BOOL bResult;
  421. bResult = (pMatchEntry->pfnPSProc)(pci->hPrinter,
  422. pUIInfo,
  423. pPpdData,
  424. pdm,
  425. pci->pPrinterData,
  426. pszFeature,
  427. pszOption,
  428. NULL,
  429. 0,
  430. NULL,
  431. PSFPROC_SETOPTION_MODE);
  432. if (bResult)
  433. {
  434. //
  435. // PS driver EMF features EMF, PageOrder, Nup need special postprocessing
  436. // to synchronize among EMF features (refer to cpcbDocumentPropertyCallback).
  437. //
  438. if ((*pszFeature == kstrPSFEMF[0]) &&
  439. (strcmp(pszFeature, kstrPSFEMF) == EQUAL_STRING))
  440. {
  441. ASSERT(!bPrinterSticky);
  442. VUpdatePSF_EMFFeatures(pci, METASPOOL_ITEM);
  443. }
  444. else if ((*pszFeature == kstrPSFPageOrder[0]) &&
  445. (strcmp(pszFeature, kstrPSFPageOrder) == EQUAL_STRING))
  446. {
  447. ASSERT(!bPrinterSticky);
  448. //
  449. // first try to sync between reverse print and output order feature
  450. //
  451. if (!BUpdatePSF_RevPrintAndOutputOrder(pci, REVPRINT_ITEM))
  452. {
  453. //
  454. // if that failed, reverse print could force EMF on
  455. //
  456. VUpdatePSF_EMFFeatures(pci, REVPRINT_ITEM);
  457. }
  458. }
  459. else if ((*pszFeature == kstrPSFNup[0]) &&
  460. (strcmp(pszFeature, kstrPSFNup) == EQUAL_STRING))
  461. {
  462. ASSERT(!bPrinterSticky);
  463. if (NUPOPTION(pdmPrivate) == BOOKLET_UP)
  464. {
  465. if (!((PUIDATA)pci)->bEMFSpooling || !SUPPORTS_DUPLEX(pci))
  466. {
  467. //
  468. // booklet is not supported if duplex is constrained by an installable
  469. // feature such as duplex unit not installed or spooler EMF is disabled
  470. // (refer to BPackItemEmfFeatures)
  471. //
  472. ERR(("Set: BOOKLET_UP ignored for %s\n", pszFeature));
  473. NUPOPTION(pdmPrivate) = iOldLayout;
  474. }
  475. else
  476. {
  477. //
  478. // Booklet will force EMF on
  479. //
  480. VUpdatePSF_EMFFeatures(pci, NUP_ITEM);
  481. //
  482. // Booklet will also turn duplex on
  483. //
  484. VUpdatePSF_BookletAndDuplex(pci, NUP_ITEM);
  485. }
  486. }
  487. }
  488. }
  489. else
  490. {
  491. if (GetLastError() == ERROR_INVALID_PARAMETER)
  492. {
  493. ERR(("Set: %%-feature handler found invalid option %s for %s\n", pszOption, pszFeature));
  494. }
  495. else
  496. {
  497. ERR(("Set: %%-feature handler failed on %s-%s: %d\n", pszFeature, pszOption, GetLastError()));
  498. }
  499. }
  500. }
  501. }
  502. else
  503. {
  504. PFEATURE pFeature;
  505. POPTION pOption;
  506. DWORD dwFeatureIndex, dwOptionIndex;
  507. POPTSELECT pOptionsArray = pci->pCombinedOptions;
  508. //
  509. // PPD *OpenUI feature
  510. //
  511. pFeature = PGetNamedFeature(pUIInfo, pszFeature, &dwFeatureIndex);
  512. //
  513. // See comments in HEnumConstrainedOptions for following stickiness mode check.
  514. //
  515. if (!pFeature ||
  516. (bPrinterSticky && pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY) ||
  517. (!bPrinterSticky && pFeature->dwFeatureType == FEATURETYPE_PRINTERPROPERTY))
  518. {
  519. VERBOSE(("Set: invalid or mode-mismatched feature %s\n", pszFeature));
  520. goto next_feature;
  521. }
  522. //
  523. // Skip GID_LEADINGEDGE, GID_USEHWMARGINS. They are not real PPD *OpenUI features.
  524. // Also skip GID_PAGEREGION, it's only set internally. We don't allow user or plugin
  525. // to set it.
  526. //
  527. if (pFeature->dwFeatureID == GID_PAGEREGION ||
  528. pFeature->dwFeatureID == GID_LEADINGEDGE ||
  529. pFeature->dwFeatureID == GID_USEHWMARGINS)
  530. {
  531. ERR(("Set: skip feature %s\n", pszFeature));
  532. goto next_feature;
  533. }
  534. pOption = PGetNamedOption(pUIInfo, pFeature, pszOption, &dwOptionIndex);
  535. if (!pOption)
  536. {
  537. ERR(("Set: invalid input option %s for feature %s\n", pszOption, pszFeature));
  538. goto next_feature;
  539. }
  540. //
  541. // update the option selection
  542. //
  543. pOptionsArray[dwFeatureIndex].ubCurOptIndex = (BYTE)dwOptionIndex;
  544. //
  545. // We don't support pick-many yet.
  546. //
  547. ASSERT(pOptionsArray[dwFeatureIndex].ubNext == NULL_OPTSELECT);
  548. //
  549. // some special postprocessing after the option setting is changed
  550. //
  551. if (pFeature->dwFeatureID == GID_PAGESIZE)
  552. {
  553. PPAGESIZE pPageSize = (PPAGESIZE)pOption;
  554. ASSERT(!bPrinterSticky);
  555. //
  556. // special handling of PS custom page size
  557. //
  558. // refer to VUnpackDocumentPropertiesItems case FORMNAME_ITEM in docprop.c
  559. //
  560. if (pPageSize->dwPaperSizeID == DMPAPER_CUSTOMSIZE)
  561. {
  562. pdm->dmFields &= ~(DM_PAPERLENGTH|DM_PAPERWIDTH|DM_FORMNAME);
  563. pdm->dmFields |= DM_PAPERSIZE;
  564. pdm->dmPaperSize = DMPAPER_CUSTOMSIZE;
  565. LOAD_STRING_PAGESIZE_NAME(pci,
  566. pPageSize,
  567. pdm->dmFormName,
  568. CCHFORMNAME);
  569. }
  570. bPageSizeSet = TRUE;
  571. }
  572. else if (pFeature->dwFeatureID == GID_OUTPUTBIN)
  573. {
  574. ASSERT(!bPrinterSticky);
  575. //
  576. // output bin change could force EMF on
  577. //
  578. VUpdatePSF_EMFFeatures(pci, REVPRINT_ITEM);
  579. }
  580. else if (pPpdData->dwOutputOrderIndex != INVALID_FEATURE_INDEX &&
  581. dwFeatureIndex == pPpdData->dwOutputOrderIndex)
  582. {
  583. ASSERT(!bPrinterSticky);
  584. //
  585. // output order change causes reverse print change
  586. //
  587. if (!BUpdatePSF_RevPrintAndOutputOrder(pci, UNKNOWN_ITEM))
  588. {
  589. ERR(("OutputOrder change syncs RevPrint failed\n"));
  590. }
  591. }
  592. }
  593. next_feature:
  594. pszFeature += cbFeatureKeySize + cbOptionKeySize;
  595. }
  596. iMode = bPrinterSticky ? MODE_PRINTER_STICKY : MODE_DOCANDPRINTER_STICKY;
  597. if (dwFlags & SETOPTIONS_FLAG_KEEP_CONFLICT)
  598. {
  599. iMode |= DONT_RESOLVE_CONFLICT;
  600. }
  601. //
  602. // If we're inside DrvDocumentPropertySheets,
  603. // we'll call the parser to resolve conflicts between
  604. // all printer features. Since all printer-sticky
  605. // features have higher priority than all doc-sticky
  606. // features, only doc-sticky option selections should
  607. // be affected.
  608. //
  609. bNoConflict = ResolveUIConflicts(pci->pRawData,
  610. pci->pCombinedOptions,
  611. MAX_COMBINED_OPTIONS,
  612. iMode);
  613. if (pdwResult)
  614. {
  615. if (dwFlags & SETOPTIONS_FLAG_RESOLVE_CONFLICT)
  616. {
  617. *pdwResult = bNoConflict ? SETOPTIONS_RESULT_NO_CONFLICT :
  618. SETOPTIONS_RESULT_CONFLICT_RESOLVED;
  619. }
  620. else
  621. {
  622. *pdwResult = bNoConflict ? SETOPTIONS_RESULT_NO_CONFLICT :
  623. SETOPTIONS_RESULT_CONFLICT_REMAINED;
  624. }
  625. }
  626. if (!bPrinterSticky)
  627. {
  628. //
  629. // Lastly we need to transfer options array settings back
  630. // to devmode so they are in sync.
  631. //
  632. VOptionsToDevmodeFields(pci, bPageSizeSet);
  633. //
  634. // A few more postprocessing here
  635. //
  636. // collate could force EMF on
  637. //
  638. VUpdatePSF_EMFFeatures(pci, COPIES_COLLATE_ITEM);
  639. //
  640. // simplex could change booklet setting
  641. //
  642. VUpdatePSF_BookletAndDuplex(pci, DUPLEX_ITEM);
  643. }
  644. return S_OK;
  645. }