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.

671 lines
17 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright � Microsoft Corporation. All rights reserved.
  4. //
  5. // analyser.cpp
  6. //
  7. // Purpose: Performs query analysis
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #pragma warning( disable : 4290 )
  12. #include <CHString.h>
  13. #include "analyser.h"
  14. #include <stack>
  15. #include <vector>
  16. #include <comdef.h>
  17. #include <scopeguard.h>
  18. #include <autoptr.h>
  19. void AutoDestructStack(std::stack<SQL_LEVEL_1_RPN_EXPRESSION*>& X )
  20. {
  21. while(!X.empty())
  22. {
  23. delete X.top();
  24. X.pop();
  25. }
  26. }
  27. HRESULT CQueryAnalyser::GetNecessaryQueryForProperty (
  28. IN SQL_LEVEL_1_RPN_EXPRESSION *pExpr,
  29. IN LPCWSTR wszPropName,
  30. DELETE_ME SQL_LEVEL_1_RPN_EXPRESSION *&pNewExpr
  31. )
  32. {
  33. pNewExpr = NULL ;
  34. // Class name and selected properties are ignored; we look at tokens only
  35. // ======================================================================
  36. std::stack<SQL_LEVEL_1_RPN_EXPRESSION*> ExprStack;
  37. ScopeGuard clearStack = MakeGuard(AutoDestructStack, ByRef(ExprStack));
  38. HRESULT hres = WBEM_S_NO_ERROR;
  39. // "Evaluate" the query
  40. // ====================
  41. if(pExpr->nNumTokens == 0)
  42. {
  43. // Empty query --- no information
  44. // ==============================
  45. pNewExpr = new SQL_LEVEL_1_RPN_EXPRESSION;
  46. if ( ! pNewExpr )
  47. {
  48. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  49. }
  50. return WBEM_S_NO_ERROR;
  51. }
  52. for(int i = 0; i < pExpr->nNumTokens; i++)
  53. {
  54. SQL_LEVEL_1_TOKEN &Token = pExpr->pArrayOfTokens[i];
  55. wmilib::auto_ptr<SQL_LEVEL_1_RPN_EXPRESSION> pNew(new SQL_LEVEL_1_RPN_EXPRESSION);
  56. if ( pNew.get() )
  57. {
  58. switch(Token.nTokenType)
  59. {
  60. case SQL_LEVEL_1_TOKEN::OP_EXPRESSION:
  61. {
  62. if(IsTokenAboutProperty(Token, wszPropName))
  63. {
  64. wmilib::auto_ptr<SQL_LEVEL_1_TOKEN> pToken(new SQL_LEVEL_1_TOKEN(Token));
  65. if ( pToken.get() )
  66. {
  67. pNew->AddToken(pToken.get());
  68. pToken.release();
  69. }
  70. else
  71. {
  72. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  73. }
  74. }
  75. ExprStack.push(pNew.get());
  76. pNew.release();
  77. }
  78. break;
  79. case SQL_LEVEL_1_TOKEN::TOKEN_AND:
  80. {
  81. if(ExprStack.size() < 2)
  82. {
  83. hres = WBEM_E_CRITICAL_ERROR;
  84. break;
  85. }
  86. wmilib::auto_ptr<SQL_LEVEL_1_RPN_EXPRESSION> pFirst(ExprStack.top());
  87. ExprStack.pop();
  88. wmilib::auto_ptr<SQL_LEVEL_1_RPN_EXPRESSION> pSecond(ExprStack.top());
  89. ExprStack.pop();
  90. hres = AndQueryExpressions(pFirst.get(), pSecond.get(), pNew.get());
  91. ExprStack.push(pNew.get());
  92. pNew.release();
  93. }
  94. break;
  95. case SQL_LEVEL_1_TOKEN::TOKEN_OR:
  96. {
  97. if(ExprStack.size() < 2)
  98. {
  99. hres = WBEM_E_CRITICAL_ERROR;
  100. break;
  101. }
  102. wmilib::auto_ptr<SQL_LEVEL_1_RPN_EXPRESSION> pFirst(ExprStack.top());
  103. ExprStack.pop();
  104. wmilib::auto_ptr<SQL_LEVEL_1_RPN_EXPRESSION> pSecond(ExprStack.top());
  105. ExprStack.pop();
  106. hres = OrQueryExpressions(pFirst.get(), pSecond.get(), pNew.get());
  107. ExprStack.push(pNew.get());
  108. pNew.release();
  109. }
  110. break;
  111. case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
  112. {
  113. if(ExprStack.size() < 1)
  114. {
  115. hres = WBEM_E_CRITICAL_ERROR;
  116. break;
  117. }
  118. wmilib::auto_ptr<SQL_LEVEL_1_RPN_EXPRESSION> pFirst(ExprStack.top());
  119. ExprStack.pop();
  120. // No information
  121. ExprStack.push(pNew.get());
  122. pNew.release();
  123. }
  124. break;
  125. default:
  126. {
  127. hres = WBEM_E_CRITICAL_ERROR;
  128. }
  129. break ;
  130. }
  131. if(FAILED(hres))
  132. {
  133. // An error occurred, break out of the loop
  134. // ========================================
  135. break;
  136. }
  137. }
  138. else
  139. {
  140. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  141. }
  142. }
  143. if(SUCCEEDED(hres) && ExprStack.size() != 1)
  144. {
  145. hres = WBEM_E_CRITICAL_ERROR;
  146. }
  147. if(FAILED(hres))
  148. {
  149. return hres;
  150. // The guard will take care of stack
  151. }
  152. // All is good
  153. // ===========
  154. pNewExpr = ExprStack.top();
  155. clearStack.Dismiss();
  156. return S_OK;
  157. }
  158. BOOL CQueryAnalyser::IsTokenAboutProperty (
  159. IN SQL_LEVEL_1_TOKEN &Token,
  160. IN LPCWSTR wszPropName
  161. )
  162. {
  163. return (wbem_wcsicmp(wszPropName, Token.pPropertyName) == 0);
  164. }
  165. void CQueryAnalyser::AppendQueryExpression (
  166. IN SQL_LEVEL_1_RPN_EXPRESSION *pDest,
  167. IN SQL_LEVEL_1_RPN_EXPRESSION *pSource
  168. )
  169. {
  170. for(int i = 0; i < pSource->nNumTokens; i++)
  171. {
  172. SQL_LEVEL_1_TOKEN *pToken = new SQL_LEVEL_1_TOKEN(pSource->pArrayOfTokens[i]);
  173. if ( pToken )
  174. {
  175. pDest->AddToken(pToken);
  176. }
  177. else
  178. {
  179. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  180. }
  181. }
  182. }
  183. HRESULT CQueryAnalyser::AndQueryExpressions (
  184. IN SQL_LEVEL_1_RPN_EXPRESSION *pFirst,
  185. IN SQL_LEVEL_1_RPN_EXPRESSION *pSecond,
  186. OUT SQL_LEVEL_1_RPN_EXPRESSION *pNew
  187. )
  188. {
  189. // If either one is empty, take the other
  190. // ======================================
  191. if(pFirst->nNumTokens == 0)
  192. {
  193. AppendQueryExpression(pNew, pSecond);
  194. return WBEM_S_NO_ERROR;
  195. }
  196. if(pSecond->nNumTokens == 0)
  197. {
  198. AppendQueryExpression(pNew, pFirst);
  199. return WBEM_S_NO_ERROR;
  200. }
  201. // Both are there --- and together
  202. // ===============================
  203. AppendQueryExpression(pNew, pFirst);
  204. AppendQueryExpression(pNew, pSecond);
  205. SQL_LEVEL_1_TOKEN Token;
  206. Token.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  207. SQL_LEVEL_1_TOKEN *pToken = new SQL_LEVEL_1_TOKEN(Token);
  208. if ( pToken )
  209. {
  210. pNew->AddToken(pToken);
  211. }
  212. else
  213. {
  214. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  215. }
  216. return WBEM_S_NO_ERROR;
  217. }
  218. HRESULT CQueryAnalyser::OrQueryExpressions (
  219. IN SQL_LEVEL_1_RPN_EXPRESSION *pFirst,
  220. IN SQL_LEVEL_1_RPN_EXPRESSION *pSecond,
  221. OUT SQL_LEVEL_1_RPN_EXPRESSION *pNew
  222. )
  223. {
  224. // If either one is empty, so is the result
  225. // ======================================
  226. if(pFirst->nNumTokens == 0 || pSecond->nNumTokens == 0)
  227. {
  228. return WBEM_S_NO_ERROR;
  229. }
  230. // Both are there --- or together
  231. // ==============================
  232. AppendQueryExpression(pNew, pFirst);
  233. AppendQueryExpression(pNew, pSecond);
  234. SQL_LEVEL_1_TOKEN Token;
  235. Token.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  236. SQL_LEVEL_1_TOKEN *pToken = new SQL_LEVEL_1_TOKEN(Token);
  237. if ( pToken )
  238. {
  239. pNew->AddToken(pToken);
  240. }
  241. else
  242. {
  243. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  244. }
  245. return WBEM_S_NO_ERROR;
  246. }
  247. HRESULT CQueryAnalyser::GetValuesForProp (
  248. SQL_LEVEL_1_RPN_EXPRESSION *pExpr,
  249. LPCWSTR wszPropName,
  250. CHStringArray &awsVals
  251. )
  252. {
  253. awsVals.RemoveAll();
  254. // Get the necessary query
  255. // =======================
  256. SQL_LEVEL_1_RPN_EXPRESSION *pPropExpr = NULL ;
  257. HRESULT hres = CQueryAnalyser::GetNecessaryQueryForProperty (
  258. pExpr,
  259. wszPropName,
  260. pPropExpr
  261. );
  262. if(FAILED(hres))
  263. {
  264. return hres;
  265. }
  266. // See if there are any tokens
  267. // ===========================
  268. if(pPropExpr->nNumTokens == 0)
  269. {
  270. delete pPropExpr;
  271. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  272. }
  273. // Combine them all
  274. // ================
  275. for(int i = 0; i < pPropExpr->nNumTokens; i++)
  276. {
  277. SQL_LEVEL_1_TOKEN& Token = pPropExpr->pArrayOfTokens[i];
  278. switch ( Token.nTokenType )
  279. {
  280. case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
  281. {
  282. delete pPropExpr;
  283. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  284. }
  285. break ;
  286. case SQL_LEVEL_1_TOKEN::TOKEN_AND:
  287. case SQL_LEVEL_1_TOKEN::TOKEN_OR:
  288. {
  289. // We treat them all as ORs
  290. // ========================
  291. }
  292. break;
  293. default:
  294. {
  295. // This is a token
  296. // ===============
  297. if(Token.nOperator != SQL_LEVEL_1_TOKEN::OP_EQUAL)
  298. {
  299. delete pPropExpr;
  300. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  301. }
  302. // Skip NULLs, but report them.
  303. if (V_VT(&Token.vConstValue) == VT_NULL)
  304. {
  305. hres = WBEM_S_PARTIAL_RESULTS;
  306. continue;
  307. }
  308. if(V_VT(&Token.vConstValue) != VT_BSTR)
  309. {
  310. delete pPropExpr;
  311. return WBEM_E_TYPE_MISMATCH;
  312. }
  313. // This token is a string equality. Add the string to the list
  314. // ===========================================================
  315. awsVals.Add(CHString(V_BSTR(&Token.vConstValue)));
  316. }
  317. break ;
  318. }
  319. }
  320. delete pPropExpr;
  321. return hres;
  322. }
  323. HRESULT CQueryAnalyser::GetValuesForProp (
  324. SQL_LEVEL_1_RPN_EXPRESSION *pExpr,
  325. LPCWSTR wszPropName,
  326. std::vector<_bstr_t> &vectorVals
  327. )
  328. {
  329. vectorVals.erase(vectorVals.begin(),vectorVals.end());
  330. // Get the necessary query
  331. // =======================
  332. SQL_LEVEL_1_RPN_EXPRESSION *pPropExpr = NULL ;
  333. HRESULT hres = CQueryAnalyser::GetNecessaryQueryForProperty (
  334. pExpr,
  335. wszPropName,
  336. pPropExpr
  337. );
  338. if(FAILED(hres))
  339. {
  340. return hres;
  341. }
  342. // See if there are any tokens
  343. // ===========================
  344. if(pPropExpr->nNumTokens == 0)
  345. {
  346. delete pPropExpr;
  347. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  348. }
  349. // Combine them all
  350. // ================
  351. for(int i = 0; i < pPropExpr->nNumTokens; i++)
  352. {
  353. SQL_LEVEL_1_TOKEN& Token = pPropExpr->pArrayOfTokens[i];
  354. switch ( Token.nTokenType )
  355. {
  356. case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
  357. {
  358. delete pPropExpr;
  359. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  360. }
  361. break ;
  362. case SQL_LEVEL_1_TOKEN::TOKEN_AND:
  363. case SQL_LEVEL_1_TOKEN::TOKEN_OR:
  364. {
  365. // We treat them all as ORs
  366. // ========================
  367. }
  368. break ;
  369. default:
  370. {
  371. // This is a token
  372. // ===============
  373. if(Token.nOperator != SQL_LEVEL_1_TOKEN::OP_EQUAL)
  374. {
  375. delete pPropExpr;
  376. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  377. }
  378. // Skip NULLs, but report them.
  379. if (V_VT(&Token.vConstValue) == VT_NULL)
  380. {
  381. hres = WBEM_S_PARTIAL_RESULTS;
  382. continue;
  383. }
  384. if(V_VT(&Token.vConstValue) != VT_BSTR)
  385. {
  386. delete pPropExpr;
  387. return WBEM_E_INVALID_QUERY;
  388. }
  389. // This token is a string equality. Add the string to the list
  390. // ===========================================================
  391. vectorVals.push_back(_bstr_t(V_BSTR(&Token.vConstValue)));
  392. }
  393. break ;
  394. }
  395. }
  396. delete pPropExpr;
  397. return hres;
  398. }
  399. HRESULT CQueryAnalyser::GetValuesForProp (
  400. SQL_LEVEL_1_RPN_EXPRESSION *pExpr,
  401. LPCWSTR wszPropName,
  402. std::vector<int> &vectorVals
  403. )
  404. {
  405. vectorVals.erase(vectorVals.begin(),vectorVals.end());
  406. // Get the necessary query
  407. // =======================
  408. SQL_LEVEL_1_RPN_EXPRESSION *pPropExpr = NULL ;
  409. HRESULT hres = CQueryAnalyser::GetNecessaryQueryForProperty (
  410. pExpr,
  411. wszPropName,
  412. pPropExpr
  413. );
  414. if(FAILED(hres))
  415. {
  416. return hres;
  417. }
  418. // See if there are any tokens
  419. // ===========================
  420. if(pPropExpr->nNumTokens == 0)
  421. {
  422. delete pPropExpr;
  423. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  424. }
  425. // Combine them all
  426. // ================
  427. for(int i = 0; i < pPropExpr->nNumTokens; i++)
  428. {
  429. SQL_LEVEL_1_TOKEN &Token = pPropExpr->pArrayOfTokens[i];
  430. switch ( Token.nTokenType )
  431. {
  432. case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
  433. {
  434. delete pPropExpr;
  435. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  436. }
  437. break ;
  438. case SQL_LEVEL_1_TOKEN::TOKEN_AND:
  439. case SQL_LEVEL_1_TOKEN::TOKEN_OR:
  440. {
  441. // We treat them all as ORs
  442. // ========================
  443. }
  444. break ;
  445. default:
  446. {
  447. // This is a token
  448. // ===============
  449. if(Token.nOperator != SQL_LEVEL_1_TOKEN::OP_EQUAL)
  450. {
  451. delete pPropExpr;
  452. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  453. }
  454. // Skip NULLs, but report them.
  455. if (V_VT(&Token.vConstValue) == VT_NULL)
  456. {
  457. hres = WBEM_S_PARTIAL_RESULTS;
  458. continue;
  459. }
  460. if(V_VT(&Token.vConstValue) != VT_I4)
  461. {
  462. delete pPropExpr;
  463. return WBEM_E_INVALID_QUERY;
  464. }
  465. // This token is an int equality. Add the string to the list
  466. // ===========================================================
  467. vectorVals.push_back(V_I4(&Token.vConstValue));
  468. }
  469. break ;
  470. }
  471. }
  472. delete pPropExpr;
  473. return hres;
  474. }
  475. HRESULT CQueryAnalyser::GetValuesForProp (
  476. SQL_LEVEL_1_RPN_EXPRESSION *pExpr,
  477. LPCWSTR wszPropName,
  478. std::vector<_variant_t> &vectorVals
  479. )
  480. {
  481. vectorVals.erase(vectorVals.begin(),vectorVals.end());
  482. // Get the necessary query
  483. // =======================
  484. SQL_LEVEL_1_RPN_EXPRESSION *pPropExpr = NULL ;
  485. HRESULT hres = CQueryAnalyser::GetNecessaryQueryForProperty (
  486. pExpr,
  487. wszPropName,
  488. pPropExpr
  489. );
  490. if(FAILED(hres))
  491. {
  492. return hres;
  493. }
  494. // See if there are any tokens
  495. // ===========================
  496. if(pPropExpr->nNumTokens == 0)
  497. {
  498. delete pPropExpr;
  499. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  500. }
  501. // Combine them all
  502. // ================
  503. for(int i = 0; i < pPropExpr->nNumTokens; i++)
  504. {
  505. SQL_LEVEL_1_TOKEN &Token = pPropExpr->pArrayOfTokens[i];
  506. switch ( Token.nTokenType )
  507. {
  508. case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
  509. {
  510. delete pPropExpr;
  511. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  512. }
  513. break ;
  514. case SQL_LEVEL_1_TOKEN::TOKEN_AND:
  515. case SQL_LEVEL_1_TOKEN::TOKEN_OR:
  516. {
  517. // We treat them all as ORs
  518. // ========================
  519. }
  520. break ;
  521. default:
  522. {
  523. // This is a token
  524. // ===============
  525. if(Token.nOperator != SQL_LEVEL_1_TOKEN::OP_EQUAL)
  526. {
  527. delete pPropExpr;
  528. return WBEMESS_E_REGISTRATION_TOO_BROAD;
  529. }
  530. // This token is a string equality. Add the string to the list
  531. // ===========================================================
  532. vectorVals.push_back(_variant_t(Token.vConstValue));
  533. }
  534. break ;
  535. }
  536. }
  537. delete pPropExpr;
  538. return WBEM_S_NO_ERROR;
  539. }