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.9 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // xprparse.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // This file implements the function IASParseExpression.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/06/1998 Original version.
  16. // 05/21/1999 Remove old style trace.
  17. // 03/23/2000 Use two quotes to escape a quote.
  18. //
  19. ///////////////////////////////////////////////////////////////////////////////
  20. #include <ias.h>
  21. #include <ExprBuilder.h>
  22. #include <Parser.h>
  23. #include <xprparse.h>
  24. //////////
  25. // Struct for converting an identifier to a logical token.
  26. //////////
  27. struct KeyWord
  28. {
  29. PCWSTR identifier;
  30. IAS_LOGICAL_TOKEN token;
  31. };
  32. //////////
  33. // Table of keywords. These must be sorted alphabetically.
  34. //////////
  35. const KeyWord KEYWORDS[] =
  36. {
  37. { L"AND", IAS_LOGICAL_AND },
  38. { L"FALSE", IAS_LOGICAL_FALSE },
  39. { L"NOT", IAS_LOGICAL_NOT },
  40. { L"OR", IAS_LOGICAL_OR },
  41. { L"TRUE", IAS_LOGICAL_TRUE },
  42. { L"XOR", IAS_LOGICAL_XOR },
  43. { NULL, IAS_LOGICAL_NUM_TOKENS }
  44. };
  45. //////////
  46. // Returns the IAS_LOGICAL_TOKEN equivalent for 'key' or IAS_LOGICAL_NUM_TOKENS
  47. // if no such equivalent exists.
  48. //////////
  49. IAS_LOGICAL_TOKEN findKeyWord(PCWSTR key) throw ()
  50. {
  51. // We'll use a linear search since the table is so small.
  52. for (const KeyWord* i = KEYWORDS; i->identifier; ++i)
  53. {
  54. int cmp = _wcsicmp(key, i->identifier);
  55. // Did we find it ?
  56. if (cmp == 0) { return i->token; }
  57. // Did we we go past it ?
  58. if (cmp < 0) { break; }
  59. }
  60. return IAS_LOGICAL_NUM_TOKENS;
  61. }
  62. //////////
  63. // Special characters for parsing.
  64. //////////
  65. const WCHAR WHITESPACE[] = L" \t\n";
  66. const WCHAR TOKEN_DELIMITERS[] = L" \t\n()";
  67. //////////
  68. // Parse a chunk of expression text and add it to the ExpressionBuilder.
  69. //////////
  70. void addExpressionString(ExpressionBuilder& expression, PCWSTR szExpression)
  71. {
  72. //////////
  73. // Make a local copy because parser can temporarily modify the string.
  74. //////////
  75. size_t len = sizeof(WCHAR) * (wcslen(szExpression) + 1);
  76. Parser p((PWSTR)memcpy(_alloca(len), szExpression, len));
  77. //////////
  78. // Loop through the expression until we hit the null-terminator.
  79. //////////
  80. while (*p.skip(WHITESPACE) != L'\0')
  81. {
  82. //////////
  83. // Parentheses are handled separately since they don't have to be
  84. // delimited by whitespace.
  85. //////////
  86. if (*p == L'(')
  87. {
  88. expression.addToken(IAS_LOGICAL_LEFT_PAREN);
  89. ++p;
  90. }
  91. else if (*p == L')')
  92. {
  93. expression.addToken(IAS_LOGICAL_RIGHT_PAREN);
  94. ++p;
  95. }
  96. else
  97. {
  98. // Get the next token.
  99. const wchar_t* token = p.findToken(TOKEN_DELIMITERS);
  100. // Check if it's a keyword.
  101. IAS_LOGICAL_TOKEN keyWord = findKeyWord(token);
  102. if (keyWord != IAS_LOGICAL_NUM_TOKENS)
  103. {
  104. // If it is a keyword, add it to the expression ...
  105. expression.addToken(keyWord);
  106. p.releaseToken();
  107. }
  108. else
  109. {
  110. // If it's not a keyword, it must be a condition object.
  111. expression.addCondition(token);
  112. p.releaseToken();
  113. // Skip the leading parenthesis.
  114. p.skip(WHITESPACE);
  115. p.ignore(L'(');
  116. // Skip the leading quote.
  117. p.skip(WHITESPACE);
  118. p.ignore(L'\"');
  119. // We're now at the beginning of the condition text.
  120. p.beginToken();
  121. // Find the trailing quote, skipping any escaped characters.
  122. while (p.findNext(L'\"')[1] == L'\"')
  123. {
  124. ++p;
  125. p.erase(1);
  126. }
  127. // Add the condition text.
  128. expression.addConditionText(p.endToken());
  129. p.releaseToken();
  130. // Skip the trailing quote
  131. p.ignore(L'\"');
  132. // Skip the trailing parenthesis.
  133. p.skip(WHITESPACE);
  134. p.ignore(L')');
  135. }
  136. }
  137. }
  138. }
  139. HRESULT
  140. WINAPI
  141. IASParseExpression(
  142. PCWSTR szExpression,
  143. VARIANT* pVal
  144. )
  145. {
  146. if (szExpression == NULL || pVal == NULL) { return E_INVALIDARG; }
  147. VariantInit(pVal);
  148. try
  149. {
  150. ExpressionBuilder expression;
  151. addExpressionString(expression, szExpression);
  152. expression.detach(pVal);
  153. }
  154. catch (Parser::ParseError)
  155. {
  156. return E_INVALIDARG;
  157. }
  158. CATCH_AND_RETURN()
  159. return S_OK;
  160. }
  161. HRESULT
  162. WINAPI
  163. IASParseExpressionEx(
  164. IN VARIANT* pvExpression,
  165. OUT VARIANT* pVal
  166. )
  167. {
  168. if (pvExpression == NULL || pVal == NULL) { return E_INVALIDARG; }
  169. // If the VARIANT contains a single BSTR, we can just use the method
  170. // defined above.
  171. if (V_VT(pvExpression) == VT_BSTR)
  172. {
  173. return IASParseExpression(V_BSTR(pvExpression), pVal);
  174. }
  175. VariantInit(pVal);
  176. try
  177. {
  178. ExpressionBuilder expression;
  179. if (V_VT(pvExpression) == VT_EMPTY)
  180. {
  181. // If the variant is empty, the expression is always false.
  182. expression.addToken(IAS_LOGICAL_FALSE);
  183. }
  184. else
  185. {
  186. CVariantVector<VARIANT> values(pvExpression);
  187. for (size_t i = 0; i < values.size(); ++i)
  188. {
  189. // If we have more than one value, join them by AND's.
  190. if (i != 0) { expression.addToken(IAS_LOGICAL_AND); }
  191. if (V_VT(&values[i]) != VT_BSTR)
  192. {
  193. _com_issue_error(DISP_E_TYPEMISMATCH);
  194. }
  195. addExpressionString(expression, V_BSTR(&values[i]));
  196. }
  197. }
  198. expression.detach(pVal);
  199. }
  200. catch (Parser::ParseError)
  201. {
  202. return E_INVALIDARG;
  203. }
  204. CATCH_AND_RETURN()
  205. return S_OK;
  206. }