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.

501 lines
16 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. /* constrnt.c - processing keywords imposing constraints
  3. between 2 or more option selections. */
  4. #include "gpdparse.h"
  5. // ---- functions defined in constrnt.c ---- //
  6. BOOL BparseConstraint(
  7. PABSARRAYREF paarValue,
  8. PDWORD pdwExistingCList, // index of start of contraint list.
  9. BOOL bCreate,
  10. PGLOBL pglobl) ;
  11. BOOL BexchangeDataInFOATNode(
  12. DWORD dwFeature,
  13. DWORD dwOption,
  14. DWORD dwFieldOff, // offset of field in FeatureOption struct
  15. PDWORD pdwOut, // previous contents of attribute node
  16. PDWORD pdwIn,
  17. BOOL bSynthetic, // access synthetic features
  18. PGLOBL pglobl
  19. ) ;
  20. BOOL BparseInvalidCombination(
  21. PABSARRAYREF paarValue,
  22. DWORD dwFieldOff,
  23. PGLOBL pglobl) ;
  24. BOOL BparseInvalidInstallableCombination1(
  25. PABSARRAYREF paarValue,
  26. DWORD dwFieldOff,
  27. PGLOBL pglobl) ;
  28. // ---------------------------------------------------- //
  29. /* if time and circumstances warrent may define a
  30. feature keyword *ExemptFromConstraints: <optionname>
  31. so in addition to specifying a default option, you
  32. may specify which option is exempt from wildcard constraints.
  33. Now we may introduce the concept of wildcard constraints:
  34. if a constraint statement appears at the Feature level it
  35. is equivalent to that statement appearing withing every
  36. option construct in that feature except the option
  37. named in the *ExemptFromConstraints: <optionname>.
  38. We may introduce a wildcard option for the target of a constraint
  39. say '*'. This is used in place of the option name in the
  40. a constraint statement say:
  41. *Constraint: <featurename>.*
  42. this means every option in <featurename> is disabled
  43. except for the option named in the <featurename>'s
  44. *ExemptFromConstraints: <optionname>
  45. */
  46. BOOL BparseConstraint(
  47. PABSARRAYREF paarValue,
  48. PDWORD pdwExistingCList, // index of start of contraint list.
  49. BOOL bCreate, // Create new constraint list vs. appending to existing one.
  50. PGLOBL pglobl)
  51. {
  52. BOOL bStatus ;
  53. DWORD dwNewCnstRoot,
  54. dwListRoot, // holds temp list of qualified names
  55. // this list will never be used again.
  56. dwCNode, dwLNode ;
  57. PCONSTRAINTS pcnstr ; // start of CONSTRAINTS array.
  58. PLISTNODE plstBase ; // start of LIST array
  59. PQUALNAME pqn ; // the dword in the list node is actually a
  60. // qualified name structure.
  61. pcnstr = (PCONSTRAINTS) gMasterTable[MTI_CONSTRAINTS].pubStruct ;
  62. plstBase = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
  63. bStatus = BparseList(paarValue, &dwListRoot, BparseQualifiedName,
  64. VALUE_QUALIFIED_NAME, pglobl) ;
  65. if(bStatus == FALSE || dwListRoot == END_OF_LIST)
  66. return(FALSE) ;
  67. // create list of constraints
  68. if(bStatus)
  69. bStatus =
  70. BallocElementFromMasterTable(MTI_CONSTRAINTS, &dwNewCnstRoot, pglobl) ;
  71. dwCNode = dwNewCnstRoot ;
  72. dwLNode = dwListRoot ;
  73. while(bStatus)
  74. {
  75. pqn = (PQUALNAME)(&plstBase[dwLNode].dwData) ;
  76. pcnstr[dwCNode].dwFeature = pqn->wFeatureID ;
  77. pcnstr[dwCNode].dwOption = pqn->wOptionID ;
  78. if(plstBase[dwLNode].dwNextItem == END_OF_LIST)
  79. break ;
  80. dwLNode = plstBase[dwLNode].dwNextItem ;
  81. bStatus = BallocElementFromMasterTable(MTI_CONSTRAINTS,
  82. &pcnstr[dwCNode].dwNextCnstrnt, pglobl) ;
  83. dwCNode = pcnstr[dwCNode].dwNextCnstrnt ;
  84. }
  85. if(!bStatus)
  86. return(FALSE) ;
  87. // tack existing list onto new list.
  88. if(bCreate) // there is an existing constraint list
  89. pcnstr[dwCNode].dwNextCnstrnt = END_OF_LIST ;
  90. else
  91. pcnstr[dwCNode].dwNextCnstrnt = *pdwExistingCList ;
  92. *pdwExistingCList = dwNewCnstRoot ;
  93. return(bStatus) ;
  94. }
  95. /* note: InvalidCombos are
  96. the only fields where the index of a structure
  97. is stored directly into a the offset part of
  98. an attribute tree node. But this is ok since
  99. the snapshot code never picks this data up.
  100. Indicies of Constraint structures are stored in
  101. heap like all other things.
  102. */
  103. BOOL BexchangeDataInFOATNode(
  104. DWORD dwFeature,
  105. DWORD dwOption,
  106. DWORD dwFieldOff, // offset of field in FeatureOption struct
  107. PDWORD pdwOut, // previous contents of attribute node
  108. PDWORD pdwIn,
  109. BOOL bSynthetic, // access synthetic features
  110. PGLOBL pglobl) // new contents of attribute node.
  111. /* 'FOAT' means FeatureOption AttributeTree.
  112. this function swaps the specified dword value in the specified
  113. attribute node. (normally used to hold the heap offset,
  114. but this function writes nothing to the heap.)
  115. The parameters dwFeature, dwOption, dwFieldOffset specify
  116. the structure, field, and branch of the attribute tree.
  117. If the specified option branch does not exist, one will be created,
  118. (if pdwIn is not NULL)
  119. its value will be initialized to *pdwIn and the value
  120. INVALID_INDEX will be returned in pdwOut.
  121. Assumptions: the value is dword sized - specifically holds
  122. array index of an array of structures.
  123. The tree being accessed is strictly one level deep. That is the
  124. node is fully specified by just Feature, Option.
  125. */
  126. {
  127. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  128. PATREEREF patr ;
  129. ATREEREF atrFound ;
  130. DWORD dwFeaOffset ; // Start numbering features from this
  131. // starting point. This gives synthetic features a separate
  132. // non-overlapping number space from normal features.
  133. PDFEATURE_OPTIONS pfo ;
  134. if(bSynthetic)
  135. {
  136. pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_SYNTHESIZED_FEATURES].pubStruct +
  137. dwFeature ;
  138. dwFeaOffset = gMasterTable[MTI_DFEATURE_OPTIONS].dwArraySize ;
  139. }
  140. else
  141. {
  142. pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct +
  143. dwFeature ;
  144. dwFeaOffset = 0 ;
  145. }
  146. patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
  147. patr = (PATREEREF)((PBYTE)pfo + dwFieldOff) ;
  148. if(*patr == ATTRIB_UNINITIALIZED)
  149. {
  150. if(pdwIn)
  151. {
  152. if(!BcreateEndNode(patr, dwFeature + dwFeaOffset , dwOption, pglobl) )
  153. return(FALSE) ; // resource exhaustion
  154. patt[*patr].dwOffset = *pdwIn ;
  155. patt[*patr].eOffsetMeans = VALUE_AT_HEAP ;
  156. }
  157. if(pdwOut)
  158. *pdwOut = INVALID_INDEX ;
  159. return(TRUE) ;
  160. }
  161. if(*patr & ATTRIB_HEAP_VALUE)
  162. {
  163. ERR(("Internal parser error. BexchangeDataInFOATNode should never create a branchless node.\n"));
  164. return(FALSE) ;
  165. }
  166. // offset field contains index to another node
  167. if(pdwIn)
  168. {
  169. if(!BfindOrCreateMatchingNode(*patr, &atrFound, dwFeature + dwFeaOffset , dwOption, pglobl))
  170. return(FALSE) ; // Tree inconsistency error or resource exhaustion
  171. if(patt[atrFound].eOffsetMeans != VALUE_AT_HEAP)
  172. {
  173. // just created a new node.
  174. #if 1
  175. patt[atrFound].dwOffset = *pdwIn ;
  176. #else
  177. // the way it was
  178. if(!BwriteToHeap(&(patt[atrFound].dwOffset), (PBYTE)pdwIn,
  179. sizeof(DWORD), 4) )
  180. return(FALSE) ; // A fatal error.
  181. #endif
  182. patt[atrFound].eOffsetMeans = VALUE_AT_HEAP ;
  183. if(pdwOut)
  184. *pdwOut = INVALID_INDEX ;
  185. return(TRUE) ;
  186. }
  187. if(pdwOut)
  188. *pdwOut = patt[atrFound].dwOffset ;
  189. patt[atrFound].dwOffset = *pdwIn ;
  190. }
  191. else
  192. {
  193. if(!BfindMatchingNode(*patr, &atrFound, dwFeature + dwFeaOffset , dwOption, pglobl))
  194. {
  195. if(pdwOut)
  196. *pdwOut = INVALID_INDEX ;
  197. return(TRUE) ;
  198. }
  199. if(pdwOut)
  200. *pdwOut = patt[atrFound].dwOffset ;
  201. }
  202. return(TRUE) ;
  203. }
  204. BOOL BparseInvalidCombination(
  205. PABSARRAYREF paarValue,
  206. DWORD dwFieldOff,
  207. PGLOBL pglobl)
  208. /* called by BProcessSpecialKeyword
  209. when parsing *InvalidCombination
  210. (basically is a Non-relocatable Global.)
  211. After parsing paarValue into a List of qualified names,
  212. we convert the List into list of INVALIDCOMBO structures
  213. and prepend this list to any previously existing
  214. lists of INVALIDCOMBO structures.
  215. */
  216. {
  217. BOOL bStatus, bPrevsExists ;
  218. DWORD dwListRoot, // holds temp list of qualified names
  219. dwNewInvCRoot , // start of new list of INVALIDCOMBO structures
  220. dwICNode, dwLNode, dwNumNodes ;
  221. PLISTNODE plstBase ; // start of LIST array
  222. PINVALIDCOMBO pinvc ; // start of InvalidCombo array
  223. PQUALNAME pqn ; // the dword in the list node is actually a
  224. // qualified name structure.
  225. pinvc = (PINVALIDCOMBO) gMasterTable[MTI_INVALIDCOMBO].pubStruct ;
  226. plstBase = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
  227. bStatus = BparseList(paarValue, &dwListRoot,
  228. BparseQualifiedName, VALUE_QUALIFIED_NAME, pglobl) ;
  229. if(!bStatus)
  230. return(FALSE) ;
  231. // if there are more than 2 objects in the list, process
  232. // as an InvalidCombo, else store as UIConstraint.
  233. dwLNode = dwListRoot ;
  234. for(dwNumNodes = 1 ; plstBase[dwLNode].dwNextItem != END_OF_LIST ;
  235. dwNumNodes++) // locate end of list
  236. {
  237. dwLNode = plstBase[dwLNode].dwNextItem ;
  238. }
  239. if(dwNumNodes == 1)
  240. {
  241. ERR(("Must have at least 2 objects to define an InvalidCombination.\n"));
  242. return(FALSE) ;
  243. }
  244. if(dwNumNodes == 2)
  245. {
  246. DWORD dwNewCnst, dwNextCnstrnt;
  247. PCONSTRAINTS pcnstr ; // start of CONSTRAINTS array.
  248. bStatus = BallocElementFromMasterTable(
  249. MTI_CONSTRAINTS, &dwNewCnst, pglobl) ;
  250. if(!bStatus)
  251. return(FALSE) ;
  252. dwLNode = dwListRoot ;
  253. pqn = (PQUALNAME)(&plstBase[dwLNode].dwData) ;
  254. pcnstr = (PCONSTRAINTS) gMasterTable[MTI_CONSTRAINTS].pubStruct ;
  255. // prepend new constraint node to list
  256. BexchangeArbDataInFOATNode(pqn->wFeatureID, pqn->wOptionID,
  257. offsetof(DFEATURE_OPTIONS, atrConstraints),
  258. sizeof(DWORD), (PBYTE)&dwNextCnstrnt, (PBYTE)&dwNewCnst,
  259. &bPrevsExists, FALSE, pglobl) ;
  260. if(bPrevsExists)
  261. pcnstr[dwNewCnst].dwNextCnstrnt = dwNextCnstrnt ;
  262. else
  263. pcnstr[dwNewCnst].dwNextCnstrnt = END_OF_LIST ;
  264. // copy contents of 2nd list node into first constraint node.
  265. dwLNode = plstBase[dwLNode].dwNextItem ;
  266. pqn = (PQUALNAME)(&plstBase[dwLNode].dwData) ;
  267. pcnstr[dwNewCnst].dwFeature = pqn->wFeatureID ;
  268. pcnstr[dwNewCnst].dwOption = pqn->wOptionID ;
  269. return(TRUE) ;
  270. }
  271. // create list of InvalidCombos
  272. if(bStatus)
  273. bStatus =
  274. BallocElementFromMasterTable(MTI_INVALIDCOMBO, &dwNewInvCRoot, pglobl) ;
  275. dwLNode = dwListRoot ; // reset
  276. dwICNode = dwNewInvCRoot ;
  277. while(bStatus)
  278. {
  279. DWORD dwPrevsNode ;
  280. pqn = (PQUALNAME)(&plstBase[dwLNode].dwData) ;
  281. if(pqn->wOptionID == (WORD)INVALID_SYMBOLID) // treat partially qualified
  282. pqn->wOptionID = (WORD)DEFAULT_INIT ; // name as default initializer
  283. pinvc[dwICNode].dwFeature = pqn->wFeatureID ;
  284. pinvc[dwICNode].dwOption = pqn->wOptionID ;
  285. BexchangeDataInFOATNode(pqn->wFeatureID, pqn->wOptionID,
  286. dwFieldOff, &dwPrevsNode, &dwNewInvCRoot, FALSE, pglobl) ;
  287. if(dwPrevsNode == INVALID_INDEX)
  288. pinvc[dwICNode].dwNewCombo = END_OF_LIST ;
  289. else
  290. pinvc[dwICNode].dwNewCombo = dwPrevsNode ;
  291. if(plstBase[dwLNode].dwNextItem == END_OF_LIST)
  292. break ;
  293. dwLNode = plstBase[dwLNode].dwNextItem ;
  294. bStatus = BallocElementFromMasterTable(MTI_INVALIDCOMBO,
  295. &pinvc[dwICNode].dwNextElement, pglobl) ;
  296. dwICNode = pinvc[dwICNode].dwNextElement ;
  297. }
  298. if(!bStatus)
  299. return(FALSE) ;
  300. pinvc[dwICNode].dwNextElement = END_OF_LIST ;
  301. return(bStatus) ;
  302. }
  303. BOOL BparseInvalidInstallableCombination1(
  304. PABSARRAYREF paarValue,
  305. DWORD dwFieldOff,
  306. PGLOBL pglobl)
  307. /* called by BProcessSpecialKeyword
  308. when parsing *InvalidInstallableCombination
  309. (basically is a Non-relocatable Global.)
  310. After parsing paarValue into a List of qualified names,
  311. we convert the List into list of INVALIDCOMBO structures
  312. and prepend this list to any previously existing
  313. lists of INVALIDCOMBO structures. The first node of each
  314. InvalidCombo list points to another new InvalidCombo list.
  315. The first InvalidCombo is stored in the Global atrInvldInstallCombo.
  316. */
  317. {
  318. BOOL bStatus, bPrevsExists ;
  319. DWORD dwListRoot, // holds temp list of qualified names
  320. dwNewInvCRoot , // start of new list of INVALIDCOMBO structures
  321. dwICNode, dwLNode, dwNumNodes ;
  322. PLISTNODE plstBase ; // start of LIST array
  323. PINVALIDCOMBO pinvc ; // start of InvalidCombo array
  324. PQUALNAME pqn ; // the dword in the list node is actually a
  325. // qualified name structure.
  326. PGLOBALATTRIB pga ;
  327. PATREEREF patr ;
  328. pga = (PGLOBALATTRIB)gMasterTable[MTI_GLOBALATTRIB].pubStruct ;
  329. pinvc = (PINVALIDCOMBO) gMasterTable[MTI_INVALIDCOMBO].pubStruct ;
  330. plstBase = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
  331. bStatus = BparseList(paarValue, &dwListRoot,
  332. BparsePartiallyQualifiedName, VALUE_QUALIFIED_NAME, pglobl) ;
  333. if(!bStatus)
  334. return(FALSE) ;
  335. // cannot convert to UIConstraint bacause the synthesized
  336. // Feature does not yet exist.
  337. dwLNode = dwListRoot ;
  338. for(dwNumNodes = 1 ; plstBase[dwLNode].dwNextItem != END_OF_LIST ;
  339. dwNumNodes++) // locate end of list
  340. {
  341. dwLNode = plstBase[dwLNode].dwNextItem ;
  342. }
  343. if(dwNumNodes == 1)
  344. {
  345. ERR(("Must have at least 2 objects to define an InvalidInstallableCombination.\n"));
  346. return(FALSE) ;
  347. }
  348. // create list of InvalidCombos
  349. if(bStatus)
  350. bStatus =
  351. BallocElementFromMasterTable(MTI_INVALIDCOMBO, &dwNewInvCRoot, pglobl) ;
  352. dwLNode = dwListRoot ; // reset
  353. dwICNode = dwNewInvCRoot ;
  354. // link to atrInvldInstallCombo
  355. patr = (PATREEREF)((PBYTE)pga + dwFieldOff) ;
  356. if(*patr == ATTRIB_UNINITIALIZED)
  357. pinvc[dwICNode].dwNewCombo = END_OF_LIST ;
  358. else // interpret *patr as index to INVC node.
  359. pinvc[dwICNode].dwNewCombo = *patr ;
  360. *patr = dwICNode;
  361. while(bStatus)
  362. {
  363. DWORD dwPrevsNode ; // create next element links only
  364. pqn = (PQUALNAME)(&plstBase[dwLNode].dwData) ;
  365. if(pqn->wOptionID == (WORD)INVALID_SYMBOLID) // treat partially qualified
  366. pqn->wOptionID = (WORD)DEFAULT_INIT ; // name as default initializer
  367. // this lets us know this feature
  368. // is installable.
  369. pinvc[dwICNode].dwFeature = pqn->wFeatureID ;
  370. pinvc[dwICNode].dwOption = pqn->wOptionID ;
  371. if(plstBase[dwLNode].dwNextItem == END_OF_LIST)
  372. break ;
  373. dwLNode = plstBase[dwLNode].dwNextItem ;
  374. bStatus = BallocElementFromMasterTable(MTI_INVALIDCOMBO,
  375. &pinvc[dwICNode].dwNextElement, pglobl) ;
  376. dwICNode = pinvc[dwICNode].dwNextElement ;
  377. }
  378. if(!bStatus)
  379. return(FALSE) ;
  380. pinvc[dwICNode].dwNextElement = END_OF_LIST ;
  381. return(bStatus) ;
  382. }