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.

1985 lines
49 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. commonui.c
  5. Abstract:
  6. This file contains all the functions related to preparing data for
  7. CPSUI. This includes packing data items for printer property sheets and
  8. document property sheets.
  9. Environment:
  10. Win32 subsystem, DriverUI module, user mode
  11. Revision History:
  12. 02/13/97 -davidx-
  13. Common function to handle well-known and generic printer features.
  14. 02/10/97 -davidx-
  15. Consistent handling of common printer info.
  16. 02/04/97 -davidx-
  17. Reorganize driver UI to separate ps and uni DLLs.
  18. 09/12/96 -amandan-
  19. Created it.
  20. --*/
  21. #include "precomp.h"
  22. PCOMPROPSHEETUI
  23. PPrepareDataForCommonUI(
  24. IN OUT PUIDATA pUiData,
  25. IN PDLGPAGE pDlgPage
  26. )
  27. /*++
  28. Routine Description:
  29. Allocate memory and partially fill out the data structures required
  30. to call common UI routine. Once all information in pUiData are
  31. initialized properly, it calls PackDocumentPropertyItems() or
  32. PackPrinterPropertyItems() to pack the option items.
  33. Arguments:
  34. pUiData - Pointer to our UIDATA structure
  35. pDlgPage - Pointer to dialog pages
  36. Return Value:
  37. Pointer to a COMPROPSHEETUI structure, NULL if there is an error
  38. --*/
  39. {
  40. PCOMPROPSHEETUI pCompstui;
  41. DWORD dwCount, dwIcon, dwOptItemCount, dwSize;
  42. PCOMMONINFO pci = (PCOMMONINFO) pUiData;
  43. HANDLE hHeap = pUiData->ci.hHeap;
  44. BOOL (*pfnPackItemProc)(PUIDATA);
  45. POPTITEM pOptItem;
  46. PBYTE pUserData;
  47. //
  48. // Enumerate form names supported on the printer
  49. //
  50. dwCount = DwEnumPaperSizes(pci, NULL, NULL, NULL, NULL, UNUSED_PARAM);
  51. if (dwCount != GDI_ERROR && dwCount != 0)
  52. {
  53. pUiData->dwFormNames = dwCount;
  54. pUiData->pFormNames = HEAPALLOC(hHeap, dwCount * sizeof(WCHAR) * CCHPAPERNAME);
  55. pUiData->pwPapers = HEAPALLOC(hHeap, dwCount * sizeof(WORD));
  56. pUiData->pwPaperFeatures = HEAPALLOC(hHeap, dwCount * sizeof(WORD));
  57. }
  58. if (!pUiData->pFormNames || !pUiData->pwPapers || !pUiData->pwPaperFeatures)
  59. return NULL;
  60. (VOID) DwEnumPaperSizes(
  61. pci,
  62. pUiData->pFormNames,
  63. pUiData->pwPapers,
  64. NULL,
  65. pUiData->pwPaperFeatures,
  66. UNUSED_PARAM);
  67. #ifdef PSCRIPT
  68. //
  69. // We don't need to keep information about spooler forms
  70. // after this point. So dispose of it to free up memory.
  71. //
  72. MemFree(pUiData->ci.pSplForms);
  73. pUiData->ci.pSplForms = NULL;
  74. pUiData->ci.dwSplForms = 0;
  75. #endif
  76. //
  77. // Enumerate input bin names supported on the printer
  78. //
  79. dwCount = DwEnumBinNames(pci, NULL);
  80. if (dwCount != GDI_ERROR)
  81. {
  82. pUiData->dwBinNames = dwCount;
  83. pUiData->pBinNames = HEAPALLOC(hHeap, dwCount * sizeof(WCHAR) * CCHBINNAME);
  84. }
  85. if (! pUiData->pBinNames)
  86. return NULL;
  87. //
  88. // Don't need to check return here
  89. //
  90. DwEnumBinNames(pci, pUiData->pBinNames);
  91. //
  92. // Allocate memory to hold various data structures
  93. //
  94. if (! (pCompstui = HEAPALLOC(hHeap, sizeof(COMPROPSHEETUI))))
  95. return NULL;
  96. memset(pCompstui, 0, sizeof(COMPROPSHEETUI));
  97. //
  98. // Initialize COMPROPSHEETUI structure
  99. //
  100. pCompstui->cbSize = sizeof(COMPROPSHEETUI);
  101. pCompstui->UserData = (ULONG_PTR) pUiData;
  102. pCompstui->pDlgPage = pDlgPage;
  103. pCompstui->cDlgPage = 0;
  104. pCompstui->hInstCaller = ghInstance;
  105. pCompstui->pCallerName = _PwstrGetCallerName();
  106. pCompstui->pOptItemName = pUiData->ci.pDriverInfo3->pName;
  107. pCompstui->CallerVersion = gwDriverVersion;
  108. pCompstui->OptItemVersion = 0;
  109. dwIcon = pUiData->ci.pUIInfo->loPrinterIcon;
  110. if (dwIcon && (pCompstui->IconID = HLoadIconFromResourceDLL(&pUiData->ci, dwIcon)))
  111. pCompstui->Flags |= CPSUIF_ICONID_AS_HICON;
  112. else
  113. pCompstui->IconID = _DwGetPrinterIconID();
  114. if (HASPERMISSION(pUiData))
  115. pCompstui->Flags |= CPSUIF_UPDATE_PERMISSION;
  116. pCompstui->Flags |= CPSUIF_ABOUT_CALLBACK;
  117. pCompstui->pHelpFile = pUiData->ci.pDriverInfo3->pHelpFile;
  118. //
  119. // Call either PackDocumentPropertyItems or PackPrinterPropertyItems
  120. // to get the number of items and types.
  121. //
  122. pfnPackItemProc = (pUiData->iMode == MODE_DOCUMENT_STICKY) ?
  123. BPackDocumentPropertyItems :
  124. BPackPrinterPropertyItems;
  125. pUiData->dwOptItem = 0;
  126. pUiData->pOptItem = NULL;
  127. pUiData->dwOptType = 0;
  128. pUiData->pOptType = NULL;
  129. if (! pfnPackItemProc(pUiData))
  130. {
  131. ERR(("Error while packing OPTITEM's\n"));
  132. return NULL;
  133. }
  134. //
  135. // Allocate memory to hold OPTITEMs and OPTTYPEs
  136. //
  137. ASSERT(pUiData->dwOptItem > 0);
  138. VERBOSE(("Number of OPTTYPE's: %d\n", pUiData->dwOptType));
  139. VERBOSE(("Number of OPTITEM's: %d\n", pUiData->dwOptItem));
  140. pUiData->pOptItem = HEAPALLOC(hHeap, sizeof(OPTITEM) * pUiData->dwOptItem);
  141. pUiData->pOptType = HEAPALLOC(hHeap, sizeof(OPTTYPE) * pUiData->dwOptType);
  142. pUserData = HEAPALLOC(hHeap, sizeof(USERDATA)* pUiData->dwOptItem);
  143. if (!pUiData->pOptItem || !pUiData->pOptType || !pUserData)
  144. return NULL;
  145. //
  146. // Initializes OPTITEM.USERDATA
  147. //
  148. pOptItem = pUiData->pOptItem;
  149. dwOptItemCount = pUiData->dwOptItem;
  150. dwSize = sizeof(USERDATA);
  151. while (dwOptItemCount--)
  152. {
  153. pOptItem->UserData = (ULONG_PTR)pUserData;
  154. SETUSERDATA_SIZE(pOptItem, dwSize);
  155. pUserData += sizeof(USERDATA);
  156. pOptItem++;
  157. }
  158. pUiData->pDrvOptItem = pUiData->pOptItem;
  159. pCompstui->pOptItem = pUiData->pDrvOptItem;
  160. pCompstui->cOptItem = (WORD) pUiData->dwOptItem;
  161. pUiData->dwOptItem = pUiData->dwOptType = 0;
  162. //
  163. // Call either PackDocumentPropertyItems or PackPrinterPropertyItems
  164. // to build the OPTITEMs list
  165. //
  166. if (! pfnPackItemProc(pUiData))
  167. {
  168. ERR(("Error while packing OPTITEM's\n"));
  169. return NULL;
  170. }
  171. return pCompstui;
  172. }
  173. VOID
  174. VPackOptItemGroupHeader(
  175. IN OUT PUIDATA pUiData,
  176. IN DWORD dwTitleId,
  177. IN DWORD dwIconId,
  178. IN DWORD dwHelpIndex
  179. )
  180. /*++
  181. Routine Description:
  182. Fill out a OPTITEM to be used as a header for a group of items
  183. Arguments:
  184. pUiData - Points to UIDATA structure
  185. dwTitleId - String resource ID for the item title
  186. dwIconId - Icon resource ID
  187. dwHelpIndex - Help index
  188. Return Value:
  189. NONE
  190. --*/
  191. {
  192. if (pUiData->pOptItem)
  193. {
  194. pUiData->pOptItem->cbSize = sizeof(OPTITEM);
  195. pUiData->pOptItem->pOptType = NULL;
  196. pUiData->pOptItem->pName = (PWSTR)ULongToPtr(dwTitleId);
  197. pUiData->pOptItem->Level = TVITEM_LEVEL1;
  198. pUiData->pOptItem->DMPubID = DMPUB_NONE;
  199. pUiData->pOptItem->Sel = dwIconId;
  200. //pUiData->pOptItem->UserData = 0;
  201. pUiData->pOptItem->HelpIndex = dwHelpIndex;
  202. pUiData->pOptItem++;
  203. }
  204. pUiData->dwOptItem++;
  205. }
  206. BOOL
  207. BPackOptItemTemplate(
  208. IN OUT PUIDATA pUiData,
  209. IN CONST WORD pwItemInfo[],
  210. IN DWORD dwSelection,
  211. IN PFEATURE pFeature
  212. )
  213. /*++
  214. Routine Description:
  215. Fill out an OPTITEM and an OPTTYPE structure using a template
  216. Arguments:
  217. pUiData - Points to UIDATA structure
  218. pwItemInfo - Pointer to item template
  219. dwSelection - Current item selection
  220. pFeature - Pointer to FEATURE
  221. Return Value:
  222. TRUE if successful, FALSE otherwise
  223. Note:
  224. The item template is a variable size WORD array:
  225. 0: String resource ID of the item title
  226. 1: Item level in the tree view (TVITEM_LEVELx)
  227. 2: Public devmode field ID (DMPUB_xxx)
  228. 3: User data
  229. 4: Help index
  230. 5: Number of OPTPARAMs for this item
  231. 6: Item type (TVOT_xxx)
  232. Three words for each OPTPARAM:
  233. Size of OPTPARAM
  234. String resource ID for parameter data
  235. Icon resource ID
  236. Last word must be ITEM_INFO_SIGNATURE
  237. Both OPTITEM and OPTTYPE structures are assumed to be zero-initialized.
  238. --*/
  239. {
  240. POPTITEM pOptItem;
  241. POPTPARAM pOptParam;
  242. WORD wOptParam;
  243. POPTTYPE pOptType = pUiData->pOptType;
  244. if ((pOptItem = pUiData->pOptItem) != NULL)
  245. {
  246. FILLOPTITEM(pOptItem,
  247. pUiData->pOptType,
  248. ULongToPtr(pwItemInfo[0]),
  249. ULongToPtr(dwSelection),
  250. (BYTE) pwItemInfo[1],
  251. (BYTE) pwItemInfo[2],
  252. pwItemInfo[3],
  253. pwItemInfo[4]
  254. );
  255. wOptParam = pwItemInfo[5];
  256. pOptParam = PFillOutOptType(pUiData->pOptType,
  257. pwItemInfo[6],
  258. wOptParam,
  259. pUiData->ci.hHeap);
  260. if (pOptParam == NULL)
  261. return FALSE;
  262. pwItemInfo += 7;
  263. while (wOptParam--)
  264. {
  265. pOptParam->cbSize = sizeof(OPTPARAM);
  266. pOptParam->pData = (PWSTR) *pwItemInfo++;
  267. pOptParam->IconID = *pwItemInfo++;
  268. pOptParam++;
  269. }
  270. ASSERT(*pwItemInfo == ITEM_INFO_SIGNATURE);
  271. if (pFeature)
  272. {
  273. SETUSERDATA_KEYWORDNAME(pUiData->ci, pOptItem, pFeature);
  274. #ifdef UNIDRV
  275. if (pUiData->ci.pUIInfo->loHelpFileName &&
  276. pFeature->iHelpIndex != UNUSED_ITEM )
  277. {
  278. //
  279. // Allocate memory for OIEXT
  280. //
  281. POIEXT pOIExt = HEAPALLOC(pUiData->ci.hHeap, sizeof(OIEXT));
  282. if (pOIExt)
  283. {
  284. pOIExt->cbSize = sizeof(OIEXT);
  285. pOIExt->Flags = 0;
  286. pOIExt->hInstCaller = NULL;
  287. pOIExt->pHelpFile = OFFSET_TO_POINTER(pUiData->ci.pUIInfo->pubResourceData,
  288. pUiData->ci.pUIInfo->loHelpFileName);
  289. pOptItem->pOIExt = pOIExt;
  290. pOptItem->HelpIndex = pFeature->iHelpIndex;
  291. pOptItem->Flags |= OPTIF_HAS_POIEXT;
  292. }
  293. }
  294. #endif // UNIDRV
  295. }
  296. pUiData->pOptItem++;
  297. pUiData->pOptType++;
  298. }
  299. pUiData->dwOptItem++;
  300. pUiData->dwOptType++;
  301. return TRUE;
  302. }
  303. BOOL
  304. BPackUDArrowItemTemplate(
  305. IN OUT PUIDATA pUiData,
  306. IN CONST WORD pwItemInfo[],
  307. IN DWORD dwSelection,
  308. IN DWORD dwMaxVal,
  309. IN PFEATURE pFeature
  310. )
  311. /*++
  312. Routine Description:
  313. Pack an updown arrow item using the specified template
  314. Arguments:
  315. pUiData, pwItemInfo, dwSelection - same as for BPackOptItemTemplate
  316. dwMaxVal - maximum value for the updown arrow item
  317. Return Value:
  318. TRUE if successful, FALSE if there is an error
  319. --*/
  320. {
  321. POPTTYPE pOptType = pUiData->pOptType;
  322. if (! BPackOptItemTemplate(pUiData, pwItemInfo, dwSelection, pFeature))
  323. return FALSE;
  324. if (pOptType)
  325. pOptType->pOptParam[1].lParam = dwMaxVal;
  326. return TRUE;
  327. }
  328. POPTPARAM
  329. PFillOutOptType(
  330. OUT POPTTYPE pOptType,
  331. IN DWORD dwType,
  332. IN DWORD dwParams,
  333. IN HANDLE hHeap
  334. )
  335. /*++
  336. Routine Description:
  337. Fill out an OPTTYPE structure
  338. Arguments:
  339. pOpttype - Pointer to OPTTYPE structure to be filled out
  340. wType - Value for OPTTYPE.Type field
  341. wParams - Number of OPTPARAM's
  342. hHeap - Handle to a heap from which to allocate
  343. Return Value:
  344. Pointer to OPTPARAM array if successful, NULL otherwise
  345. --*/
  346. {
  347. POPTPARAM pOptParam;
  348. pOptType->cbSize = sizeof(OPTTYPE);
  349. pOptType->Count = (WORD) dwParams;
  350. pOptType->Type = (BYTE) dwType;
  351. pOptParam = HEAPALLOC(hHeap, sizeof(OPTPARAM) * dwParams);
  352. if (pOptParam != NULL)
  353. pOptType->pOptParam = pOptParam;
  354. else
  355. ERR(("Memory allocation failed\n"));
  356. return pOptParam;
  357. }
  358. BOOL
  359. BShouldDisplayGenericFeature(
  360. IN PFEATURE pFeature,
  361. IN BOOL bPrinterSticky
  362. )
  363. /*++
  364. Routine Description:
  365. Determine whether a printer feature should be displayed
  366. as a generic feature
  367. Arguments:
  368. pFeature - Points to a FEATURE structure
  369. pPrinterSticky - Whether the feature is printer-sticky or doc-sticky
  370. Return Value:
  371. TRUE if the feature should be displayed as a generic feature
  372. FALSE if it should not be
  373. --*/
  374. {
  375. //
  376. // Check if the feature is specified marked as non-displayable
  377. // and make sure the feature type is appropriate
  378. //
  379. if ((pFeature->dwFlags & FEATURE_FLAG_NOUI) ||
  380. (bPrinterSticky &&
  381. pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY) ||
  382. (!bPrinterSticky &&
  383. pFeature->dwFeatureType != FEATURETYPE_DOCPROPERTY &&
  384. pFeature->dwFeatureType != FEATURETYPE_JOBPROPERTY))
  385. {
  386. return FALSE;
  387. }
  388. //
  389. // Exclude those features which are explicitly handled
  390. // and also those which don't have any options
  391. //
  392. return (pFeature->Options.dwCount >= MIN_OPTIONS_ALLOWED) &&
  393. (pFeature->dwFeatureID == GID_UNKNOWN ||
  394. pFeature->dwFeatureID == GID_OUTPUTBIN ||
  395. pFeature->dwFeatureID == GID_MEMOPTION);
  396. }
  397. DWORD
  398. DwCountDisplayableGenericFeature(
  399. IN PUIDATA pUiData,
  400. BOOL bPrinterSticky
  401. )
  402. /*++
  403. Routine Description:
  404. Count the number of features which can be displayed
  405. as generic features
  406. Arguments:
  407. pUiData - Points to UIDATA structure
  408. pPrinterSticky - Whether the feature is printer-sticky or doc-sticky
  409. Return Value:
  410. Number of features which can be displayed as generic features
  411. --*/
  412. {
  413. PFEATURE pFeature;
  414. DWORD dwFeature, dwCount = 0;
  415. pFeature = PGetIndexedFeature(pUiData->ci.pUIInfo, 0);
  416. dwFeature = pUiData->ci.pRawData->dwDocumentFeatures +
  417. pUiData->ci.pRawData->dwPrinterFeatures;
  418. if (pFeature && dwFeature)
  419. {
  420. for ( ; dwFeature--; pFeature++)
  421. {
  422. if (BShouldDisplayGenericFeature(pFeature, bPrinterSticky))
  423. dwCount++;
  424. }
  425. }
  426. return dwCount;
  427. }
  428. DWORD
  429. DwGuessOptionIconID(
  430. PUIINFO pUIInfo,
  431. PFEATURE pFeature,
  432. POPTION pOption
  433. )
  434. /*++
  435. Routine Description:
  436. Try to make an intelligent guess as to what icon
  437. to use for a generic printer feature option
  438. Arguments:
  439. pUIInfo - Points to UIINFO structure
  440. pFeature - Points to the feature in question
  441. pOption - Points to the option in question
  442. Return Value:
  443. Icon resource ID appropriate for the feature option
  444. --*/
  445. {
  446. DWORD dwIconID, iRes;
  447. switch (pFeature->dwFeatureID)
  448. {
  449. case GID_RESOLUTION:
  450. iRes = max(((PRESOLUTION) pOption)->iXdpi, ((PRESOLUTION) pOption)->iYdpi);
  451. if (iRes <= 150)
  452. dwIconID = IDI_CPSUI_RES_DRAFT;
  453. else if (iRes <= 300)
  454. dwIconID = IDI_CPSUI_RES_LOW;
  455. else if (iRes <= 600)
  456. dwIconID = IDI_CPSUI_RES_MEDIUM;
  457. else if (iRes <= 900)
  458. dwIconID = IDI_CPSUI_RES_HIGH;
  459. else
  460. dwIconID = IDI_CPSUI_RES_PRESENTATION;
  461. break;
  462. case GID_DUPLEX:
  463. switch (((PDUPLEX) pOption)->dwDuplexID)
  464. {
  465. case DMDUP_VERTICAL:
  466. dwIconID = IDI_CPSUI_DUPLEX_VERT;
  467. break;
  468. case DMDUP_HORIZONTAL:
  469. dwIconID = IDI_CPSUI_DUPLEX_HORZ;
  470. break;
  471. default:
  472. dwIconID = IDI_CPSUI_DUPLEX_NONE;
  473. break;
  474. }
  475. break;
  476. case GID_ORIENTATION:
  477. switch (((PORIENTATION) pOption)->dwRotationAngle)
  478. {
  479. case ROTATE_270:
  480. dwIconID = IDI_CPSUI_LANDSCAPE;
  481. break;
  482. case ROTATE_90:
  483. dwIconID = IDI_CPSUI_ROT_LAND;
  484. break;
  485. default:
  486. dwIconID = IDI_CPSUI_PORTRAIT;
  487. break;
  488. }
  489. break;
  490. case GID_INPUTSLOT:
  491. dwIconID = IDI_CPSUI_PAPER_TRAY;
  492. break;
  493. case GID_PAGEPROTECTION:
  494. dwIconID = IDI_CPSUI_PAGE_PROTECT;
  495. break;
  496. default:
  497. dwIconID = IDI_CPSUI_GENERIC_OPTION;
  498. break;
  499. }
  500. return dwIconID;
  501. }
  502. BOOL
  503. BPackItemPrinterFeature(
  504. PUIDATA pUiData,
  505. PFEATURE pFeature,
  506. DWORD dwLevel,
  507. DWORD dwPub,
  508. ULONG_PTR dwUserData,
  509. DWORD dwHelpIndex
  510. )
  511. /*++
  512. Routine Description:
  513. Pack a single printer feature item
  514. Arguments:
  515. pUiData - Points to UIDATA structure
  516. pFeature - Points to the printer feature to be packed
  517. dwLevel - Treeview item level
  518. dwPub - DMPUB_ identifier
  519. dwUserData - User data to be associated with the item
  520. dwHelpIndex - Help index to be associated with the item
  521. Return Value:
  522. TRUE if successful, FALSE if there is an error
  523. --*/
  524. {
  525. DWORD dwCount, dwIndex;
  526. DWORD dwFeature, dwSel;
  527. POPTION pOption;
  528. POPTTYPE pOptTypeHack;
  529. POPTPARAM pOptParam;
  530. PCOMMONINFO pci;
  531. if (pFeature == NULL ||
  532. (pFeature->dwFlags & FEATURE_FLAG_NOUI) ||
  533. (dwCount = pFeature->Options.dwCount) < MIN_OPTIONS_ALLOWED)
  534. return TRUE;
  535. //
  536. // HACK: for Orientation and Duplex feature
  537. // They must be of type TVOT_2STATES or TVOT_3STATES.
  538. // If not, compstui will get confused.
  539. //
  540. if (dwPub == DMPUB_ORIENTATION || dwPub == DMPUB_DUPLEX)
  541. {
  542. if (dwCount != 2 && dwCount != 3)
  543. {
  544. WARNING(("Unexpected number of Orientation/Duplex options\n"));
  545. return TRUE;
  546. }
  547. pOptTypeHack = pUiData->pOptType;
  548. }
  549. else
  550. pOptTypeHack = NULL;
  551. pUiData->dwOptItem++;
  552. pUiData->dwOptType++;
  553. if (pUiData->pOptItem == NULL)
  554. return TRUE;
  555. //
  556. // Find out the current selection first
  557. // DCR: needs to support PICKMANY
  558. //
  559. pci = (PCOMMONINFO) pUiData;
  560. dwFeature = GET_INDEX_FROM_FEATURE(pci->pUIInfo, pFeature);
  561. dwSel = pci->pCombinedOptions[dwFeature].ubCurOptIndex;
  562. if (dwSel >= dwCount)
  563. dwSel = 0;
  564. //
  565. // If we are in this function, we must have already successfully
  566. // called function PFillUiData(), where the pci->hHeap is created.
  567. //
  568. ASSERT(pci->hHeap != NULL);
  569. //
  570. // Fill in the OPTITEM structure
  571. //
  572. FILLOPTITEM(pUiData->pOptItem,
  573. pUiData->pOptType,
  574. PGetReadOnlyDisplayName(pci, pFeature->loDisplayName),
  575. ULongToPtr(dwSel),
  576. dwLevel,
  577. dwPub,
  578. dwUserData,
  579. dwHelpIndex);
  580. #ifdef UNIDRV
  581. //
  582. // Supports OEM help file. If helpfile and helpindex are defined,
  583. // we will use the help id specified by the GPD. According to GPD spec,
  584. // zero loHelpFileName means no help file name specified.
  585. //
  586. if (pci->pUIInfo->loHelpFileName &&
  587. pFeature->iHelpIndex != UNUSED_ITEM )
  588. {
  589. //
  590. // Allocate memory for OIEXT
  591. //
  592. POIEXT pOIExt = HEAPALLOC(pci->hHeap, sizeof(OIEXT));
  593. if (pOIExt)
  594. {
  595. pOIExt->cbSize = sizeof(OIEXT);
  596. pOIExt->Flags = 0;
  597. pOIExt->hInstCaller = NULL;
  598. pOIExt->pHelpFile = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData,
  599. pci->pUIInfo->loHelpFileName);
  600. pUiData->pOptItem->pOIExt = pOIExt;
  601. pUiData->pOptItem->HelpIndex = pFeature->iHelpIndex;
  602. pUiData->pOptItem->Flags |= OPTIF_HAS_POIEXT;
  603. }
  604. }
  605. #endif // UNIDRV
  606. pOptParam = PFillOutOptType(pUiData->pOptType, TVOT_LISTBOX, dwCount, pci->hHeap);
  607. if (pOptParam == NULL)
  608. return FALSE;
  609. if (pOptTypeHack)
  610. pOptTypeHack->Type = (dwCount == 2) ? TVOT_2STATES : TVOT_3STATES;
  611. //
  612. // Get the list of options for this features
  613. //
  614. for (dwIndex=0; dwIndex < dwCount; dwIndex++, pOptParam++)
  615. {
  616. //
  617. // Fill in the options name
  618. //
  619. pOption = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex);
  620. ASSERT(pOption != NULL);
  621. pOptParam->cbSize = sizeof(OPTPARAM);
  622. pOptParam->pData = GET_OPTION_DISPLAY_NAME(pci, pOption);
  623. //
  624. // Try to figure out the appropriate icon to use
  625. // If the icon comes from the resource DLL, we need to load
  626. // it ourselves and give compstui an HICON. Otherwise,
  627. // we try to figure out the appropriate icon resource ID.
  628. //
  629. if (pOption->loResourceIcon &&
  630. (pOptParam->IconID = HLoadIconFromResourceDLL(pci, pOption->loResourceIcon)))
  631. {
  632. pOptParam->Flags |= OPTPF_ICONID_AS_HICON;
  633. }
  634. else
  635. pOptParam->IconID = DwGuessOptionIconID(pci->pUIInfo, pFeature, pOption);
  636. }
  637. //
  638. // Set the Keyword name for pOptItem->UserData
  639. //
  640. SETUSERDATA_KEYWORDNAME(pUiData->ci, pUiData->pOptItem, pFeature);
  641. pUiData->pOptItem++;
  642. pUiData->pOptType++;
  643. return TRUE;
  644. }
  645. BOOL
  646. BPackItemGenericOptions(
  647. IN OUT PUIDATA pUiData
  648. )
  649. /*++
  650. Routine Description:
  651. Pack generic printer features items (doc-sticky or printer-sticky)
  652. Arguments:
  653. pUiData - Points to UIDATA structure
  654. Return Value:
  655. TRUE if successful, FALSE if there is an error.
  656. --*/
  657. {
  658. //
  659. // Extended push button for restoring to default feature selections
  660. //
  661. static EXTPUSH ExtPush =
  662. {
  663. sizeof(EXTPUSH),
  664. EPF_NO_DOT_DOT_DOT,
  665. (PWSTR) IDS_RESTORE_DEFAULTS,
  666. NULL,
  667. 0,
  668. 0,
  669. };
  670. POPTITEM pOptItem;
  671. DWORD dwHelpIndex, dwIconId;
  672. PFEATURE pFeatures;
  673. DWORD dwFeatures;
  674. BOOL bPrinterSticky;
  675. //
  676. // If there are no generic features to display, simply return success
  677. //
  678. bPrinterSticky = (pUiData->iMode == MODE_PRINTER_STICKY);
  679. if (DwCountDisplayableGenericFeature(pUiData, bPrinterSticky) == 0)
  680. return TRUE;
  681. //
  682. // Add the group header item
  683. //
  684. pOptItem = pUiData->pOptItem;
  685. if (bPrinterSticky)
  686. {
  687. VPackOptItemGroupHeader(
  688. pUiData,
  689. IDS_INSTALLABLE_OPTIONS,
  690. IDI_CPSUI_INSTALLABLE_OPTION,
  691. HELP_INDEX_INSTALLABLE_OPTIONS);
  692. }
  693. else
  694. {
  695. VPackOptItemGroupHeader(
  696. pUiData,
  697. IDS_PRINTER_FEATURES,
  698. IDI_CPSUI_PRINTER_FEATURE,
  699. HELP_INDEX_PRINTER_FEATURES);
  700. }
  701. if (pOptItem != NULL && !bPrinterSticky)
  702. {
  703. //
  704. // "Restore Defaults" button
  705. //
  706. pUiData->pFeatureHdrItem = pOptItem;
  707. pOptItem->Flags |= (OPTIF_EXT_IS_EXTPUSH|OPTIF_CALLBACK);
  708. pOptItem->pExtPush = &ExtPush;
  709. }
  710. pOptItem = pUiData->pOptItem;
  711. //
  712. // Figure out the correct help index and icon ID
  713. // depending on whether we're dealing with printer-sticky
  714. // features or document-sticky printer features
  715. //
  716. if (bPrinterSticky)
  717. {
  718. dwHelpIndex = HELP_INDEX_INSTALLABLE_OPTIONS;
  719. dwIconId = IDI_CPSUI_INSTALLABLE_OPTION;
  720. }
  721. else
  722. {
  723. dwHelpIndex = HELP_INDEX_PRINTER_FEATURES;
  724. dwIconId = IDI_CPSUI_PRINTER_FEATURE;
  725. }
  726. //
  727. // Go through each printer feature
  728. //
  729. pFeatures = PGetIndexedFeature(pUiData->ci.pUIInfo, 0);
  730. dwFeatures = pUiData->ci.pRawData->dwDocumentFeatures +
  731. pUiData->ci.pRawData->dwPrinterFeatures;
  732. ASSERT(pFeatures != NULL);
  733. for ( ; dwFeatures--; pFeatures++)
  734. {
  735. //
  736. // Don't do anything if it's the feature has no options OR
  737. // If it's not a generic feature.
  738. //
  739. if (BShouldDisplayGenericFeature(pFeatures, bPrinterSticky) &&
  740. !BPackItemPrinterFeature(pUiData,
  741. pFeatures,
  742. TVITEM_LEVEL2,
  743. DMPUB_NONE,
  744. (ULONG_PTR) pFeatures,
  745. dwHelpIndex))
  746. {
  747. return FALSE;
  748. }
  749. }
  750. if (pOptItem != NULL)
  751. {
  752. pUiData->pFeatureItems = pOptItem;
  753. pUiData->dwFeatureItem = (DWORD)(pUiData->pOptItem - pOptItem);
  754. }
  755. return TRUE;
  756. }
  757. PFEATURE
  758. PGetFeatureFromItem(
  759. IN PUIINFO pUIInfo,
  760. IN OUT POPTITEM pOptItem,
  761. OUT PDWORD pdwFeatureIndex
  762. )
  763. /*++
  764. Routine Description:
  765. Get the feature index for a given pOptItem
  766. Arguments:
  767. pUIInfo - pointer to UIINFO
  768. pOptItem - pointer to item to look for feature id
  769. pdwFeatureIndex - pointer to contain the value of returned index
  770. Return Value:
  771. Pointer to FEATURE structure associated with the item
  772. NULL if no such feature exists.
  773. --*/
  774. {
  775. PFEATURE pFeature = NULL;
  776. //
  777. // Get the dwFeature, which is the index into pOptionsArray
  778. //
  779. if (ISPRINTERFEATUREITEM(pOptItem->UserData))
  780. {
  781. //
  782. // Note: Generic Features contains pointer to feature (pFeature)
  783. // in pOptItem->UserData
  784. //
  785. pFeature = (PFEATURE) GETUSERDATAITEM(pOptItem->UserData);
  786. }
  787. else
  788. {
  789. DWORD dwFeatureId;
  790. switch (GETUSERDATAITEM(pOptItem->UserData))
  791. {
  792. case FORMNAME_ITEM:
  793. dwFeatureId = GID_PAGESIZE;
  794. break;
  795. case DUPLEX_ITEM:
  796. dwFeatureId = GID_DUPLEX;
  797. break;
  798. case RESOLUTION_ITEM:
  799. dwFeatureId = GID_RESOLUTION;
  800. break;
  801. case MEDIATYPE_ITEM:
  802. dwFeatureId = GID_MEDIATYPE;
  803. break;
  804. case INPUTSLOT_ITEM:
  805. dwFeatureId = GID_INPUTSLOT;
  806. break;
  807. case FORM_TRAY_ITEM:
  808. dwFeatureId = GID_INPUTSLOT;
  809. break;
  810. case COLORMODE_ITEM:
  811. dwFeatureId = GID_COLORMODE;
  812. break;
  813. case ORIENTATION_ITEM:
  814. dwFeatureId = GID_ORIENTATION;
  815. break;
  816. case PAGE_PROTECT_ITEM:
  817. dwFeatureId = GID_PAGEPROTECTION;
  818. break;
  819. case COPIES_COLLATE_ITEM:
  820. dwFeatureId = GID_COLLATE;
  821. break;
  822. case HALFTONING_ITEM:
  823. dwFeatureId = GID_HALFTONING;
  824. break;
  825. default:
  826. dwFeatureId = GID_UNKNOWN;
  827. break;
  828. }
  829. if (dwFeatureId != GID_UNKNOWN)
  830. pFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwFeatureId);
  831. }
  832. if (pFeature && pdwFeatureIndex)
  833. *pdwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
  834. return pFeature;
  835. }
  836. VOID
  837. VUpdateOptionsArrayWithSelection(
  838. IN OUT PUIDATA pUiData,
  839. IN POPTITEM pOptItem
  840. )
  841. /*++
  842. Routine Description:
  843. Update the options array with the current selection
  844. Arguments:
  845. pUiData - Points to UIDATA structure
  846. pOptItem - Specifies the item whose selection has changed
  847. Return Value:
  848. NONE
  849. --*/
  850. {
  851. PFEATURE pFeature;
  852. DWORD dwFeatureIndex;
  853. //
  854. // Get the feature associated with the current item
  855. //
  856. pFeature = PGetFeatureFromItem(pUiData->ci.pUIInfo, pOptItem, &dwFeatureIndex);
  857. if (pFeature == NULL)
  858. return;
  859. if (pOptItem->Sel < 0 || pOptItem->Sel >= (LONG) pFeature->Options.dwCount)
  860. {
  861. RIP(("Invalid selection for the current item\n"));
  862. return;
  863. }
  864. ZeroMemory(pUiData->abEnabledOptions, sizeof(pUiData->abEnabledOptions));
  865. pUiData->abEnabledOptions[pOptItem->Sel] = TRUE;
  866. ReconstructOptionArray(pUiData->ci.pRawData,
  867. pUiData->ci.pCombinedOptions,
  868. MAX_COMBINED_OPTIONS,
  869. dwFeatureIndex,
  870. pUiData->abEnabledOptions);
  871. }
  872. VOID
  873. VMarkSelectionConstrained(
  874. IN OUT POPTITEM pOptItem,
  875. IN DWORD dwIndex,
  876. IN BOOL bEnable
  877. )
  878. /*++
  879. Routine Description:
  880. Indicate whether a selection is constrained or not
  881. Arguments:
  882. pOptItem - Pointer to the OPTITEM in question
  883. pOptParam - Specifies the index of the OPTPARAM in question
  884. bEnable - Whether the selection is constrained or not
  885. Enable means not constrained!
  886. Return Value:
  887. NONE
  888. Note:
  889. bEnable is the returned value from EnumEnabledOptions,
  890. bEnable is FALSE if the option is contrained by some
  891. other feature, selections.
  892. bEnable is TRUE if the options is not constrained
  893. by other feature, selections.
  894. --*/
  895. {
  896. POPTPARAM pOptParam;
  897. //
  898. // This function only work on certain types of OPTTYPE
  899. //
  900. ASSERT(pOptItem->pOptType->Type == TVOT_2STATES ||
  901. pOptItem->pOptType->Type == TVOT_3STATES ||
  902. pOptItem->pOptType->Type == TVOT_LISTBOX ||
  903. pOptItem->pOptType->Type == TVOT_COMBOBOX);
  904. pOptParam = pOptItem->pOptType->pOptParam + dwIndex;
  905. //
  906. // Set the constrained flag or clear it depending on the latest
  907. // check with EnumEnabledOptions
  908. //
  909. if (!bEnable && ! (pOptParam->Flags & CONSTRAINED_FLAG))
  910. {
  911. pOptParam->Flags |= CONSTRAINED_FLAG;
  912. pOptItem->Flags |= OPTIF_CHANGED;
  913. }
  914. else if (bEnable && (pOptParam->Flags & CONSTRAINED_FLAG))
  915. {
  916. pOptParam->Flags &= ~CONSTRAINED_FLAG;
  917. pOptItem->Flags |= OPTIF_CHANGED;
  918. }
  919. pOptParam->lParam = (LONG) bEnable;
  920. }
  921. VOID
  922. VPropShowConstraints(
  923. IN PUIDATA pUiData,
  924. IN INT iMode
  925. )
  926. /*++
  927. Routine Description:
  928. Indicate which items are constrained.
  929. General rule - Any features that has a coresponding an applicable GID or a
  930. Generic Feature Item, check for constrained. Ignore all others
  931. because it's not applicable.
  932. Arguments:
  933. pUiData - Pointer to our UIDATA structure
  934. iMode - MODE_DOCANDPRINTER_STICKY, MODE_PRINTER_STICKY
  935. Return Value:
  936. NONE
  937. --*/
  938. {
  939. POPTITEM pOptItem;
  940. DWORD dwOptItem;
  941. DWORD dwFeature, dwOption, dwNumOptions, dwIndex;
  942. #ifdef PSCRIPT
  943. if (iMode != MODE_PRINTER_STICKY)
  944. {
  945. VSyncRevPrintAndOutputOrder(pUiData, NULL);
  946. }
  947. #endif // PSCRIPT
  948. //
  949. // Go through all the features in the treeview
  950. //
  951. pOptItem = pUiData->pDrvOptItem;
  952. dwOptItem = pUiData->dwDrvOptItem;
  953. for ( ; dwOptItem--; pOptItem++)
  954. {
  955. if (! ISCONSTRAINABLEITEM(pOptItem->UserData) ||
  956. ! PGetFeatureFromItem(pUiData->ci.pUIInfo, pOptItem, &dwFeature))
  957. {
  958. continue;
  959. }
  960. //
  961. // Call the parser to get which options to be disable, or contrained
  962. // for this feature , so need to gray it out.
  963. //
  964. ZeroMemory(pUiData->abEnabledOptions, sizeof(pUiData->abEnabledOptions));
  965. if (! EnumEnabledOptions(pUiData->ci.pRawData,
  966. pUiData->ci.pCombinedOptions,
  967. dwFeature,
  968. pUiData->abEnabledOptions,
  969. iMode))
  970. {
  971. VERBOSE(("EnumEnabledOptions failed\n"));
  972. }
  973. //
  974. // Loop through all options and mark the constraint
  975. //
  976. dwNumOptions = pOptItem->pOptType->Count;
  977. if (GETUSERDATAITEM(pOptItem->UserData) == FORMNAME_ITEM)
  978. {
  979. for (dwIndex = 0; dwIndex < dwNumOptions; dwIndex++)
  980. {
  981. dwOption = pUiData->pwPaperFeatures[dwIndex];
  982. if (dwOption == OPTION_INDEX_ANY)
  983. continue;
  984. VMarkSelectionConstrained(pOptItem,
  985. dwIndex,
  986. pUiData->abEnabledOptions[dwOption]);
  987. }
  988. }
  989. else if (GETUSERDATAITEM(pOptItem->UserData) == FORM_TRAY_ITEM)
  990. {
  991. if (pOptItem == pUiData->pFormTrayItems)
  992. {
  993. POPTITEM pTrayItem;
  994. PBOOL pbEnable;
  995. //
  996. // Update form-to-tray assignment table items
  997. //
  998. pbEnable = pUiData->abEnabledOptions;
  999. pTrayItem = pUiData->pFormTrayItems;
  1000. dwIndex = pUiData->dwFormTrayItem;
  1001. for ( ; dwIndex--; pTrayItem++, pbEnable++)
  1002. {
  1003. if (pTrayItem->Flags & OPTIF_HIDE)
  1004. continue;
  1005. if (*pbEnable && (pTrayItem->Flags & OPTIF_DISABLED))
  1006. {
  1007. pTrayItem->Flags &= ~OPTIF_DISABLED;
  1008. pTrayItem->Flags |= OPTIF_CHANGED;
  1009. }
  1010. else if (!*pbEnable && !(pTrayItem->Flags & OPTIF_DISABLED))
  1011. {
  1012. pTrayItem->Flags |= (OPTIF_DISABLED|OPTIF_CHANGED);
  1013. pTrayItem->Sel = -1;
  1014. }
  1015. }
  1016. }
  1017. }
  1018. else
  1019. {
  1020. for (dwOption=0; dwOption < dwNumOptions; dwOption++)
  1021. {
  1022. VMarkSelectionConstrained(pOptItem,
  1023. dwOption,
  1024. pUiData->abEnabledOptions[dwOption]);
  1025. }
  1026. }
  1027. }
  1028. }
  1029. INT_PTR CALLBACK
  1030. BConflictsDlgProc(
  1031. HWND hDlg,
  1032. UINT uMsg,
  1033. WPARAM wParam,
  1034. LPARAM lParam
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. Dialog procedure for handle "Conflicts" dialog
  1039. Arguments:
  1040. hDlg - Handle to dialog window
  1041. uMsg - Message
  1042. wParam, lParam - Parameters
  1043. Return Value:
  1044. TRUE or FALSE depending on whether message is processed
  1045. --*/
  1046. {
  1047. PDLGPARAM pDlgParam;
  1048. POPTITEM pOptItem;
  1049. PFEATURE pFeature;
  1050. POPTION pOption;
  1051. DWORD dwFeature, dwOption;
  1052. PCWSTR pDisplayName;
  1053. WCHAR awchBuf[MAX_DISPLAY_NAME];
  1054. PCOMMONINFO pci;
  1055. CONFLICTPAIR ConflictPair;
  1056. switch (uMsg)
  1057. {
  1058. case WM_INITDIALOG:
  1059. pDlgParam = (PDLGPARAM) lParam;
  1060. ASSERT(pDlgParam != NULL);
  1061. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pDlgParam);
  1062. pci = (PCOMMONINFO) pDlgParam->pUiData;
  1063. pOptItem = pDlgParam->pOptItem;
  1064. if (GETUSERDATAITEM(pOptItem->UserData) == FORMNAME_ITEM)
  1065. dwOption = pDlgParam->pUiData->pwPaperFeatures[pOptItem->Sel];
  1066. else
  1067. dwOption = pOptItem->Sel;
  1068. //
  1069. // Get the feature id for the current feature and selection
  1070. //
  1071. if (! PGetFeatureFromItem(pci->pUIInfo, pOptItem, &dwFeature))
  1072. return FALSE;
  1073. //
  1074. // Get the first conflicting feature, option for the current pair
  1075. //
  1076. if (! EnumNewPickOneUIConflict(pci->pRawData,
  1077. pci->pCombinedOptions,
  1078. dwFeature,
  1079. dwOption,
  1080. &ConflictPair))
  1081. {
  1082. ERR(("No conflict found?\n"));
  1083. return FALSE;
  1084. }
  1085. pFeature = PGetIndexedFeature(pci->pUIInfo, ConflictPair.dwFeatureIndex1);
  1086. pOption = PGetIndexedOption(pci->pUIInfo, pFeature, ConflictPair.dwOptionIndex1);
  1087. //
  1088. // Display the current feature selection
  1089. // Get feature name first
  1090. //
  1091. if (pDisplayName = PGetReadOnlyDisplayName(pci, pFeature->loDisplayName))
  1092. {
  1093. StringCchCopyW(awchBuf, CCHOF(awchBuf), pDisplayName);
  1094. StringCchCatW(awchBuf, CCHOF(awchBuf), TEXT(" : "));
  1095. }
  1096. //
  1097. // Kludgy fix for form - We show the form enumerated by
  1098. // form database and map these logical forms to our supported physical
  1099. // papersize. So we have to notify the user with the logical form
  1100. // selected and not the mapped physical form returned by EnumConflict
  1101. //
  1102. if (pFeature->dwFeatureID == GID_PAGESIZE)
  1103. pDisplayName = pOptItem->pOptType->pOptParam[pOptItem->Sel].pData;
  1104. else if (pOption)
  1105. pDisplayName = GET_OPTION_DISPLAY_NAME(pci, pOption);
  1106. else
  1107. pDisplayName = NULL;
  1108. if (pDisplayName)
  1109. StringCchCatW(awchBuf, CCHOF(awchBuf), pDisplayName);
  1110. SetDlgItemText(hDlg, IDC_FEATURE1, awchBuf);
  1111. pFeature = PGetIndexedFeature(pci->pUIInfo, ConflictPair.dwFeatureIndex2);
  1112. pOption = PGetIndexedOption(pci->pUIInfo, pFeature, ConflictPair.dwOptionIndex2);
  1113. //
  1114. // Display the current feature selection
  1115. // Get feature name first
  1116. //
  1117. if (pDisplayName = PGetReadOnlyDisplayName(pci, pFeature->loDisplayName))
  1118. {
  1119. StringCchCopyW(awchBuf, CCHOF(awchBuf), pDisplayName);
  1120. StringCchCatW(awchBuf, CCHOF(awchBuf), TEXT(" : "));
  1121. }
  1122. if (pFeature->dwFeatureID == GID_PAGESIZE)
  1123. pDisplayName = pOptItem->pOptType->pOptParam[pOptItem->Sel].pData;
  1124. else if (pOption)
  1125. pDisplayName = GET_OPTION_DISPLAY_NAME(pci, pOption);
  1126. else
  1127. pDisplayName = NULL;
  1128. if (pDisplayName)
  1129. StringCchCatW(awchBuf, CCHOF(awchBuf), pDisplayName);
  1130. SetDlgItemText(hDlg, IDC_FEATURE2, awchBuf);
  1131. if (pDlgParam->bFinal)
  1132. {
  1133. //
  1134. // If user is trying to exit the dialog
  1135. //
  1136. ShowWindow(GetDlgItem(hDlg, IDC_IGNORE), SW_HIDE);
  1137. ShowWindow(GetDlgItem(hDlg, IDC_CANCEL), SW_HIDE);
  1138. CheckRadioButton(hDlg, IDC_RESOLVE, IDC_CANCEL_FINAL, IDC_RESOLVE);
  1139. pDlgParam->dwResult = CONFLICT_RESOLVE;
  1140. }
  1141. else
  1142. {
  1143. //
  1144. // Hide the Resolve button
  1145. //
  1146. ShowWindow(GetDlgItem(hDlg, IDC_RESOLVE), SW_HIDE);
  1147. ShowWindow(GetDlgItem(hDlg, IDC_CANCEL_FINAL), SW_HIDE);
  1148. CheckRadioButton(hDlg, IDC_IGNORE, IDC_CANCEL, IDC_IGNORE);
  1149. pDlgParam->dwResult = CONFLICT_IGNORE;
  1150. }
  1151. ShowWindow(hDlg, SW_SHOW);
  1152. return TRUE;
  1153. case WM_COMMAND:
  1154. pDlgParam = (PDLGPARAM)GetWindowLongPtr(hDlg, DWLP_USER);
  1155. switch (LOWORD(wParam))
  1156. {
  1157. case IDC_CANCEL:
  1158. case IDC_CANCEL_FINAL:
  1159. pDlgParam->dwResult = CONFLICT_CANCEL;
  1160. break;
  1161. case IDC_IGNORE:
  1162. pDlgParam->dwResult = CONFLICT_IGNORE;
  1163. break;
  1164. case IDC_RESOLVE:
  1165. pDlgParam->dwResult = CONFLICT_RESOLVE;
  1166. break;
  1167. case IDOK:
  1168. case IDCANCEL:
  1169. EndDialog(hDlg, LOWORD(wParam));
  1170. return TRUE;
  1171. }
  1172. }
  1173. return FALSE;
  1174. }
  1175. VOID
  1176. VUpdateOptItemList(
  1177. IN OUT PUIDATA pUiData,
  1178. IN POPTSELECT pOldCombinedOptions,
  1179. IN POPTSELECT pNewCombinedOptions
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. Ssync up OPTITEM list with the updated options array.
  1184. Arguments:
  1185. pUiData - Pointer to our UIDATA structure
  1186. pOldCombinedOptions - A copy of the pre-resolved options array,
  1187. this should cut down the updating costs, only updated if it's changed
  1188. pNewCombinedOptions - the current options array
  1189. Return Value:
  1190. None
  1191. --*/
  1192. {
  1193. DWORD i, dwFeatures, dwDrvOptItem;
  1194. PFEATURE pFeature;
  1195. PUIINFO pUIInfo = pUiData->ci.pUIInfo;
  1196. PCSTR pKeywordName, pFeatureKeywordName;
  1197. POPTITEM pOptItem;
  1198. if (pUiData->dwDrvOptItem == 0)
  1199. {
  1200. //
  1201. // nothing to update
  1202. //
  1203. return;
  1204. }
  1205. dwFeatures = pUiData->ci.pRawData->dwDocumentFeatures +
  1206. pUiData->ci.pRawData->dwPrinterFeatures;
  1207. for (i = 0; i < dwFeatures; i++)
  1208. {
  1209. if (pOldCombinedOptions[i].ubCurOptIndex != pNewCombinedOptions[i].ubCurOptIndex)
  1210. {
  1211. dwDrvOptItem = pUiData->dwDrvOptItem;
  1212. pOptItem = pUiData->pDrvOptItem;
  1213. pFeature = PGetIndexedFeature(pUIInfo, i);
  1214. ASSERT(pFeature);
  1215. while( dwDrvOptItem--)
  1216. {
  1217. pKeywordName = GETUSERDATAKEYWORDNAME(pOptItem->UserData);
  1218. pFeatureKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData,
  1219. pFeature->loKeywordName);
  1220. ASSERT(pFeatureKeywordName);
  1221. if (pKeywordName && pFeatureKeywordName &&
  1222. (strcmp(pFeatureKeywordName, pKeywordName) == EQUAL_STRING))
  1223. break;
  1224. pOptItem++;
  1225. }
  1226. pOptItem->Sel = pNewCombinedOptions[i].ubCurOptIndex;
  1227. pOptItem->Flags |= OPTIF_CHANGED;
  1228. //
  1229. // This is necessary to ssync up the colormode changes with the color information
  1230. //
  1231. #ifdef UNIDRV
  1232. if (GETUSERDATAITEM(pOptItem->UserData) == COLORMODE_ITEM)
  1233. VSyncColorInformation(pUiData, pOptItem);
  1234. #endif
  1235. }
  1236. }
  1237. VPropShowConstraints(pUiData,
  1238. (pUiData->iMode == MODE_PRINTER_STICKY) ? pUiData->iMode : MODE_DOCANDPRINTER_STICKY);
  1239. }
  1240. INT
  1241. ICheckConstraintsDlg(
  1242. IN OUT PUIDATA pUiData,
  1243. IN OUT POPTITEM pOptItem,
  1244. IN DWORD dwOptItem,
  1245. IN BOOL bFinal
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. Check if the user chose any constrained selection
  1250. Arguments:
  1251. pUiData - Pointer to our UIDATA structure
  1252. pOptItem - Pointer to an array of OPTITEMs
  1253. dwOptItem - Number of items to be checked
  1254. bFinal - Whether this is called when user tries to exit the dialog
  1255. Return Value:
  1256. CONFLICT_NONE - no conflicts
  1257. CONFLICT_RESOLVE - click RESOLVE to automatically resolve conflicts
  1258. CONFLICT_CANCEL - click CANCEL to back out of changes
  1259. CONFLICT_IGNORE - click IGNORE to ignore conflicts
  1260. --*/
  1261. {
  1262. DLGPARAM DlgParam;
  1263. OPTSELECT OldCombinedOptions[MAX_COMBINED_OPTIONS];
  1264. DlgParam.pfnComPropSheet = pUiData->pfnComPropSheet;
  1265. DlgParam.hComPropSheet = pUiData->hComPropSheet;
  1266. DlgParam.pUiData = pUiData;
  1267. DlgParam.bFinal = bFinal;
  1268. DlgParam.dwResult = CONFLICT_NONE;
  1269. for ( ; dwOptItem--; pOptItem++)
  1270. {
  1271. //
  1272. // If the item is not constrainable, skip it.
  1273. //
  1274. if (! ISCONSTRAINABLEITEM(pOptItem->UserData))
  1275. continue;
  1276. //
  1277. // If user has clicked IGNORE before, then don't bother
  1278. // checking anymore until he tries to exit the dialog.
  1279. //
  1280. //if (pUiData->bIgnoreConflict && !bFinal)
  1281. // break;
  1282. //
  1283. // If there is a conflict, then display a warning message
  1284. //
  1285. if (IS_CONSTRAINED(pOptItem, pOptItem->Sel))
  1286. {
  1287. DlgParam.pOptItem = pOptItem;
  1288. DlgParam.dwResult = CONFLICT_NONE;
  1289. DialogBoxParam(ghInstance,
  1290. MAKEINTRESOURCE(IDD_CONFLICTS),
  1291. pUiData->hDlg,
  1292. BConflictsDlgProc,
  1293. (LPARAM) &DlgParam);
  1294. //
  1295. // Automatically resolve conflicts. We're being very
  1296. // simple-minded here, i.e. picking the first selection
  1297. // that's not constrained.
  1298. //
  1299. if (DlgParam.dwResult == CONFLICT_RESOLVE)
  1300. {
  1301. ASSERT((bFinal == TRUE));
  1302. //
  1303. // Save a copy the pre-resolve optionarray
  1304. //
  1305. CopyMemory(OldCombinedOptions,
  1306. pUiData->ci.pCombinedOptions,
  1307. MAX_COMBINED_OPTIONS * sizeof(OPTSELECT));
  1308. //
  1309. // Call the parsers to resolve the conflicts
  1310. //
  1311. // Note: If we're inside DrvDocumentPropertySheets,
  1312. // we'll call the parser to resolve conflicts between
  1313. // all printer features. Since all printer-sticky
  1314. // features have higher priority than all doc-sticky
  1315. // features, only doc-sticky option selections should
  1316. // be affected.
  1317. //
  1318. ResolveUIConflicts(pUiData->ci.pRawData,
  1319. pUiData->ci.pCombinedOptions,
  1320. MAX_COMBINED_OPTIONS,
  1321. (pUiData->iMode == MODE_PRINTER_STICKY) ?
  1322. pUiData->iMode :
  1323. MODE_DOCANDPRINTER_STICKY);
  1324. //
  1325. // Update the OPTITEM list to match the updated options array
  1326. //
  1327. VUpdateOptItemList(pUiData, OldCombinedOptions, pUiData->ci.pCombinedOptions);
  1328. }
  1329. else if (DlgParam.dwResult == CONFLICT_IGNORE)
  1330. {
  1331. //
  1332. // Ignore any future conflicts until the
  1333. // user tries to close the property sheet.
  1334. //
  1335. pUiData->bIgnoreConflict = TRUE;
  1336. }
  1337. break;
  1338. }
  1339. }
  1340. return DlgParam.dwResult;
  1341. }
  1342. BOOL
  1343. BOptItemSelectionsChanged(
  1344. IN POPTITEM pItems,
  1345. IN DWORD dwItems
  1346. )
  1347. /*++
  1348. Routine Description:
  1349. Check if any of the OPTITEM's was changed by the user
  1350. Arguments:
  1351. pItems - Pointer to an array of OPTITEM's
  1352. dwItems - Number of OPTITEM's
  1353. Return Value:
  1354. TRUE if anything was changed, FALSE otherwise
  1355. --*/
  1356. {
  1357. for ( ; dwItems--; pItems++)
  1358. {
  1359. if (pItems->Flags & OPTIF_CHANGEONCE)
  1360. return TRUE;
  1361. }
  1362. return FALSE;
  1363. }
  1364. POPTITEM
  1365. PFindOptItem(
  1366. IN PUIDATA pUiData,
  1367. IN DWORD dwItemId
  1368. )
  1369. /*++
  1370. Routine Description:
  1371. Find an OPTITEM with the specified identifier
  1372. Arguments:
  1373. pUiData - Points to UIDATA structure
  1374. dwItemId - Specifies the interested item identifier
  1375. Return Value:
  1376. Pointer to OPTITEM with the specified id,
  1377. NULL if no such item is found
  1378. --*/
  1379. {
  1380. POPTITEM pOptItem = pUiData->pDrvOptItem;
  1381. DWORD dwOptItem = pUiData->dwDrvOptItem;
  1382. for ( ; dwOptItem--; pOptItem++)
  1383. {
  1384. if (GETUSERDATAITEM(pOptItem->UserData) == dwItemId)
  1385. return pOptItem;
  1386. }
  1387. return NULL;
  1388. }
  1389. INT
  1390. IDisplayErrorMessageBox(
  1391. HWND hwndParent,
  1392. UINT uType,
  1393. INT iTitleStrId,
  1394. INT iFormatStrId,
  1395. ...
  1396. )
  1397. /*++
  1398. Routine Description:
  1399. Display an error message box
  1400. Arguments:
  1401. hwndParent - Handle to the parent window
  1402. uType - Type of message box to display
  1403. if 0, the default value is MB_OK | MB_ICONERROR
  1404. iTitleStrId - String resource ID for the message box title
  1405. iFormatStrId - String resource ID for the message itself.
  1406. This string can contain printf format specifications.
  1407. ... - Optional arguments.
  1408. Return Value:
  1409. Return value from MessageBox() call.
  1410. --*/
  1411. #define MAX_MBTITLE_LEN 128
  1412. #define MAX_MBFORMAT_LEN 512
  1413. #define MAX_MBMESSAGE_LEN 1024
  1414. {
  1415. PWSTR pwstrTitle, pwstrFormat, pwstrMessage;
  1416. INT iResult;
  1417. va_list ap;
  1418. pwstrTitle = pwstrFormat = pwstrMessage = NULL;
  1419. if ((pwstrTitle = MemAllocZ(sizeof(WCHAR) * MAX_MBTITLE_LEN)) &&
  1420. (pwstrFormat = MemAllocZ(sizeof(WCHAR) * MAX_MBFORMAT_LEN)) &&
  1421. (pwstrMessage = MemAllocZ(sizeof(WCHAR) * MAX_MBMESSAGE_LEN)))
  1422. {
  1423. //
  1424. // Load message box title and format string resources
  1425. //
  1426. LoadString(ghInstance, iTitleStrId, pwstrTitle, MAX_MBTITLE_LEN);
  1427. LoadString(ghInstance, iFormatStrId, pwstrFormat, MAX_MBFORMAT_LEN);
  1428. //
  1429. // Compose the message string
  1430. //
  1431. va_start(ap, iFormatStrId);
  1432. StringCchVPrintfW(pwstrMessage, MAX_MBMESSAGE_LEN, pwstrFormat, ap);
  1433. va_end(ap);
  1434. //
  1435. // Display the message box
  1436. //
  1437. if (uType == 0)
  1438. uType = MB_OK | MB_ICONERROR;
  1439. iResult = MessageBox(hwndParent, pwstrMessage, pwstrTitle, uType);
  1440. }
  1441. else
  1442. {
  1443. MessageBeep(MB_ICONERROR);
  1444. iResult = 0;
  1445. }
  1446. MemFree(pwstrTitle);
  1447. MemFree(pwstrFormat);
  1448. MemFree(pwstrMessage);
  1449. return iResult;
  1450. }