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.

244 lines
5.5 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // FILE
  4. //
  5. // BuildTree.cpp
  6. //
  7. // SYNOPSIS
  8. //
  9. // This file defines IASBuildExpression.
  10. //
  11. // MODIFICATION HISTORY
  12. //
  13. // 02/04/1998 Original version.
  14. // 04/17/1998 Add Release in extractCondition to fix leak.
  15. //
  16. ///////////////////////////////////////////////////////////////////////////////
  17. #include <ias.h>
  18. #include <BuildTree.h>
  19. #include <Tokens.h>
  20. #include <VarVec.h>
  21. #include <new>
  22. using _com_util::CheckError;
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //
  25. // FUNCTION
  26. //
  27. // extractCondition
  28. //
  29. // DESCRIPTION
  30. //
  31. // Extracts an ICondition* from a VARIANT.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////////
  34. inline ICondition* extractCondition(VARIANT* pv)
  35. {
  36. ICondition* cond;
  37. IUnknown* unk = V_UNKNOWN(pv);
  38. if (unk)
  39. {
  40. CheckError(unk->QueryInterface(__uuidof(ICondition), (PVOID*)&cond));
  41. // We don't need to hold a reference since it's still in the VARIANT.
  42. cond->Release();
  43. }
  44. else
  45. {
  46. _com_issue_error(E_POINTER);
  47. }
  48. return cond;
  49. }
  50. //////////
  51. // We'll use IAS_LOGICAL_NUM_TOKENS to indicate a condition token.
  52. //////////
  53. #define IAS_CONDITION IAS_LOGICAL_NUM_TOKENS
  54. ///////////////////////////////////////////////////////////////////////////////
  55. //
  56. // FUNCTION
  57. //
  58. // getTokenType
  59. //
  60. // DESCRIPTION
  61. //
  62. // Determines what type of token is contained in the VARIANT.
  63. //
  64. ///////////////////////////////////////////////////////////////////////////////
  65. inline IAS_LOGICAL_TOKEN getTokenType(VARIANT* pv)
  66. {
  67. // If it's an object pointer, it must be a condition.
  68. if (V_VT(pv) == VT_UNKNOWN || V_VT(pv) == VT_DISPATCH)
  69. {
  70. return IAS_CONDITION;
  71. }
  72. // Convert to a long ...
  73. CheckError(VariantChangeType(pv, pv, 0, VT_I4));
  74. // ... and see if its a valid operator.
  75. if (V_I4(pv) < 0 || V_I4(pv) >= IAS_LOGICAL_NUM_TOKENS)
  76. {
  77. _com_issue_error(E_INVALIDARG);
  78. }
  79. return (IAS_LOGICAL_TOKEN)V_I4(pv);
  80. }
  81. //////////
  82. // Prototype for growBranch below.
  83. //////////
  84. ICondition* growBranch(VARIANT*& pcur, VARIANT* pend);
  85. ///////////////////////////////////////////////////////////////////////////////
  86. //
  87. // FUNCTION
  88. //
  89. // getOperand
  90. //
  91. // DESCRIPTION
  92. //
  93. // Retrieves the next operand from the expression array.
  94. //
  95. ///////////////////////////////////////////////////////////////////////////////
  96. ICondition* getOperand(VARIANT*& pcur, VARIANT* pend)
  97. {
  98. // If we've reached the end of the expression, something's gone wrong.
  99. if (pcur >= pend)
  100. {
  101. _com_issue_error(E_INVALIDARG);
  102. }
  103. // Tokens that represent the start of an operand ...
  104. switch (getTokenType(pcur))
  105. {
  106. case IAS_LOGICAL_LEFT_PAREN:
  107. return growBranch(++pcur, pend);
  108. case IAS_LOGICAL_NOT:
  109. return new NotOperator(getOperand(++pcur, pend));
  110. case IAS_CONDITION:
  111. return extractCondition(pcur++);
  112. case IAS_LOGICAL_TRUE:
  113. ++pcur;
  114. return new ConstantCondition<VARIANT_TRUE>;
  115. case IAS_LOGICAL_FALSE:
  116. ++pcur;
  117. return new ConstantCondition<VARIANT_FALSE>;
  118. }
  119. // ... anything else is an error.
  120. _com_issue_error(E_INVALIDARG);
  121. return NULL;
  122. }
  123. ///////////////////////////////////////////////////////////////////////////////
  124. //
  125. // FUNCTION
  126. //
  127. // growBranch
  128. //
  129. // DESCRIPTION
  130. //
  131. // Recursively grows a complete branch of the logic tree.
  132. //
  133. ///////////////////////////////////////////////////////////////////////////////
  134. ICondition* growBranch(VARIANT*& pcur, VARIANT* pend)
  135. {
  136. // All branches must start with an operand.
  137. IConditionPtr node(getOperand(pcur, pend));
  138. // Loop until we hit the end.
  139. while (pcur < pend)
  140. {
  141. // At this point we must either have a binary operator or a right ).
  142. switch(getTokenType(pcur))
  143. {
  144. case IAS_LOGICAL_AND:
  145. node = new AndOperator(node, getOperand(++pcur, pend));
  146. break;
  147. case IAS_LOGICAL_OR:
  148. node = new OrOperator(node, getOperand(++pcur, pend));
  149. break;
  150. case IAS_LOGICAL_XOR:
  151. node = new XorOperator(node, getOperand(++pcur, pend));
  152. break;
  153. case IAS_LOGICAL_RIGHT_PAREN:
  154. ++pcur;
  155. return node.Detach();
  156. default:
  157. _com_issue_error(E_INVALIDARG);
  158. }
  159. }
  160. return node.Detach();
  161. }
  162. ///////////////////////////////////////////////////////////////////////////////
  163. //
  164. // FUNCTION
  165. //
  166. // IASBuildExpression
  167. //
  168. // DESCRIPTION
  169. //
  170. // Builds a logic tree from an expression array.
  171. //
  172. ///////////////////////////////////////////////////////////////////////////////
  173. HRESULT
  174. WINAPI
  175. IASBuildExpression(
  176. IN VARIANT* pv,
  177. OUT ICondition** ppExpression
  178. )
  179. {
  180. if (pv == NULL || ppExpression == NULL) { return E_POINTER; }
  181. *ppExpression = NULL;
  182. try
  183. {
  184. CVariantVector<VARIANT> av(pv);
  185. // Get the start ...
  186. VARIANT* pcur = av.data();
  187. // ... and end of the tree.
  188. VARIANT* pend = pcur + av.size();
  189. // Grow the root branch.
  190. *ppExpression = growBranch(pcur, pend);
  191. }
  192. catch (const _com_error& ce)
  193. {
  194. return ce.Error();
  195. }
  196. catch (std::bad_alloc)
  197. {
  198. return E_OUTOFMEMORY;
  199. }
  200. catch (...)
  201. {
  202. return E_FAIL;
  203. }
  204. return S_OK;
  205. }