Source code of Windows XP (NT5)
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.

732 lines
18 KiB

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