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.

3759 lines
122 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. /* helper1.c - helper functions */
  3. #include "gpdparse.h"
  4. // ---- functions defined in helper1.c ---- //
  5. PTSTR pwstrGenerateGPDfilename(
  6. PTSTR ptstrSrcFilename
  7. ) ;
  8. #ifndef PARSERDLL
  9. PCOMMAND
  10. CommandPtr(
  11. IN PGPDDRIVERINFO pGPDDrvInfo,
  12. IN DWORD UniCmdID
  13. ) ;
  14. BOOL
  15. InitDefaultOptions(
  16. IN PRAWBINARYDATA pnRawData,
  17. OUT POPTSELECT poptsel,
  18. IN INT iMaxOptions,
  19. IN INT iMode
  20. ) ;
  21. BOOL
  22. SeparateOptionArray(
  23. IN PRAWBINARYDATA pnRawData,
  24. IN POPTSELECT pCombinedOptions,
  25. OUT POPTSELECT pOptions,
  26. IN INT iMaxOptions,
  27. IN INT iMode
  28. ) ;
  29. BOOL
  30. CombineOptionArray(
  31. IN PRAWBINARYDATA pnRawData,
  32. OUT POPTSELECT pCombinedOptions,
  33. IN INT iMaxOptions,
  34. IN POPTSELECT pDocOptions,
  35. IN POPTSELECT pPrinterOptions
  36. ) ;
  37. PINFOHEADER
  38. UpdateBinaryData(
  39. IN PRAWBINARYDATA pnRawData,
  40. IN PINFOHEADER pInfoHdr,
  41. IN POPTSELECT poptsel
  42. ) ;
  43. BOOL
  44. ReconstructOptionArray(
  45. IN PRAWBINARYDATA pnRawData,
  46. IN OUT POPTSELECT pOptions,
  47. IN INT iMaxOptions,
  48. IN DWORD dwFeatureIndex,
  49. IN PBOOL pbSelectedOptions
  50. ) ;
  51. BOOL
  52. ChangeOptionsViaID(
  53. IN PINFOHEADER pInfoHdr ,
  54. IN OUT POPTSELECT pOptions,
  55. IN DWORD dwFeatureID,
  56. IN PDEVMODE pDevmode
  57. ) ;
  58. BOOL BMapDmColorToOptIndex(
  59. PINFOHEADER pInfoHdr ,
  60. IN OUT PDWORD pdwOptIndex , // is current setting ok?
  61. // if not return new index to caller
  62. DWORD dwDmColor // what is requested in Devmode
  63. ) ;
  64. BOOL BMapOptIDtoOptIndex(
  65. PINFOHEADER pInfoHdr ,
  66. OUT PDWORD pdwOptIndex , // return index to caller
  67. DWORD dwFeatureGID,
  68. DWORD dwOptID
  69. ) ;
  70. BOOL BMapPaperDimToOptIndex(
  71. PINFOHEADER pInfoHdr ,
  72. OUT PDWORD pdwOptIndex , // return index to caller
  73. DWORD dwWidth, // in Microns
  74. DWORD dwLength, // in Microns
  75. OUT PDWORD pdwOptionIndexes
  76. ) ;
  77. BOOL BMapResToOptIndex(
  78. PINFOHEADER pInfoHdr ,
  79. OUT PDWORD pdwOptIndex , // return index to caller
  80. DWORD dwXres,
  81. DWORD dwYres
  82. ) ;
  83. BOOL BGIDtoFeaIndex(
  84. PINFOHEADER pInfoHdr ,
  85. PDWORD pdwFeaIndex ,
  86. DWORD dwFeatureGID ) ;
  87. DWORD
  88. MapToDeviceOptIndex(
  89. IN PINFOHEADER pInfoHdr ,
  90. IN DWORD dwFeatureID,
  91. IN LONG lParam1,
  92. IN LONG lParam2,
  93. OUT PDWORD pdwOptionIndexes
  94. ) ;
  95. DWORD
  96. UniMapToDeviceOptIndex(
  97. IN PINFOHEADER pInfoHdr ,
  98. IN DWORD dwFeatureID,
  99. IN LONG lParam1,
  100. IN LONG lParam2,
  101. OUT PDWORD pdwOptionIndexes, // used only for GID_PAGESIZE
  102. IN PDWORD pdwPaperID // optional paperID
  103. ) ;
  104. DWORD MapPaperAttribToOptIndex(
  105. PINFOHEADER pInfoHdr ,
  106. IN PDWORD pdwPaperID , // optional paperID
  107. DWORD dwWidth, // in Microns (set to zero to ignore)
  108. DWORD dwLength, // in Microns
  109. OUT PDWORD pdwOptionIndexes // cannot be NULL
  110. ) ;
  111. BOOL
  112. CheckFeatureOptionConflict(
  113. IN PRAWBINARYDATA pnRawData,
  114. IN DWORD dwFeature1,
  115. IN DWORD dwOption1,
  116. IN DWORD dwFeature2,
  117. IN DWORD dwOption2
  118. ) ;
  119. BOOL
  120. ResolveUIConflicts(
  121. IN PRAWBINARYDATA pnRawData,
  122. IN OUT POPTSELECT pOptions,
  123. IN INT iMaxOptions,
  124. IN INT iMode
  125. ) ;
  126. BOOL
  127. EnumEnabledOptions(
  128. IN PRAWBINARYDATA pnRawData,
  129. IN POPTSELECT pOptions,
  130. IN DWORD dwFeatureIndex,
  131. OUT PBOOL pbEnabledOptions ,
  132. IN INT iMode
  133. ) ;
  134. BOOL
  135. EnumOptionsUnconstrainedByPrinterSticky(
  136. IN PRAWBINARYDATA pnRawData,
  137. IN POPTSELECT pOptions,
  138. IN DWORD dwFeatureIndex,
  139. OUT PBOOL pbEnabledOptions
  140. ) ;
  141. BOOL
  142. EnumNewUIConflict(
  143. IN PRAWBINARYDATA pnRawData,
  144. IN POPTSELECT pOptions,
  145. IN DWORD dwFeatureIndex,
  146. IN PBOOL pbSelectedOptions,
  147. OUT PCONFLICTPAIR pConflictPair
  148. ) ;
  149. BOOL
  150. EnumNewPickOneUIConflict(
  151. IN PRAWBINARYDATA pnRawData,
  152. IN POPTSELECT pOptions,
  153. IN DWORD dwFeatureIndex,
  154. IN DWORD dwOptionIndex,
  155. OUT PCONFLICTPAIR pConflictPair
  156. ) ;
  157. BOOL
  158. BIsFeaOptionCurSelected(
  159. IN POPTSELECT pOptions,
  160. IN DWORD dwFeatureIndex,
  161. IN DWORD dwOptionIndex
  162. ) ;
  163. BOOL
  164. BSelectivelyEnumEnabledOptions(
  165. IN PRAWBINARYDATA pnRawData,
  166. IN POPTSELECT pOptions,
  167. IN DWORD dwFeatureIndex,
  168. IN PBOOL pbHonorConstraints, // if non NULL
  169. // points to array of BOOL corresponding to each feature.
  170. // if TRUE means constraint involving this feature is
  171. // to be honored. Otherwise ignore the constraint.
  172. OUT PBOOL pbEnabledOptions, // assume uninitialized
  173. // if pConflictPair is NULL else contains current or proposed
  174. // selections. We will leave this array unchanged in this case.
  175. IN DWORD dwOptSel, // if pConflictPair exists but pbEnabledOptions
  176. // is NULL, assume pickone and dwOptSel holds that selection for
  177. // the feature: dwFeatureIndex.
  178. OUT PCONFLICTPAIR pConflictPair // if present, pbEnabledOptions
  179. // actually lists the current selections. Function then
  180. // exits after encountering the first conflict.
  181. // if a conflict exists, all fields in pConflictPair
  182. // will be properly initialized else dwFeatureIndex1 = -1
  183. // the return value will be TRUE regardless.
  184. ) ;
  185. BOOL
  186. BEnumImposedConstraintsOnFeature
  187. (
  188. IN PRAWBINARYDATA pnRawData,
  189. IN DWORD dwTgtFeature,
  190. IN DWORD dwFeature2,
  191. IN DWORD dwOption2,
  192. OUT PBOOL pbEnabledOptions,
  193. OUT PCONFLICTPAIR pConflictPair // if present, pbEnabledOptions
  194. ) ;
  195. DWORD DwFindNodeInCurLevel(
  196. PATTRIB_TREE patt , // start of ATTRIBUTE tree array.
  197. PATREEREF patr , // index to a level in the attribute tree.
  198. DWORD dwOption // search current level for this option
  199. ) ;
  200. BOOL BIsConstraintActive(
  201. IN PCONSTRAINTS pcnstr , // root of Constraint nodes
  202. IN DWORD dwCNode, // first constraint node in list.
  203. IN PBOOL pbHonorConstraints, // if non NULL
  204. IN POPTSELECT pOptions,
  205. OUT PCONFLICTPAIR pConflictPair ) ;
  206. #ifdef GMACROS
  207. BOOL
  208. ResolveDependentSettings(
  209. IN PRAWBINARYDATA pnRawData,
  210. IN OUT POPTSELECT pOptions,
  211. IN INT iMaxOptions
  212. ) ;
  213. void EnumSelectedOptions(
  214. IN PRAWBINARYDATA pnRawData,
  215. IN OUT POPTSELECT pOptions,
  216. IN DWORD dwFeature,
  217. IN PBOOL pbSelectedOptions) ;
  218. BOOL
  219. ExecuteMacro(
  220. IN PRAWBINARYDATA pnRawData,
  221. IN OUT POPTSELECT pOptions,
  222. IN INT iMaxOptions,
  223. IN DWORD dwFea, // what feature was selected in UI
  224. IN DWORD dwOpt , // what option was selected in UI
  225. OUT PBOOL pbFeaturesChanged // tell Amanda what Features were changed.
  226. ) ;
  227. #endif
  228. #endif PARSERDLL
  229. // ------- end function declarations ------- //
  230. PTSTR pwstrGenerateGPDfilename(
  231. PTSTR ptstrSrcFilename
  232. )
  233. /*++
  234. Routine Description:
  235. Generate a filename for the cached binary GPD data given a GPD filename
  236. Arguments:
  237. ptstrSrcFilename - Specifies the GPD src filename
  238. Return Value:
  239. Pointer to BPD filename string, NULL if there is an error
  240. --*/
  241. {
  242. PTSTR ptstrBpdFilename, ptstrExtension;
  243. INT iLength;
  244. //
  245. // If the GPD filename has .GPD extension, replace it with .BUD extension.
  246. // Otherwise, append .BUD extension at the end.
  247. //
  248. if(!ptstrSrcFilename)
  249. return NULL ; // will never happen in reality, just to silence PREFIX
  250. iLength = _tcslen(ptstrSrcFilename);
  251. if ((ptstrExtension = _tcsrchr(ptstrSrcFilename, TEXT('.'))) == NULL ||
  252. _tcsicmp(ptstrExtension, GPD_FILENAME_EXT) != EQUAL_STRING)
  253. {
  254. WARNING(("Bad GPD filename extension: %ws\n", ptstrSrcFilename));
  255. ptstrExtension = ptstrSrcFilename + iLength;
  256. iLength += _tcslen(BUD_FILENAME_EXT);
  257. }
  258. //
  259. // Allocate memory and compose the BUD filename
  260. //
  261. if (ptstrBpdFilename = MemAlloc((iLength + 1) * sizeof(TCHAR)))
  262. {
  263. // _tcscpy(ptstrBpdFilename, ptstrSrcFilename);
  264. // _tcscpy(ptstrBpdFilename + (ptstrExtension - ptstrSrcFilename),
  265. // BUD_FILENAME_EXT);
  266. StringCchCopy(ptstrBpdFilename, iLength + 1, ptstrSrcFilename) ;
  267. StringCchCopy(ptstrBpdFilename + (ptstrExtension - ptstrSrcFilename),
  268. iLength + 1 - (ptstrExtension - ptstrSrcFilename) ,
  269. BUD_FILENAME_EXT);
  270. VERBOSE(("BUD filename: %ws\n", ptstrBpdFilename));
  271. }
  272. else
  273. {
  274. ERR(("Fatal: pwstrGenerateGPDfilename - unable to alloc %d bytes.\n",
  275. (iLength + 1) * sizeof(TCHAR)));
  276. }
  277. return (ptstrBpdFilename);
  278. }
  279. #ifndef PARSERDLL
  280. PCOMMAND
  281. CommandPtr(
  282. IN PGPDDRIVERINFO pGPDDrvInfo,
  283. IN DWORD UniCmdID
  284. )
  285. {
  286. return ((((PDWORD)((PBYTE)(pGPDDrvInfo)->pInfoHeader +
  287. (pGPDDrvInfo)->DataType[DT_COMMANDTABLE].loOffset))
  288. [(UniCmdID)] == UNUSED_ITEM ) ? NULL :
  289. (PCOMMAND)((pGPDDrvInfo)->pubResourceData +
  290. (pGPDDrvInfo)->DataType[DT_COMMANDARRAY].loOffset)
  291. + ((PDWORD)((PBYTE)(pGPDDrvInfo)->pInfoHeader +
  292. (pGPDDrvInfo)->DataType[DT_COMMANDTABLE].loOffset))[(UniCmdID)]);
  293. }
  294. BOOL
  295. InitDefaultOptions(
  296. IN PRAWBINARYDATA pnRawData,
  297. OUT POPTSELECT poptsel,
  298. IN INT iMaxOptions,
  299. IN INT iMode
  300. )
  301. {
  302. INT iOptionsNeeded ;
  303. PRAWBINARYDATA pRawData ;
  304. PSTATICFIELDS pStatic ;
  305. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  306. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  307. // to BUDDATA
  308. if(iMode != MODE_DOCANDPRINTER_STICKY)
  309. {
  310. POPTSELECT pOptions = NULL;
  311. BOOL bStatus = TRUE ;
  312. if(iMode == MODE_DOCUMENT_STICKY)
  313. iOptionsNeeded = pRawData->dwDocumentFeatures ;
  314. else // MODE_PRINTER_STICKY
  315. iOptionsNeeded = pRawData->dwPrinterFeatures ;
  316. if(iOptionsNeeded > iMaxOptions)
  317. return(FALSE);
  318. pOptions = (POPTSELECT)MemAlloc(sizeof(OPTSELECT) * MAX_COMBINED_OPTIONS) ;
  319. if(!poptsel || !pOptions ||
  320. !BinitDefaultOptionArray(pOptions, (PBYTE)pnRawData))
  321. {
  322. bStatus = FALSE;
  323. }
  324. if(!bStatus || !SeparateOptionArray(pnRawData,
  325. pOptions, // pCombinedOptions,
  326. poptsel, // dest array
  327. iMaxOptions, iMode))
  328. {
  329. bStatus = FALSE;
  330. ERR(("InitDefaultOptions: internal failure.\n"));
  331. }
  332. if(pOptions)
  333. MemFree(pOptions) ;
  334. return(bStatus);
  335. }
  336. else // MODE_DOCANDPRINTER_STICKY
  337. {
  338. iOptionsNeeded = pRawData->dwDocumentFeatures + pRawData->dwPrinterFeatures ;
  339. if(iOptionsNeeded > iMaxOptions)
  340. return(FALSE);
  341. if(!poptsel ||
  342. !BinitDefaultOptionArray(poptsel, (PBYTE)pnRawData))
  343. {
  344. return(FALSE);
  345. }
  346. }
  347. return(TRUE);
  348. }
  349. BOOL
  350. SeparateOptionArray(
  351. IN PRAWBINARYDATA pnRawData,
  352. IN POPTSELECT pCombinedOptions,
  353. OUT POPTSELECT pOptions,
  354. IN INT iMaxOptions,
  355. IN INT iMode
  356. )
  357. {
  358. DWORD dwNumSrcFea, dwNumDestFea, dwStart, dwI, dwDestTail,
  359. dwDest, dwSrcTail;
  360. PENHARRAYREF pearTableContents ;
  361. PDFEATURE_OPTIONS pfo ;
  362. // PMINIRAWBINARYDATA pmrbd ;
  363. PBYTE pubRaw ; // raw binary data.
  364. INT iOptionsNeeded;
  365. PRAWBINARYDATA pRawData ;
  366. PSTATICFIELDS pStatic ;
  367. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  368. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  369. // to BUDDATA
  370. pubRaw = (PBYTE)pRawData ;
  371. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  372. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  373. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  374. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  375. dwStart = 0 ; // starting src index
  376. if(iMode == MODE_DOCUMENT_STICKY)
  377. {
  378. dwNumSrcFea = pearTableContents[MTI_DFEATURE_OPTIONS].dwCount ;
  379. // number of candidates - not same as num of doc sticky features.
  380. dwNumDestFea = pRawData->dwDocumentFeatures ;
  381. }
  382. else // MODE_PRINTER_STICKY
  383. {
  384. dwNumSrcFea = pearTableContents[MTI_DFEATURE_OPTIONS].dwCount
  385. + pearTableContents[MTI_SYNTHESIZED_FEATURES].dwCount ;
  386. dwNumDestFea = pRawData->dwPrinterFeatures ;
  387. }
  388. // assume pCombinedOptions large enough to
  389. // hold all Feature and any pickmany selections.
  390. dwDestTail = dwNumDestFea ; // where pickmany selections are stored.
  391. dwDest = 0 ; // where to store first selection for each feature.
  392. // first pass:
  393. // Just count number of optselect elements needed.
  394. iOptionsNeeded = 0 ;
  395. for(dwI = dwStart ; dwI < dwStart + dwNumSrcFea ; dwI++)
  396. {
  397. DWORD dwNextOpt, dwFeatureType = FT_PRINTERPROPERTY, dwUnresolvedFeature ;
  398. PATREEREF patrRoot ; // root of attribute tree to navigate.
  399. // is this a printer or doc sticky feature?
  400. patrRoot = &(pfo[dwI].atrFeatureType) ;
  401. dwNextOpt = 0 ; // extract info for first option selected for
  402. // this feature.
  403. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSFeatureTypeIndex,
  404. (PBYTE)&dwFeatureType,
  405. &dwUnresolvedFeature, *patrRoot, pCombinedOptions,
  406. 0, // set to any value. Doesn't matter.
  407. &dwNextOpt) != TRI_SUCCESS)
  408. {
  409. ERR(("SeparateOptionArray: EextractValueFromTree failed.\n"));
  410. return(FALSE) ;
  411. }
  412. if(dwI < pearTableContents[MTI_DFEATURE_OPTIONS].dwCount)
  413. {
  414. if(dwFeatureType != FT_PRINTERPROPERTY)
  415. {
  416. if(iMode == MODE_PRINTER_STICKY)
  417. continue ;
  418. }
  419. else
  420. {
  421. if(iMode == MODE_DOCUMENT_STICKY)
  422. continue ;
  423. }
  424. }
  425. else
  426. {
  427. // synthesized features are always printer sticky.
  428. if(iMode == MODE_DOCUMENT_STICKY)
  429. continue ;
  430. }
  431. iOptionsNeeded++ ;
  432. dwSrcTail = dwI ;
  433. while(dwSrcTail = pCombinedOptions[dwSrcTail].ubNext)
  434. {
  435. iOptionsNeeded++ ;
  436. }
  437. }
  438. if(iOptionsNeeded > iMaxOptions)
  439. return(FALSE);
  440. for(dwI = dwStart ; dwI < dwStart + dwNumSrcFea ; dwI++)
  441. {
  442. DWORD dwNextOpt, dwFeatureType, dwUnresolvedFeature ;
  443. PATREEREF patrRoot ; // root of attribute tree to navigate.
  444. // is this a printer or doc sticky feature?
  445. patrRoot = &(pfo[dwI].atrFeatureType) ;
  446. dwNextOpt = 0 ; // extract info for first option selected for
  447. // this feature.
  448. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSFeatureTypeIndex,
  449. (PBYTE)&dwFeatureType,
  450. &dwUnresolvedFeature, *patrRoot, pCombinedOptions,
  451. 0, // set to any value. Doesn't matter.
  452. &dwNextOpt) != TRI_SUCCESS)
  453. {
  454. ERR(("SeparateOptionArray: EextractValueFromTree failed.\n"));
  455. return(FALSE) ;
  456. }
  457. if(dwI < pearTableContents[MTI_DFEATURE_OPTIONS].dwCount)
  458. {
  459. if(dwFeatureType != FT_PRINTERPROPERTY)
  460. {
  461. if(iMode == MODE_PRINTER_STICKY)
  462. continue ;
  463. }
  464. else
  465. {
  466. if(iMode == MODE_DOCUMENT_STICKY)
  467. continue ;
  468. }
  469. }
  470. else
  471. {
  472. // synthesized features are always printer sticky.
  473. if(iMode == MODE_DOCUMENT_STICKY)
  474. continue ;
  475. }
  476. pOptions[dwDest].ubCurOptIndex = pCombinedOptions[dwI].ubCurOptIndex;
  477. if(!pCombinedOptions[dwI].ubNext) // end of list
  478. pOptions[dwDest].ubNext = 0 ;
  479. else
  480. {
  481. dwSrcTail = pCombinedOptions[dwI].ubNext ;
  482. // this node holds another selection.
  483. pOptions[dwDest].ubNext = (BYTE)dwDestTail ;
  484. while(dwSrcTail)
  485. {
  486. pOptions[dwDestTail].ubCurOptIndex =
  487. pCombinedOptions[dwSrcTail].ubCurOptIndex;
  488. pOptions[dwDestTail].ubNext = (BYTE)dwDestTail + 1 ;
  489. dwDestTail++ ;
  490. dwSrcTail = pCombinedOptions[dwSrcTail].ubNext ;
  491. }
  492. pOptions[dwDestTail - 1].ubNext = 0 ;
  493. }
  494. dwDest++ ;
  495. }
  496. return(TRUE);
  497. }
  498. BOOL
  499. CombineOptionArray(
  500. IN PRAWBINARYDATA pnRawData,
  501. OUT POPTSELECT pCombinedOptions,
  502. IN INT iMaxOptions,
  503. IN POPTSELECT pDocOptions,
  504. IN POPTSELECT pPrinterOptions
  505. )
  506. /* Note:
  507. Either pDocOptions or pPrinterOptions could be NULL but not both. If pDocOptions
  508. is NULL, then in the combined option array, the options for document-sticky
  509. features will be OPTION_INDEX_ANY. Same is true when pPrinterOptions is NULL.
  510. */
  511. {
  512. DWORD dwNumSrcFea, dwNumDestFea, dwStart, dwI, dwDestTail,
  513. dwSrcTail, dwNDoc,
  514. dwSrcPrnStickyIndex, dwSrcDocStickyIndex ;
  515. PENHARRAYREF pearTableContents ;
  516. PDFEATURE_OPTIONS pfo ;
  517. // PMINIRAWBINARYDATA pmrbd ;
  518. PBYTE pubRaw ; // raw binary data.
  519. INT iOptionsNeeded;
  520. PRAWBINARYDATA pRawData ;
  521. PSTATICFIELDS pStatic ;
  522. DWORD dwFea, //Feature Index of Locale
  523. dwOptIndex; // Index of the Option that matches
  524. // the system locale.
  525. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  526. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  527. // to BUDDATA
  528. pubRaw = (PBYTE)pRawData ;
  529. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  530. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  531. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  532. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  533. dwStart = 0 ; // starting src index
  534. dwNumDestFea = pRawData->dwDocumentFeatures +
  535. pRawData->dwPrinterFeatures ;
  536. // how many option nodes will be used in the combined array?
  537. iOptionsNeeded = pRawData->dwDocumentFeatures ;
  538. if(pDocOptions)
  539. {
  540. for(dwI = 0 ; dwI < pRawData->dwDocumentFeatures ; dwI++)
  541. {
  542. dwSrcTail = dwI ;
  543. while(dwSrcTail = pDocOptions[dwSrcTail].ubNext)
  544. {
  545. iOptionsNeeded++ ;
  546. }
  547. }
  548. }
  549. iOptionsNeeded += pRawData->dwPrinterFeatures ;
  550. if(pPrinterOptions)
  551. {
  552. for(dwI = 0 ; dwI < pRawData->dwPrinterFeatures ; dwI++)
  553. {
  554. dwSrcTail = dwI ;
  555. while(dwSrcTail = pPrinterOptions[dwSrcTail].ubNext)
  556. {
  557. iOptionsNeeded++ ;
  558. }
  559. }
  560. }
  561. if(iOptionsNeeded > iMaxOptions)
  562. return(FALSE);
  563. dwDestTail = dwNumDestFea ; // start of pickmany selections
  564. dwSrcPrnStickyIndex = dwSrcDocStickyIndex = 0 ;
  565. // where to start reading from as we interleave the
  566. // two sources to form the combined array.
  567. for(dwI = 0 ; dwI < pearTableContents[MTI_DFEATURE_OPTIONS].dwCount +
  568. pearTableContents[MTI_SYNTHESIZED_FEATURES].dwCount ;
  569. dwI++)
  570. {
  571. DWORD dwNextOpt, dwFeatureType, dwUnresolvedFeature ;
  572. PATREEREF patrRoot ; // root of attribute tree to navigate.
  573. POPTSELECT pSrcOptions ;
  574. PDWORD pdwSrcIndex ;
  575. // assume printer sticky until proven otherwise.
  576. pSrcOptions = pPrinterOptions ; // may be null.
  577. pdwSrcIndex = &dwSrcPrnStickyIndex ;
  578. if(dwI < pearTableContents[MTI_DFEATURE_OPTIONS].dwCount)
  579. {
  580. // GPD defined features may be Doc or Printer sticky.
  581. patrRoot = &(pfo[dwI].atrFeatureType) ;
  582. dwNextOpt = 0 ; // extract info for first option selected for
  583. // this feature.
  584. // note we give EextractValueFromTree a ptr to
  585. // an uninitialized option array pCombinedOptions just
  586. // in case it has the urge to access an option array.
  587. // I point out that FeatureType is not multi-valued.
  588. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSFeatureTypeIndex,
  589. (PBYTE)&dwFeatureType,
  590. &dwUnresolvedFeature, *patrRoot, pCombinedOptions,
  591. 0, // set to any value. Doesn't matter.
  592. &dwNextOpt) != TRI_SUCCESS)
  593. {
  594. ERR(("CombineOptionArray: EextractValueFromTree failed.\n"));
  595. return(FALSE) ;
  596. }
  597. if(dwFeatureType != FT_PRINTERPROPERTY)
  598. {
  599. pSrcOptions = pDocOptions ;
  600. pdwSrcIndex = &dwSrcDocStickyIndex ;
  601. }
  602. }
  603. if(!pSrcOptions) // no option array supplied.
  604. {
  605. pCombinedOptions[dwI].ubCurOptIndex = OPTION_INDEX_ANY ;
  606. pCombinedOptions[dwI].ubNext = 0 ; // eol
  607. }
  608. else
  609. {
  610. dwSrcTail = *pdwSrcIndex ;
  611. pCombinedOptions[dwI].ubCurOptIndex =
  612. pSrcOptions[*pdwSrcIndex].ubCurOptIndex ;
  613. if(pSrcOptions[*pdwSrcIndex].ubNext)
  614. {
  615. pCombinedOptions[dwI].ubNext = (BYTE)dwDestTail ;
  616. while(dwSrcTail = pSrcOptions[dwSrcTail].ubNext)
  617. {
  618. pCombinedOptions[dwDestTail].ubCurOptIndex =
  619. pSrcOptions[dwSrcTail].ubCurOptIndex ;
  620. pCombinedOptions[dwDestTail].ubNext = (BYTE)dwDestTail + 1;
  621. dwDestTail++ ;
  622. }
  623. pCombinedOptions[dwDestTail - 1].ubNext = 0 ;
  624. }
  625. else
  626. pCombinedOptions[dwI].ubNext = 0 ;
  627. (*pdwSrcIndex)++ ;
  628. }
  629. }
  630. // Special case processing for Locale. If there is a conflict between
  631. // locale as stored in the registry ( i.e. the printer feature option
  632. // related registry) and the System Locale, then give importance to
  633. // the option that matches the system locale.
  634. dwFea = dwOptIndex = (DWORD)-1; // Safety sake initialization.
  635. if ( !BgetLocFeaOptIndex(pnRawData, &dwFea, &dwOptIndex) )
  636. {
  637. return FALSE;
  638. }
  639. if ( dwFea == -1 ) //Locale keyword not in gpd. Nothing to do.
  640. {
  641. return TRUE;
  642. }
  643. if (dwOptIndex == -1) // Find the default option.
  644. {
  645. // Here we want to find the default option index.
  646. // The assumption here is that Locale option is not dependent
  647. // on any other feature. This is true cos Locale is only system
  648. // dependent and should not depend on any other feature. But
  649. // in the long run if some other dependency arises, we may have to
  650. // change the code.
  651. ATREEREF atrOptIDNode = pfo[dwFea].atrDefaultOption;
  652. PBYTE pubHeap = (PBYTE)(pubRaw +
  653. pearTableContents[MTI_STRINGHEAP]. loOffset) ;
  654. if ( atrOptIDNode & ATTRIB_HEAP_VALUE)
  655. {
  656. dwOptIndex = *((PDWORD)(pubHeap +
  657. (atrOptIDNode & ~ATTRIB_HEAP_VALUE))) ;
  658. }
  659. else {
  660. ERR(("Error in processing Default Option for Feature Locale. Continuing....\n"));
  661. return TRUE; //Dont do any processing.
  662. }
  663. // i.e.
  664. }
  665. // Could have used ReconstructOptionArray() but prefered to go
  666. // with the constructs used in this function.
  667. // Another assumption is that multiple options cannot be selected.
  668. // Thats why pCombinedOptions[dwFea].ubNext = 0
  669. pCombinedOptions[dwFea].ubCurOptIndex = (BYTE)dwOptIndex;
  670. pCombinedOptions[dwFea].ubNext = 0;
  671. return(TRUE);
  672. }
  673. #ifndef KERNEL_MODE
  674. PINFOHEADER
  675. UpdateBinaryData(
  676. IN PRAWBINARYDATA pnRawData,
  677. IN PINFOHEADER pInfoHdr,
  678. IN POPTSELECT poptsel
  679. )
  680. {
  681. DWORD dwNumFeatures, loFeatures, dwFea, dwI, dwNumOptions ,
  682. dwSizeOption ;
  683. PGPDDRIVERINFO pGPDdriverInfo;
  684. PUIINFO pUIinfo ;
  685. PFEATURE pFeaturesDest ;
  686. PENHARRAYREF pearTableContents ;
  687. PDFEATURE_OPTIONS pfo ;
  688. // PMINIRAWBINARYDATA pmrbd ;
  689. PBYTE pubRaw, // raw binary data.
  690. pubOptionsDest , // ptr to any of the several varieties
  691. pubDestOptionEx ; // of option structures.
  692. PRAWBINARYDATA pRawData ;
  693. PSTATICFIELDS pStatic ;
  694. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  695. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ; // to BUDDATA
  696. pubRaw = (PBYTE)pRawData ;
  697. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  698. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  699. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  700. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  701. dwNumFeatures = pearTableContents[MTI_DFEATURE_OPTIONS].dwCount ;
  702. dwNumFeatures += pearTableContents[MTI_SYNTHESIZED_FEATURES].dwCount ;
  703. /* also works ...
  704. dwNumFeatures =
  705. pRawData->dwDocumentFeatures + pRawData->dwPrinterFeatures ;
  706. */
  707. pGPDdriverInfo = (PGPDDRIVERINFO)((PBYTE)(pInfoHdr) +
  708. pInfoHdr->loDriverOffset) ;
  709. if(!BinitGlobals(&pGPDdriverInfo->Globals, (PBYTE)pnRawData, poptsel, TRUE) )
  710. {
  711. return(NULL) ;
  712. }
  713. pUIinfo = (PUIINFO)((PBYTE)(pInfoHdr) +
  714. pInfoHdr->loUIInfoOffset) ;
  715. if(!BinitUIinfo(pUIinfo, (PBYTE)pnRawData, poptsel, TRUE) )
  716. {
  717. return(NULL) ;
  718. }
  719. loFeatures = pUIinfo->loFeatureList ; // from pInfoHdr
  720. pFeaturesDest = (PFEATURE)((PBYTE)(pInfoHdr) + loFeatures) ;
  721. // always points to first Feature structure in array
  722. for( dwFea = 0 ; dwFea < dwNumFeatures ; dwFea++)
  723. {
  724. dwSizeOption = (pFeaturesDest + dwFea)->dwOptionSize ;
  725. dwNumOptions = pFeaturesDest[dwFea].Options.dwCount ;
  726. pubOptionsDest = (PBYTE)(pInfoHdr) + pFeaturesDest[dwFea].Options.loOffset ;
  727. if(!BinitFeatures(pFeaturesDest + dwFea, pfo + dwFea,
  728. (PBYTE)pnRawData, poptsel, TRUE))
  729. {
  730. return(NULL) ;
  731. }
  732. for(dwI = 0 ; dwI < dwNumOptions ; dwI++)
  733. {
  734. if(((POPTION)pubOptionsDest)->loRenderOffset)
  735. {
  736. pubDestOptionEx = (PBYTE)(pInfoHdr) +
  737. ((POPTION)pubOptionsDest)->loRenderOffset ;
  738. }
  739. else
  740. pubDestOptionEx = NULL ;
  741. if(!BinitOptionFields(pubOptionsDest, pubDestOptionEx,
  742. (PBYTE)pnRawData, dwFea, dwI, poptsel, pInfoHdr, TRUE) )
  743. {
  744. MemFree(pInfoHdr) ;
  745. return(NULL) ;
  746. }
  747. pubOptionsDest += dwSizeOption ;
  748. }
  749. }
  750. return(pInfoHdr);
  751. }
  752. #endif
  753. BOOL
  754. ReconstructOptionArray(
  755. IN PRAWBINARYDATA pnRawData,
  756. IN OUT POPTSELECT pOptions,
  757. IN INT iMaxOptions,
  758. IN DWORD dwFeatureIndex,
  759. IN PBOOL pbSelectedOptions
  760. )
  761. /*++
  762. Routine Description:
  763. Modify an option array to change the selected options for the specified feature
  764. Arguments:
  765. pRawData - Points to raw binary printer description data
  766. pOptions - Points to an array of OPTSELECT structures to be modified
  767. iMaxOptions - Max number of entries in pOptions array
  768. dwFeatureIndex - Specifies the index of printer feature in question
  769. pbSelectedOptions - Which options of the specified feature is selected
  770. Return Value:
  771. FALSE if the input option array is not large enough to hold
  772. all modified option values. TRUE otherwise.
  773. Note:
  774. Number of BOOLs in pSelectedOptions must match the number of options
  775. for the specified feature.
  776. This function always leaves the option array in a compact format (i.e.
  777. all unused entries are left at the end of the array).
  778. --*/
  779. {
  780. BOOL bStatus = TRUE ;
  781. DWORD dwDestTail, dwSrcTail, dwNumFea , dwI ;
  782. // POPTSELECT pNewOptions ;
  783. PENHARRAYREF pearTableContents ;
  784. PDFEATURE_OPTIONS pfo ;
  785. PBYTE pubRaw ; // raw binary data.
  786. PRAWBINARYDATA pRawData ;
  787. PSTATICFIELDS pStatic ;
  788. OPTSELECT pNewOptions[MAX_COMBINED_OPTIONS] ;
  789. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  790. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  791. // to BUDDATA
  792. pubRaw = (PBYTE)pRawData ;
  793. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  794. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  795. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  796. if(!pOptions)
  797. {
  798. ERR(("ReconstructOptionArray: caller passed in invalid pOptions.\n"));
  799. return(FALSE); // Missing array.
  800. }
  801. #if 0
  802. pNewOptions = (POPTSELECT)MemAlloc(sizeof(OPTSELECT) * MAX_COMBINED_OPTIONS) ;
  803. if( !pNewOptions )
  804. {
  805. ERR(("Fatal: ReconstructOptionArray - unable to alloc %d bytes.\n",
  806. sizeof(OPTSELECT) * MAX_COMBINED_OPTIONS));
  807. return(FALSE); // Missing array.
  808. }
  809. #endif
  810. dwDestTail = dwNumFea = pRawData->dwDocumentFeatures +
  811. pRawData->dwPrinterFeatures ;
  812. for(dwI = 0 ; dwI < dwNumFea ; dwI++)
  813. {
  814. if(dwI == dwFeatureIndex)
  815. {
  816. DWORD dwNumOptions, dwOpt ;
  817. dwNumOptions = pfo[dwI].dwNumOptions ;
  818. // determine first selected option, must have
  819. // at least one.
  820. for(dwOpt = 0 ; dwOpt < dwNumOptions &&
  821. !pbSelectedOptions[dwOpt] ; dwOpt++)
  822. {
  823. ; // null body
  824. }
  825. if(dwOpt >= dwNumOptions)
  826. {
  827. ERR(("ReconstructOptionArray: caller passed in invalid option selection.\n"));
  828. bStatus = FALSE ;
  829. break ;
  830. }
  831. pNewOptions[dwI].ubCurOptIndex = (BYTE)dwOpt ;
  832. for(++dwOpt ; dwOpt < dwNumOptions &&
  833. !pbSelectedOptions[dwOpt] ; dwOpt++)
  834. {
  835. ; // null body
  836. }
  837. if(dwOpt == dwNumOptions) // no other options selected.
  838. pNewOptions[dwI].ubNext = 0 ;
  839. else
  840. {
  841. // pbSelectedOptions holds another selection.
  842. pNewOptions[dwI].ubNext = (BYTE)dwDestTail ;
  843. while(dwOpt < dwNumOptions)
  844. {
  845. pNewOptions[dwDestTail].ubCurOptIndex = (BYTE)dwOpt ;
  846. pNewOptions[dwDestTail].ubNext = (BYTE)dwDestTail + 1 ;
  847. dwDestTail++ ;
  848. if(dwDestTail > MAX_COMBINED_OPTIONS)
  849. {
  850. ERR(("ReconstructOptionArray: exceeded limit of MAX_COMBINED_OPTIONS.\n"));
  851. // MemFree(pNewOptions) ;
  852. return(FALSE);
  853. }
  854. for(++dwOpt ; dwOpt < dwNumOptions &&
  855. !pbSelectedOptions[dwOpt] ; dwOpt++)
  856. {
  857. ; // null body
  858. }
  859. }
  860. pNewOptions[dwDestTail - 1].ubNext = 0 ;
  861. }
  862. continue ;
  863. }
  864. pNewOptions[dwI].ubCurOptIndex = pOptions[dwI].ubCurOptIndex;
  865. if(!(dwSrcTail = pOptions[dwI].ubNext)) // end of list
  866. pNewOptions[dwI].ubNext = 0 ;
  867. else
  868. {
  869. // dwSrcTail holds another selection.
  870. pNewOptions[dwI].ubNext = (BYTE)dwDestTail ;
  871. while(dwSrcTail)
  872. {
  873. pNewOptions[dwDestTail].ubCurOptIndex =
  874. pOptions[dwSrcTail].ubCurOptIndex;
  875. pNewOptions[dwDestTail].ubNext = (BYTE)dwDestTail + 1 ;
  876. dwDestTail++ ;
  877. if(dwDestTail > MAX_COMBINED_OPTIONS)
  878. {
  879. ERR(("ReconstructOptionArray: exceeded limit of MAX_COMBINED_OPTIONS.\n"));
  880. // MemFree(pNewOptions) ;
  881. return(FALSE);
  882. }
  883. dwSrcTail = pOptions[dwSrcTail].ubNext ;
  884. }
  885. pNewOptions[dwDestTail - 1].ubNext = 0 ;
  886. }
  887. }
  888. if (dwDestTail > (DWORD)iMaxOptions)
  889. {
  890. ERR(("ReconstructOptionArray: exceeded size of array OPTSELECT.\n"));
  891. bStatus = FALSE;
  892. }
  893. if(bStatus)
  894. {
  895. for(dwI = 0 ; dwI < dwDestTail ; dwI++)
  896. pOptions[dwI] = pNewOptions[dwI] ;
  897. }
  898. // MemFree(pNewOptions) ;
  899. return(bStatus);
  900. }
  901. BOOL
  902. ChangeOptionsViaID(
  903. IN PINFOHEADER pInfoHdr ,
  904. IN OUT POPTSELECT pOptions,
  905. IN DWORD dwFeatureID,
  906. IN PDEVMODE pDevmode
  907. )
  908. /*++
  909. Routine Description:
  910. Modifies an option array using the information in public devmode fields
  911. Arguments:
  912. pRawData - Points to raw binary printer description data
  913. pOptions - Points to the option array to be modified
  914. dwFeatureID - Specifies which field(s) of the input devmode should be used
  915. pDevmode - Specifies the input devmode
  916. Return Value:
  917. TRUE if successful, FALSE if the specified feature ID is not supported
  918. or there is an error
  919. Note:
  920. We assume the input devmode fields have been validated by the caller.
  921. this GID: is determined by this devmode field: optID
  922. GID_RESOLUTION dmPrintQuality, dmYResolution
  923. GID_PAGESIZE dmPaperSize, dmPaperLength, dmPaperWidth CL_CONS_PAPERSIZE
  924. GID_PAGEREGION N/A
  925. GID_DUPLEX dmDuplex CL_CONS_DUPLEX
  926. GID_INPUTSLOT dmDefaultSource CL_CONS_INPUTSLOT
  927. GID_MEDIATYPE dmMediaType CL_CONS_MEDIATYPE
  928. GID_MEMOPTION N/A
  929. GID_COLORMODE N/A (hack something if needed.)
  930. GID_ORIENTATION dmOrientation CL_CONS_ORIENTATION
  931. GID_PAGEPROTECTION N/A
  932. GID_COLLATE dmCollate CL_CONS_COLLATE
  933. {DMCOLLATE_TRUE, DMCOLLATE_FALSE}
  934. GID_OUTPUTBIN N/A
  935. GID_HALFTONING N/A
  936. see DEVMODE in sdk\inc\wingdi.h
  937. --*/
  938. {
  939. BOOL bStatus = FALSE ;
  940. DWORD dwFeaIndex = 0, dwOptIndex, dwOptID ;
  941. switch(dwFeatureID)
  942. {
  943. case GID_RESOLUTION:
  944. {
  945. DWORD dwXres, dwYres ;
  946. // we assume caller has initialized both dmPrintQuality and
  947. // dmYResolution.
  948. dwXres = pDevmode->dmPrintQuality ;
  949. dwYres = pDevmode->dmYResolution ;
  950. bStatus = BMapResToOptIndex(pInfoHdr, &dwOptIndex, dwXres, dwYres) ;
  951. if(bStatus &&
  952. (bStatus = BGIDtoFeaIndex(pInfoHdr,
  953. &dwFeaIndex, dwFeatureID)) )
  954. {
  955. // don't need to worry about truncating
  956. // a list of options, these features
  957. // are all PICKONE.
  958. pOptions[dwFeaIndex].ubCurOptIndex = (BYTE)dwOptIndex ;
  959. pOptions[dwFeaIndex].ubNext = 0 ;
  960. }
  961. return (bStatus);
  962. }
  963. case GID_PAGESIZE:
  964. {
  965. if( pDevmode->dmFields & DM_PAPERLENGTH &&
  966. pDevmode->dmFields & DM_PAPERWIDTH &&
  967. pDevmode->dmPaperWidth &&
  968. pDevmode->dmPaperLength)
  969. {
  970. // must convert devmode's tenths of mm to microns
  971. // before calling.
  972. bStatus = BMapPaperDimToOptIndex(pInfoHdr, &dwOptIndex,
  973. pDevmode->dmPaperWidth * 100L,
  974. pDevmode->dmPaperLength * 100L, NULL) ;
  975. }
  976. else if(pDevmode->dmFields & DM_PAPERSIZE)
  977. {
  978. dwOptID = pDevmode->dmPaperSize ;
  979. bStatus = BMapOptIDtoOptIndex(pInfoHdr, &dwOptIndex,
  980. dwFeatureID, dwOptID) ;
  981. }
  982. else
  983. bStatus = FALSE ;
  984. if(bStatus &&
  985. (bStatus = BGIDtoFeaIndex(pInfoHdr,
  986. &dwFeaIndex, dwFeatureID)) )
  987. {
  988. pOptions[dwFeaIndex].ubCurOptIndex = (BYTE)dwOptIndex ;
  989. pOptions[dwFeaIndex].ubNext = 0 ;
  990. return (bStatus); // must exit now.
  991. }
  992. break ;
  993. }
  994. case GID_DUPLEX:
  995. {
  996. if(pDevmode->dmFields & DM_DUPLEX)
  997. {
  998. dwOptID = pDevmode->dmDuplex ;
  999. bStatus = TRUE ;
  1000. }
  1001. break ;
  1002. }
  1003. case GID_INPUTSLOT:
  1004. {
  1005. if(pDevmode->dmFields & DM_DEFAULTSOURCE)
  1006. {
  1007. dwOptID = pDevmode->dmDefaultSource ;
  1008. bStatus = TRUE ;
  1009. }
  1010. break ;
  1011. }
  1012. case GID_MEDIATYPE:
  1013. {
  1014. if(pDevmode->dmFields & DM_MEDIATYPE)
  1015. {
  1016. dwOptID = pDevmode->dmMediaType ;
  1017. bStatus = TRUE ;
  1018. }
  1019. break ;
  1020. }
  1021. case GID_COLORMODE:
  1022. {
  1023. if(pDevmode->dmFields & DM_COLOR)
  1024. {
  1025. // special processing since devmode
  1026. // only specifies BW or color printing.
  1027. bStatus = BGIDtoFeaIndex(pInfoHdr,
  1028. &dwFeaIndex, dwFeatureID) ;
  1029. if(!bStatus) // dwFeaIndex could be invalid at this point.
  1030. return (bStatus);
  1031. // what is the current color setting?
  1032. dwOptIndex = pOptions[dwFeaIndex].ubCurOptIndex ;
  1033. if(bStatus &&
  1034. (bStatus = BMapDmColorToOptIndex(pInfoHdr, &dwOptIndex,
  1035. pDevmode->dmColor)) )
  1036. {
  1037. pOptions[dwFeaIndex].ubCurOptIndex = (BYTE)dwOptIndex ;
  1038. pOptions[dwFeaIndex].ubNext = 0 ;
  1039. }
  1040. }
  1041. return (bStatus);
  1042. }
  1043. case GID_ORIENTATION:
  1044. {
  1045. if(pDevmode->dmFields & DM_ORIENTATION)
  1046. {
  1047. dwOptID = pDevmode->dmOrientation ;
  1048. if(dwOptID == DMORIENT_PORTRAIT)
  1049. dwOptID = ROTATE_NONE ;
  1050. else
  1051. {
  1052. dwOptID = ROTATE_90 ;
  1053. bStatus = BMapOptIDtoOptIndex(pInfoHdr, &dwOptIndex,
  1054. dwFeatureID, dwOptID) ;
  1055. if(!bStatus)
  1056. {
  1057. dwOptID = ROTATE_270 ;
  1058. }
  1059. }
  1060. bStatus = TRUE ;
  1061. }
  1062. break ;
  1063. }
  1064. case GID_COLLATE:
  1065. {
  1066. if(pDevmode->dmFields & DM_COLLATE)
  1067. {
  1068. dwOptID = pDevmode->dmCollate ;
  1069. bStatus = TRUE ;
  1070. }
  1071. break ;
  1072. }
  1073. default:
  1074. {
  1075. break ;
  1076. }
  1077. }
  1078. // Complete processing for typical case.
  1079. if(bStatus)
  1080. {
  1081. bStatus = BMapOptIDtoOptIndex(pInfoHdr, &dwOptIndex,
  1082. dwFeatureID, dwOptID) ;
  1083. }
  1084. if(bStatus &&
  1085. (bStatus = BGIDtoFeaIndex(pInfoHdr,
  1086. &dwFeaIndex, dwFeatureID) ))
  1087. {
  1088. // don't need to worry about truncating
  1089. // a list of options, these features
  1090. // are all PICKONE.
  1091. pOptions[dwFeaIndex].ubCurOptIndex = (BYTE)dwOptIndex ;
  1092. pOptions[dwFeaIndex].ubNext = 0 ;
  1093. }
  1094. return (bStatus);
  1095. }
  1096. BOOL BMapDmColorToOptIndex(
  1097. PINFOHEADER pInfoHdr ,
  1098. IN OUT PDWORD pdwOptIndex , // is current setting ok?
  1099. // if not return new index to caller
  1100. DWORD dwDmColor // what is requested in Devmode
  1101. )
  1102. {
  1103. PUIINFO pUIInfo ;
  1104. PFEATURE pFeature ;
  1105. DWORD dwNumOpts, loOptOffset, dwI ;
  1106. PCOLORMODE pColorModeOption ;
  1107. BOOL bColor ;
  1108. DWORD loOptExOffset ;
  1109. PCOLORMODEEX pColorModeOptionEx ;
  1110. bColor = (dwDmColor == DMCOLOR_COLOR) ;
  1111. pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHdr) ;
  1112. pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_COLORMODE) ;
  1113. if(!pFeature)
  1114. return(FALSE) ; // no such feature defined in GPD
  1115. dwNumOpts = pFeature->Options.dwCount ;
  1116. loOptOffset = pFeature->Options.loOffset ;
  1117. if(*pdwOptIndex >= dwNumOpts) // option index out of range - fix for 185245
  1118. {
  1119. *pdwOptIndex = pFeature->dwDefaultOptIndex ; // use the default option
  1120. return(FALSE) ;
  1121. }
  1122. pColorModeOption = OFFSET_TO_POINTER(pInfoHdr, loOptOffset) ;
  1123. loOptExOffset = pColorModeOption[*pdwOptIndex].GenericOption.loRenderOffset ;
  1124. pColorModeOptionEx = OFFSET_TO_POINTER(pInfoHdr, loOptExOffset) ;
  1125. if(bColor == pColorModeOptionEx->bColor)
  1126. return(TRUE) ; // currently selected colormode
  1127. // matches devmode request.
  1128. loOptExOffset = pColorModeOption[pFeature->dwDefaultOptIndex].
  1129. GenericOption.loRenderOffset ;
  1130. pColorModeOptionEx = OFFSET_TO_POINTER(pInfoHdr, loOptExOffset) ;
  1131. if(bColor == pColorModeOptionEx->bColor)
  1132. {
  1133. *pdwOptIndex = pFeature->dwDefaultOptIndex ;
  1134. return(TRUE) ; // the default colormode option
  1135. } // matches devmode request.
  1136. // last ditch effort - just find the first matching one.
  1137. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  1138. {
  1139. loOptExOffset = pColorModeOption[dwI].GenericOption.loRenderOffset ;
  1140. pColorModeOptionEx = OFFSET_TO_POINTER(pInfoHdr, loOptExOffset) ;
  1141. if(bColor == pColorModeOptionEx->bColor)
  1142. {
  1143. *pdwOptIndex = dwI ;
  1144. return(TRUE) ;
  1145. }
  1146. }
  1147. return(FALSE) ; // no matching colormode found.
  1148. }
  1149. BOOL BMapOptIDtoOptIndex(
  1150. PINFOHEADER pInfoHdr ,
  1151. OUT PDWORD pdwOptIndex , // return index to caller
  1152. DWORD dwFeatureGID,
  1153. DWORD dwOptID
  1154. )
  1155. {
  1156. PUIINFO pUIInfo ;
  1157. PFEATURE pFeature ;
  1158. DWORD dwNumOpts, loOptOffset, dwI, dwIDOffset, dwOptSize, dwCurID ;
  1159. POPTION pOption ;
  1160. switch(dwFeatureGID)
  1161. {
  1162. case GID_HALFTONING:
  1163. dwIDOffset = offsetof(HALFTONING, dwHTID ) ;
  1164. break ;
  1165. case GID_DUPLEX:
  1166. dwIDOffset = offsetof(DUPLEX, dwDuplexID ) ;
  1167. break ;
  1168. case GID_ORIENTATION:
  1169. dwIDOffset = offsetof(ORIENTATION, dwRotationAngle ) ;
  1170. break ;
  1171. case GID_PAGESIZE:
  1172. dwIDOffset = offsetof(PAGESIZE, dwPaperSizeID ) ;
  1173. break ;
  1174. case GID_INPUTSLOT:
  1175. dwIDOffset = offsetof(INPUTSLOT, dwPaperSourceID ) ;
  1176. break ;
  1177. case GID_MEDIATYPE:
  1178. dwIDOffset = offsetof(MEDIATYPE, dwMediaTypeID ) ;
  1179. break ;
  1180. case GID_COLLATE:
  1181. dwIDOffset = offsetof(COLLATE, dwCollateID ) ;
  1182. break ;
  1183. default:
  1184. return(FALSE); // this feature has no ID value!
  1185. }
  1186. pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHdr) ;
  1187. pFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwFeatureGID) ;
  1188. if(!pFeature)
  1189. return(FALSE) ; // no such feature defined in GPD
  1190. dwNumOpts = pFeature->Options.dwCount ;
  1191. loOptOffset = pFeature->Options.loOffset ;
  1192. dwOptSize = pFeature->dwOptionSize ;
  1193. pOption = OFFSET_TO_POINTER(pInfoHdr, loOptOffset) ;
  1194. // just find the first matching one.
  1195. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  1196. {
  1197. dwCurID = *(PDWORD)((PBYTE)pOption + dwI * dwOptSize + dwIDOffset) ;
  1198. if(dwOptID == dwCurID)
  1199. {
  1200. *pdwOptIndex = dwI ;
  1201. return(TRUE) ;
  1202. }
  1203. }
  1204. return(FALSE) ; // no matching ID found.
  1205. }
  1206. BOOL BMapPaperDimToOptIndex(
  1207. PINFOHEADER pInfoHdr ,
  1208. OUT PDWORD pdwOptIndex , // return index to caller
  1209. DWORD dwWidth, // in Microns
  1210. DWORD dwLength, // in Microns
  1211. OUT PDWORD pdwOptionIndexes
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. Map logical values to PaperSize option index
  1216. Arguments:
  1217. pdwOptIndex - if pdwOptionIndexs == NULL, this
  1218. holds the option index of the first paper matching the
  1219. requested dimensions. Otherwise this holds the number
  1220. of papers matching the requested dimensions.
  1221. dwWidth , dwLength - requested Paper Size in Microns
  1222. pdwOptionIndexes - if Not NULL, this array will be initialized
  1223. with all option indicies of papers which match the requested size.
  1224. In this case the return value
  1225. is the number of elements in the array initialized. Currently
  1226. we assume the array is large enough (256 elements).
  1227. Return Value:
  1228. TRUE: found one or more papers of the size requested.
  1229. --*/
  1230. {
  1231. PUIINFO pUIInfo ;
  1232. PGPDDRIVERINFO pDrvInfo ;
  1233. PFEATURE pFeature ;
  1234. DWORD dwNumOpts, loOptOffset, dwI ,
  1235. dwError, dwErrorY, dwCustomIndex,
  1236. dwOptWidth , dwOptLength,
  1237. dwMinWidth , dwMinLength,
  1238. dwMaxWidth , dwMaxLength,
  1239. dwOutArrayIndex = 0;
  1240. PPAGESIZE pPaperOption ;
  1241. BOOL bFits = FALSE ; // does custom size fit request?
  1242. // Convert from Microns to Master units.
  1243. dwWidth /= 100 ; // microns to tenths of mm
  1244. dwLength /= 100 ;
  1245. pDrvInfo = (PGPDDRIVERINFO) GET_DRIVER_INFO_FROM_INFOHEADER(pInfoHdr) ;
  1246. dwWidth *= pDrvInfo->Globals.ptMasterUnits.x ;
  1247. dwLength *= pDrvInfo->Globals.ptMasterUnits.y ;
  1248. dwWidth /= 254 ;
  1249. dwLength /= 254 ;
  1250. dwError = pDrvInfo->Globals.ptMasterUnits.x / 100 ;
  1251. dwErrorY = pDrvInfo->Globals.ptMasterUnits.y / 100 ;
  1252. dwError = (dwError > dwErrorY) ? dwError : dwErrorY ;
  1253. dwError = (dwError > 3) ? dwError : 3 ;
  1254. // give leeway of 3 master units or 1/100 inch whichever
  1255. // is greater.
  1256. dwMinWidth = (dwWidth < dwError) ? 0 : (dwWidth - dwError) ;
  1257. dwMinLength = (dwLength < dwError) ? 0 : (dwLength - dwError) ;
  1258. dwMaxWidth = dwWidth + dwError ;
  1259. dwMaxLength = dwLength + dwError ;
  1260. pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHdr) ;
  1261. pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE) ;
  1262. if(!pFeature)
  1263. return(FALSE) ; // no such feature defined in GPD
  1264. dwNumOpts = pFeature->Options.dwCount ;
  1265. loOptOffset = pFeature->Options.loOffset ;
  1266. pPaperOption = OFFSET_TO_POINTER(pInfoHdr, loOptOffset) ;
  1267. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  1268. {
  1269. if(pPaperOption[dwI].dwPaperSizeID != DMPAPER_USER)
  1270. {
  1271. dwOptWidth = pPaperOption[dwI].szPaperSize.cx ;
  1272. dwOptLength = pPaperOption[dwI].szPaperSize.cy ;
  1273. if(dwOptWidth > dwMinWidth && dwOptWidth < dwMaxWidth &&
  1274. dwOptLength > dwMinLength && dwOptLength < dwMaxLength )
  1275. {
  1276. if(pdwOptionIndexes)
  1277. pdwOptionIndexes[dwOutArrayIndex++] = dwI ;
  1278. else
  1279. {
  1280. *pdwOptIndex = dwI ;
  1281. return(TRUE) ;
  1282. }
  1283. }
  1284. }
  1285. else // this is the custom size:
  1286. {
  1287. DWORD loOptExOffset ;
  1288. PPAGESIZEEX pPaperOptionEx ;
  1289. loOptExOffset = pPaperOption[dwI].GenericOption.loRenderOffset ;
  1290. pPaperOptionEx = OFFSET_TO_POINTER(pInfoHdr, loOptExOffset) ;
  1291. // does it fit the requested size?
  1292. if(dwWidth <= (DWORD)pPaperOptionEx->ptMaxSize.x &&
  1293. dwWidth >= (DWORD)pPaperOptionEx->ptMinSize.x &&
  1294. dwLength <= (DWORD)pPaperOptionEx->ptMaxSize.y &&
  1295. dwLength >= (DWORD)pPaperOptionEx->ptMinSize.y )
  1296. {
  1297. bFits = TRUE ;
  1298. dwCustomIndex = dwI ;
  1299. }
  1300. }
  1301. }
  1302. if(pdwOptionIndexes)
  1303. {
  1304. if(bFits)
  1305. {
  1306. pdwOptionIndexes[dwOutArrayIndex++] = dwCustomIndex ;
  1307. }
  1308. *pdwOptIndex = dwOutArrayIndex ;
  1309. // cover the case where dwOutArrayIndex = 0.
  1310. if(dwOutArrayIndex)
  1311. return(TRUE) ;
  1312. return(FALSE) ;
  1313. }
  1314. if(bFits)
  1315. {
  1316. *pdwOptIndex = dwCustomIndex ;
  1317. return(TRUE) ;
  1318. }
  1319. return(FALSE) ;
  1320. }
  1321. BOOL BMapResToOptIndex(
  1322. PINFOHEADER pInfoHdr ,
  1323. OUT PDWORD pdwOptIndex , // return index to caller
  1324. DWORD dwXres,
  1325. DWORD dwYres
  1326. )
  1327. {
  1328. PUIINFO pUIInfo ;
  1329. PFEATURE pFeature ;
  1330. DWORD dwNumOpts, loOptOffset, dwI ;
  1331. DWORD dwHighRes, dwLowRes, dwMedRes, dwDefRes, dwCurRes,
  1332. // in pixels per square inch.
  1333. dwHighIndex, dwLowIndex, dwMedIndex, dwDefIndex ;
  1334. PRESOLUTION pResOption ;
  1335. pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHdr) ;
  1336. pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_RESOLUTION) ;
  1337. if(!pFeature)
  1338. return(FALSE) ; // no such feature defined in GPD
  1339. dwNumOpts = pFeature->Options.dwCount ;
  1340. loOptOffset = pFeature->Options.loOffset ;
  1341. pResOption = OFFSET_TO_POINTER(pInfoHdr, loOptOffset) ;
  1342. if((signed)dwXres > 0)
  1343. {
  1344. dwDefIndex = pFeature->dwDefaultOptIndex ;
  1345. if(dwXres == (DWORD)pResOption[dwDefIndex].iXdpi &&
  1346. dwYres == (DWORD)pResOption[dwDefIndex].iYdpi)
  1347. {
  1348. *pdwOptIndex = dwDefIndex ;
  1349. return(TRUE) ;
  1350. }
  1351. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  1352. {
  1353. if(dwXres == (DWORD)pResOption[dwI].iXdpi &&
  1354. dwYres == (DWORD)pResOption[dwI].iYdpi)
  1355. {
  1356. *pdwOptIndex = dwI ;
  1357. return(TRUE) ;
  1358. }
  1359. }
  1360. }
  1361. else if ((signed)dwXres > RES_ID_IGNORE) // OEM defined ID
  1362. {
  1363. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  1364. {
  1365. if(dwXres == (DWORD)pResOption[dwI].dwResolutionID)
  1366. {
  1367. *pdwOptIndex = dwI ;
  1368. return(TRUE) ;
  1369. }
  1370. }
  1371. }
  1372. // if exact match fails, or predefined negative value or nonsense
  1373. // resort to fuzzy match.
  1374. // first determine the highest, lowest, 2nd highest and default resolutions.
  1375. dwHighIndex = dwLowIndex = dwMedIndex = dwDefIndex =
  1376. pFeature->dwDefaultOptIndex ;
  1377. dwHighRes = dwLowRes = dwMedRes = dwDefRes =
  1378. (DWORD)pResOption[dwDefIndex].iXdpi *
  1379. (DWORD)pResOption[dwDefIndex].iYdpi ;
  1380. // note overflow possible if resolution exceeds 64k dpi.
  1381. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  1382. {
  1383. dwCurRes = (DWORD)pResOption[dwI].iXdpi *
  1384. (DWORD)pResOption[dwI].iYdpi ;
  1385. if(dwCurRes > dwHighRes)
  1386. {
  1387. dwHighIndex = dwI ;
  1388. dwHighRes = dwCurRes ;
  1389. }
  1390. else if(dwCurRes < dwLowRes)
  1391. {
  1392. dwLowIndex = dwI ;
  1393. dwLowRes = dwCurRes ;
  1394. }
  1395. else if(dwCurRes < dwHighRes && dwCurRes > dwLowRes &&
  1396. (dwMedRes == dwHighRes || dwMedRes == dwLowRes || dwCurRes > dwMedRes))
  1397. {
  1398. dwMedIndex = dwI ; // if more than one middle res possible
  1399. dwMedRes = dwCurRes ; // choose the largest.
  1400. }
  1401. }
  1402. // if (default res is not the highest or lowest, make default res the middle resolution
  1403. if(dwDefRes < dwHighRes && dwDefRes > dwLowRes)
  1404. {
  1405. dwMedIndex = dwDefIndex ;
  1406. dwMedRes = dwDefRes ; // unnecessary code, but just in case
  1407. // like the last break in a switch statement.
  1408. }
  1409. switch(dwXres)
  1410. {
  1411. case(DMRES_DRAFT):
  1412. case(DMRES_LOW):
  1413. *pdwOptIndex = dwLowIndex ;
  1414. break;
  1415. case(DMRES_MEDIUM):
  1416. *pdwOptIndex = dwMedIndex ;
  1417. break;
  1418. case(DMRES_HIGH):
  1419. *pdwOptIndex = dwHighIndex ;
  1420. break;
  1421. default:
  1422. *pdwOptIndex = dwDefIndex ;
  1423. break;
  1424. }
  1425. return(TRUE) ;
  1426. }
  1427. BOOL BGIDtoFeaIndex(
  1428. PINFOHEADER pInfoHdr ,
  1429. PDWORD pdwFeaIndex ,
  1430. DWORD dwFeatureGID )
  1431. {
  1432. PUIINFO pUIInfo ;
  1433. PFEATURE pFeature ;
  1434. pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHdr) ;
  1435. pFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwFeatureGID) ;
  1436. if(!pFeature)
  1437. return(FALSE) ; // no such feature defined in GPD
  1438. *pdwFeaIndex = (DWORD)GET_INDEX_FROM_FEATURE(pUIInfo, pFeature) ;
  1439. return(TRUE) ;
  1440. }
  1441. DWORD
  1442. MapToDeviceOptIndex(
  1443. IN PINFOHEADER pInfoHdr ,
  1444. IN DWORD dwFeatureID,
  1445. IN LONG lParam1,
  1446. IN LONG lParam2,
  1447. OUT PDWORD pdwOptionIndexes // used only for GID_PAGESIZE
  1448. )
  1449. {
  1450. return ( UniMapToDeviceOptIndex(
  1451. pInfoHdr , dwFeatureID, lParam1, lParam2,
  1452. pdwOptionIndexes, // used only for GID_PAGESIZE
  1453. NULL) ) ;
  1454. }
  1455. DWORD
  1456. UniMapToDeviceOptIndex(
  1457. IN PINFOHEADER pInfoHdr ,
  1458. IN DWORD dwFeatureID,
  1459. IN LONG lParam1,
  1460. IN LONG lParam2,
  1461. OUT PDWORD pdwOptionIndexes, // used only for GID_PAGESIZE
  1462. IN PDWORD pdwPaperID // optional paperID
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Map logical values to device feature option index
  1467. Arguments:
  1468. pRawData - Points to raw binary printer description data
  1469. dwFeatureID - Indicate which feature the logical values are related to
  1470. lParam1, lParam2 - Parameters depending on dwFeatureID
  1471. pdwOptionIndexes - if Not NULL, means fill this array with all indicies
  1472. which match the search criteria. In this case the return value
  1473. is the number of elements in the array initialized. Currently
  1474. we assume the array is large enough (256 elements).
  1475. dwFeatureID = GID_PAGESIZE:
  1476. map logical paper specification to physical page size option
  1477. lParam1 = paper width in microns
  1478. lParam2 = paper height in microns
  1479. IF lParam1 or 2 is set to zero, this function assumes
  1480. pdwPaperID points to the OptionID of a paper.
  1481. It will return the first paper found matching this ID.
  1482. dwFeatureID = GID_RESOLUTION:
  1483. map logical resolution to physical resolution option
  1484. lParam1 = x-resolution in dpi
  1485. lParam2 = y-resolution in dpi
  1486. Return Value:
  1487. Index of the feature option corresponding to the specified logical values;
  1488. OPTION_INDEX_ANY if the specified logical values cannot be mapped to
  1489. any feature option.
  1490. if pdwOptionIndexes Not NULL, the return value is the number of elements
  1491. written to. Zero means the specified logical values cannot be mapped to
  1492. any feature option.
  1493. --*/
  1494. {
  1495. DWORD dwOptIndex;
  1496. switch (dwFeatureID)
  1497. {
  1498. case GID_PAGESIZE:
  1499. {
  1500. if(pdwOptionIndexes)
  1501. return( MapPaperAttribToOptIndex(
  1502. pInfoHdr ,
  1503. pdwPaperID , // optional paperID
  1504. (DWORD)lParam1, (DWORD)lParam2, // in Microns
  1505. pdwOptionIndexes) ) ;
  1506. if(BMapPaperDimToOptIndex(pInfoHdr, &dwOptIndex,
  1507. (DWORD)lParam1, (DWORD)lParam2, NULL) )
  1508. return(dwOptIndex) ;
  1509. break ;
  1510. }
  1511. case GID_RESOLUTION:
  1512. {
  1513. if( BMapResToOptIndex(pInfoHdr, &dwOptIndex,
  1514. (DWORD)lParam1, (DWORD)lParam2) )
  1515. return(dwOptIndex) ;
  1516. break ;
  1517. }
  1518. default:
  1519. break ;
  1520. }
  1521. return(OPTION_INDEX_ANY) ;
  1522. }
  1523. DWORD MapPaperAttribToOptIndex(
  1524. PINFOHEADER pInfoHdr ,
  1525. IN PDWORD pdwPaperID , // optional paperID
  1526. DWORD dwWidth, // in Microns (set to zero to ignore)
  1527. DWORD dwLength, // in Microns
  1528. OUT PDWORD pdwOptionIndexes // cannot be NULL
  1529. )
  1530. {
  1531. DWORD dwNumFound;
  1532. BOOL bStatus ;
  1533. if(dwWidth && dwLength)
  1534. {
  1535. if( BMapPaperDimToOptIndex(pInfoHdr, &dwNumFound,
  1536. dwWidth , dwLength, pdwOptionIndexes) )
  1537. return(dwNumFound);
  1538. return(0);
  1539. }
  1540. if(pdwPaperID) // use paperID instead of dimensions
  1541. {
  1542. bStatus = BMapOptIDtoOptIndex(pInfoHdr, pdwOptionIndexes,
  1543. GID_PAGESIZE, *pdwPaperID) ;
  1544. return(bStatus ? 1 : 0) ;
  1545. }
  1546. return(0); // if given nothing, return nothing
  1547. }
  1548. BOOL
  1549. CheckFeatureOptionConflict(
  1550. IN PRAWBINARYDATA pnRawData,
  1551. IN DWORD dwFeature1,
  1552. IN DWORD dwOption1,
  1553. IN DWORD dwFeature2,
  1554. IN DWORD dwOption2
  1555. )
  1556. {
  1557. #ifndef KERNEL_MODE
  1558. PENHARRAYREF pearTableContents ;
  1559. PDFEATURE_OPTIONS pfo ;
  1560. // PMINIRAWBINARYDATA pmrbd ;
  1561. PBYTE pubHeap , // start of string heap.
  1562. pubRaw ; // raw binary data.
  1563. DWORD dwNodeIndex ,
  1564. dwCNode ; // index to a Constraint node
  1565. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  1566. PATREEREF patrRoot ; // root of attribute tree to navigate.
  1567. // PINVALIDCOMBO pinvc ; // root of invalid combo nodes
  1568. PCONSTRAINTS pcnstr ; // root of Constraint nodes
  1569. BOOL bReflected = FALSE ;
  1570. PRAWBINARYDATA pRawData ;
  1571. PSTATICFIELDS pStatic ;
  1572. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  1573. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  1574. // to BUDDATA
  1575. pubRaw = (PBYTE)pRawData ;
  1576. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  1577. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  1578. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  1579. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  1580. patt = (PATTRIB_TREE)(pubRaw +
  1581. pearTableContents[MTI_ATTRIBTREE].loOffset) ;
  1582. // pinvc = (PINVALIDCOMBO) (pubRaw +
  1583. // pearTableContents[MTI_INVALIDCOMBO].loOffset) ;
  1584. pcnstr = (PCONSTRAINTS) (pubRaw +
  1585. pearTableContents[MTI_CONSTRAINTS].loOffset) ;
  1586. pubHeap = (PBYTE)(pubRaw + pearTableContents[MTI_STRINGHEAP].
  1587. loOffset) ;
  1588. TRYAGAIN:
  1589. patrRoot = &(pfo[dwFeature1].atrConstraints) ;
  1590. dwNodeIndex = DwFindNodeInCurLevel(patt , patrRoot , dwOption1) ;
  1591. if(dwNodeIndex == INVALID_INDEX)
  1592. goto REFLECTCONSTRAINT ;
  1593. if(patt[dwNodeIndex].eOffsetMeans != VALUE_AT_HEAP)
  1594. {
  1595. ERR(("Internal error. CheckFeatureOptionConflict - Unexpected Sublevel found for atrConstraints.\n"));
  1596. goto REFLECTCONSTRAINT ;
  1597. }
  1598. dwCNode = *(PDWORD)(pubHeap + patt[dwNodeIndex].dwOffset) ;
  1599. while(1)
  1600. {
  1601. if(pcnstr[dwCNode].dwFeature == dwFeature2 &&
  1602. pcnstr[dwCNode].dwOption == dwOption2)
  1603. return(TRUE) ; // a constraint does exist.
  1604. dwCNode = pcnstr[dwCNode].dwNextCnstrnt ;
  1605. if(dwCNode == END_OF_LIST)
  1606. break ;
  1607. }
  1608. REFLECTCONSTRAINT :
  1609. if(!bReflected)
  1610. {
  1611. DWORD dwSwap ;
  1612. dwSwap = dwFeature2 ;
  1613. dwFeature2 = dwFeature1 ;
  1614. dwFeature1 = dwSwap ;
  1615. dwSwap = dwOption2 ;
  1616. dwOption2 = dwOption1 ;
  1617. dwOption1 = dwSwap ;
  1618. bReflected = TRUE ;
  1619. goto TRYAGAIN;
  1620. }
  1621. // else continue on to FINDINVALIDCOMBOS
  1622. // oops this function doesn't care about
  1623. // InvalidCombos! It only knows about
  1624. // 2 qualified objects.
  1625. #else
  1626. RIP(("CheckFeatureOptionConflict not implemented in Kernel Mode")) ;
  1627. #endif
  1628. return(FALSE); // no constraint found.
  1629. }
  1630. VOID
  1631. ValidateDocOptions(
  1632. IN PRAWBINARYDATA pnRawData,
  1633. IN OUT POPTSELECT pOptions,
  1634. IN INT iMaxOptions
  1635. )
  1636. /*++
  1637. Routine Description:
  1638. Validate the devmode option array and correct any invalid option selections
  1639. Arguments:
  1640. pnRawData - Points to raw binary printer description data
  1641. pOptions - Points to an array of OPTSELECT structures that need validation
  1642. iMaxOptions - Max number of entries in pOptions array
  1643. Return Value:
  1644. None
  1645. --*/
  1646. {
  1647. PENHARRAYREF pearTableContents ;
  1648. PDFEATURE_OPTIONS pfo ;
  1649. // PMINIRAWBINARYDATA pmrbd ;
  1650. PBYTE pubRaw ; // raw binary data.
  1651. INT NumDocFea = 0;
  1652. INT iIndex = 0;
  1653. DWORD nFeatures = 0 ; // total number of Doc and Printer Features
  1654. DWORD FeaIndex = 0 ;
  1655. PRAWBINARYDATA pRawData ;
  1656. PSTATICFIELDS pStatic ;
  1657. POPTSELECT pCombinedOptions = NULL; // holds result of merging pOptions with a NULL array
  1658. POPTSELECT pDefaultOptions = NULL; // holds a default option array. Source of default values.
  1659. BOOL bStatus = TRUE ;
  1660. DWORD MaxIndex = (iMaxOptions < MAX_COMBINED_OPTIONS) ? iMaxOptions : MAX_COMBINED_OPTIONS ;
  1661. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  1662. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  1663. // to BUDDATA
  1664. NumDocFea = pRawData->dwDocumentFeatures ;
  1665. if(!pOptions)
  1666. {
  1667. RIP(("ValidateDocOptions: NULL Option array not permitted.\n"));
  1668. return ;
  1669. }
  1670. if(iMaxOptions < NumDocFea)
  1671. {
  1672. RIP(("ValidateDocOptions: Option array too small: %d < %d\n", iMaxOptions, NumDocFea));
  1673. goto Abort;
  1674. }
  1675. pubRaw = (PBYTE)pRawData ;
  1676. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  1677. pfo = (PDFEATURE_OPTIONS)(pubRaw + pearTableContents[MTI_DFEATURE_OPTIONS].
  1678. loOffset) ; // location of Feature 0.
  1679. // allocate memory to hold combined option array
  1680. // allocate another one to hold initialized default option array
  1681. pCombinedOptions = (POPTSELECT)MemAlloc(sizeof(OPTSELECT) * MAX_COMBINED_OPTIONS) ;
  1682. pDefaultOptions = (POPTSELECT)MemAlloc(sizeof(OPTSELECT) * MAX_COMBINED_OPTIONS) ;
  1683. if( !pCombinedOptions || !pDefaultOptions )
  1684. goto Abort;
  1685. // verify any pick many slots don't create overlapping or endless loops.
  1686. // use pCombinedOptions to track them.
  1687. for(iIndex = NumDocFea ; iIndex < MAX_COMBINED_OPTIONS ; iIndex++)
  1688. {
  1689. pCombinedOptions[iIndex].ubCurOptIndex = 0 ; // these are available to hold pickmany selections
  1690. }
  1691. for(iIndex = 0 ; iIndex < NumDocFea ; iIndex++)
  1692. {
  1693. DWORD NextArrayEle = pOptions[iIndex].ubNext ;
  1694. for ( ; (NextArrayEle != NULL_OPTSELECT) ; NextArrayEle = pOptions[NextArrayEle].ubNext)
  1695. {
  1696. if((NextArrayEle >= MaxIndex) || ((INT)NextArrayEle < NumDocFea) ||
  1697. (pCombinedOptions[NextArrayEle].ubCurOptIndex) )
  1698. { // NextArrayEle out of bounds or overwrites a previous slot.
  1699. pOptions[iIndex].ubNext = NULL_OPTSELECT;
  1700. break; // just terminate this pickmany list.
  1701. }
  1702. pCombinedOptions[NextArrayEle].ubCurOptIndex = 1 ; // reserve this slot.
  1703. }
  1704. }
  1705. bStatus = InitDefaultOptions( pnRawData, pDefaultOptions, MAX_COMBINED_OPTIONS,
  1706. MODE_DOCANDPRINTER_STICKY) ;
  1707. if(!bStatus)
  1708. goto Abort;
  1709. // must merge input pOptions to create a combined option array.
  1710. bStatus = CombineOptionArray( pnRawData, pCombinedOptions, iMaxOptions,
  1711. pOptions, NULL) ;
  1712. if(!bStatus)
  1713. goto Abort;
  1714. nFeatures = pRawData->dwDocumentFeatures + pRawData->dwPrinterFeatures ;
  1715. if(nFeatures > MAX_COMBINED_OPTIONS)
  1716. goto Abort;
  1717. for(FeaIndex = 0 ; FeaIndex < nFeatures ; FeaIndex++)
  1718. {
  1719. DWORD nOptions = 0 ; // number of options available for this Feature
  1720. DWORD NextArrayEle = 0 ; // index into option array esp for PickMany
  1721. DWORD cSelectedOptions = 0; // how many options have been selected for this feature?
  1722. nOptions = pfo[FeaIndex].dwNumOptions ;
  1723. NextArrayEle = FeaIndex;
  1724. bStatus = TRUE;
  1725. do
  1726. {
  1727. cSelectedOptions++;
  1728. if ((NextArrayEle >= MAX_COMBINED_OPTIONS) || // index out of range
  1729. (pCombinedOptions[NextArrayEle].ubCurOptIndex >= nOptions) || // selected option out of range
  1730. (cSelectedOptions > nOptions)) // too many options selected (for pick many)
  1731. {
  1732. //
  1733. // either the option index is out of range,
  1734. // or the current option selection is invalid,
  1735. // or the number of selected options (for PICKMANY)
  1736. // exceeds available options
  1737. //
  1738. bStatus = FALSE;
  1739. break;
  1740. }
  1741. NextArrayEle = pCombinedOptions[NextArrayEle].ubNext;
  1742. } while (NextArrayEle != NULL_OPTSELECT);
  1743. if (!bStatus)
  1744. {
  1745. pCombinedOptions[FeaIndex].ubCurOptIndex =
  1746. pDefaultOptions[FeaIndex].ubCurOptIndex;
  1747. pCombinedOptions[FeaIndex].ubNext = NULL_OPTSELECT;
  1748. }
  1749. }
  1750. // separate combined option array into doc sticky part and
  1751. // store that in pOptions.
  1752. bStatus = SeparateOptionArray(pnRawData, pCombinedOptions,
  1753. pOptions, iMaxOptions, MODE_DOCUMENT_STICKY ) ;
  1754. if(!bStatus)
  1755. goto Abort;
  1756. if(pCombinedOptions)
  1757. MemFree(pCombinedOptions) ;
  1758. if(pDefaultOptions)
  1759. MemFree(pDefaultOptions) ;
  1760. return ; // Normal return path
  1761. Abort: // something has gone totally haywire.
  1762. if(iMaxOptions > NumDocFea )
  1763. iMaxOptions = NumDocFea ;
  1764. for(iIndex = 0 ; iIndex < iMaxOptions ; iIndex++)
  1765. {
  1766. pOptions[iIndex].ubCurOptIndex = 0 ;
  1767. pOptions[iIndex].ubNext = NULL_OPTSELECT;
  1768. }
  1769. if(pCombinedOptions)
  1770. MemFree(pCombinedOptions) ;
  1771. if(pDefaultOptions)
  1772. MemFree(pDefaultOptions) ;
  1773. return ; // error return path.
  1774. }
  1775. BOOL
  1776. ResolveUIConflicts(
  1777. IN PRAWBINARYDATA pnRawData,
  1778. IN OUT POPTSELECT pOptions,
  1779. IN INT iMaxOptions,
  1780. IN INT iMode
  1781. )
  1782. {
  1783. DWORD dwNumFeatures, dwFea, dwStart, dwI, dwDestTail,
  1784. dwDest, dwSrcTail, dwNumOpts, dwNEnabled, dwJ ;
  1785. PENHARRAYREF pearTableContents ;
  1786. PDFEATURE_OPTIONS pfo ;
  1787. // PMINIRAWBINARYDATA pmrbd ;
  1788. PBYTE pubRaw ; // raw binary data.
  1789. PDWORD pdwPriority ;
  1790. BOOL bStatus = FALSE, bUnresolvedConflict = FALSE ,
  1791. bEnable = FALSE ; // feature will constrain others
  1792. PBOOL pbUseConstrnt, pbEnabledOptions, pbSelectedOptions ;
  1793. INT iOptionsNeeded;
  1794. PRAWBINARYDATA pRawData ;
  1795. PSTATICFIELDS pStatic ;
  1796. #ifdef GMACROS
  1797. if(!ResolveDependentSettings( pnRawData, pOptions, iMaxOptions) )
  1798. return(FALSE);
  1799. #endif
  1800. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  1801. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  1802. // to BUDDATA
  1803. pubRaw = (PBYTE)pRawData ;
  1804. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  1805. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  1806. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  1807. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  1808. pdwPriority = (PDWORD)(pubRaw +
  1809. pearTableContents[MTI_PRIORITYARRAY].loOffset) ;
  1810. dwNumFeatures = pearTableContents[MTI_DFEATURE_OPTIONS].dwCount ;
  1811. dwNumFeatures += pearTableContents[MTI_SYNTHESIZED_FEATURES].dwCount ;
  1812. if(dwNumFeatures > (DWORD)iMaxOptions)
  1813. {
  1814. iOptionsNeeded = dwNumFeatures ;
  1815. return(FALSE); // too many to save in option array.
  1816. }
  1817. #if 0
  1818. pbUseConstrnt = (PBOOL)MemAlloc(dwNumFeatures * sizeof(BOOL) ) ;
  1819. pbEnabledOptions = (PBOOL)MemAlloc(256 * sizeof(BOOL) ) ;
  1820. pbSelectedOptions = (PBOOL)MemAlloc(256 * sizeof(BOOL) ) ;
  1821. #endif
  1822. pbSelectedOptions = (PBOOL)MemAlloc((256*2 + dwNumFeatures) * sizeof(BOOL) ) ;
  1823. // this is the union of the allowable selections
  1824. // and what was actually selected in pOptions for this feature.
  1825. // BUG_BUG: assumes we won't have more than 256 options
  1826. pbEnabledOptions = pbSelectedOptions + 256 ;
  1827. // these are the allowable selections
  1828. pbUseConstrnt = pbEnabledOptions + 256 ;
  1829. if(!(pbUseConstrnt && pbEnabledOptions && pbSelectedOptions ))
  1830. {
  1831. ERR(("Fatal: ResolveUIConflicts - unable to alloc requested memory: %d bytes.\n",
  1832. dwNumFeatures * sizeof(BOOL)));
  1833. goto ABORTRESOLVEUICONFLICTS ;
  1834. }
  1835. for(dwI = 0 ; dwI < dwNumFeatures ; dwI++)
  1836. pbUseConstrnt[dwI] = FALSE ;
  1837. for(dwNEnabled = dwI = 0 ; dwI < dwNumFeatures ; dwI++)
  1838. {
  1839. // The order of evaluation is determined
  1840. // by the priority array.
  1841. dwFea = pdwPriority[dwI] ;
  1842. bEnable = FALSE ;
  1843. if(iMode == MODE_DOCANDPRINTER_STICKY)
  1844. bEnable = TRUE ;
  1845. else
  1846. {
  1847. DWORD dwFeatureType = FT_PRINTERPROPERTY, dwNextOpt, dwUnresolvedFeature ;
  1848. PATREEREF patrRoot ; // root of attribute tree to navigate.
  1849. // is this a printer or doc sticky feature?
  1850. patrRoot = &(pfo[dwFea].atrFeatureType) ;
  1851. dwNextOpt = 0 ; // extract info for first option selected for
  1852. // this feature.
  1853. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSFeatureTypeIndex,
  1854. (PBYTE)&dwFeatureType,
  1855. &dwUnresolvedFeature, *patrRoot, pOptions,
  1856. 0, // set to any value. Doesn't matter.
  1857. &dwNextOpt) != TRI_SUCCESS)
  1858. {
  1859. ERR(("ResolveUIConflicts: EextractValueFromTree failed.\n"));
  1860. bUnresolvedConflict = TRUE ;
  1861. goto ABORTRESOLVEUICONFLICTS ; // return(FALSE) ;
  1862. }
  1863. if(dwFeatureType != FT_PRINTERPROPERTY)
  1864. {
  1865. if(iMode == MODE_DOCUMENT_STICKY)
  1866. bEnable = TRUE ;
  1867. }
  1868. else
  1869. {
  1870. if(iMode == MODE_PRINTER_STICKY)
  1871. bEnable = TRUE ;
  1872. }
  1873. }
  1874. if(bEnable) // Feature is to be applied as constraint
  1875. {
  1876. pbUseConstrnt[dwFea] = TRUE ;
  1877. dwNEnabled++ ;
  1878. }
  1879. else
  1880. continue ; // not interested in this feature
  1881. if(dwNEnabled < 2)
  1882. continue ; // not enough Features enabled
  1883. // to constrain each other.
  1884. bStatus = BSelectivelyEnumEnabledOptions(
  1885. pnRawData,
  1886. pOptions,
  1887. dwFea,
  1888. pbUseConstrnt, // if non NULL
  1889. pbEnabledOptions,
  1890. 0,
  1891. NULL // pConflictPair
  1892. ) ;
  1893. dwNumOpts = pfo[dwFea].dwNumOptions ;
  1894. for(dwJ = 0 ; dwJ < dwNumOpts ; dwJ++)
  1895. pbSelectedOptions[dwJ] = FALSE ;
  1896. if(!bStatus)
  1897. {
  1898. pbSelectedOptions[0] = TRUE ;
  1899. // just set this to a harmless value.
  1900. }
  1901. else
  1902. {
  1903. DWORD dwNext = dwFea ;
  1904. while(1)
  1905. {
  1906. if(pbEnabledOptions[pOptions[dwNext].ubCurOptIndex])
  1907. pbSelectedOptions[pOptions[dwNext].ubCurOptIndex] = TRUE ;
  1908. dwNext = pOptions[dwNext].ubNext ;
  1909. if(!dwNext)
  1910. break ; // end of list of options.
  1911. }
  1912. }
  1913. for(dwJ = 0 ; dwJ < dwNumOpts ; dwJ++)
  1914. {
  1915. if(pbSelectedOptions[dwJ])
  1916. break ; // is anything actually selected?
  1917. }
  1918. if(dwJ >= dwNumOpts)
  1919. {
  1920. DWORD dwDefaultOption, dwNextOpt, dwUnresolvedFeature ;
  1921. PATREEREF patrRoot ; // root of attribute tree to navigate.
  1922. // none of the original selections survived
  1923. // see if the default option can be used.
  1924. // first, determine the index of the default option.
  1925. patrRoot = &(pfo[dwFea].atrDefaultOption) ;
  1926. dwNextOpt = 0 ; // extract info for first option selected for
  1927. // this feature.
  1928. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSdefaultOptionIndex,
  1929. (PBYTE)&dwDefaultOption,
  1930. &dwUnresolvedFeature, *patrRoot, pOptions,
  1931. 0, // set to any value. Doesn't matter.
  1932. &dwNextOpt) == TRI_SUCCESS &&
  1933. pbEnabledOptions[dwDefaultOption])
  1934. {
  1935. pbSelectedOptions[dwDefaultOption] = TRUE ;
  1936. }
  1937. else // randomly pick something that isn't constrained.
  1938. {
  1939. if(!dwFea) // hack for synthesized Inputslot.
  1940. pbEnabledOptions[0] = FALSE ; // never allow autoselect to be selected
  1941. // if it wasn't initially selected. bug 100722
  1942. for(dwJ = 0 ; dwJ < dwNumOpts ; dwJ++)
  1943. {
  1944. if(pbEnabledOptions[dwJ])
  1945. break ;
  1946. }
  1947. if(dwJ >= dwNumOpts)
  1948. {
  1949. ERR(("ResolveUIConflicts: Constraints prevent any option from being selected!\n"));
  1950. pbSelectedOptions[0] = TRUE ; // ignoring constraint.
  1951. bUnresolvedConflict = TRUE ;
  1952. }
  1953. else
  1954. pbSelectedOptions[dwJ] = TRUE ; // Picked one.
  1955. }
  1956. }
  1957. bStatus = ReconstructOptionArray(
  1958. pnRawData,
  1959. pOptions,
  1960. iMaxOptions,
  1961. dwFea,
  1962. pbSelectedOptions) ;
  1963. if(!bStatus)
  1964. {
  1965. ERR(("ResolveUIConflicts: ReconstructOptionArray failed.\n"));
  1966. bUnresolvedConflict = TRUE ;
  1967. }
  1968. } // end of processing for this feature
  1969. ABORTRESOLVEUICONFLICTS:
  1970. #if 0
  1971. if(pbUseConstrnt)
  1972. MemFree(pbUseConstrnt) ;
  1973. if(pbEnabledOptions)
  1974. MemFree(pbEnabledOptions) ;
  1975. #endif
  1976. if(pbSelectedOptions)
  1977. MemFree(pbSelectedOptions) ;
  1978. return(!bUnresolvedConflict);
  1979. }
  1980. BOOL
  1981. EnumEnabledOptions(
  1982. IN PRAWBINARYDATA pnRawData,
  1983. IN POPTSELECT pOptions,
  1984. IN DWORD dwFeatureIndex,
  1985. OUT PBOOL pbEnabledOptions ,
  1986. IN INT iMode
  1987. // either MODE_DOCANDPRINTER_STICKY or MODE_PRINTER_STICKY
  1988. )
  1989. {
  1990. #ifndef KERNEL_MODE
  1991. if(iMode == MODE_PRINTER_STICKY)
  1992. {
  1993. return(EnumOptionsUnconstrainedByPrinterSticky(
  1994. pnRawData,
  1995. pOptions,
  1996. dwFeatureIndex,
  1997. pbEnabledOptions
  1998. ) ) ;
  1999. }
  2000. else
  2001. {
  2002. return(BSelectivelyEnumEnabledOptions(
  2003. pnRawData,
  2004. pOptions,
  2005. dwFeatureIndex,
  2006. NULL, // pbHonorConstraints
  2007. pbEnabledOptions,
  2008. 0, // dwOptSel
  2009. NULL) ) ;
  2010. }
  2011. #else
  2012. RIP(("GpdEnumEnabledOptions not implemented in Kernel Mode")) ;
  2013. return(FALSE);
  2014. #endif
  2015. }
  2016. BOOL
  2017. EnumOptionsUnconstrainedByPrinterSticky(
  2018. IN PRAWBINARYDATA pnRawData,
  2019. IN POPTSELECT pOptions,
  2020. IN DWORD dwFeatureIndex,
  2021. OUT PBOOL pbEnabledOptions
  2022. )
  2023. {
  2024. DWORD dwNumFeatures, dwFea, dwI, dwNumOpts, dwNEnabled, dwJ ;
  2025. PENHARRAYREF pearTableContents ;
  2026. PDFEATURE_OPTIONS pfo ;
  2027. // PMINIRAWBINARYDATA pmrbd ;
  2028. PBYTE pubRaw ; // raw binary data.
  2029. BOOL bStatus = FALSE ;
  2030. PBOOL pbUseConstrnt ;
  2031. PRAWBINARYDATA pRawData ;
  2032. PSTATICFIELDS pStatic ;
  2033. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  2034. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  2035. // to BUDDATA
  2036. pubRaw = (PBYTE)pRawData ;
  2037. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  2038. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  2039. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  2040. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  2041. dwNumFeatures = pearTableContents[MTI_DFEATURE_OPTIONS].dwCount ;
  2042. dwNumFeatures += pearTableContents[MTI_SYNTHESIZED_FEATURES].dwCount ;
  2043. pbUseConstrnt = (PBOOL)MemAlloc(dwNumFeatures * sizeof(BOOL) ) ;
  2044. if(!pbUseConstrnt)
  2045. {
  2046. ERR(("Fatal: EnumOptionsUnconstrainedByPrinterSticky - unable to alloc requested memory: %d bytes.\n",
  2047. dwNumFeatures * sizeof(BOOL)));
  2048. goto ABORTENUMOPTIONSUNCONSTRAINEDBYPRINTERSTICKY ;
  2049. }
  2050. for(dwI = 0 ; dwI < dwNumFeatures ; dwI++)
  2051. pbUseConstrnt[dwI] = FALSE ;
  2052. for(dwNEnabled = dwFea = 0 ; dwFea < dwNumFeatures ; dwFea++)
  2053. {
  2054. DWORD dwFeatureType = FT_PRINTERPROPERTY,
  2055. dwNextOpt, dwUnresolvedFeature ;
  2056. PATREEREF patrRoot ; // root of attribute tree to navigate.
  2057. // is this a printer or doc sticky feature?
  2058. patrRoot = &(pfo[dwFea].atrFeatureType) ;
  2059. dwNextOpt = 0 ; // extract info for first option selected for
  2060. // this feature.
  2061. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSFeatureTypeIndex,
  2062. (PBYTE)&dwFeatureType,
  2063. &dwUnresolvedFeature, *patrRoot, pOptions,
  2064. 0, // set to any value. Doesn't matter.
  2065. &dwNextOpt) != TRI_SUCCESS)
  2066. {
  2067. ERR(("ResolveUIConflicts: EextractValueFromTree failed.\n"));
  2068. bStatus = FALSE ;
  2069. goto ABORTENUMOPTIONSUNCONSTRAINEDBYPRINTERSTICKY ;
  2070. }
  2071. if(dwFeatureType == FT_PRINTERPROPERTY)
  2072. {
  2073. pbUseConstrnt[dwFea] = TRUE ;
  2074. dwNEnabled++ ;
  2075. }
  2076. }
  2077. if(!pbUseConstrnt[dwFeatureIndex]) // queried feature isn't PrinterSticky
  2078. {
  2079. pbUseConstrnt[dwFeatureIndex] = TRUE ;
  2080. dwNEnabled++ ;
  2081. }
  2082. if(dwNEnabled < 2)
  2083. {
  2084. dwNumOpts = pfo[dwFeatureIndex].dwNumOptions ;
  2085. for(dwJ = 0 ; dwJ < dwNumOpts ; dwJ++)
  2086. pbEnabledOptions[dwJ] = TRUE ;
  2087. bStatus = TRUE ; // not enough Features enabled
  2088. // to constrain each other.
  2089. }
  2090. else
  2091. {
  2092. bStatus = BSelectivelyEnumEnabledOptions(
  2093. pnRawData,
  2094. pOptions,
  2095. dwFeatureIndex,
  2096. pbUseConstrnt, // if non NULL
  2097. pbEnabledOptions,
  2098. 0,
  2099. NULL // pConflictPair
  2100. ) ;
  2101. }
  2102. ABORTENUMOPTIONSUNCONSTRAINEDBYPRINTERSTICKY:
  2103. if(pbUseConstrnt)
  2104. MemFree(pbUseConstrnt) ;
  2105. return(bStatus);
  2106. }
  2107. BOOL
  2108. EnumNewUIConflict(
  2109. IN PRAWBINARYDATA pnRawData,
  2110. IN POPTSELECT pOptions,
  2111. IN DWORD dwFeatureIndex,
  2112. IN PBOOL pbSelectedOptions,
  2113. OUT PCONFLICTPAIR pConflictPair
  2114. )
  2115. {
  2116. #ifndef KERNEL_MODE
  2117. BSelectivelyEnumEnabledOptions(
  2118. pnRawData,
  2119. pOptions,
  2120. dwFeatureIndex,
  2121. NULL,
  2122. pbSelectedOptions,
  2123. 0, // dwOptSel
  2124. pConflictPair ) ;
  2125. return (pConflictPair->dwFeatureIndex1 != 0xFFFFFFFF);
  2126. #else
  2127. RIP(("GpdEnumNewUIConflict not implemented in Kernel Mode")) ;
  2128. return(FALSE);
  2129. #endif
  2130. }
  2131. BOOL
  2132. EnumNewPickOneUIConflict(
  2133. IN PRAWBINARYDATA pnRawData,
  2134. IN POPTSELECT pOptions,
  2135. IN DWORD dwFeatureIndex,
  2136. IN DWORD dwOptionIndex,
  2137. OUT PCONFLICTPAIR pConflictPair
  2138. )
  2139. {
  2140. #ifndef KERNEL_MODE
  2141. BSelectivelyEnumEnabledOptions(
  2142. pnRawData,
  2143. pOptions,
  2144. dwFeatureIndex,
  2145. NULL,
  2146. NULL, // pbSelectedOptions
  2147. dwOptionIndex,
  2148. pConflictPair ) ;
  2149. return (pConflictPair->dwFeatureIndex1 != 0xFFFFFFFF);
  2150. #else
  2151. RIP(("GpdEnumNewPickOneUIConflict not implemented in Kernel Mode")) ;
  2152. return(FALSE);
  2153. #endif
  2154. }
  2155. BOOL
  2156. BIsFeaOptionCurSelected(
  2157. IN POPTSELECT pOptions,
  2158. IN DWORD dwFeatureIndex,
  2159. IN DWORD dwOptionIndex
  2160. )
  2161. /*
  2162. returns TRUE if the specified Feature/Option is
  2163. currently selected in pOptions. FALSE otherwise.
  2164. */
  2165. {
  2166. DWORD dwSrcTail ;
  2167. if(pOptions[dwFeatureIndex].ubCurOptIndex == dwOptionIndex)
  2168. return(TRUE);
  2169. dwSrcTail = pOptions[dwFeatureIndex].ubNext ;
  2170. while(dwSrcTail) // PickMany options
  2171. {
  2172. if(pOptions[dwSrcTail].ubCurOptIndex == dwOptionIndex)
  2173. return(TRUE);
  2174. dwSrcTail = pOptions[dwSrcTail].ubNext ;
  2175. }
  2176. return(FALSE);
  2177. }
  2178. BOOL
  2179. BSelectivelyEnumEnabledOptions(
  2180. IN PRAWBINARYDATA pnRawData,
  2181. IN POPTSELECT pOptions,
  2182. IN DWORD dwFeatureIndex,
  2183. IN PBOOL pbHonorConstraints, // if non NULL
  2184. // points to array of BOOL corresponding to each feature.
  2185. // if TRUE means constraint involving this feature is
  2186. // to be honored. Otherwise ignore the constraint.
  2187. OUT PBOOL pbEnabledOptions, // assume uninitialized
  2188. // if pConflictPair is NULL else contains current or proposed
  2189. // selections. We will leave this array unchanged in this case.
  2190. IN DWORD dwOptSel, // if pConflictPair exists but pbEnabledOptions
  2191. // is NULL, assume pickone and dwOptSel holds that selection for
  2192. // the feature: dwFeatureIndex.
  2193. OUT PCONFLICTPAIR pConflictPair // if present, pbEnabledOptions
  2194. // actually lists the current selections. Function then
  2195. // exits after encountering the first conflict.
  2196. // if a conflict exists, all fields in pConflictPair
  2197. // will be properly initialized else dwFeatureIndex1 = -1
  2198. // the return value will be TRUE regardless.
  2199. )
  2200. /*
  2201. return value is FALSE if every option for this
  2202. feature is constrained or other abnormal condition
  2203. was encountered.
  2204. */
  2205. {
  2206. PDFEATURE_OPTIONS pfo ;
  2207. PBYTE pubHeap , // start of string heap.
  2208. pubRaw ; // raw binary data.
  2209. PENHARRAYREF pearTableContents ;
  2210. DWORD dwI, dwNumFea , dwNumOpts, dwFea, dwSrcTail, dwNodeIndex,
  2211. dwCFeature, dwCOption ,
  2212. dwCNode, dwICNode, dwNextInvCombo;
  2213. BOOL bStatus, bConstrained, bNextLinkFound ;
  2214. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  2215. PATREEREF patrRoot ; // root of attribute tree to navigate.
  2216. PCONSTRAINTS pcnstr ; // root of Constraint nodes
  2217. PINVALIDCOMBO pinvc ; // root of invalid combo nodes
  2218. PRAWBINARYDATA pRawData ;
  2219. PSTATICFIELDS pStatic ;
  2220. BOOL pbNewEnabledOptions[MAX_COMBINED_OPTIONS] ;
  2221. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  2222. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  2223. // to BUDDATA
  2224. pubRaw = (PBYTE)pRawData ;
  2225. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  2226. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  2227. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  2228. patt = (PATTRIB_TREE)(pubRaw +
  2229. pearTableContents[MTI_ATTRIBTREE].loOffset) ;
  2230. pcnstr = (PCONSTRAINTS) (pubRaw +
  2231. pearTableContents[MTI_CONSTRAINTS].loOffset) ;
  2232. pinvc = (PINVALIDCOMBO) (pubRaw +
  2233. pearTableContents[MTI_INVALIDCOMBO].loOffset) ;
  2234. pubHeap = (PBYTE)(pubRaw + pearTableContents[MTI_STRINGHEAP].
  2235. loOffset) ;
  2236. dwNumFea = pRawData->dwDocumentFeatures +
  2237. pRawData->dwPrinterFeatures ;
  2238. dwNumOpts = pfo[dwFeatureIndex].dwNumOptions ;
  2239. if(pConflictPair)
  2240. {
  2241. pConflictPair->dwFeatureIndex1 = dwFeatureIndex ;
  2242. pConflictPair->dwFeatureIndex2 = 0xFFFFFFFF;
  2243. // Gets set to indicate we have a constraint.
  2244. // leave pbEnabledOptions as is. These are
  2245. // the options currently selected for this feature.
  2246. #if 0
  2247. if(!(pbNewEnabledOptions = (PBOOL)MemAlloc(dwNumOpts * sizeof(BOOL) ) ))
  2248. {
  2249. ERR(("Fatal: BSelectivelyEnumEnabledOptions - unable to alloc %d bytes.\n",
  2250. dwNumOpts * sizeof(BOOL) ));
  2251. return(FALSE) ;
  2252. }
  2253. #endif
  2254. if(pbEnabledOptions)
  2255. {
  2256. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  2257. pbNewEnabledOptions[dwI] = pbEnabledOptions[dwI] ;
  2258. }
  2259. else
  2260. {
  2261. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  2262. pbNewEnabledOptions[dwI] = FALSE ;
  2263. pbNewEnabledOptions[dwOptSel] = TRUE ;
  2264. }
  2265. pbEnabledOptions = pbNewEnabledOptions ; // forget the original.
  2266. }
  2267. else
  2268. {
  2269. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  2270. pbEnabledOptions[dwI] = TRUE ;
  2271. }
  2272. if(!pbEnabledOptions)
  2273. {
  2274. RIP(("BSelectivelyEnumEnabledOptions: pbEnabledOptions is NULL")) ;
  2275. return(FALSE);
  2276. }
  2277. for(dwFea = 0 ; dwFea < dwNumFea ; dwFea++)
  2278. {
  2279. if(dwFea == dwFeatureIndex)
  2280. continue ;
  2281. if(pbHonorConstraints && !pbHonorConstraints[dwFea])
  2282. continue ;
  2283. bStatus = BEnumImposedConstraintsOnFeature(pnRawData, dwFeatureIndex,
  2284. dwFea, pOptions[dwFea].ubCurOptIndex, pbEnabledOptions, pConflictPair) ;
  2285. if(pConflictPair && pConflictPair->dwFeatureIndex2 != 0xFFFFFFFF)
  2286. {
  2287. // MemFree(pbEnabledOptions) ;
  2288. return(TRUE) ; // Meaningless return value.
  2289. }
  2290. dwSrcTail = pOptions[dwFea].ubNext ;
  2291. while(dwSrcTail) // PickMany options
  2292. {
  2293. if(!BEnumImposedConstraintsOnFeature(pnRawData, dwFeatureIndex,
  2294. dwFea, pOptions[dwSrcTail].ubCurOptIndex, pbEnabledOptions,
  2295. pConflictPair) )
  2296. bStatus = FALSE;
  2297. if(pConflictPair && pConflictPair->dwFeatureIndex2 != 0xFFFFFFFF)
  2298. {
  2299. // MemFree(pbEnabledOptions) ;
  2300. return(TRUE) ; // Meaningless return value.
  2301. }
  2302. dwSrcTail = pOptions[dwSrcTail].ubNext ;
  2303. }
  2304. }
  2305. patrRoot = &(pfo[dwFeatureIndex].atrConstraints) ;
  2306. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  2307. {
  2308. if(!pbEnabledOptions[dwI])
  2309. continue ;
  2310. dwNodeIndex = DwFindNodeInCurLevel(patt , patrRoot , dwI) ;
  2311. if(dwNodeIndex == INVALID_INDEX)
  2312. continue ; // this option has no constraints
  2313. if(patt[dwNodeIndex].eOffsetMeans != VALUE_AT_HEAP)
  2314. {
  2315. ERR(("Internal error. BSelectivelyEnumEnabledOptions - Unexpected Sublevel found for atrConstraints.\n"));
  2316. continue ; // skip this anomaly
  2317. }
  2318. dwCNode = *(PDWORD)(pubHeap + patt[dwNodeIndex].dwOffset) ;
  2319. if(BIsConstraintActive(pcnstr , dwCNode, pbHonorConstraints, pOptions, pConflictPair) )
  2320. {
  2321. pbEnabledOptions[dwI] = FALSE ;
  2322. if(pConflictPair)
  2323. {
  2324. // MemFree(pbEnabledOptions) ;
  2325. pConflictPair->dwOptionIndex1 = dwI ;
  2326. return(TRUE) ; // Meaningless return value.
  2327. }
  2328. }
  2329. }
  2330. // lastly must walk InvalidCombos for each option of dwFeatureIndex
  2331. // and mark pbEnabledOptions accordingly.
  2332. patrRoot = &(pfo[dwFeatureIndex].atrInvalidCombos) ;
  2333. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  2334. {
  2335. if(!pbEnabledOptions[dwI])
  2336. continue ;
  2337. dwNodeIndex = DwFindNodeInCurLevel(patt , patrRoot , dwI) ;
  2338. if(dwNodeIndex == INVALID_INDEX)
  2339. continue ; // this option has no invalid combos
  2340. if(patt[dwNodeIndex].eOffsetMeans != VALUE_AT_HEAP)
  2341. {
  2342. ERR(("Internal error. BSelectivelyEnumEnabledOptions - Unexpected Sublevel found for atrInvalidCombos.\n"));
  2343. continue ; // skip this anomaly
  2344. }
  2345. dwICNode = patt[dwNodeIndex].dwOffset ;
  2346. while(dwICNode != END_OF_LIST)
  2347. // search through each applicable invalid combo
  2348. {
  2349. dwNextInvCombo = END_OF_LIST ; // fail safe - stop
  2350. // search in the event this invalid combo doesn't
  2351. // contain dwFeatureIndex/dwI
  2352. bConstrained = TRUE ; // Assume true initially
  2353. bNextLinkFound = FALSE ;
  2354. while(dwICNode != END_OF_LIST)
  2355. // for each element comprising the invalid combo
  2356. {
  2357. if(!bNextLinkFound &&
  2358. pinvc[dwICNode].dwFeature == dwFeatureIndex &&
  2359. (pinvc[dwICNode].dwOption == dwI ||
  2360. (WORD)pinvc[dwICNode].dwOption == (WORD)DEFAULT_INIT))
  2361. {
  2362. dwNextInvCombo = pinvc[dwICNode].dwNewCombo ;
  2363. bNextLinkFound = TRUE ;
  2364. // we are just asking if this option was selected
  2365. // will it trigger an invalid combo?
  2366. // this means currently this option is not selected
  2367. // but we want to pretend for the purposes of
  2368. // evaluating invalid combos that it is.
  2369. // this is why an else if() statement follows.
  2370. }
  2371. else if(bConstrained && ((pbHonorConstraints &&
  2372. !pbHonorConstraints[pinvc[dwICNode].dwFeature])
  2373. || !BIsFeaOptionCurSelected(pOptions,
  2374. pinvc[dwICNode].dwFeature,
  2375. pinvc[dwICNode].dwOption) ) )
  2376. {
  2377. bConstrained = FALSE ;
  2378. }
  2379. else if(pConflictPair)
  2380. {
  2381. // need to remember one of the constrainers
  2382. // so we can emit a warning message.
  2383. dwCFeature = pinvc[dwICNode].dwFeature ;
  2384. dwCOption = pinvc[dwICNode].dwOption ;
  2385. }
  2386. if(!bConstrained && bNextLinkFound)
  2387. break ; // no need to keep traversing elements
  2388. // in this invalid combo.
  2389. dwICNode = pinvc[dwICNode].dwNextElement ;
  2390. }
  2391. if(bConstrained)
  2392. {
  2393. pbEnabledOptions[dwI] = FALSE ;
  2394. if(pConflictPair)
  2395. {
  2396. pConflictPair->dwOptionIndex1 = dwI ;
  2397. pConflictPair->dwFeatureIndex2 = dwCFeature ;
  2398. pConflictPair->dwOptionIndex2 = dwCOption ;
  2399. // MemFree(pbEnabledOptions) ;
  2400. return(TRUE) ; // Meaningless return value.
  2401. }
  2402. break ; // no need to see if any other invalid
  2403. // combos apply. One is enough.
  2404. }
  2405. dwICNode = dwNextInvCombo ;
  2406. }
  2407. }
  2408. if(pConflictPair)
  2409. {
  2410. pConflictPair->dwFeatureIndex1 = 0xFFFFFFFF ;
  2411. // no constraints found.
  2412. // MemFree(pbEnabledOptions) ;
  2413. return(TRUE) ; // Meaningless return value.
  2414. }
  2415. for(dwI = 0 ; dwI < dwNumOpts ; dwI++)
  2416. {
  2417. if(pbEnabledOptions[dwI])
  2418. break ;
  2419. }
  2420. if(dwI >= dwNumOpts)
  2421. bStatus = FALSE ; // Feature is disabled.
  2422. return(bStatus) ;
  2423. }
  2424. BOOL
  2425. BEnumImposedConstraintsOnFeature
  2426. (
  2427. IN PRAWBINARYDATA pnRawData,
  2428. IN DWORD dwTgtFeature,
  2429. IN DWORD dwFeature2,
  2430. IN DWORD dwOption2,
  2431. OUT PBOOL pbEnabledOptions,
  2432. OUT PCONFLICTPAIR pConflictPair // if present, pbEnabledOptions
  2433. )
  2434. /*
  2435. This function only searches for the unidirctional
  2436. constraints found at dwFeature2, dwOption2 and
  2437. records their effect on the options of feature1 by
  2438. setting to FALSE the BOOL element in pbEnabledOptions
  2439. corresponding to the option disabled.
  2440. (ANDing mask)
  2441. Assumes: pbEnabledOptions is properly initialized to all
  2442. TRUE (or was that way at some point.) This function never
  2443. sets any elements TRUE. Only sets some elements FALSE.
  2444. */
  2445. {
  2446. PENHARRAYREF pearTableContents ;
  2447. PDFEATURE_OPTIONS pfo ;
  2448. // PMINIRAWBINARYDATA pmrbd ;
  2449. PBYTE pubHeap , // start of string heap.
  2450. pubRaw ; // raw binary data.
  2451. DWORD dwNodeIndex ,
  2452. dwCNode ; // index to a Constraint node
  2453. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  2454. PATREEREF patrRoot ; // root of attribute tree to navigate.
  2455. // PINVALIDCOMBO pinvc ; // root of invalid combo nodes
  2456. PCONSTRAINTS pcnstr ; // root of Constraint nodes
  2457. PRAWBINARYDATA pRawData ;
  2458. PSTATICFIELDS pStatic ;
  2459. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  2460. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  2461. // to BUDDATA
  2462. pubRaw = (PBYTE)pRawData ;
  2463. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  2464. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  2465. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  2466. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  2467. patt = (PATTRIB_TREE)(pubRaw +
  2468. pearTableContents[MTI_ATTRIBTREE].loOffset) ;
  2469. // pinvc = (PINVALIDCOMBO) (pubRaw +
  2470. // pearTableContents[MTI_INVALIDCOMBO].loOffset) ;
  2471. pcnstr = (PCONSTRAINTS) (pubRaw +
  2472. pearTableContents[MTI_CONSTRAINTS].loOffset) ;
  2473. pubHeap = (PBYTE)(pubRaw + pearTableContents[MTI_STRINGHEAP].
  2474. loOffset) ;
  2475. patrRoot = &(pfo[dwFeature2].atrConstraints) ;
  2476. dwNodeIndex = DwFindNodeInCurLevel(patt , patrRoot , dwOption2) ;
  2477. if(dwNodeIndex == INVALID_INDEX)
  2478. return(TRUE) ; // no imposed constraints found
  2479. if(patt[dwNodeIndex].eOffsetMeans != VALUE_AT_HEAP)
  2480. {
  2481. ERR(("Internal error. BEnumImposedConstraintsOnFeature - Unexpected Sublevel found for atrConstraints.\n"));
  2482. return(FALSE) ;
  2483. }
  2484. dwCNode = *(PDWORD)(pubHeap + patt[dwNodeIndex].dwOffset) ;
  2485. while(1)
  2486. {
  2487. if(pcnstr[dwCNode].dwFeature == dwTgtFeature &&
  2488. pbEnabledOptions[pcnstr[dwCNode].dwOption] == TRUE )
  2489. {
  2490. pbEnabledOptions[pcnstr[dwCNode].dwOption] = FALSE ;
  2491. // this option in dwTgtFeature is constrained.
  2492. if(pConflictPair)
  2493. {
  2494. pConflictPair->dwOptionIndex1 = pcnstr[dwCNode].dwOption ;
  2495. pConflictPair->dwFeatureIndex2 = dwFeature2 ;
  2496. pConflictPair->dwOptionIndex2 = dwOption2 ;
  2497. return(TRUE) ; // Meaningless return value.
  2498. }
  2499. }
  2500. dwCNode = pcnstr[dwCNode].dwNextCnstrnt ;
  2501. if(dwCNode == END_OF_LIST)
  2502. break ;
  2503. }
  2504. return(TRUE) ; // nothing bad happened.
  2505. }
  2506. DWORD DwFindNodeInCurLevel(
  2507. PATTRIB_TREE patt , // start of ATTRIBUTE tree array.
  2508. PATREEREF patr , // index to a level in the attribute tree.
  2509. DWORD dwOption // search current level for this option
  2510. )
  2511. /*
  2512. this function returns the node index to the node containing
  2513. the specified dwOption in the selected level of the tree.
  2514. If the specified option branch does not exist, the function returns
  2515. INVALID_INDEX.
  2516. Assumes caller has verified dwFeature matches.
  2517. */
  2518. {
  2519. DWORD dwNodeIndex ;
  2520. if(*patr == ATTRIB_UNINITIALIZED)
  2521. return(INVALID_INDEX) ;
  2522. if(*patr & ATTRIB_HEAP_VALUE)
  2523. {
  2524. ERR(("Internal error. DwFindNodeInCurLevel - Unexpected branchless node found.\n"));
  2525. return(INVALID_INDEX) ;
  2526. }
  2527. // search for matching option.
  2528. dwNodeIndex = *patr ;
  2529. while(1)
  2530. {
  2531. if(patt[dwNodeIndex].dwOption == dwOption )
  2532. {
  2533. // we found it!
  2534. return(dwNodeIndex) ;
  2535. }
  2536. if(patt[dwNodeIndex].dwNext == END_OF_LIST)
  2537. break ;
  2538. dwNodeIndex = patt[dwNodeIndex].dwNext ;
  2539. }
  2540. return(INVALID_INDEX) ;
  2541. }
  2542. BOOL BIsConstraintActive(
  2543. IN PCONSTRAINTS pcnstr , // root of Constraint nodes
  2544. IN DWORD dwCNode, // first constraint node in list.
  2545. IN PBOOL pbHonorConstraints, // if non NULL
  2546. IN POPTSELECT pOptions,
  2547. OUT PCONFLICTPAIR pConflictPair )
  2548. /*
  2549. This function walks the list of constraint nodes
  2550. starting at dwNodeIndex and checks to see if the
  2551. Feature/Option specified within is in fact currently
  2552. selected in pOptions. If yes, immediately return true.
  2553. If not, go to the next node in the list and repeat.
  2554. */
  2555. {
  2556. while(1)
  2557. {
  2558. if(!pbHonorConstraints || pbHonorConstraints[pcnstr[dwCNode].dwFeature])
  2559. {
  2560. if(BIsFeaOptionCurSelected(pOptions,
  2561. pcnstr[dwCNode].dwFeature,
  2562. pcnstr[dwCNode].dwOption) )
  2563. {
  2564. if(pConflictPair)
  2565. {
  2566. pConflictPair->dwFeatureIndex2 = pcnstr[dwCNode].dwFeature;
  2567. pConflictPair->dwOptionIndex2 = pcnstr[dwCNode].dwOption ;
  2568. }
  2569. return(TRUE) ; // a constraint does exist.
  2570. }
  2571. }
  2572. dwCNode = pcnstr[dwCNode].dwNextCnstrnt ;
  2573. if(dwCNode == END_OF_LIST)
  2574. break ;
  2575. }
  2576. return(FALSE);
  2577. }
  2578. #ifdef GMACROS
  2579. // note: must precede calls to ResolveUIConflict
  2580. // with a call to ResolveDependentSettings
  2581. BOOL
  2582. ResolveDependentSettings(
  2583. IN PRAWBINARYDATA pnRawData,
  2584. IN OUT POPTSELECT pOptions,
  2585. IN INT iMaxOptions
  2586. )
  2587. // Note this function does handle multiple selections
  2588. // it will treat them as additional links in the chain.
  2589. {
  2590. PRAWBINARYDATA pRawData ;
  2591. PSTATICFIELDS pStatic ;
  2592. PBYTE pubRaw ; // raw binary data.
  2593. PLISTNODE plstRoot ; // start of LIST array
  2594. DWORD dwListsRoot, dwListIndex; // Root of the chain
  2595. DWORD dwNumFeatures, dwI, dwJ, dwFea, dwNodeIndex,
  2596. dwFeature, dwOption ;
  2597. PENHARRAYREF pearTableContents ;
  2598. PDFEATURE_OPTIONS pfo ;
  2599. PDWORD pdwPriority ;
  2600. PQUALNAME pqn ; // the dword in the list node is actually a
  2601. // qualified name structure.
  2602. INT iOptionsNeeded;
  2603. PBOOL pbOneShotFlag, pbSelectedOptions ;
  2604. BOOL bMatchFound ; // a DependentSettings matches the current config.
  2605. POPTSELECT pDestOptions ;
  2606. BOOL bStatus = TRUE ;
  2607. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  2608. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  2609. // to BUDDATA
  2610. pubRaw = (PBYTE)pRawData ;
  2611. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  2612. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  2613. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  2614. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  2615. pdwPriority = (PDWORD)(pubRaw +
  2616. pearTableContents[MTI_PRIORITYARRAY].loOffset) ;
  2617. plstRoot = (PLISTNODE)(pubRaw + pearTableContents[MTI_LISTNODES].
  2618. loOffset) ;
  2619. dwNumFeatures = pearTableContents[MTI_DFEATURE_OPTIONS].dwCount ;
  2620. dwNumFeatures += pearTableContents[MTI_SYNTHESIZED_FEATURES].dwCount ;
  2621. if(dwNumFeatures > (DWORD)iMaxOptions)
  2622. {
  2623. iOptionsNeeded = dwNumFeatures ;
  2624. return(FALSE); // too many to save in option array.
  2625. }
  2626. pbOneShotFlag = (PBOOL)MemAlloc(dwNumFeatures * sizeof(BOOL) ) ;
  2627. pbSelectedOptions = (PBOOL)MemAlloc(iMaxOptions * sizeof(BOOL) ) ;
  2628. // iMaxOptions must be greater than the max number of options availible for
  2629. // any feature.
  2630. // to extend to pickmany, have a dest optionarray.
  2631. // each time the source optionarray completely contains
  2632. // a DependentSettings list (in that each Fea.Option
  2633. // listed as a DependentSetting is also selected in the
  2634. // source option array) we turn on those Fea.Options
  2635. // in the dest option array. After all DependentSettings
  2636. // lists for that feature have been processed, we set
  2637. // the OneShotFlag for each Feature that has been affected
  2638. // in the dest option array. For each such feature we will
  2639. // let the dest option array determine the setting of the
  2640. // source option array.
  2641. // this code does not verify that a Feature is pickmany
  2642. // before treating it as pickmany. If the source option
  2643. // array has more than one option selected for a feature,
  2644. // that feature is automatically treated as a pickmany.
  2645. pDestOptions = (POPTSELECT)MemAlloc(iMaxOptions * sizeof(OPTSELECT) ) ;
  2646. // 'or' all acceptable DependentSettings here.
  2647. if(!(pbOneShotFlag && pDestOptions && pbSelectedOptions))
  2648. {
  2649. ERR(("Fatal: ResolveDependentSettings - unable to alloc requested memory: %d bytes.\n",
  2650. dwNumFeatures * sizeof(BOOL)));
  2651. bStatus = FALSE ;
  2652. goto ABORTRESOLVEDEPENDENTSETTINGS ;
  2653. }
  2654. for(dwI = 0 ; dwI < dwNumFeatures ; dwI++)
  2655. pbOneShotFlag[dwI] = FALSE ;
  2656. // this boolean array tracks if the feature has been
  2657. // referenced in a DependentSettings entry.
  2658. // If a feature is referenced again in DependentSettings
  2659. // entry belonging to another feature, the subsequent
  2660. // references will be ignored. This ensures only the
  2661. // highest priority Feature's request shall have precedence.
  2662. for(dwI = 0 ; dwI < dwNumFeatures ; dwI++)
  2663. {
  2664. DWORD dwNextOpt, dwListsRootOpt1 ;
  2665. // The order of evaluation is determined
  2666. // by the priority array.
  2667. dwFea = pdwPriority[dwI] ;
  2668. pbOneShotFlag[dwFea] = TRUE ;
  2669. dwNextOpt = 0 ; // extract info for first option selected for
  2670. // this feature.
  2671. dwListsRootOpt1 = END_OF_LIST ; // list for the 1st selected
  2672. // option of a pickmany feature.
  2673. for( dwJ = 0 ; dwJ < dwNumFeatures ; dwJ++)
  2674. {
  2675. pDestOptions[dwJ].ubCurOptIndex = OPTION_INDEX_ANY ;
  2676. pDestOptions[dwJ].ubNext = 0 ; // eol
  2677. // DestOptions is now blank.
  2678. }
  2679. bMatchFound = FALSE ;
  2680. do
  2681. { // for each option selected in a pick many feature
  2682. // treat associated DepSettings same as more than
  2683. // one DepSettings entry defined for one feature.
  2684. {
  2685. DWORD dwUnresolvedFeature ;
  2686. PATREEREF patrRoot ; // root of attribute tree to navigate.
  2687. patrRoot = &(pfo[dwFea].atrDependentSettings) ;
  2688. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSDepSettingsIndex,
  2689. (PBYTE)&dwListsRoot,
  2690. &dwUnresolvedFeature, *patrRoot, pOptions,
  2691. dwFea,
  2692. &dwNextOpt) != TRI_SUCCESS)
  2693. {
  2694. goto END_OF_FOR_LOOP ; // no DependentSettings to apply.
  2695. }
  2696. if(dwListsRoot == END_OF_LIST)
  2697. continue; // maybe another option does have a list.
  2698. }
  2699. if(dwListsRootOpt1 == END_OF_LIST) // first time thru do loop?
  2700. dwListsRootOpt1 = dwListsRoot ;
  2701. // now we need to see if the current pOption matches any
  2702. // of the lists accessed using dwListsRoot.
  2703. for(dwListIndex = dwListsRoot ;
  2704. dwListIndex != END_OF_LIST ;
  2705. dwListIndex = plstRoot[dwListIndex].dwNextItem )
  2706. {
  2707. // for each DepSettings list....
  2708. // now walk that DepSettings list at dwListIndex and compare
  2709. // to current settings at pOptions. If there is a match, use
  2710. // depSettings list to OR on options in pDestOptions.
  2711. // Note: Features with their one-shot flag set cannot be
  2712. // considered. They will be ignored.
  2713. BOOL bActiveMatch = FALSE, // requires an actual match
  2714. bOptionArrayMatchesDepSettings = TRUE ; // assume true
  2715. // until proven otherwise.
  2716. for(dwNodeIndex = plstRoot[dwListIndex].dwData ; dwNodeIndex != END_OF_LIST ;
  2717. dwNodeIndex = plstRoot[dwNodeIndex].dwNextItem)
  2718. {
  2719. pqn = (PQUALNAME)(&plstRoot[dwNodeIndex].dwData) ;
  2720. dwFeature = pqn->wFeatureID ;
  2721. dwOption = pqn->wOptionID ;
  2722. if(pbOneShotFlag[dwFeature] == TRUE)
  2723. continue;
  2724. if(!BIsFeaOptionCurSelected(pOptions, dwFeature, dwOption) )
  2725. {
  2726. bOptionArrayMatchesDepSettings = FALSE ;
  2727. break;
  2728. }
  2729. else
  2730. bActiveMatch = TRUE;
  2731. }
  2732. if(bOptionArrayMatchesDepSettings && bActiveMatch)
  2733. // at least one DepSetting was honored.
  2734. {
  2735. // 'or' DepSettings into DestOptions
  2736. for(dwNodeIndex = plstRoot[dwListIndex].dwData ; dwNodeIndex != END_OF_LIST ;
  2737. dwNodeIndex = plstRoot[dwNodeIndex].dwNextItem)
  2738. {
  2739. pqn = (PQUALNAME)(&plstRoot[dwNodeIndex].dwData) ;
  2740. dwFeature = pqn->wFeatureID ;
  2741. dwOption = pqn->wOptionID ;
  2742. if(pbOneShotFlag[dwFeature] == TRUE)
  2743. continue;
  2744. // select dwOption in DestOptions in addition to any other options
  2745. // already selected.
  2746. EnumSelectedOptions(pnRawData, pDestOptions, dwFeature,
  2747. pbSelectedOptions) ;
  2748. if(!pbSelectedOptions[dwOption]) // the option that should be selected isn't.
  2749. { // so let's turn it on.
  2750. pbSelectedOptions[dwOption] = TRUE ; // This is the ORing process.
  2751. ReconstructOptionArray( pnRawData, pDestOptions, iMaxOptions,
  2752. dwFeature, pbSelectedOptions ) ;
  2753. bMatchFound = TRUE ; // there really is something to set.
  2754. }
  2755. }
  2756. }
  2757. }
  2758. } while (dwNextOpt);
  2759. if (dwListsRootOpt1 == END_OF_LIST)
  2760. continue; // you cannot set anything if there is no list to use.
  2761. if (!bMatchFound)
  2762. {
  2763. // set dest Option array according to depSettings(dwListsRoot)
  2764. for(dwNodeIndex = plstRoot[dwListsRootOpt1].dwData ; dwNodeIndex != END_OF_LIST ;
  2765. dwNodeIndex = plstRoot[dwNodeIndex].dwNextItem)
  2766. {
  2767. pqn = (PQUALNAME)(&plstRoot[dwNodeIndex].dwData) ;
  2768. dwFeature = pqn->wFeatureID ;
  2769. dwOption = pqn->wOptionID ;
  2770. if(pbOneShotFlag[dwFeature] == TRUE)
  2771. continue;
  2772. pDestOptions[dwFeature].ubCurOptIndex = (BYTE)dwOption ;
  2773. }
  2774. }
  2775. // propagate Dest option array settings to pOptions
  2776. // note which features got set and set their one-shot
  2777. // flag.
  2778. for( dwFeature = 0 ; dwFeature < dwNumFeatures ; dwFeature++)
  2779. {
  2780. if(pDestOptions[dwFeature].ubCurOptIndex == OPTION_INDEX_ANY)
  2781. continue;
  2782. EnumSelectedOptions( pnRawData, pDestOptions,
  2783. dwFeature, pbSelectedOptions) ;
  2784. ReconstructOptionArray( pnRawData, pOptions, iMaxOptions,
  2785. dwFeature, pbSelectedOptions ) ;
  2786. pbOneShotFlag[dwFeature] = TRUE ;
  2787. }
  2788. END_OF_FOR_LOOP:
  2789. ; // dummy statement after every label.
  2790. } // end for loop. for each Feature in order of priority.
  2791. ABORTRESOLVEDEPENDENTSETTINGS:
  2792. if(pbOneShotFlag)
  2793. MemFree(pbOneShotFlag);
  2794. if(pDestOptions)
  2795. MemFree(pDestOptions);
  2796. if(pbSelectedOptions)
  2797. MemFree(pbSelectedOptions);
  2798. return(bStatus);
  2799. }
  2800. void EnumSelectedOptions(
  2801. IN PRAWBINARYDATA pnRawData,
  2802. IN OUT POPTSELECT pOptions,
  2803. IN DWORD dwFeature,
  2804. IN PBOOL pbSelectedOptions)
  2805. {
  2806. PENHARRAYREF pearTableContents ;
  2807. PDFEATURE_OPTIONS pfo ;
  2808. PBYTE pubRaw ; // raw binary data.
  2809. PRAWBINARYDATA pRawData ;
  2810. PSTATICFIELDS pStatic ;
  2811. DWORD dwNumOptions, dwI, dwOption, dwNextOpt ;
  2812. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  2813. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  2814. // to BUDDATA
  2815. pubRaw = (PBYTE)pRawData ;
  2816. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  2817. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  2818. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  2819. dwNumOptions = pfo[dwFeature].dwNumOptions ;
  2820. for( dwI = 0 ; dwI < dwNumOptions ; dwI++)
  2821. pbSelectedOptions[dwI] = FALSE ;
  2822. if((dwOption = pOptions[dwFeature].ubCurOptIndex) == OPTION_INDEX_ANY)
  2823. return;
  2824. pbSelectedOptions[dwOption] = TRUE ;
  2825. dwNextOpt = dwFeature ; // case of pick many
  2826. while(dwNextOpt = pOptions[dwNextOpt].ubNext)
  2827. {
  2828. pbSelectedOptions[pOptions[dwNextOpt].ubCurOptIndex] = TRUE ;
  2829. }
  2830. return;
  2831. }
  2832. BOOL
  2833. ExecuteMacro(
  2834. IN PRAWBINARYDATA pnRawData,
  2835. IN OUT POPTSELECT pOptions,
  2836. IN INT iMaxOptions,
  2837. IN DWORD dwFea, // what feature was selected in UI
  2838. IN DWORD dwOpt , // what option was selected in UI
  2839. OUT PBOOL pbFeaturesChanged // tell Amanda what Features were changed.
  2840. )
  2841. // does this for one feature and one option only!
  2842. {
  2843. PRAWBINARYDATA pRawData ;
  2844. PSTATICFIELDS pStatic ;
  2845. PBYTE pubRaw ; // raw binary data.
  2846. PLISTNODE plstRoot ; // start of LIST array
  2847. DWORD dwListsRoot, dwListIndex; // Root of the chain
  2848. DWORD dwNumFeatures, dwI, dwJ, dwNodeIndex,
  2849. dwFeature, dwOption ;
  2850. PENHARRAYREF pearTableContents ;
  2851. PDFEATURE_OPTIONS pfo ;
  2852. PDWORD pdwPriority ;
  2853. PQUALNAME pqn ; // the dword in the list node is actually a
  2854. // qualified name structure.
  2855. INT iOptionsNeeded;
  2856. PBOOL pbOneShotFlag, pbSelectedOptions ;
  2857. BOOL bHigherPri, // divides features into two groups those with higher priority
  2858. // than dwFea, and those with lower priority.
  2859. // the Macro cannot change Features with higher priority.
  2860. bMatchFound ; // a DependentSettings matches the current config.
  2861. POPTSELECT pDestOptions ;
  2862. BOOL bStatus = TRUE ;
  2863. pStatic = (PSTATICFIELDS)pnRawData ; // transform pubRaw from PSTATIC
  2864. pRawData = (PRAWBINARYDATA)pStatic->pubBUDData ;
  2865. // to BUDDATA
  2866. pubRaw = (PBYTE)pRawData ;
  2867. // pmrbd = (PMINIRAWBINARYDATA)pubRaw ;
  2868. pearTableContents = (PENHARRAYREF)(pubRaw + sizeof(MINIRAWBINARYDATA)) ;
  2869. pfo = (PDFEATURE_OPTIONS)(pubRaw +
  2870. pearTableContents[MTI_DFEATURE_OPTIONS].loOffset) ;
  2871. pdwPriority = (PDWORD)(pubRaw +
  2872. pearTableContents[MTI_PRIORITYARRAY].loOffset) ;
  2873. plstRoot = (PLISTNODE)(pubRaw + pearTableContents[MTI_LISTNODES].
  2874. loOffset) ;
  2875. dwNumFeatures = pearTableContents[MTI_DFEATURE_OPTIONS].dwCount ;
  2876. dwNumFeatures += pearTableContents[MTI_SYNTHESIZED_FEATURES].dwCount ;
  2877. if(dwNumFeatures > (DWORD)iMaxOptions)
  2878. {
  2879. iOptionsNeeded = dwNumFeatures ;
  2880. return(FALSE); // too many to save in option array.
  2881. }
  2882. pbOneShotFlag = (PBOOL)MemAlloc(dwNumFeatures * sizeof(BOOL) ) ;
  2883. pbSelectedOptions = (PBOOL)MemAlloc(iMaxOptions * sizeof(BOOL) ) ;
  2884. // iMaxOptions must be greater than the max number of options availible for
  2885. // any feature.
  2886. // to extend to pickmany, have a dest optionarray.
  2887. // each time the source optionarray completely contains
  2888. // a DependentSettings list (in that each Fea.Option
  2889. // listed as a DependentSetting is also selected in the
  2890. // source option array) we turn on those Fea.Options
  2891. // in the dest option array. After all DependentSettings
  2892. // lists for that feature have been processed, we set
  2893. // the OneShotFlag for each Feature that has been affected
  2894. // in the dest option array. For each such feature we will
  2895. // let the dest option array determine the setting of the
  2896. // source option array.
  2897. // this code does not verify that a Feature is pickmany
  2898. // before treating it as pickmany. If the source option
  2899. // array has more than one option selected for a feature,
  2900. // that feature is automatically treated as a pickmany.
  2901. pDestOptions = (POPTSELECT)MemAlloc(iMaxOptions * sizeof(OPTSELECT) ) ;
  2902. // 'or' all acceptable DependentSettings here.
  2903. if(!(pbOneShotFlag && pDestOptions && pbSelectedOptions))
  2904. {
  2905. ERR(("Fatal: ResolveDependentSettings - unable to alloc requested memory: %d bytes.\n",
  2906. dwNumFeatures * sizeof(BOOL)));
  2907. bStatus = FALSE ;
  2908. goto ABORTEXECUTEMACROS ;
  2909. }
  2910. for(bHigherPri = TRUE, dwI = 0 ; dwI < dwNumFeatures ; dwI++)
  2911. {
  2912. pbFeaturesChanged[dwI] = FALSE ; // start with no Features changed
  2913. pbOneShotFlag[pdwPriority[dwI]] = bHigherPri ;
  2914. if(pdwPriority[dwI] == dwFea)
  2915. bHigherPri = FALSE ; // all remaining features are of lower priority
  2916. // and therefore susceptible to getting changed by the macro.
  2917. }
  2918. // this boolean array tracks if the feature has been
  2919. // referenced in a DependentSettings entry.
  2920. // If a feature is referenced again in DependentSettings
  2921. // entry belonging to another feature, the subsequent
  2922. // references will be ignored. This ensures only the
  2923. // highest priority Feature's request shall have precedence.
  2924. {
  2925. DWORD dwNextOpt ;
  2926. // The order of evaluation is determined
  2927. // by the priority array.
  2928. dwNextOpt = 0 ; // extract info for first option selected for
  2929. // this feature.
  2930. for( dwJ = 0 ; dwJ < dwNumFeatures ; dwJ++)
  2931. {
  2932. pDestOptions[dwJ].ubCurOptIndex = OPTION_INDEX_ANY ;
  2933. pDestOptions[dwJ].ubNext = 0 ; // eol
  2934. // DestOptions is now blank.
  2935. }
  2936. bMatchFound = FALSE ;
  2937. {
  2938. DWORD dwUnresolvedFeature, dwOldOpt ;
  2939. PATREEREF patrRoot ; // root of attribute tree to navigate.
  2940. patrRoot = &(pfo[dwFea].atrUIChangeTriggersMacro) ;
  2941. // if dwFea is a pickmany, we must force selection of
  2942. // the Macro associated with just dwOpt. We do this by
  2943. // changing the optionarray temporarily.
  2944. dwOldOpt = pOptions[dwFea].ubCurOptIndex ;
  2945. pOptions[dwFea].ubCurOptIndex = (BYTE)dwOpt ;
  2946. if(EextractValueFromTree((PBYTE)pnRawData, pStatic->dwSSUIChangeTriggersMacroIndex,
  2947. (PBYTE)&dwListsRoot,
  2948. &dwUnresolvedFeature, *patrRoot, pOptions,
  2949. dwFea,
  2950. &dwNextOpt) != TRI_SUCCESS)
  2951. {
  2952. pOptions[dwFea].ubCurOptIndex = (BYTE)dwOldOpt ; // restore
  2953. goto ABORTEXECUTEMACROS ; // no UIChangeTriggersMacro to apply.
  2954. }
  2955. pOptions[dwFea].ubCurOptIndex = (BYTE)dwOldOpt ; // restore
  2956. if(dwListsRoot == END_OF_LIST)
  2957. goto ABORTEXECUTEMACROS ; // no UIChangeTriggersMacro to apply.
  2958. }
  2959. // now we need to see if the current pOption matches any
  2960. // of the lists accessed using dwListsRoot.
  2961. for(dwListIndex = dwListsRoot ;
  2962. dwListIndex != END_OF_LIST ;
  2963. dwListIndex = plstRoot[dwListIndex].dwNextItem )
  2964. {
  2965. // for each DepSettings list....
  2966. // now walk that DepSettings list at dwListIndex and compare
  2967. // to current settings at pOptions. If there is a match, use
  2968. // depSettings list to OR on options in pDestOptions.
  2969. // Note: Features with their one-shot flag set cannot be
  2970. // considered. They will be ignored.
  2971. BOOL bActiveMatch = FALSE, // requires an actual match
  2972. bOptionArrayMatchesDepSettings = TRUE ; // assume true
  2973. // until proven otherwise.
  2974. for(dwNodeIndex = plstRoot[dwListIndex].dwData ; dwNodeIndex != END_OF_LIST ;
  2975. dwNodeIndex = plstRoot[dwNodeIndex].dwNextItem)
  2976. {
  2977. pqn = (PQUALNAME)(&plstRoot[dwNodeIndex].dwData) ;
  2978. dwFeature = pqn->wFeatureID ;
  2979. dwOption = pqn->wOptionID ;
  2980. if(pbOneShotFlag[dwFeature] == TRUE)
  2981. continue;
  2982. if(!BIsFeaOptionCurSelected(pOptions, dwFeature, dwOption) )
  2983. {
  2984. bOptionArrayMatchesDepSettings = FALSE ;
  2985. break;
  2986. }
  2987. else
  2988. bActiveMatch = TRUE;
  2989. }
  2990. if(bOptionArrayMatchesDepSettings && bActiveMatch)
  2991. // at least one DepSetting was honored.
  2992. {
  2993. // 'or' DepSettings into DestOptions
  2994. for(dwNodeIndex = plstRoot[dwListIndex].dwData ; dwNodeIndex != END_OF_LIST ;
  2995. dwNodeIndex = plstRoot[dwNodeIndex].dwNextItem)
  2996. {
  2997. pqn = (PQUALNAME)(&plstRoot[dwNodeIndex].dwData) ;
  2998. dwFeature = pqn->wFeatureID ;
  2999. dwOption = pqn->wOptionID ;
  3000. if(pbOneShotFlag[dwFeature] == TRUE)
  3001. continue;
  3002. // select dwOption in DestOptions in addition to any other options
  3003. // already selected.
  3004. EnumSelectedOptions(pnRawData, pDestOptions, dwFeature,
  3005. pbSelectedOptions) ;
  3006. if(!pbSelectedOptions[dwOption]) // the option that should be selected isn't.
  3007. { // so let's turn it on.
  3008. pbSelectedOptions[dwOption] = TRUE ; // This is the ORing process.
  3009. ReconstructOptionArray( pnRawData, pDestOptions, iMaxOptions,
  3010. dwFeature, pbSelectedOptions ) ;
  3011. bMatchFound = TRUE ; // there really is something to set.
  3012. }
  3013. }
  3014. }
  3015. }
  3016. if (!bMatchFound)
  3017. {
  3018. // set dest Option array according to depSettings(dwListsRoot)
  3019. for(dwNodeIndex = plstRoot[dwListsRoot].dwData ; dwNodeIndex != END_OF_LIST ;
  3020. dwNodeIndex = plstRoot[dwNodeIndex].dwNextItem)
  3021. {
  3022. pqn = (PQUALNAME)(&plstRoot[dwNodeIndex].dwData) ;
  3023. dwFeature = pqn->wFeatureID ;
  3024. dwOption = pqn->wOptionID ;
  3025. if(pbOneShotFlag[dwFeature] == TRUE)
  3026. continue;
  3027. pDestOptions[dwFeature].ubCurOptIndex = (BYTE)dwOption ;
  3028. }
  3029. }
  3030. // propagate Dest option array settings to pOptions
  3031. // note which features got set and set their one-shot
  3032. // flag.
  3033. for( dwFeature = 0 ; dwFeature < dwNumFeatures ; dwFeature++)
  3034. {
  3035. if(pDestOptions[dwFeature].ubCurOptIndex == OPTION_INDEX_ANY)
  3036. continue;
  3037. EnumSelectedOptions( pnRawData, pDestOptions,
  3038. dwFeature, pbSelectedOptions) ;
  3039. ReconstructOptionArray( pnRawData, pOptions, iMaxOptions,
  3040. dwFeature, pbSelectedOptions ) ;
  3041. pbOneShotFlag[dwFeature] = TRUE ;
  3042. pbFeaturesChanged[dwFeature] = TRUE ; // this Feature may have changed
  3043. }
  3044. } // end non-existent for loop.
  3045. ABORTEXECUTEMACROS:
  3046. if(pbOneShotFlag)
  3047. MemFree(pbOneShotFlag);
  3048. if(pDestOptions)
  3049. MemFree(pDestOptions);
  3050. if(pbSelectedOptions)
  3051. MemFree(pbSelectedOptions);
  3052. return(bStatus);
  3053. }
  3054. #endif
  3055. #endif PARSERDLL