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.

5856 lines
158 KiB

  1. //***************************************************************************
  2. //
  3. // WQL.CPP
  4. //
  5. // WQL Parser
  6. //
  7. // Implements the LL(1) syntax described in WQL.BNF via a recursive
  8. // descent parser.
  9. //
  10. // raymcc 14-Sep-97 Created for WMI/SMS.
  11. // raymcc 18-Oct-97 Additional extensions for SMS team.
  12. // raymcc 20-Apr-00 Whistler RPN extensions
  13. // raymcc 19-May-00 Whistler delete/insert/update extensions
  14. //
  15. //***************************************************************************
  16. // TO DO:
  17. #include "precomp.h"
  18. #include <stdio.h>
  19. #include <genlex.h>
  20. #include <flexarry.h>
  21. #include <wqllex.h>
  22. #include <wqlnode.h>
  23. #include <wql.h>
  24. #include <helpers.h>
  25. #include "wmiquery.h"
  26. #include <corex.h>
  27. #include <memory>
  28. #include <autoptr.h>
  29. #include <math.h>
  30. #include <comdef.h>
  31. void __stdcall _com_issue_error(long hResult) { throw hResult;};
  32. POLARITY BOOL ReadI64(LPCWSTR wsz, UNALIGNED __int64& ri64);
  33. POLARITY BOOL ReadUI64(LPCWSTR wsz, UNALIGNED unsigned __int64& rui64);
  34. //***************************************************************************
  35. //
  36. // Misc
  37. //
  38. //***************************************************************************
  39. //
  40. static DWORD FlipOperator(DWORD dwOp);
  41. #define trace(x) printf x
  42. void StrArrayDelete(ULONG, LPWSTR *);
  43. HRESULT StrArrayCopy(
  44. ULONG uSize,
  45. LPWSTR *pSrc,
  46. LPWSTR **pDest
  47. );
  48. //***************************************************************************
  49. //
  50. // CloneLPWSTR
  51. //
  52. //***************************************************************************
  53. // ok
  54. static LPWSTR CloneLPWSTR(LPCWSTR pszSrc)
  55. {
  56. if (pszSrc == 0) return 0;
  57. size_t cchTmp = wcslen(pszSrc) + 1;
  58. LPWSTR pszTemp = new wchar_t[cchTmp];
  59. if (pszTemp ) memcpy(pszTemp, pszSrc,cchTmp*sizeof(wchar_t));
  60. return pszTemp;
  61. }
  62. static LPWSTR Clone(LPCWSTR pszSrc)
  63. {
  64. if (pszSrc == 0) return 0;
  65. size_t cchTmp = wcslen(pszSrc) + 1;
  66. LPWSTR pszTemp = new wchar_t[cchTmp];
  67. if (pszTemp ) memcpy(pszTemp, pszSrc,cchTmp*sizeof(wchar_t));
  68. else throw CX_MemoryException();
  69. return pszTemp;
  70. }
  71. //***************************************************************************
  72. //
  73. // CloneFailed
  74. //
  75. //***************************************************************************
  76. bool inline CloneFailed(LPCWSTR p1, LPCWSTR p2)
  77. {
  78. if (0 == p1 && 0 == p2 ) return false;
  79. if (p1 && p2) return false;
  80. return true;
  81. }
  82. //***************************************************************************
  83. //
  84. // CWQLParser::CWQLParser
  85. //
  86. // Constructor
  87. //
  88. // Parameters:
  89. // <pSrc> A source from which to lex from.
  90. //
  91. //***************************************************************************
  92. //
  93. CWQLParser::CWQLParser(
  94. LPWSTR pszQueryText,
  95. CGenLexSource *pSrc
  96. )
  97. {
  98. if (pszQueryText == 0 || pSrc == 0)
  99. throw CX_Exception();
  100. m_pLexer = new CGenLexer(WQL_LexTable, pSrc);
  101. if (m_pLexer == 0)
  102. throw CX_Exception();
  103. m_pszQueryText = CloneLPWSTR(pszQueryText);
  104. if (m_pszQueryText == 0 && pszQueryText!=0 )
  105. {
  106. delete m_pLexer;
  107. m_pLexer = 0;
  108. throw CX_Exception();
  109. }
  110. m_nLine = 0;
  111. m_pTokenText = 0;
  112. m_nCurrentToken = 0;
  113. m_uFeatures = 0I64;
  114. m_pQueryRoot = 0;
  115. m_pRootWhere = 0;
  116. m_pRootColList = 0;
  117. m_pRootFrom = 0;
  118. m_pRootWhereOptions = 0;
  119. m_nParseContext = Ctx_Default;
  120. m_bAllowPromptForConstant = false;
  121. }
  122. //***************************************************************************
  123. //
  124. // CWQLParser::~CWQLParser
  125. //
  126. //***************************************************************************
  127. //
  128. CWQLParser::~CWQLParser()
  129. {
  130. Empty();
  131. delete m_pLexer;
  132. }
  133. //***************************************************************************
  134. //
  135. // CWQLParser::Empty
  136. //
  137. //***************************************************************************
  138. // ok
  139. void CWQLParser::Empty()
  140. {
  141. m_aReferencedTables.Empty();
  142. m_aReferencedAliases.Empty();
  143. m_pTokenText = 0; // We don't delete this, it was never allocated
  144. m_nLine = 0;
  145. m_nCurrentToken = 0;
  146. m_uFeatures = 0I64;
  147. delete m_pQueryRoot; // Clean up previous query, if any
  148. m_pQueryRoot = 0;
  149. m_pRootWhere = 0;
  150. m_pRootColList = 0;
  151. m_pRootFrom = 0;
  152. m_pRootWhereOptions = 0;
  153. m_nParseContext = Ctx_Default;
  154. // For the next two, we don't delete the pointers since they
  155. // were copies of structs elsewhere in the tree.
  156. // =========================================================
  157. m_aSelAliases.Empty();
  158. m_aSelColumns.Empty();
  159. delete [] m_pszQueryText;
  160. }
  161. //***************************************************************************
  162. //
  163. // CWQLParser::GetTokenLong
  164. //
  165. // Converts the current token to a 32/64 bit integer. Returns info
  166. // about the size of the constant.
  167. //
  168. //***************************************************************************
  169. // ok
  170. BOOL CWQLParser::GetIntToken(
  171. OUT BOOL *bSigned,
  172. OUT BOOL *b64Bit,
  173. OUT unsigned __int64 *pVal
  174. )
  175. {
  176. BOOL bRes;
  177. if (m_pTokenText == 0 || *m_pTokenText == 0)
  178. return FALSE;
  179. if (*m_pTokenText == L'-')
  180. {
  181. __int64 Temp;
  182. bRes = ReadI64(m_pTokenText, Temp);
  183. if (bRes == FALSE)
  184. return FALSE;
  185. *bSigned = TRUE;
  186. if (Temp < -2147483648I64)
  187. {
  188. *b64Bit = TRUE;
  189. }
  190. else
  191. {
  192. *b64Bit = FALSE;
  193. }
  194. *pVal = (unsigned __int64) Temp;
  195. }
  196. else
  197. {
  198. bRes = ReadUI64(m_pTokenText, *pVal);
  199. if (bRes == FALSE)
  200. return FALSE;
  201. *bSigned = FALSE;
  202. if (*pVal >> 32)
  203. {
  204. *b64Bit = TRUE;
  205. if (*pVal <= 0x7FFFFFFFFFFFFFFFI64)
  206. {
  207. *bSigned = TRUE;
  208. }
  209. }
  210. else
  211. {
  212. *b64Bit = FALSE;
  213. // See if we can dumb down to 32-bit VT_I4 for simplicity.
  214. // Much code recognizes VT_I4 and doesn't recognize VT_UI4
  215. // because it can't be packed into a VARIANT. So, if there
  216. // are only 31 bits used, let's convert to VT_I4. We do this
  217. // by returning this as a 'signed' value (the positive sign :).
  218. if (*pVal <= 0x7FFFFFFF)
  219. {
  220. *bSigned = TRUE;
  221. }
  222. }
  223. }
  224. return TRUE;
  225. }
  226. //***************************************************************************
  227. //
  228. // CWQLParser::GetReferencedTables
  229. //
  230. // Creates an array of the names of the tables referenced in this query
  231. //
  232. //***************************************************************************
  233. // ok
  234. BOOL CWQLParser::GetReferencedTables(OUT CWStringArray& Tables)
  235. {
  236. Tables = m_aReferencedTables;
  237. return TRUE;
  238. }
  239. //***************************************************************************
  240. //
  241. // CWQLParser::GetReferencedAliases
  242. //
  243. //***************************************************************************
  244. // ok
  245. BOOL CWQLParser::GetReferencedAliases(OUT CWStringArray & Aliases)
  246. {
  247. Aliases = m_aReferencedAliases;
  248. return TRUE;
  249. }
  250. //***************************************************************************
  251. //
  252. // Next()
  253. //
  254. // Advances to the next token and recognizes keywords, etc.
  255. //
  256. //***************************************************************************
  257. // ok
  258. struct WqlKeyword
  259. {
  260. LPWSTR m_pKeyword;
  261. int m_nTokenCode;
  262. };
  263. static WqlKeyword KeyWords[] = // Keep this alphabetized for binary search
  264. {
  265. L"ALL", WQL_TOK_ALL,
  266. L"AND", WQL_TOK_AND,
  267. L"AS", WQL_TOK_AS,
  268. L"ASC", WQL_TOK_ASC,
  269. L"ASSOCIATORS", WQL_TOK_ASSOCIATORS,
  270. L"BETWEEN", WQL_TOK_BETWEEN,
  271. L"BY", WQL_TOK_BY,
  272. L"COUNT", WQL_TOK_COUNT,
  273. L"DATEPART", WQL_TOK_DATEPART,
  274. L"DELETE", WQL_TOK_DELETE,
  275. L"DESC", WQL_TOK_DESC,
  276. L"DISTINCT", WQL_TOK_DISTINCT,
  277. L"FROM", WQL_TOK_FROM,
  278. L"FULL", WQL_TOK_FULL,
  279. L"GROUP", WQL_TOK_GROUP,
  280. L"HAVING", WQL_TOK_HAVING,
  281. L"IN", WQL_TOK_IN,
  282. L"INNER", WQL_TOK_INNER,
  283. L"INSERT", WQL_TOK_INSERT,
  284. L"IS", WQL_TOK_IS,
  285. L"ISA", WQL_TOK_ISA,
  286. L"ISNULL", WQL_TOK_ISNULL,
  287. L"JOIN", WQL_TOK_JOIN,
  288. L"LEFT", WQL_TOK_LEFT,
  289. L"LIKE", WQL_TOK_LIKE,
  290. L"LOWER", WQL_TOK_LOWER,
  291. L"NOT", WQL_TOK_NOT,
  292. L"NULL", WQL_TOK_NULL,
  293. L"ON", WQL_TOK_ON,
  294. L"OR", WQL_TOK_OR,
  295. L"ORDER", WQL_TOK_ORDER,
  296. L"OUTER", WQL_TOK_OUTER,
  297. L"__QUALIFIER", WQL_TOK_QUALIFIER,
  298. L"REFERENCES", WQL_TOK_REFERENCES,
  299. L"RIGHT", WQL_TOK_RIGHT,
  300. L"SELECT", WQL_TOK_SELECT,
  301. L"__THIS", WQL_TOK_THIS,
  302. L"UPDATE", WQL_TOK_UPDATE,
  303. L"UPPER", WQL_TOK_UPPER,
  304. L"WHERE", WQL_TOK_WHERE
  305. };
  306. const int NumKeywords = sizeof(KeyWords)/sizeof(WqlKeyword);
  307. BOOL CWQLParser::Next()
  308. {
  309. m_nCurrentToken = m_pLexer->NextToken();
  310. if (m_nCurrentToken == WQL_TOK_ERROR
  311. || (m_nCurrentToken == WQL_TOK_PROMPT && !m_bAllowPromptForConstant))
  312. return FALSE;
  313. m_nLine = m_pLexer->GetLineNum();
  314. m_pTokenText = m_pLexer->GetTokenText();
  315. if (m_nCurrentToken == WQL_TOK_EOF)
  316. m_pTokenText = L"<end of file>";
  317. // Keyword check. Do a binary search
  318. // on the keyword table.
  319. // =================================
  320. if (m_nCurrentToken == WQL_TOK_IDENT)
  321. {
  322. int l = 0, u = NumKeywords - 1;
  323. while (l <= u)
  324. {
  325. int m = (l + u) / 2;
  326. if (wbem_wcsicmp(m_pTokenText, KeyWords[m].m_pKeyword) < 0)
  327. u = m - 1;
  328. else if (wbem_wcsicmp(m_pTokenText, KeyWords[m].m_pKeyword) > 0)
  329. l = m + 1;
  330. else // Match
  331. {
  332. m_nCurrentToken = KeyWords[m].m_nTokenCode;
  333. break;
  334. }
  335. }
  336. }
  337. return TRUE;
  338. }
  339. //***************************************************************************
  340. //
  341. // <parse> ::= SELECT <select_stmt>;
  342. // ::= DELETE <delete_stmt>;
  343. // ::= INSERT <insert_stmt>;
  344. // ::= UPDATE <update_stmt>;
  345. //
  346. // Precondition: All cleanup has been performed from previous parse
  347. // by a call to Empty()
  348. //
  349. //***************************************************************************
  350. // ok
  351. HRESULT CWQLParser::Parse()
  352. {
  353. HRESULT hRes = WBEM_E_INVALID_SYNTAX;
  354. m_pQueryRoot = new SWQLNode_QueryRoot;
  355. if (!m_pQueryRoot)
  356. return WBEM_E_OUT_OF_MEMORY;
  357. try
  358. {
  359. m_pLexer->Reset();
  360. if (!Next())
  361. return WBEM_E_INVALID_SYNTAX;
  362. // See which kind of query we have.
  363. // ================================
  364. switch (m_nCurrentToken)
  365. {
  366. case WQL_TOK_SELECT:
  367. {
  368. if (!Next())
  369. return WBEM_E_INVALID_SYNTAX;
  370. SWQLNode_Select *pSelStmt = 0;
  371. hRes = select_stmt(&pSelStmt);
  372. if (FAILED(hRes))
  373. return hRes;
  374. m_pQueryRoot->m_pLeft = pSelStmt;
  375. m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eSelect;
  376. }
  377. break;
  378. case WQL_TOK_ASSOCIATORS:
  379. case WQL_TOK_REFERENCES:
  380. {
  381. SWQLNode_AssocQuery *pAQ = 0;
  382. hRes = assocquery(&pAQ);
  383. if (FAILED(hRes))
  384. return hRes;
  385. m_pQueryRoot->m_pLeft = pAQ;
  386. m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eAssoc;
  387. }
  388. break;
  389. case WQL_TOK_INSERT:
  390. {
  391. if (!Next())
  392. return WBEM_E_INVALID_SYNTAX;
  393. SWQLNode_Insert *pIns = 0;
  394. hRes = insert_stmt(&pIns);
  395. if (FAILED(hRes))
  396. return hRes;
  397. m_pQueryRoot->m_pLeft = pIns;
  398. m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eInsert;
  399. }
  400. break;
  401. case WQL_TOK_DELETE:
  402. {
  403. if (!Next())
  404. return WBEM_E_INVALID_SYNTAX;
  405. SWQLNode_Delete *pDel = 0;
  406. hRes = delete_stmt(&pDel);
  407. if (FAILED(hRes))
  408. return hRes;
  409. m_pQueryRoot->m_pLeft = pDel;
  410. m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eDelete;
  411. }
  412. break;
  413. case WQL_TOK_UPDATE:
  414. {
  415. if (!Next())
  416. return WBEM_E_INVALID_SYNTAX;
  417. SWQLNode_Update *pUpd = 0;
  418. hRes = update_stmt(&pUpd);
  419. if (FAILED(hRes))
  420. return hRes;
  421. m_pQueryRoot->m_pLeft = pUpd;
  422. m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eUpdate;
  423. }
  424. break;
  425. default:
  426. return WBEM_E_INVALID_SYNTAX;
  427. }
  428. }
  429. catch (CX_MemoryException)
  430. {
  431. hRes = WBEM_E_OUT_OF_MEMORY;
  432. }
  433. catch (...)
  434. {
  435. hRes = WBEM_E_CRITICAL_ERROR;
  436. }
  437. return hRes;
  438. }
  439. //***************************************************************************
  440. //
  441. // <select_stmt> ::=
  442. // <select_type>
  443. // <col_ref_list>
  444. // <from_clause>
  445. // <where_clause>
  446. //
  447. //***************************************************************************
  448. // ok
  449. int CWQLParser::select_stmt(OUT SWQLNode_Select **pSelStmt)
  450. {
  451. int nRes = 0;
  452. int nType = 0;
  453. SWQLNode_FromClause *pFrom = 0;
  454. SWQLNode_Select *pSel = 0;
  455. SWQLNode_TableRefs *pTblRefs = 0;
  456. SWQLNode_WhereClause *pWhere = 0;
  457. *pSelStmt = 0;
  458. // Set up the basic AST.
  459. // =====================
  460. pSel = new SWQLNode_Select;
  461. if (!pSel)
  462. return WBEM_E_OUT_OF_MEMORY;
  463. pTblRefs = new SWQLNode_TableRefs;
  464. if (!pTblRefs)
  465. {
  466. delete pSel;
  467. return WBEM_E_OUT_OF_MEMORY;
  468. }
  469. pSel->m_pLeft = pTblRefs;
  470. // Get the select type.
  471. // ====================
  472. nRes = select_type(nType);
  473. if (nRes)
  474. goto Exit;
  475. pTblRefs->m_nSelectType = nType; // ALL, DISTINCT
  476. // Get the selected list of columns.
  477. // =================================
  478. nRes = col_ref_list(pTblRefs);
  479. if (nRes)
  480. goto Exit;
  481. m_pRootColList = (SWQLNode_ColumnList *) pTblRefs->m_pLeft;
  482. // Get the FROM clause and patch it into the AST.
  483. // ===============================================
  484. nRes = from_clause(&pFrom);
  485. if (nRes)
  486. goto Exit;
  487. m_pRootFrom = pFrom;
  488. pTblRefs->m_pRight = pFrom;
  489. // Get the WHERE clause.
  490. // =====================
  491. nRes = where_clause(&pWhere);
  492. if (nRes)
  493. goto Exit;
  494. m_pRootWhere = pWhere;
  495. pSel->m_pRight = pWhere;
  496. // Verify we are at the end of the query.
  497. // ======================================
  498. if (m_nCurrentToken != WQL_TOK_EOF)
  499. {
  500. nRes = WBEM_E_INVALID_SYNTAX;
  501. goto Exit;
  502. }
  503. nRes = NO_ERROR;
  504. Exit:
  505. if (nRes)
  506. delete pSel;
  507. else
  508. {
  509. *pSelStmt = pSel;
  510. }
  511. return nRes;
  512. }
  513. //***************************************************************************
  514. //
  515. // CWQLParser::delete_stmt
  516. //
  517. //***************************************************************************
  518. // ok
  519. int CWQLParser::delete_stmt(OUT SWQLNode_Delete **pDelStmt)
  520. {
  521. int nRes = 0;
  522. int nType = 0;
  523. SWQLNode_TableRef *pTblRef = 0;
  524. SWQLNode_WhereClause *pWhere = 0;
  525. // Default in case of error.
  526. // =========================
  527. *pDelStmt = 0;
  528. if (m_nCurrentToken != WQL_TOK_FROM)
  529. return WBEM_E_INVALID_SYNTAX;
  530. if (!Next())
  531. return WBEM_E_INVALID_SYNTAX;
  532. // Otherwise, traditional SQL.
  533. // ===========================
  534. nRes = single_table_decl(&pTblRef);
  535. if (nRes)
  536. return nRes;
  537. // Get the WHERE clause.
  538. // =====================
  539. nRes = where_clause(&pWhere);
  540. if (nRes)
  541. {
  542. delete pTblRef;
  543. return nRes;
  544. }
  545. // Verify we are at the end of the query.
  546. // ======================================
  547. if (m_nCurrentToken != WQL_TOK_EOF)
  548. {
  549. nRes = WBEM_E_INVALID_SYNTAX;
  550. delete pTblRef;
  551. delete pWhere;
  552. }
  553. else
  554. {
  555. // If here, everything is wonderful.
  556. // ==================================
  557. SWQLNode_Delete *pDel = new SWQLNode_Delete;
  558. if (!pDel)
  559. {
  560. // Except that we might have just run out of memory...
  561. // ====================================================
  562. delete pTblRef;
  563. delete pWhere;
  564. return WBEM_E_OUT_OF_MEMORY;
  565. }
  566. // Patch in the new node.
  567. // =====================
  568. pDel->m_pLeft = pTblRef;
  569. pDel->m_pRight = pWhere;
  570. *pDelStmt = pDel;
  571. nRes = WBEM_S_NO_ERROR;
  572. }
  573. return nRes;
  574. }
  575. //***************************************************************************
  576. //
  577. // <select_type> ::= ALL;
  578. // <select_type> ::= DISTINCT;
  579. // <select_type> ::= <>;
  580. //
  581. // Returns type through nSelType :
  582. // WQL_TOK_ALL or WQL_TOK_DISTINCT
  583. //
  584. //***************************************************************************
  585. // done
  586. int CWQLParser::select_type(int & nSelType)
  587. {
  588. nSelType = WQL_FLAG_ALL; // Default
  589. if (m_nCurrentToken == WQL_TOK_ALL)
  590. {
  591. nSelType = WQL_FLAG_ALL;
  592. if (!Next())
  593. return WBEM_E_INVALID_SYNTAX;
  594. return NO_ERROR;
  595. }
  596. if (m_nCurrentToken == WQL_TOK_DISTINCT)
  597. {
  598. nSelType = WQL_FLAG_DISTINCT;
  599. if (!Next())
  600. return WBEM_E_INVALID_SYNTAX;
  601. return NO_ERROR;
  602. }
  603. return NO_ERROR;
  604. }
  605. //***************************************************************************
  606. //
  607. // <col_ref_list> ::= <col_ref> <col_ref_rest>;
  608. // <col_ref_list> ::= ASTERISK;
  609. // <col_ref_list> ::= COUNT <count_clause>;
  610. //
  611. //***************************************************************************
  612. // ?
  613. int CWQLParser::col_ref_list(
  614. IN OUT SWQLNode_TableRefs *pTblRefs
  615. )
  616. {
  617. int nRes;
  618. DWORD dwFuncFlags = 0;
  619. // Allocate a new left node of type SWQLNode_ColumnList and patch it in
  620. // if it doesn't already exist.
  621. // =====================================================================
  622. SWQLNode_ColumnList *pColList = (SWQLNode_ColumnList *) pTblRefs->m_pLeft;
  623. if (pColList == NULL)
  624. {
  625. pColList = new SWQLNode_ColumnList;
  626. if (!pColList)
  627. return WBEM_E_OUT_OF_MEMORY;
  628. pTblRefs->m_pLeft = pColList;
  629. }
  630. // If here, it is a "select *..." query.
  631. // =====================================
  632. if (m_nCurrentToken == WQL_TOK_ASTERISK)
  633. {
  634. // Allocate a new column list which has a single asterisk.
  635. // =======================================================
  636. SWQLColRef *pColRef = new SWQLColRef;
  637. if (!pColRef)
  638. return WBEM_E_OUT_OF_MEMORY;
  639. pColRef->m_pColName = CloneLPWSTR(L"*");
  640. if (pColRef->m_pColName == 0)
  641. {
  642. delete pColRef;
  643. return WBEM_E_OUT_OF_MEMORY;
  644. }
  645. m_uFeatures |= WMIQ_RPNF_FEATURE_SELECT_STAR;
  646. pColRef->m_dwFlags = WQL_FLAG_ASTERISK;
  647. if (pColList->m_aColumnRefs.Add(pColRef) != CFlexArray::no_error)
  648. {
  649. delete pColRef;
  650. return WBEM_E_OUT_OF_MEMORY;
  651. };
  652. if (!Next())
  653. {
  654. return WBEM_E_INVALID_SYNTAX;
  655. }
  656. return NO_ERROR;
  657. }
  658. // If here, we have a "select COUNT..." operation.
  659. // ===============================================
  660. if (m_nCurrentToken == WQL_TOK_COUNT)
  661. {
  662. if (!Next())
  663. return WBEM_E_INVALID_SYNTAX;
  664. SWQLQualifiedName *pQN = 0;
  665. nRes = count_clause(&pQN);
  666. if (!nRes)
  667. {
  668. pTblRefs->m_nSelectType |= WQL_FLAG_COUNT;
  669. SWQLColRef *pCR = 0;
  670. if (SUCCEEDED(nRes = QNameToSWQLColRef(pQN, &pCR)))
  671. {
  672. if (pColList->m_aColumnRefs.Add(pCR))
  673. {
  674. delete pCR;
  675. return WBEM_E_OUT_OF_MEMORY;
  676. }
  677. }
  678. return nRes;
  679. }
  680. else
  681. {
  682. // This may be a column named count
  683. // in which case the current token is
  684. // either an ident or "from"
  685. if (m_nCurrentToken == WQL_TOK_FROM ||
  686. m_nCurrentToken == WQL_TOK_COMMA)
  687. {
  688. wmilib::auto_ptr<SWQLColRef> pCR = wmilib::auto_ptr<SWQLColRef>(new SWQLColRef);
  689. if (pCR.get())
  690. {
  691. pCR->m_pColName = CloneLPWSTR(L"count");
  692. if (pCR->m_pColName == 0)
  693. return WBEM_E_OUT_OF_MEMORY;
  694. if (pColList->m_aColumnRefs.Add(pCR.get()) != CFlexArray::no_error)
  695. return WBEM_E_OUT_OF_MEMORY;
  696. pCR.release();
  697. }
  698. else
  699. return WBEM_E_OUT_OF_MEMORY;
  700. if (WQL_TOK_FROM == m_nCurrentToken)
  701. return 0;
  702. else
  703. {
  704. return col_ref_rest(pTblRefs);
  705. }
  706. }
  707. else
  708. return WBEM_E_INVALID_SYNTAX;
  709. }
  710. }
  711. // Make a provision for wrapping the
  712. // column in a function all UPPER or LOWER
  713. // =======================================
  714. if (m_nCurrentToken == WQL_TOK_UPPER)
  715. dwFuncFlags = WQL_FLAG_FUNCTIONIZED | WQL_FLAG_UPPER;
  716. else if (m_nCurrentToken == WQL_TOK_LOWER)
  717. dwFuncFlags = WQL_FLAG_FUNCTIONIZED | WQL_FLAG_LOWER;
  718. if (dwFuncFlags)
  719. {
  720. // Common procedure for cases where UPPER or LOWER are used.
  721. if (!Next())
  722. return WBEM_E_INVALID_SYNTAX;
  723. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  724. return WBEM_E_INVALID_SYNTAX;
  725. if (!Next())
  726. return WBEM_E_INVALID_SYNTAX;
  727. }
  728. // If here, must be an identifier.
  729. // ===============================
  730. if (m_nCurrentToken != WQL_TOK_IDENT)
  731. return WBEM_E_INVALID_SYNTAX;
  732. SWQLQualifiedName *pInitCol = 0;
  733. nRes = col_ref(&pInitCol);
  734. if (nRes)
  735. return nRes;
  736. wmilib::auto_ptr<SWQLQualifiedName> initCol(pInitCol);
  737. SWQLColRef *pCR = 0;
  738. nRes = QNameToSWQLColRef(initCol.get(), &pCR);
  739. if (nRes)
  740. return nRes;
  741. initCol.release();
  742. pCR->m_dwFlags |= dwFuncFlags;
  743. if (dwFuncFlags)
  744. {
  745. // If a function call was invoked, remove the trailing paren.
  746. // ==========================================================
  747. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  748. return WBEM_E_INVALID_SYNTAX;
  749. if (!Next())
  750. return WBEM_E_INVALID_SYNTAX;
  751. }
  752. pColList->m_aColumnRefs.Add(pCR);
  753. m_uFeatures |= WMIQ_RPNF_PROJECTION;
  754. return col_ref_rest(pTblRefs);
  755. }
  756. //***************************************************************************
  757. //
  758. // <count_clause> ::= OPEN_PAREN <count_col> CLOSE_PAREN;
  759. // <count_col> ::= ASTERISK;
  760. // <count_col> ::= IDENT;
  761. //
  762. // On NO_ERROR returns:
  763. // <bAsterisk> set to TRUE if a * occurred in the COUNT clause,
  764. // or <bAsterisk> set to FALSE and <pQualName> set to point to the
  765. // qualified name of the column referenced.
  766. //
  767. //***************************************************************************
  768. // ok
  769. int CWQLParser::count_clause(
  770. OUT SWQLQualifiedName **pQualName
  771. )
  772. {
  773. int nRes;
  774. *pQualName = 0;
  775. // Syntax check.
  776. // =============
  777. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  778. return WBEM_E_INVALID_SYNTAX;
  779. if (!Next())
  780. return WBEM_E_INVALID_SYNTAX;
  781. // Determine whether an asterisk was used COUNT(*) or
  782. // a col-ref COUNT(col-ref)
  783. // ==================================================
  784. if (m_nCurrentToken == WQL_TOK_ASTERISK)
  785. {
  786. SWQLQualifiedName *pQN = new SWQLQualifiedName;
  787. if (!pQN)
  788. return WBEM_E_OUT_OF_MEMORY;
  789. SWQLQualifiedNameField *pQF = new SWQLQualifiedNameField;
  790. if (!pQF)
  791. {
  792. delete pQN;
  793. return WBEM_E_OUT_OF_MEMORY;
  794. }
  795. pQF->m_pName = CloneLPWSTR(L"*");
  796. if (pQF->m_pName == 0)
  797. {
  798. delete pQN;
  799. delete pQF;
  800. return WBEM_E_OUT_OF_MEMORY;
  801. }
  802. pQN->Add(pQF);
  803. *pQualName = pQN;
  804. if (!Next())
  805. return WBEM_E_INVALID_SYNTAX;
  806. m_uFeatures |= WMIQ_RPNF_COUNT_STAR;
  807. }
  808. else if (m_nCurrentToken == WQL_TOK_IDENT)
  809. {
  810. SWQLQualifiedName *pQN = 0;
  811. nRes = col_ref(&pQN);
  812. if (nRes)
  813. return nRes;
  814. *pQualName = pQN;
  815. }
  816. // Check for errors in syntax and clean up
  817. // if so.
  818. // =======================================
  819. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  820. {
  821. if (*pQualName)
  822. delete *pQualName;
  823. *pQualName = 0;
  824. return WBEM_E_INVALID_SYNTAX;
  825. }
  826. if (!Next())
  827. {
  828. if (*pQualName)
  829. delete *pQualName;
  830. *pQualName = 0;
  831. return WBEM_E_INVALID_SYNTAX;
  832. }
  833. return NO_ERROR;
  834. }
  835. //***************************************************************************
  836. //
  837. // <col_ref_rest> ::= COMMA <col_ref_list>;
  838. // <col_ref_rest> ::= <>;
  839. //
  840. //***************************************************************************
  841. int CWQLParser::col_ref_rest(IN OUT SWQLNode_TableRefs *pTblRefs)
  842. {
  843. int nRes;
  844. if (m_nCurrentToken != WQL_TOK_COMMA)
  845. return NO_ERROR;
  846. if (!Next())
  847. return WBEM_E_INVALID_SYNTAX;
  848. nRes = col_ref_list(pTblRefs);
  849. return nRes;
  850. }
  851. //***************************************************************************
  852. //
  853. // <from_clause> ::= <table_list>;
  854. // <from_clause> ::= <wmi_scoped_select>;
  855. //
  856. // <table_list> ::= <single_table_decl> <optional_join>;
  857. //
  858. // <optional_join> ::= <sql89_join_entry>;
  859. // <optional_join> ::= <sql92_join_entry>;
  860. //
  861. // <optional_join> ::= <>; // Unary query
  862. //
  863. //***************************************************************************
  864. int CWQLParser::from_clause(OUT SWQLNode_FromClause **pFrom)
  865. {
  866. int nRes = 0;
  867. SWQLNode_TableRef *pTbl = 0;
  868. std::auto_ptr<SWQLNode_FromClause> pFC (new SWQLNode_FromClause);
  869. if (pFC.get() == 0)
  870. return WBEM_E_OUT_OF_MEMORY;
  871. if (m_nCurrentToken != WQL_TOK_FROM)
  872. {
  873. return WBEM_E_INVALID_SYNTAX;
  874. }
  875. if (!Next())
  876. {
  877. return WBEM_E_INVALID_SYNTAX;
  878. }
  879. // Special case for WMI scope selections.
  880. // ======================================
  881. if (m_nCurrentToken == WQL_TOK_BRACKETED_STRING)
  882. {
  883. nRes = wmi_scoped_select (pFC.get ());
  884. *pFrom = pFC.release();
  885. return nRes;
  886. }
  887. // Otherwise, traditional SQL.
  888. // ===========================
  889. nRes = single_table_decl(&pTbl);
  890. if (nRes)
  891. {
  892. return nRes;
  893. }
  894. // Check for joins.
  895. // ===============
  896. if (m_nCurrentToken == WQL_TOK_COMMA)
  897. {
  898. SWQLNode_Sql89Join *pJoin = 0;
  899. nRes = sql89_join_entry(pTbl, &pJoin);
  900. if (nRes)
  901. {
  902. return nRes;
  903. }
  904. pFC->m_pLeft = pJoin;
  905. }
  906. else
  907. {
  908. if (m_nCurrentToken == WQL_TOK_INNER ||
  909. m_nCurrentToken == WQL_TOK_FULL ||
  910. m_nCurrentToken == WQL_TOK_LEFT ||
  911. m_nCurrentToken == WQL_TOK_RIGHT ||
  912. m_nCurrentToken == WQL_TOK_JOIN
  913. )
  914. {
  915. SWQLNode_Join *pJoin = 0;
  916. nRes = sql92_join_entry(pTbl, &pJoin);
  917. if (nRes)
  918. {
  919. return nRes;
  920. }
  921. pFC->m_pLeft = pJoin;
  922. }
  923. // Single table select (unary query).
  924. // ==================================
  925. else
  926. {
  927. pFC->m_pLeft = pTbl;
  928. }
  929. }
  930. *pFrom = pFC.release();
  931. return NO_ERROR;
  932. }
  933. //***************************************************************************
  934. //
  935. // wmi_scoped_select
  936. //
  937. // '[' objectpath ']' <class-list>
  938. //
  939. // <class-list> ::= CLASS
  940. // <class-list> ::= '{' class1, class2, ...classn '}'
  941. //
  942. //***************************************************************************
  943. //
  944. int CWQLParser::wmi_scoped_select(SWQLNode_FromClause *pFC)
  945. {
  946. // Strip all input up to the next closing bracket.
  947. // ===============================================
  948. SWQLNode_WmiScopedSelect *pSS = new SWQLNode_WmiScopedSelect;
  949. if (!pSS)
  950. throw CX_MemoryException();
  951. pSS->m_pszScope = CloneLPWSTR(m_pTokenText);
  952. if (!pSS->m_pszScope)
  953. {
  954. delete pSS;
  955. throw CX_MemoryException();
  956. }
  957. if (!Next())
  958. goto Error;
  959. if (m_nCurrentToken == WQL_TOK_IDENT)
  960. {
  961. // Get simple class name.
  962. // ======================
  963. LPWSTR pszTmp = CloneLPWSTR(m_pTokenText);
  964. if (pszTmp == 0)
  965. {
  966. delete pSS;
  967. return WBEM_E_OUT_OF_MEMORY;
  968. }
  969. pSS->m_aTables.Add(pszTmp);
  970. if (!Next())
  971. goto Error;
  972. }
  973. else if (m_nCurrentToken == WQL_TOK_OPEN_BRACE)
  974. {
  975. while(1)
  976. {
  977. if (!Next())
  978. goto Error;
  979. if (m_nCurrentToken == WQL_TOK_IDENT)
  980. {
  981. LPWSTR pszTmp = CloneLPWSTR(m_pTokenText);
  982. if (pszTmp == 0)
  983. {
  984. delete pSS;
  985. return WBEM_E_OUT_OF_MEMORY;
  986. }
  987. pSS->m_aTables.Add(pszTmp);
  988. }
  989. else
  990. goto Error;
  991. if (!Next())
  992. goto Error;
  993. if (m_nCurrentToken == WQL_TOK_CLOSE_BRACE)
  994. break;
  995. if (m_nCurrentToken == WQL_TOK_COMMA)
  996. continue;
  997. }
  998. if (!Next())
  999. goto Error;
  1000. }
  1001. // Patch in the node.
  1002. // ==================
  1003. pFC->m_pRight = pSS;
  1004. return NO_ERROR;
  1005. Error:
  1006. delete pSS;
  1007. return WBEM_E_INVALID_SYNTAX;
  1008. }
  1009. //***************************************************************************
  1010. //
  1011. // <sql89_join_entry> ::= COMMA <sql89_join_list>;
  1012. //
  1013. //***************************************************************************
  1014. int CWQLParser::sql89_join_entry(IN SWQLNode_TableRef *pInitialTblRef,
  1015. OUT SWQLNode_Sql89Join **pJoin )
  1016. {
  1017. if (m_nCurrentToken != WQL_TOK_COMMA)
  1018. return WBEM_E_INVALID_SYNTAX;
  1019. if (!Next())
  1020. return WBEM_E_INVALID_SYNTAX;
  1021. return sql89_join_list(pInitialTblRef, pJoin);
  1022. }
  1023. //***************************************************************************
  1024. //
  1025. // <sql89_join_list> ::= <single_table_decl> <sql89_join_rest>;
  1026. //
  1027. // <sql89_join_rest> ::= COMMA <sql89_join_list>;
  1028. // <sql89_join_rest> ::= <>;
  1029. //
  1030. //***************************************************************************
  1031. int CWQLParser::sql89_join_list(IN SWQLNode_TableRef *pInitialTblRef,
  1032. OUT SWQLNode_Sql89Join **pJoin )
  1033. {
  1034. int nRes;
  1035. SWQLNode_Sql89Join *p89Join = new SWQLNode_Sql89Join;
  1036. if (!p89Join)
  1037. return WBEM_E_OUT_OF_MEMORY;
  1038. p89Join->m_aValues.Add(pInitialTblRef);
  1039. while (1)
  1040. {
  1041. SWQLNode_TableRef *pTR = 0;
  1042. nRes = single_table_decl(&pTR);
  1043. if (nRes)
  1044. {
  1045. delete p89Join;
  1046. return nRes;
  1047. }
  1048. p89Join->m_aValues.Add(pTR);
  1049. if (m_nCurrentToken != WQL_TOK_COMMA)
  1050. break;
  1051. if (!Next())
  1052. {
  1053. delete p89Join;
  1054. return WBEM_E_INVALID_SYNTAX;
  1055. }
  1056. }
  1057. *pJoin = p89Join;
  1058. return NO_ERROR;
  1059. }
  1060. //***************************************************************************
  1061. //
  1062. // <where_clause> ::= WQL_TOK_WHERE <rel_expr> <where_options>;
  1063. // <where_clause> ::= <>; // 'where' is not required
  1064. //
  1065. //***************************************************************************
  1066. // done
  1067. int CWQLParser::where_clause(OUT SWQLNode_WhereClause **pRetWhere)
  1068. {
  1069. SWQLNode_WhereClause *pWhere = new SWQLNode_WhereClause;
  1070. if (!pWhere)
  1071. return WBEM_E_OUT_OF_MEMORY;
  1072. *pRetWhere = pWhere;
  1073. SWQLNode_RelExpr *pRelExpr = 0;
  1074. int nRes;
  1075. // 'where' is optional.
  1076. // ====================
  1077. if (m_nCurrentToken == WQL_TOK_WHERE)
  1078. {
  1079. if (!Next())
  1080. return WBEM_E_INVALID_SYNTAX;
  1081. m_uFeatures |= WMIQ_RPNF_WHERE_CLAUSE_PRESENT;
  1082. // Get the primary relational expression for the 'where' clause.
  1083. // =============================================================
  1084. nRes = rel_expr(&pRelExpr);
  1085. if (nRes)
  1086. {
  1087. delete pRelExpr;
  1088. return nRes;
  1089. }
  1090. }
  1091. // Get the options, such as ORDER BY, GROUP BY, etc.
  1092. // =================================================
  1093. SWQLNode_WhereOptions *pWhereOpt = 0;
  1094. nRes = where_options(&pWhereOpt);
  1095. if (nRes)
  1096. {
  1097. delete pRelExpr;
  1098. delete pWhereOpt;
  1099. return nRes;
  1100. }
  1101. pWhere->m_pLeft = pRelExpr;
  1102. pWhere->m_pRight = pWhereOpt;
  1103. m_pRootWhereOptions = pWhereOpt;
  1104. return NO_ERROR;
  1105. }
  1106. //***************************************************************************
  1107. //
  1108. // <where_options> ::=
  1109. // <group_by_clause>
  1110. // <order_by_clause>
  1111. //
  1112. //***************************************************************************
  1113. // done
  1114. int CWQLParser::where_options(OUT SWQLNode_WhereOptions **pRetWhereOpt)
  1115. {
  1116. int nRes;
  1117. *pRetWhereOpt = 0;
  1118. SWQLNode_GroupBy *pGroupBy = 0;
  1119. nRes = group_by_clause(&pGroupBy);
  1120. if (nRes)
  1121. {
  1122. delete pGroupBy;
  1123. return nRes;
  1124. }
  1125. SWQLNode_OrderBy *pOrderBy = 0;
  1126. nRes = order_by_clause(&pOrderBy);
  1127. if (nRes)
  1128. {
  1129. delete pOrderBy;
  1130. delete pGroupBy;
  1131. return nRes;
  1132. }
  1133. SWQLNode_WhereOptions *pWhereOpt = 0;
  1134. if (pGroupBy || pOrderBy)
  1135. {
  1136. pWhereOpt = new SWQLNode_WhereOptions;
  1137. if (!pWhereOpt)
  1138. {
  1139. delete pOrderBy;
  1140. delete pGroupBy;
  1141. return WBEM_E_OUT_OF_MEMORY;
  1142. }
  1143. pWhereOpt->m_pLeft = pGroupBy;
  1144. pWhereOpt->m_pRight = pOrderBy;
  1145. }
  1146. *pRetWhereOpt = pWhereOpt;
  1147. return NO_ERROR;
  1148. }
  1149. //***************************************************************************
  1150. //
  1151. // <group_by_clause> ::= WQL_TOK_GROUP WQL_TOK_BY <col_list> <having_clause>;
  1152. // <group_by_clause> ::= <>;
  1153. //
  1154. //***************************************************************************
  1155. // done
  1156. int CWQLParser::group_by_clause(OUT SWQLNode_GroupBy **pRetGroupBy)
  1157. {
  1158. int nRes;
  1159. *pRetGroupBy = 0;
  1160. if (m_nCurrentToken != WQL_TOK_GROUP)
  1161. return NO_ERROR;
  1162. if (!Next())
  1163. return WBEM_E_INVALID_SYNTAX;
  1164. if (m_nCurrentToken != WQL_TOK_BY)
  1165. return WBEM_E_INVALID_SYNTAX;
  1166. if (!Next())
  1167. return WBEM_E_INVALID_SYNTAX;
  1168. // Get the guts of the GROUP BY.
  1169. // =============================
  1170. SWQLNode_GroupBy *pGroupBy = new SWQLNode_GroupBy;
  1171. if (!pGroupBy)
  1172. {
  1173. return WBEM_E_OUT_OF_MEMORY;
  1174. }
  1175. SWQLNode_ColumnList *pColList = 0;
  1176. nRes = col_list(&pColList);
  1177. if (nRes)
  1178. {
  1179. delete pGroupBy;
  1180. delete pColList;
  1181. return nRes;
  1182. }
  1183. pGroupBy->m_pLeft = pColList;
  1184. // Check for the HAVING clause.
  1185. // ============================
  1186. SWQLNode_Having *pHaving = 0;
  1187. nRes = having_clause(&pHaving);
  1188. if (pHaving)
  1189. pGroupBy->m_pRight = pHaving;
  1190. *pRetGroupBy = pGroupBy;
  1191. m_uFeatures |= WMIQ_RPNF_GROUP_BY_HAVING;
  1192. return NO_ERROR;
  1193. }
  1194. //***************************************************************************
  1195. //
  1196. // <having_clause> ::= WQL_TOK_HAVING <rel_expr>;
  1197. // <having_clause> ::= <>;
  1198. //
  1199. //***************************************************************************
  1200. // done
  1201. int CWQLParser::having_clause(OUT SWQLNode_Having **pRetHaving)
  1202. {
  1203. int nRes;
  1204. *pRetHaving = 0;
  1205. if (m_nCurrentToken != WQL_TOK_HAVING)
  1206. return NO_ERROR;
  1207. if (!Next())
  1208. return WBEM_E_INVALID_SYNTAX;
  1209. // If here, we have a HAVING clause.
  1210. // =================================
  1211. SWQLNode_RelExpr *pRelExpr = 0;
  1212. nRes = rel_expr(&pRelExpr);
  1213. if (nRes)
  1214. {
  1215. delete pRelExpr;
  1216. return nRes;
  1217. }
  1218. SWQLNode_Having *pHaving = new SWQLNode_Having;
  1219. if (!pHaving)
  1220. {
  1221. delete pRelExpr;
  1222. return WBEM_E_OUT_OF_MEMORY;
  1223. }
  1224. pHaving->m_pLeft = pRelExpr;
  1225. *pRetHaving = pHaving;
  1226. return NO_ERROR;
  1227. }
  1228. //***************************************************************************
  1229. //
  1230. // <order_by_clause> ::= WQL_TOK_ORDER WQL_TOK_BY <col_list>;
  1231. // <order_by_clause> ::= <>;
  1232. //
  1233. //***************************************************************************
  1234. // done
  1235. int CWQLParser::order_by_clause(OUT SWQLNode_OrderBy **pRetOrderBy)
  1236. {
  1237. int nRes;
  1238. if (m_nCurrentToken != WQL_TOK_ORDER)
  1239. return NO_ERROR;
  1240. if (!Next())
  1241. return WBEM_E_INVALID_SYNTAX;
  1242. if (m_nCurrentToken != WQL_TOK_BY)
  1243. return WBEM_E_INVALID_SYNTAX;
  1244. if (!Next())
  1245. return WBEM_E_INVALID_SYNTAX;
  1246. // If here, we have an ORDER BY clause.
  1247. // ====================================
  1248. m_uFeatures |= WMIQ_RPNF_ORDER_BY;
  1249. SWQLNode_ColumnList *pColList = 0;
  1250. nRes = col_list(&pColList);
  1251. if (nRes)
  1252. {
  1253. delete pColList;
  1254. return nRes;
  1255. }
  1256. SWQLNode_OrderBy *pOrderBy = new SWQLNode_OrderBy;
  1257. if (!pOrderBy)
  1258. {
  1259. delete pColList;
  1260. return WBEM_E_OUT_OF_MEMORY;
  1261. }
  1262. pOrderBy->m_pLeft = pColList;
  1263. *pRetOrderBy = pOrderBy;
  1264. return NO_ERROR;
  1265. }
  1266. //***************************************************************************
  1267. //
  1268. // <single_table_decl> ::= <unbound_table_ident> <table_decl_rest>;
  1269. //
  1270. // <unbound_table_ident> ::= IDENT;
  1271. // <table_decl_rest> ::= <redundant_as> <table_alias>;
  1272. // <table_decl_rest> ::= <>;
  1273. // <table_alias> ::= IDENT;
  1274. //
  1275. // <redundant_as> ::= AS;
  1276. // <redundant_as> ::= <>;
  1277. //
  1278. //***************************************************************************
  1279. // done; no cleanup
  1280. int CWQLParser::single_table_decl(OUT SWQLNode_TableRef **pTblRef)
  1281. {
  1282. if (pTblRef == 0)
  1283. return WBEM_E_CRITICAL_ERROR;
  1284. *pTblRef = 0;
  1285. if (m_nCurrentToken != WQL_TOK_IDENT)
  1286. return WBEM_E_INVALID_SYNTAX;
  1287. SWQLNode_TableRef *pTR = new SWQLNode_TableRef;
  1288. if (!pTR)
  1289. return WBEM_E_OUT_OF_MEMORY;
  1290. pTR->m_pTableName = CloneLPWSTR(m_pTokenText);
  1291. if (pTR->m_pTableName == 0)
  1292. {
  1293. delete pTR;
  1294. return WBEM_E_OUT_OF_MEMORY;
  1295. }
  1296. m_aReferencedTables.Add(m_pTokenText);
  1297. if (!Next())
  1298. {
  1299. delete pTR;
  1300. return WBEM_E_INVALID_SYNTAX;
  1301. }
  1302. if (m_nCurrentToken == WQL_TOK_AS)
  1303. {
  1304. // Here we have a redundant AS and an alias.
  1305. // =========================================
  1306. if (!Next())
  1307. {
  1308. delete pTR;
  1309. return WBEM_E_INVALID_SYNTAX;
  1310. }
  1311. }
  1312. // If no Alias was used, we simply copy the table name into
  1313. // the alias slot.
  1314. // ========================================================
  1315. else
  1316. {
  1317. pTR->m_pAlias = CloneLPWSTR(pTR->m_pTableName);
  1318. if (pTR->m_pAlias == 0)
  1319. {
  1320. delete pTR;
  1321. return WBEM_E_OUT_OF_MEMORY;
  1322. }
  1323. m_aReferencedAliases.Add(pTR->m_pTableName);
  1324. }
  1325. // For the primary select, we are keeping a list of tables
  1326. // we are selecting from.
  1327. // =======================================================
  1328. if ((m_nParseContext & Ctx_Subselect) == 0)
  1329. m_aSelAliases.Add(pTR);
  1330. // Return the pointer to the caller.
  1331. // =================================
  1332. *pTblRef = pTR;
  1333. return NO_ERROR;
  1334. }
  1335. //***************************************************************************
  1336. //
  1337. // SQL-92 Joins.
  1338. //
  1339. // We support:
  1340. // 1. [INNER] JOIN
  1341. // 2. LEFT [OUTER] JOIN
  1342. // 3. RIGHT [OUTER] JOIN
  1343. // 4. FULL [OUTER] JOIN
  1344. //
  1345. //
  1346. // <sql92_join_entry> ::= <simple_join_clause>;
  1347. // <sql92_join_entry> ::= INNER <simple_join_clause>;
  1348. // <sql92_join_entry> ::= FULL <opt_outer> <simple_join_clause>;
  1349. // <sql92_join_entry> ::= LEFT <opt_outer> <simple_join_clause>;
  1350. // <sql92_join_entry> ::= RIGHT <opt_outer> <simple_join_clause>;
  1351. //
  1352. // <opt_outer> ::= WQL_TOK_OUTER;
  1353. // <opt_outer> ::= <>;
  1354. //
  1355. // <simple_join_clause> ::=
  1356. // JOIN
  1357. // <single_table_decl>
  1358. // <on_clause>
  1359. // <sql92_join_continuator>
  1360. //
  1361. // <sql92_join_continuator> ::= <sql92_join_entry>;
  1362. // <sql92_join_continuator> ::= <>;
  1363. //
  1364. //***************************************************************************
  1365. int CWQLParser::sql92_join_entry(
  1366. IN SWQLNode_TableRef *pInitialTblRef, // inherited
  1367. OUT SWQLNode_Join **pJoin // synthesized
  1368. )
  1369. {
  1370. int nRes;
  1371. /* Build a nested join tree bottom up. Currently, the tree is always left-heavy:
  1372. JN = Join Noe
  1373. JP = Join Pair
  1374. OC = On Clause
  1375. TR = Table Ref
  1376. JN
  1377. / \
  1378. JP OC
  1379. / \
  1380. JN TR
  1381. / \
  1382. JP OC
  1383. / \
  1384. TR TR
  1385. */
  1386. // State 1: Attempting to build a new JOIN node.
  1387. // =============================================
  1388. std::auto_ptr<SWQLNode_Join> pCurrentLeftNode;
  1389. SWQLNode_JoinPair *pBottomJP = 0;
  1390. while (1)
  1391. {
  1392. std::auto_ptr<SWQLNode_Join> pJN (new SWQLNode_Join);
  1393. if (pJN.get() == 0)
  1394. return WBEM_E_OUT_OF_MEMORY;
  1395. // Join-type.
  1396. // ==========
  1397. pJN->m_dwJoinType = WQL_FLAG_INNER_JOIN; // Default
  1398. if (m_nCurrentToken == WQL_TOK_INNER)
  1399. {
  1400. if (!Next())
  1401. return WBEM_E_INVALID_SYNTAX;
  1402. pJN->m_dwJoinType = WQL_FLAG_INNER_JOIN;
  1403. }
  1404. else if (m_nCurrentToken == WQL_TOK_FULL)
  1405. {
  1406. if (!Next())
  1407. return WBEM_E_INVALID_SYNTAX;
  1408. if (m_nCurrentToken == WQL_TOK_OUTER)
  1409. if (!Next())
  1410. return WBEM_E_INVALID_SYNTAX;
  1411. pJN->m_dwJoinType = WQL_FLAG_FULL_OUTER_JOIN;
  1412. }
  1413. else if (m_nCurrentToken == WQL_TOK_LEFT)
  1414. {
  1415. if (!Next())
  1416. return WBEM_E_INVALID_SYNTAX;
  1417. if (m_nCurrentToken == WQL_TOK_OUTER)
  1418. if (!Next())
  1419. return WBEM_E_INVALID_SYNTAX;
  1420. pJN->m_dwJoinType = WQL_FLAG_LEFT_OUTER_JOIN;
  1421. }
  1422. else if (m_nCurrentToken == WQL_TOK_RIGHT)
  1423. {
  1424. if (!Next())
  1425. return WBEM_E_INVALID_SYNTAX;
  1426. if (m_nCurrentToken == WQL_TOK_OUTER)
  1427. if (!Next())
  1428. return WBEM_E_INVALID_SYNTAX;
  1429. pJN->m_dwJoinType = WQL_FLAG_RIGHT_OUTER_JOIN;
  1430. }
  1431. // <simple_join_clause>
  1432. // =====================
  1433. if (m_nCurrentToken != WQL_TOK_JOIN)
  1434. {
  1435. return WBEM_E_INVALID_SYNTAX;
  1436. }
  1437. if (!Next())
  1438. return WBEM_E_INVALID_SYNTAX;
  1439. std::auto_ptr<SWQLNode_JoinPair> pJP (new SWQLNode_JoinPair);
  1440. if (pJP.get() == 0)
  1441. return WBEM_E_OUT_OF_MEMORY;
  1442. // Determine the table to which to join.
  1443. // =====================================
  1444. SWQLNode_TableRef *pTR = 0;
  1445. nRes = single_table_decl(&pTR);
  1446. if (nRes)
  1447. return nRes;
  1448. pJP->m_pRight = pTR;
  1449. pJP->m_pLeft = pCurrentLeftNode.release();
  1450. pCurrentLeftNode = pJN;
  1451. if (pBottomJP==0)
  1452. pBottomJP = pJP.get();
  1453. // If FIRSTROW is used, add it in.
  1454. // ===============================
  1455. if (m_nCurrentToken == WQL_TOK_IDENT)
  1456. {
  1457. if (wbem_wcsicmp(L"FIRSTROW", m_pTokenText) != 0)
  1458. return WBEM_E_INVALID_SYNTAX;
  1459. pCurrentLeftNode/*pJN*/->m_dwFlags |= WQL_FLAG_FIRSTROW;
  1460. if (!Next())
  1461. return WBEM_E_INVALID_SYNTAX;
  1462. }
  1463. // Get the ON clause.
  1464. // ==================
  1465. SWQLNode_OnClause *pOC = 0;
  1466. nRes = on_clause(&pOC);
  1467. if (nRes)
  1468. return nRes;
  1469. pCurrentLeftNode/*pJN*/->m_pRight = pOC; // On clause
  1470. pCurrentLeftNode/*pJN*/->m_pLeft = pJP.release();
  1471. // sql92_join_continuator();
  1472. // =========================
  1473. if (m_nCurrentToken == WQL_TOK_INNER ||
  1474. m_nCurrentToken == WQL_TOK_FULL ||
  1475. m_nCurrentToken == WQL_TOK_LEFT ||
  1476. m_nCurrentToken == WQL_TOK_RIGHT ||
  1477. m_nCurrentToken == WQL_TOK_JOIN
  1478. )
  1479. continue;
  1480. break;
  1481. }
  1482. // Return the join node to the caller.
  1483. // ====================================
  1484. // Set
  1485. pBottomJP->m_pLeft = pInitialTblRef;
  1486. *pJoin = pCurrentLeftNode.release();
  1487. return NO_ERROR;
  1488. }
  1489. //***************************************************************************
  1490. //
  1491. // <on_clause> ::= ON <rel_expr>;
  1492. //
  1493. //***************************************************************************
  1494. int CWQLParser::on_clause(OUT SWQLNode_OnClause **pOC)
  1495. {
  1496. if (m_nCurrentToken != WQL_TOK_ON)
  1497. return WBEM_E_INVALID_SYNTAX;
  1498. if (!Next())
  1499. return WBEM_E_INVALID_SYNTAX;
  1500. wmilib::auto_ptr<SWQLNode_OnClause> pNewOC( new SWQLNode_OnClause);
  1501. if (NULL == pNewOC.get()) return WBEM_E_OUT_OF_MEMORY;
  1502. SWQLNode_RelExpr *pRelExpr = 0;
  1503. int nRes = rel_expr(&pRelExpr);
  1504. if (nRes)
  1505. {
  1506. delete pRelExpr;
  1507. return nRes;
  1508. }
  1509. pNewOC->m_pLeft = pRelExpr;
  1510. *pOC = pNewOC.release();
  1511. return NO_ERROR;
  1512. }
  1513. //***************************************************************************
  1514. //
  1515. // <rel_expr> ::= <rel_term> <rel_expr2>;
  1516. //
  1517. // We are creating a new expression or subexpression each time
  1518. // we enter this recursively. No inherited attributes are
  1519. // propagated to this production.
  1520. //
  1521. //***************************************************************************
  1522. int CWQLParser::rel_expr(OUT SWQLNode_RelExpr **pRelExpr)
  1523. {
  1524. int nRes;
  1525. *pRelExpr = 0;
  1526. // Get the new node. This becomes a temporary root.
  1527. // =================================================
  1528. SWQLNode_RelExpr *pRE = 0;
  1529. nRes = rel_term(&pRE);
  1530. if (nRes)
  1531. return nRes;
  1532. // At this point, we have a possible root. If
  1533. // there are OR operations, the root will be
  1534. // replaced by the next function. Otherwise,
  1535. // the call will pass through pRE into pNewRoot.
  1536. // =============================================
  1537. SWQLNode_RelExpr *pNewRoot = 0;
  1538. nRes = rel_expr2(pRE, &pNewRoot);
  1539. if (nRes)
  1540. return nRes;
  1541. // Return the expression to the caller.
  1542. // ====================================
  1543. *pRelExpr = pNewRoot;
  1544. return NO_ERROR;
  1545. }
  1546. //***************************************************************************
  1547. //
  1548. // <rel_expr2> ::= OR <rel_term> <rel_expr2>;
  1549. // <rel_expr2> ::= <>;
  1550. //
  1551. //***************************************************************************
  1552. // done!
  1553. int CWQLParser::rel_expr2(
  1554. IN OUT SWQLNode_RelExpr *pLeftSide,
  1555. OUT SWQLNode_RelExpr **pNewRootRE
  1556. )
  1557. {
  1558. int nRes;
  1559. *pNewRootRE = pLeftSide; // Default for the nullable production
  1560. while (1)
  1561. {
  1562. // Build a series of OR subtrees bottom-up. We use iteration
  1563. // and pointer juggling to simulate recursion.
  1564. // ============================================================
  1565. if (m_nCurrentToken == WQL_TOK_OR)
  1566. {
  1567. if (!Next())
  1568. return WBEM_E_INVALID_SYNTAX;
  1569. SWQLNode_RelExpr *pNewRoot = new SWQLNode_RelExpr;
  1570. if (!pNewRoot)
  1571. return WBEM_E_OUT_OF_MEMORY;
  1572. pNewRoot->m_dwExprType = WQL_TOK_OR;
  1573. pNewRoot->m_pLeft = pLeftSide;
  1574. pLeftSide = pNewRoot;
  1575. *pNewRootRE = pNewRoot; // Communicate this fact to the caller
  1576. SWQLNode_RelExpr *pRight = 0;
  1577. if (nRes = rel_term(&pRight))
  1578. return nRes;
  1579. pNewRoot->m_pRight = pRight;
  1580. // Right node becomes the new subexpr
  1581. }
  1582. else break;
  1583. }
  1584. return NO_ERROR;
  1585. }
  1586. //***************************************************************************
  1587. //
  1588. // <rel_term> ::= <rel_simple_expr> <rel_term2>;
  1589. //
  1590. //***************************************************************************
  1591. // done!
  1592. int CWQLParser::rel_term(
  1593. OUT SWQLNode_RelExpr **pNewTerm
  1594. )
  1595. {
  1596. int nRes;
  1597. SWQLNode_RelExpr *pNewSimple = 0;
  1598. if (nRes = rel_simple_expr(&pNewSimple))
  1599. return nRes;
  1600. SWQLNode_RelExpr *pNewRoot = 0;
  1601. if (nRes = rel_term2(pNewSimple, &pNewRoot))
  1602. return nRes;
  1603. *pNewTerm = pNewRoot;
  1604. return NO_ERROR;
  1605. }
  1606. //***************************************************************************
  1607. //
  1608. // <rel_term2> ::= AND <rel_simple_expr> <rel_term2>;
  1609. // <rel_term2> ::= <>;
  1610. //
  1611. //***************************************************************************
  1612. // done!
  1613. int CWQLParser::rel_term2(
  1614. IN SWQLNode_RelExpr *pLeftSide, // Inherited
  1615. OUT SWQLNode_RelExpr **pNewRootRE // Synthesized
  1616. )
  1617. {
  1618. int nRes;
  1619. *pNewRootRE = pLeftSide; // Default for the nullable production
  1620. while (1)
  1621. {
  1622. // Build a series of AND subtrees bottom-up. We use iteration
  1623. // and pointer juggling to simulate recursion.
  1624. // ============================================================
  1625. if (m_nCurrentToken == WQL_TOK_AND)
  1626. {
  1627. if (!Next())
  1628. return WBEM_E_INVALID_SYNTAX;
  1629. SWQLNode_RelExpr *pNewRoot = new SWQLNode_RelExpr;
  1630. if (!pNewRoot)
  1631. {
  1632. return WBEM_E_OUT_OF_MEMORY;
  1633. }
  1634. pNewRoot->m_dwExprType = WQL_TOK_AND;
  1635. pNewRoot->m_pLeft = pLeftSide;
  1636. pLeftSide = pNewRoot;
  1637. *pNewRootRE = pNewRoot; // Communicate this fact to the caller
  1638. SWQLNode_RelExpr *pRight = 0;
  1639. if (nRes = rel_simple_expr(&pRight))
  1640. return nRes;
  1641. pNewRoot->m_pRight = pRight;
  1642. }
  1643. else break;
  1644. }
  1645. return NO_ERROR;
  1646. }
  1647. //***************************************************************************
  1648. //
  1649. // <rel_simple_expr> ::= NOT <rel_expr>;
  1650. // <rel_simple_expr> ::= OPEN_PAREN <rel_expr> CLOSE_PAREN;
  1651. // <rel_simple_expr> ::= <typed_expr>;
  1652. //
  1653. //***************************************************************************
  1654. // done!
  1655. int CWQLParser::rel_simple_expr(OUT SWQLNode_RelExpr **pRelExpr)
  1656. {
  1657. int nRes;
  1658. *pRelExpr = 0; // Default
  1659. // NOT <rel_expr>
  1660. // ==============
  1661. if (m_nCurrentToken == WQL_TOK_NOT)
  1662. {
  1663. if (!Next())
  1664. return WBEM_E_INVALID_SYNTAX;
  1665. // Allocate a NOT root and place the NOTed subexpr
  1666. // under it.
  1667. // ===============================================
  1668. SWQLNode_RelExpr *pNotRoot = new SWQLNode_RelExpr;
  1669. if (!pNotRoot)
  1670. return WBEM_E_OUT_OF_MEMORY;
  1671. pNotRoot->m_dwExprType = WQL_TOK_NOT;
  1672. SWQLNode_RelExpr *pRelSubExpr = 0;
  1673. if (nRes = rel_expr(&pRelSubExpr))
  1674. return nRes;
  1675. pNotRoot->m_pLeft = pRelSubExpr;
  1676. pNotRoot->m_pRight = NULL; // intentional
  1677. *pRelExpr = pNotRoot;
  1678. return NO_ERROR;
  1679. }
  1680. // OPEN_PAREN <rel_expr> CLOSE_PAREN
  1681. // =================================
  1682. else if (m_nCurrentToken == WQL_TOK_OPEN_PAREN)
  1683. {
  1684. if (!Next())
  1685. return WBEM_E_INVALID_SYNTAX;
  1686. SWQLNode_RelExpr *pSubExpr = 0;
  1687. if (rel_expr(&pSubExpr))
  1688. return WBEM_E_INVALID_SYNTAX;
  1689. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  1690. return WBEM_E_INVALID_SYNTAX;
  1691. if (!Next())
  1692. return WBEM_E_INVALID_SYNTAX;
  1693. *pRelExpr = pSubExpr;
  1694. return NO_ERROR;
  1695. }
  1696. // <typed_expr>
  1697. // ============
  1698. SWQLNode_RelExpr *pSubExpr = 0;
  1699. nRes = typed_expr(&pSubExpr);
  1700. if (nRes)
  1701. return nRes;
  1702. *pRelExpr = pSubExpr;
  1703. return NO_ERROR;
  1704. }
  1705. //***************************************************************************
  1706. //
  1707. // <typed_expr> ::= <typed_subexpr> <rel_op> <typed_subexpr_rh>;
  1708. //
  1709. //***************************************************************************
  1710. // done
  1711. int CWQLParser::typed_expr(OUT SWQLNode_RelExpr **pRelExpr)
  1712. {
  1713. int nRes;
  1714. // Allocate a node for this typed expression.
  1715. // There are no possible child nodes, so <pRelExpr> this becomes
  1716. // a synthesized attribute.
  1717. // =============================================================
  1718. SWQLNode_RelExpr *pRE = new SWQLNode_RelExpr;
  1719. if (!pRE)
  1720. return WBEM_E_OUT_OF_MEMORY;
  1721. pRE->m_dwExprType = WQL_TOK_TYPED_EXPR;
  1722. *pRelExpr = pRE;
  1723. SWQLTypedExpr *pTE = new SWQLTypedExpr;
  1724. if (!pTE)
  1725. return WBEM_E_OUT_OF_MEMORY;
  1726. // Look at the left hand side.
  1727. // ===========================
  1728. nRes = typed_subexpr(pTE);
  1729. if (nRes)
  1730. {
  1731. delete pTE;
  1732. return nRes;
  1733. }
  1734. int nOperator;
  1735. // Get the operator.
  1736. // =================
  1737. nRes = rel_op(nOperator);
  1738. if (nRes)
  1739. return nRes;
  1740. pTE->m_dwRelOperator = DWORD(nOperator);
  1741. if (nOperator == WQL_TOK_ISNULL || nOperator == WQL_TOK_NOT_NULL)
  1742. {
  1743. pRE->m_pTypedExpr = pTE;
  1744. return NO_ERROR;
  1745. }
  1746. // Get the right-hand side.
  1747. // ========================
  1748. nRes = typed_subexpr_rh(pTE);
  1749. if (nRes)
  1750. {
  1751. delete pTE;
  1752. return nRes;
  1753. }
  1754. // Check for IN, NOT IN and a const-list, to change the operator
  1755. // to a more specific variety.
  1756. // =============================================================
  1757. if (pTE->m_pConstList)
  1758. {
  1759. if (pTE->m_dwRelOperator == WQL_TOK_IN)
  1760. pTE->m_dwRelOperator = WQL_TOK_IN_CONST_LIST;
  1761. if (pTE->m_dwRelOperator == WQL_TOK_NOT_IN)
  1762. pTE->m_dwRelOperator = WQL_TOK_NOT_IN_CONST_LIST;
  1763. }
  1764. // Post-processing. If the left side is a const and the right
  1765. // side is a col-ref, flip the operator and swap so that
  1766. // such expressions are normalized with the constant on the
  1767. // right hand side and the column on the left.
  1768. // ============================================================
  1769. if (pTE->m_pConstValue && pTE->m_pJoinColRef)
  1770. {
  1771. pTE->m_dwRelOperator = FlipOperator(pTE->m_dwRelOperator);
  1772. pTE->m_pColRef = pTE->m_pJoinColRef;
  1773. pTE->m_pTableRef = pTE->m_pJoinTableRef;
  1774. pTE->m_pJoinTableRef = 0;
  1775. pTE->m_pJoinColRef = 0;
  1776. DWORD dwTmp = pTE->m_dwRightFlags;
  1777. pTE->m_dwRightFlags = pTE->m_dwLeftFlags;
  1778. pTE->m_dwLeftFlags = dwTmp;
  1779. // Interchange function references.
  1780. // ================================
  1781. pTE->m_pIntrinsicFuncOnColRef = pTE->m_pIntrinsicFuncOnJoinColRef;
  1782. pTE->m_pIntrinsicFuncOnJoinColRef = 0;
  1783. }
  1784. pRE->m_pTypedExpr = pTE;
  1785. return NO_ERROR;
  1786. }
  1787. //***************************************************************************
  1788. //
  1789. // <typed_subexpr> ::= <col_ref>;
  1790. // <typed_subexpr> ::= <function_call>;
  1791. // <typed_subexpr> ::= <typed_const>;
  1792. //
  1793. //***************************************************************************
  1794. // ok
  1795. int CWQLParser::typed_subexpr(
  1796. SWQLTypedExpr *pTE
  1797. )
  1798. {
  1799. int nRes;
  1800. BOOL bStripTrailingParen = FALSE;
  1801. SWQLQualifiedName *pColRef = 0;
  1802. wmilib::auto_buffer<wchar_t> pFuncHolder;
  1803. // Check for <function_call>
  1804. // =========================
  1805. if (m_nCurrentToken == WQL_TOK_UPPER)
  1806. {
  1807. pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED;
  1808. pFuncHolder.reset(CloneLPWSTR(L"UPPER"));
  1809. if (pFuncHolder.get() == 0)
  1810. {
  1811. return WBEM_E_OUT_OF_MEMORY;
  1812. }
  1813. if (!Next())
  1814. return WBEM_E_INVALID_SYNTAX;
  1815. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1816. return WBEM_E_INVALID_SYNTAX;
  1817. if (!Next())
  1818. return WBEM_E_INVALID_SYNTAX;
  1819. bStripTrailingParen = TRUE;
  1820. }
  1821. if (m_nCurrentToken == WQL_TOK_LOWER)
  1822. {
  1823. pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED;
  1824. pFuncHolder.reset(CloneLPWSTR(L"LOWER"));
  1825. if (pFuncHolder.get() == 0)
  1826. {
  1827. return WBEM_E_OUT_OF_MEMORY;
  1828. }
  1829. if (!Next())
  1830. return WBEM_E_INVALID_SYNTAX;
  1831. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1832. return WBEM_E_INVALID_SYNTAX;
  1833. if (!Next())
  1834. return WBEM_E_INVALID_SYNTAX;
  1835. bStripTrailingParen = TRUE;
  1836. }
  1837. if (
  1838. m_nCurrentToken == WQL_TOK_DATEPART ||
  1839. m_nCurrentToken == WQL_TOK_QUALIFIER ||
  1840. m_nCurrentToken == WQL_TOK_ISNULL
  1841. )
  1842. {
  1843. nRes = function_call(TRUE, pTE);
  1844. if (nRes)
  1845. return nRes;
  1846. return NO_ERROR;
  1847. }
  1848. if (m_nCurrentToken == WQL_TOK_QSTRING ||
  1849. m_nCurrentToken == WQL_TOK_INT ||
  1850. m_nCurrentToken == WQL_TOK_HEX_CONST ||
  1851. m_nCurrentToken == WQL_TOK_REAL ||
  1852. m_nCurrentToken == WQL_TOK_CHAR ||
  1853. m_nCurrentToken == WQL_TOK_PROMPT ||
  1854. m_nCurrentToken == WQL_TOK_NULL
  1855. )
  1856. {
  1857. SWQLTypedConst *pTC = 0;
  1858. nRes = typed_const(&pTC);
  1859. if (nRes)
  1860. return nRes;
  1861. pTE->m_pConstValue = pTC;
  1862. pTE->m_dwLeftFlags |= WQL_FLAG_CONST; // Intentional!
  1863. pTE->m_pIntrinsicFuncOnConstValue = pFuncHolder.release();
  1864. goto Exit;
  1865. }
  1866. // If here, must be a <col_ref>.
  1867. // =============================
  1868. nRes = col_ref(&pColRef); // TBD
  1869. if (nRes)
  1870. return nRes;
  1871. pTE->m_pIntrinsicFuncOnColRef = pFuncHolder.release();
  1872. // Convert the col_ref to be part of the current SWQLTypedExpr. We analyze the
  1873. // qualified name and extract the table and col name.
  1874. // ============================================================================
  1875. if (pColRef->m_aFields.Size() == 1)
  1876. {
  1877. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  1878. pTE->m_pColRef = CloneLPWSTR(pCol->m_pName);
  1879. if (pTE->m_pColRef == 0 && pCol->m_pName != 0)
  1880. {
  1881. return WBEM_E_OUT_OF_MEMORY;
  1882. }
  1883. pTE->m_dwLeftFlags |= WQL_FLAG_COLUMN;
  1884. if (pCol->m_bArrayRef)
  1885. {
  1886. pTE->m_dwLeftFlags |= WQL_FLAG_ARRAY_REF;
  1887. pTE->m_dwLeftArrayIndex = pCol->m_dwArrayIndex;
  1888. }
  1889. }
  1890. else if (pColRef->m_aFields.Size() == 2)
  1891. {
  1892. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[1];
  1893. SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  1894. pTE->m_pColRef = CloneLPWSTR(pCol->m_pName);
  1895. if (pTE->m_pColRef == 0 && pCol->m_pName != 0)
  1896. {
  1897. return WBEM_E_OUT_OF_MEMORY;
  1898. }
  1899. pTE->m_pTableRef = CloneLPWSTR(pTbl->m_pName);
  1900. if (pTE->m_pTableRef == 0 && pTbl->m_pName != 0)
  1901. {
  1902. return WBEM_E_OUT_OF_MEMORY;
  1903. }
  1904. pTE->m_dwLeftFlags |= WQL_FLAG_TABLE | WQL_FLAG_COLUMN;
  1905. if (pCol->m_bArrayRef)
  1906. {
  1907. pTE->m_dwLeftFlags |= WQL_FLAG_ARRAY_REF;
  1908. pTE->m_dwLeftArrayIndex = pCol->m_dwArrayIndex;
  1909. }
  1910. }
  1911. // If UPPER or LOWER was used, we have to strip a trailing
  1912. // parenthesis.
  1913. // =======================================================
  1914. Exit:
  1915. delete pColRef;
  1916. if (bStripTrailingParen)
  1917. {
  1918. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  1919. return WBEM_E_INVALID_SYNTAX;
  1920. if (!Next())
  1921. return WBEM_E_INVALID_SYNTAX;
  1922. }
  1923. return NO_ERROR;
  1924. }
  1925. //***************************************************************************
  1926. //
  1927. // <typed_subexpr_rh> ::= <function_call>;
  1928. // <typed_subexpr_rh> ::= <typed_const>;
  1929. // <typed_subexpr_rh> ::= <col_ref>;
  1930. //
  1931. // <typed_subexpr_rh> ::= <in_clause>; // Operator must be _IN or _NOT_IN
  1932. //
  1933. //***************************************************************************
  1934. int CWQLParser::typed_subexpr_rh(IN SWQLTypedExpr *pTE)
  1935. {
  1936. int nRes;
  1937. BOOL bStripTrailingParen = FALSE;
  1938. SWQLQualifiedName *pColRef = 0;
  1939. wmilib::auto_buffer<wchar_t> pFuncHolder;
  1940. // Check for <function_call>
  1941. // =========================
  1942. if (m_nCurrentToken == WQL_TOK_UPPER)
  1943. {
  1944. pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED;
  1945. pFuncHolder.reset(CloneLPWSTR(L"UPPER"));
  1946. if (pFuncHolder.get() == 0)
  1947. {
  1948. return WBEM_E_OUT_OF_MEMORY;
  1949. }
  1950. if (!Next())
  1951. return WBEM_E_INVALID_SYNTAX;
  1952. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1953. return WBEM_E_INVALID_SYNTAX;
  1954. if (!Next())
  1955. return WBEM_E_INVALID_SYNTAX;
  1956. bStripTrailingParen = TRUE;
  1957. }
  1958. if (m_nCurrentToken == WQL_TOK_LOWER)
  1959. {
  1960. pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED;
  1961. pFuncHolder.reset(CloneLPWSTR(L"LOWER"));
  1962. if (pFuncHolder.get() == 0)
  1963. {
  1964. return WBEM_E_OUT_OF_MEMORY;
  1965. }
  1966. if (!Next())
  1967. return WBEM_E_INVALID_SYNTAX;
  1968. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  1969. return WBEM_E_INVALID_SYNTAX;
  1970. if (!Next())
  1971. return WBEM_E_INVALID_SYNTAX;
  1972. bStripTrailingParen = TRUE;
  1973. }
  1974. if (m_nCurrentToken == WQL_TOK_DATEPART ||
  1975. m_nCurrentToken == WQL_TOK_QUALIFIER ||
  1976. m_nCurrentToken == WQL_TOK_ISNULL
  1977. )
  1978. {
  1979. nRes = function_call(FALSE, pTE);
  1980. if (nRes)
  1981. return nRes;
  1982. return NO_ERROR;
  1983. }
  1984. if (m_nCurrentToken == WQL_TOK_QSTRING ||
  1985. m_nCurrentToken == WQL_TOK_INT ||
  1986. m_nCurrentToken == WQL_TOK_HEX_CONST ||
  1987. m_nCurrentToken == WQL_TOK_REAL ||
  1988. m_nCurrentToken == WQL_TOK_CHAR ||
  1989. m_nCurrentToken == WQL_TOK_PROMPT ||
  1990. m_nCurrentToken == WQL_TOK_NULL
  1991. )
  1992. {
  1993. // If we already have a typed constant, then the expression doesn't
  1994. // really make sense, trying to do a relop around two constants,
  1995. // so we'll fail the operation here
  1996. if ( NULL != pTE->m_pConstValue )
  1997. {
  1998. return WBEM_E_INVALID_SYNTAX;
  1999. }
  2000. SWQLTypedConst *pTC = 0;
  2001. nRes = typed_const(&pTC);
  2002. if (nRes)
  2003. return nRes;
  2004. pTE->m_pConstValue = pTC;
  2005. pTE->m_dwRightFlags |= WQL_FLAG_CONST;
  2006. pTE->m_pIntrinsicFuncOnConstValue = pFuncHolder.release();
  2007. // Check for BETWEEN operator, since we have
  2008. // the other end of the range to parse.
  2009. // =========================================
  2010. if (pTE->m_dwRelOperator == WQL_TOK_BETWEEN ||
  2011. pTE->m_dwRelOperator == WQL_TOK_NOT_BETWEEN)
  2012. {
  2013. if (m_nCurrentToken != WQL_TOK_AND)
  2014. return WBEM_E_INVALID_SYNTAX;
  2015. if (!Next())
  2016. return WBEM_E_INVALID_SYNTAX;
  2017. SWQLTypedConst *pTC2 = 0;
  2018. nRes = typed_const(&pTC2);
  2019. if (nRes)
  2020. return nRes;
  2021. pTE->m_pConstValue2 = pTC2;
  2022. pTE->m_dwRightFlags |= WQL_FLAG_CONST_RANGE;
  2023. }
  2024. goto Exit;
  2025. }
  2026. if (m_nCurrentToken == WQL_TOK_OPEN_PAREN)
  2027. {
  2028. // IN clause.
  2029. nRes = in_clause(pTE);
  2030. if (nRes)
  2031. return nRes;
  2032. goto Exit;
  2033. }
  2034. // If here, must be a <col_ref>.
  2035. // =============================
  2036. nRes = col_ref(&pColRef);
  2037. if (nRes)
  2038. return nRes;
  2039. pTE->m_pIntrinsicFuncOnJoinColRef = pFuncHolder.release();
  2040. // Convert the col_ref to be part of the current SWQLTypedExpr. We analyze the
  2041. // qualified name and extract the table and col name.
  2042. // ============================================================================
  2043. if (pColRef->m_aFields.Size() == 1)
  2044. {
  2045. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  2046. pTE->m_pJoinColRef = CloneLPWSTR(pCol->m_pName);
  2047. if (pTE->m_pJoinColRef == 0 && pCol->m_pName != 0)
  2048. {
  2049. return WBEM_E_OUT_OF_MEMORY;
  2050. }
  2051. pTE->m_dwRightFlags |= WQL_FLAG_COLUMN;
  2052. if (pCol->m_bArrayRef)
  2053. {
  2054. pTE->m_dwRightFlags |= WQL_FLAG_ARRAY_REF;
  2055. pTE->m_dwRightArrayIndex = pCol->m_dwArrayIndex;
  2056. }
  2057. }
  2058. else if (pColRef->m_aFields.Size() == 2)
  2059. {
  2060. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[1];
  2061. SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pColRef->m_aFields[0];
  2062. pTE->m_pJoinColRef = CloneLPWSTR(pCol->m_pName);
  2063. if (pTE->m_pJoinColRef == 0 && pCol->m_pName != 0)
  2064. {
  2065. return WBEM_E_OUT_OF_MEMORY;
  2066. }
  2067. pTE->m_pJoinTableRef = CloneLPWSTR(pTbl->m_pName);
  2068. if (pTE->m_pJoinTableRef == 0 && pTbl->m_pName != 0)
  2069. {
  2070. return WBEM_E_OUT_OF_MEMORY;
  2071. }
  2072. pTE->m_dwRightFlags |= WQL_FLAG_TABLE | WQL_FLAG_COLUMN;
  2073. if (pCol->m_bArrayRef)
  2074. {
  2075. pTE->m_dwRightFlags |= WQL_FLAG_ARRAY_REF;
  2076. pTE->m_dwRightArrayIndex = pCol->m_dwArrayIndex;
  2077. }
  2078. }
  2079. Exit:
  2080. delete pColRef;
  2081. if (bStripTrailingParen)
  2082. {
  2083. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  2084. return WBEM_E_INVALID_SYNTAX;
  2085. if (!Next())
  2086. return WBEM_E_INVALID_SYNTAX;
  2087. }
  2088. return NO_ERROR;
  2089. }
  2090. //*****************************************************************************************
  2091. //
  2092. // <rel_op> ::= WQL_TOK_LE;
  2093. // <rel_op> ::= WQL_TOK_LT;
  2094. // <rel_op> ::= WQL_TOK_GE;
  2095. // <rel_op> ::= WQL_TOK_GT;
  2096. // <rel_op> ::= WQL_TOK_EQ;
  2097. // <rel_op> ::= WQL_TOK_NE;
  2098. // <rel_op> ::= WQL_TOK_LIKE;
  2099. // <rel_op> ::= WQL_TOK_BETWEEN;
  2100. // <rel_op> ::= WQL_TOK_IS <is_continuator>;
  2101. // <rel_op> ::= WQL_TOK_ISA;
  2102. // <rel_op> ::= WQL_TOK_IN;
  2103. // <rel_op> ::= WQL_TOK_NOT <not_continuator>;
  2104. //
  2105. // Operator type is returned via <nReturnedOp>
  2106. //
  2107. //*****************************************************************************************
  2108. // done
  2109. int CWQLParser::rel_op(OUT int & nReturnedOp)
  2110. {
  2111. int nRes;
  2112. nReturnedOp = WQL_TOK_ERROR;
  2113. switch (m_nCurrentToken)
  2114. {
  2115. case WQL_TOK_LE:
  2116. nReturnedOp = WQL_TOK_LE;
  2117. if (!Next())
  2118. return WBEM_E_INVALID_SYNTAX;
  2119. return NO_ERROR;
  2120. case WQL_TOK_LT:
  2121. nReturnedOp = WQL_TOK_LT;
  2122. if (!Next())
  2123. return WBEM_E_INVALID_SYNTAX;
  2124. return NO_ERROR;
  2125. case WQL_TOK_GE:
  2126. nReturnedOp = WQL_TOK_GE;
  2127. if (!Next())
  2128. return WBEM_E_INVALID_SYNTAX;
  2129. return NO_ERROR;
  2130. case WQL_TOK_GT:
  2131. nReturnedOp = WQL_TOK_GT;
  2132. if (!Next())
  2133. return WBEM_E_INVALID_SYNTAX;
  2134. return NO_ERROR;
  2135. case WQL_TOK_EQ:
  2136. nReturnedOp = WQL_TOK_EQ;
  2137. if (!Next())
  2138. return WBEM_E_INVALID_SYNTAX;
  2139. return NO_ERROR;
  2140. case WQL_TOK_NE:
  2141. nReturnedOp = WQL_TOK_NE;
  2142. if (!Next())
  2143. return WBEM_E_INVALID_SYNTAX;
  2144. return NO_ERROR;
  2145. case WQL_TOK_LIKE:
  2146. nReturnedOp = WQL_TOK_LIKE;
  2147. if (!Next())
  2148. return WBEM_E_INVALID_SYNTAX;
  2149. return NO_ERROR;
  2150. case WQL_TOK_BETWEEN:
  2151. nReturnedOp = WQL_TOK_BETWEEN;
  2152. if (!Next())
  2153. return WBEM_E_INVALID_SYNTAX;
  2154. return NO_ERROR;
  2155. case WQL_TOK_IS:
  2156. if (!Next())
  2157. return WBEM_E_INVALID_SYNTAX;
  2158. nRes = is_continuator(nReturnedOp);
  2159. return nRes;
  2160. case WQL_TOK_ISA:
  2161. nReturnedOp = WQL_TOK_ISA;
  2162. if (!Next())
  2163. return WBEM_E_INVALID_SYNTAX;
  2164. m_uFeatures |= WMIQ_RPNF_ISA_USED;
  2165. return NO_ERROR;
  2166. case WQL_TOK_IN:
  2167. nReturnedOp = WQL_TOK_IN;
  2168. if (!Next())
  2169. return WBEM_E_INVALID_SYNTAX;
  2170. return NO_ERROR;
  2171. case WQL_TOK_NOT:
  2172. if (!Next())
  2173. return WBEM_E_INVALID_SYNTAX;
  2174. nRes = not_continuator(nReturnedOp);
  2175. return nRes;
  2176. }
  2177. return WBEM_E_INVALID_SYNTAX;
  2178. }
  2179. //*****************************************************************************************
  2180. //
  2181. // <typed_const> ::= WQL_TOK_QSTRING;
  2182. // <typed_const> ::= WQL_TOK_HEX_CONST;
  2183. // <typed_const> ::= WQL_TOK_INT;
  2184. // <typed_const> ::= WQL_TOK_REAL;
  2185. // <typed_const> ::= WQL_TOK_PROMPT;
  2186. // <typed_const> ::= WQL_TOK_NULL;
  2187. //
  2188. //*****************************************************************************************
  2189. // done
  2190. int CWQLParser::typed_const(OUT SWQLTypedConst **pRetVal)
  2191. {
  2192. SWQLTypedConst *pNew = new SWQLTypedConst;
  2193. if (!pNew)
  2194. return WBEM_E_OUT_OF_MEMORY;
  2195. *pRetVal = pNew;
  2196. if (m_nCurrentToken == WQL_TOK_QSTRING
  2197. || m_nCurrentToken == WQL_TOK_PROMPT)
  2198. {
  2199. pNew->m_dwType = VT_LPWSTR;
  2200. pNew->m_bPrompt = (m_nCurrentToken == WQL_TOK_PROMPT);
  2201. pNew->m_Value.m_pString = CloneLPWSTR(m_pTokenText);
  2202. if (NULL == pNew->m_Value.m_pString)
  2203. return WBEM_E_OUT_OF_MEMORY;
  2204. if (!Next())
  2205. goto Error;
  2206. return NO_ERROR;
  2207. }
  2208. if (m_nCurrentToken == WQL_TOK_INT || m_nCurrentToken == WQL_TOK_HEX_CONST)
  2209. {
  2210. unsigned __int64 val = 0;
  2211. BOOL bSigned = FALSE;
  2212. BOOL b64Bit = FALSE;
  2213. if (!GetIntToken(&bSigned, &b64Bit, &val))
  2214. return WBEM_E_INVALID_SYNTAX;
  2215. if (!b64Bit)
  2216. {
  2217. if (bSigned)
  2218. pNew->m_dwType = VT_I4;
  2219. else
  2220. pNew->m_dwType = VT_UI4;
  2221. pNew->m_Value.m_lValue = (LONG) val;
  2222. }
  2223. else // 64 bit moved into string
  2224. {
  2225. if (bSigned)
  2226. pNew->m_dwType = VT_I8;
  2227. else
  2228. pNew->m_dwType = VT_UI8;
  2229. pNew->m_Value.m_i64Value = val;
  2230. }
  2231. if (!Next())
  2232. goto Error;
  2233. return NO_ERROR;
  2234. }
  2235. if (m_nCurrentToken == WQL_TOK_REAL)
  2236. {
  2237. pNew->m_dwType = VT_R8;
  2238. wchar_t *pStopper = 0;
  2239. BSTR bstrValue = SysAllocString(m_pTokenText);
  2240. if (!bstrValue)
  2241. return WBEM_E_OUT_OF_MEMORY;
  2242. _variant_t varValue;
  2243. V_VT(&varValue) = VT_BSTR;
  2244. V_BSTR(&varValue) = bstrValue;
  2245. if (FAILED(VariantChangeTypeEx(&varValue,&varValue, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), VARIANT_NOUSEROVERRIDE, VT_R8)))
  2246. return WBEM_E_INVALID_SYNTAX;
  2247. double d = varValue;
  2248. pNew->m_Value.m_dblValue = d;
  2249. if (!Next())
  2250. goto Error;
  2251. return NO_ERROR;
  2252. }
  2253. if (m_nCurrentToken == WQL_TOK_NULL)
  2254. {
  2255. pNew->m_dwType = VT_NULL;
  2256. if (!Next())
  2257. goto Error;
  2258. return NO_ERROR;
  2259. }
  2260. // Unrecognized constant.
  2261. // ======================
  2262. Error:
  2263. *pRetVal = 0;
  2264. delete pNew;
  2265. return WBEM_E_INVALID_SYNTAX;
  2266. }
  2267. //*****************************************************************************************
  2268. //
  2269. // <datepart_call> ::=
  2270. // WQL_TOK_OPEN_PAREN
  2271. // WQL_TOK_IDENT // yy, mm,dd, hh, mm, ss, year, month, etc.
  2272. // WQL_TOK_COMMA
  2273. // <col_ref>
  2274. // WQL_TOK_CLOSE_PAREN
  2275. //
  2276. //*****************************************************************************************
  2277. static WqlKeyword DateKeyWords[] = // Keep this alphabetized for binary search
  2278. {
  2279. L"DAY", WQL_TOK_DAY,
  2280. L"DD", WQL_TOK_DAY,
  2281. L"HH", WQL_TOK_HOUR,
  2282. L"HOUR", WQL_TOK_HOUR,
  2283. L"MI", WQL_TOK_MINUTE,
  2284. L"MILLISECOND", WQL_TOK_MILLISECOND,
  2285. L"MINUTE", WQL_TOK_MINUTE,
  2286. L"MONTH", WQL_TOK_MONTH,
  2287. L"MM", WQL_TOK_MONTH,
  2288. L"MS", WQL_TOK_MILLISECOND,
  2289. L"YEAR", WQL_TOK_YEAR,
  2290. L"YY", WQL_TOK_YEAR
  2291. };
  2292. const int NumDateKeywords = sizeof(DateKeyWords)/sizeof(WqlKeyword);
  2293. int CWQLParser::datepart_call(OUT SWQLNode_Datepart **pRetDP)
  2294. {
  2295. DWORD dwDatepartTok = 0;
  2296. int nRes;
  2297. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  2298. return WBEM_E_INVALID_SYNTAX;
  2299. if (!Next())
  2300. return WBEM_E_INVALID_SYNTAX;
  2301. if (m_nCurrentToken != WQL_TOK_IDENT)
  2302. return WBEM_E_INVALID_SYNTAX;
  2303. // Ident must be one of the DATEPART identifiers.
  2304. // ==============================================
  2305. BOOL bFound = FALSE;
  2306. int l = 0, u = NumDateKeywords - 1;
  2307. while (l <= u)
  2308. {
  2309. int m = (l + u) / 2;
  2310. if (wbem_wcsicmp(m_pTokenText, DateKeyWords[m].m_pKeyword) < 0)
  2311. u = m - 1;
  2312. else if (wbem_wcsicmp(m_pTokenText, DateKeyWords[m].m_pKeyword) > 0)
  2313. l = m + 1;
  2314. else // Match
  2315. {
  2316. bFound = TRUE;
  2317. dwDatepartTok = DateKeyWords[m].m_nTokenCode;
  2318. break;
  2319. }
  2320. }
  2321. if (!bFound)
  2322. return WBEM_E_INVALID_SYNTAX;
  2323. // If here, we know the date part.
  2324. // ===============================
  2325. if (!Next())
  2326. return WBEM_E_INVALID_SYNTAX;
  2327. if (m_nCurrentToken != WQL_TOK_COMMA)
  2328. return WBEM_E_INVALID_SYNTAX;
  2329. if (!Next())
  2330. return WBEM_E_INVALID_SYNTAX;
  2331. SWQLQualifiedName *pQN = 0;
  2332. nRes = col_ref(&pQN);
  2333. if (nRes)
  2334. return nRes;
  2335. SWQLColRef *pCR = 0;
  2336. nRes = QNameToSWQLColRef(pQN, &pCR);
  2337. if (nRes)
  2338. {
  2339. delete pQN;
  2340. return WBEM_E_INVALID_PARAMETER;
  2341. }
  2342. std::auto_ptr <SWQLColRef> _1(pCR);
  2343. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  2344. return WBEM_E_INVALID_SYNTAX;
  2345. if (!Next())
  2346. return WBEM_E_INVALID_SYNTAX;
  2347. // Return the new node.
  2348. // ====================
  2349. SWQLNode_Datepart *pDP = new SWQLNode_Datepart;
  2350. if (!pDP)
  2351. return WBEM_E_OUT_OF_MEMORY;
  2352. _1.release();
  2353. pDP->m_nDatepart = dwDatepartTok;
  2354. pDP->m_pColRef = pCR;
  2355. *pRetDP = pDP;
  2356. return NO_ERROR;
  2357. }
  2358. //*****************************************************************************************
  2359. //
  2360. // <function_call> ::= WQL_TOK_UPPER <function_call_parms>;
  2361. // <function_call> ::= WQL_TOK_LOWER <function_call_parms>;
  2362. // <function_call> ::= WQL_TOK_DATEPART <datepart_call>;
  2363. // <function_call> ::= WQL_TOK_QUALIFIER <function_call_parms>;
  2364. // <function_call> ::= WQL_TOK_ISNULL <function_call_parms>;
  2365. //
  2366. //*****************************************************************************************
  2367. int CWQLParser::function_call(
  2368. IN BOOL bLeftSide,
  2369. IN SWQLTypedExpr *pTE
  2370. )
  2371. {
  2372. int nRes;
  2373. SWQLNode_Datepart *pDP = 0;
  2374. switch (m_nCurrentToken)
  2375. {
  2376. case WQL_TOK_DATEPART:
  2377. {
  2378. if (!Next())
  2379. return WBEM_E_INVALID_SYNTAX;
  2380. nRes = datepart_call(&pDP);
  2381. if (nRes)
  2382. return nRes;
  2383. if (bLeftSide)
  2384. {
  2385. pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED;
  2386. pTE->m_pLeftFunction = pDP;
  2387. pTE->m_pIntrinsicFuncOnColRef = CloneLPWSTR(L"DATEPART");
  2388. if (!pTE->m_pIntrinsicFuncOnColRef)
  2389. return WBEM_E_OUT_OF_MEMORY;
  2390. }
  2391. else
  2392. {
  2393. pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED;
  2394. pTE->m_pRightFunction = pDP;
  2395. pTE->m_pIntrinsicFuncOnJoinColRef = CloneLPWSTR(L"DATEPART");
  2396. if (!pTE->m_pIntrinsicFuncOnJoinColRef)
  2397. return WBEM_E_OUT_OF_MEMORY;
  2398. }
  2399. return NO_ERROR;
  2400. }
  2401. case WQL_TOK_QUALIFIER:
  2402. trace(("EMIT: QUALIFIER\n"));
  2403. if (!Next())
  2404. return WBEM_E_INVALID_SYNTAX;
  2405. nRes = function_call_parms();
  2406. return nRes;
  2407. case WQL_TOK_ISNULL:
  2408. trace(("EMIT: ISNULL\n"));
  2409. if (!Next())
  2410. return WBEM_E_INVALID_SYNTAX;
  2411. nRes = function_call_parms();
  2412. return nRes;
  2413. }
  2414. return WBEM_E_INVALID_SYNTAX;
  2415. }
  2416. //*****************************************************************************************
  2417. //
  2418. // <function_call_parms> ::=
  2419. // WQL_TOK_OPEN_PAREN
  2420. // <func_args>
  2421. // WQL_TOK_CLOSE_PAREN
  2422. //
  2423. //*****************************************************************************************
  2424. int CWQLParser::function_call_parms()
  2425. {
  2426. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  2427. return WBEM_E_INVALID_SYNTAX;
  2428. if (!Next())
  2429. return WBEM_E_INVALID_SYNTAX;
  2430. int nRes = func_args();
  2431. if (nRes)
  2432. return nRes;
  2433. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  2434. return WBEM_E_INVALID_SYNTAX;
  2435. if (!Next())
  2436. return WBEM_E_INVALID_SYNTAX;
  2437. return NO_ERROR;
  2438. }
  2439. //*****************************************************************************************
  2440. //
  2441. // <func_args> ::= <func_arg> <func_arg_list>;
  2442. // <func_arg_list> ::= WQL_TOK_COMMA <func_arg> <func_arg_list>;
  2443. // <func_arg_list> ::= <>;
  2444. //
  2445. //*****************************************************************************************
  2446. int CWQLParser::func_args()
  2447. {
  2448. int nRes;
  2449. while (1)
  2450. {
  2451. nRes = func_arg();
  2452. if (nRes)
  2453. return nRes;
  2454. if (m_nCurrentToken != WQL_TOK_COMMA)
  2455. break;
  2456. if (!Next())
  2457. return WBEM_E_INVALID_SYNTAX;
  2458. }
  2459. return NO_ERROR;
  2460. }
  2461. //*****************************************************************************************
  2462. //
  2463. // <func_arg> ::= <typed_const>;
  2464. // <func_arg> ::= <col_ref>;
  2465. //
  2466. //*****************************************************************************************
  2467. int CWQLParser::func_arg()
  2468. {
  2469. SWQLQualifiedName *pColRef = 0;
  2470. int nRes;
  2471. if (m_nCurrentToken == WQL_TOK_IDENT)
  2472. {
  2473. nRes = col_ref(&pColRef);
  2474. return nRes;
  2475. }
  2476. SWQLTypedConst *pTC = 0;
  2477. return typed_const(&pTC);
  2478. }
  2479. // Tokens which can follow IS
  2480. // ===========================
  2481. //*****************************************************************************************
  2482. //
  2483. // <is_continuator> ::= WQL_TOK_LIKE;
  2484. // <is_continuator> ::= WQL_TOK_BEFORE;
  2485. // <is_continuator> ::= WQL_TOK_AFTER;
  2486. // <is_continuator> ::= WQL_TOK_BETWEEN;
  2487. // <is_continuator> ::= WQL_TOK_NULL;
  2488. // <is_continuator> ::= WQL_TOK_NOT <not_continuator>;
  2489. // <is_continuator> ::= WQL_TOK_IN;
  2490. // <is_continuator> ::= WQL_TOK_A;
  2491. //
  2492. //*****************************************************************************************
  2493. // done
  2494. int CWQLParser::is_continuator(int & nReturnedOp)
  2495. {
  2496. int nRes;
  2497. nReturnedOp = WQL_TOK_ERROR;
  2498. switch (m_nCurrentToken)
  2499. {
  2500. case WQL_TOK_LIKE:
  2501. nReturnedOp = WQL_TOK_LIKE;
  2502. if (!Next())
  2503. return WBEM_E_INVALID_SYNTAX;
  2504. return NO_ERROR;
  2505. case WQL_TOK_BEFORE:
  2506. nReturnedOp = WQL_TOK_BEFORE;
  2507. if (!Next())
  2508. return WBEM_E_INVALID_SYNTAX;
  2509. return NO_ERROR;
  2510. case WQL_TOK_AFTER:
  2511. nReturnedOp = WQL_TOK_AFTER;
  2512. if (!Next())
  2513. return WBEM_E_INVALID_SYNTAX;
  2514. return NO_ERROR;
  2515. case WQL_TOK_BETWEEN:
  2516. nReturnedOp = WQL_TOK_BETWEEN;
  2517. if (!Next())
  2518. return WBEM_E_INVALID_SYNTAX;
  2519. return NO_ERROR;
  2520. case WQL_TOK_NULL:
  2521. nReturnedOp = WQL_TOK_ISNULL;
  2522. if (!Next())
  2523. return WBEM_E_INVALID_SYNTAX;
  2524. return NO_ERROR;
  2525. case WQL_TOK_NOT:
  2526. if (!Next())
  2527. return WBEM_E_INVALID_SYNTAX;
  2528. nRes = not_continuator(nReturnedOp);
  2529. return nRes;
  2530. case WQL_TOK_IN:
  2531. nReturnedOp = WQL_TOK_IN;
  2532. if (!Next())
  2533. return WBEM_E_INVALID_SYNTAX;
  2534. return NO_ERROR;
  2535. case WQL_TOK_A:
  2536. nReturnedOp = WQL_TOK_ISA;
  2537. if (!Next())
  2538. return WBEM_E_INVALID_SYNTAX;
  2539. m_uFeatures |= WMIQ_RPNF_ISA_USED;
  2540. return NO_ERROR;
  2541. }
  2542. return WBEM_E_INVALID_SYNTAX;
  2543. }
  2544. //*****************************************************************************************
  2545. //
  2546. // <not_continuator> ::= WQL_TOK_LIKE;
  2547. // <not_continuator> ::= WQL_TOK_BEFORE;
  2548. // <not_continuator> ::= WQL_TOK_AFTER;
  2549. // <not_continuator> ::= WQL_TOK_BETWEEN;
  2550. // <not_continuator> ::= WQL_TOK_NULL;
  2551. // <not_continuator> ::= WQL_TOK_IN;
  2552. //
  2553. // Returns WQL_TOK_NOT_LIKE, WQL_TOK_NOT_BEFORE, WQL_TOK_NOT_AFTER, WQL_TOK_NOT_BETWEEN
  2554. // WQL_TOK_NOT_NULL, WQL_TOK_NOT_IN
  2555. //
  2556. //*****************************************************************************************
  2557. // done
  2558. int CWQLParser::not_continuator(int & nReturnedOp)
  2559. {
  2560. nReturnedOp = WQL_TOK_ERROR;
  2561. switch (m_nCurrentToken)
  2562. {
  2563. case WQL_TOK_LIKE:
  2564. nReturnedOp = WQL_TOK_NOT_LIKE;
  2565. if (!Next())
  2566. return WBEM_E_INVALID_SYNTAX;
  2567. return NO_ERROR;
  2568. case WQL_TOK_BEFORE:
  2569. nReturnedOp = WQL_TOK_NOT_BEFORE;
  2570. if (!Next())
  2571. return WBEM_E_INVALID_SYNTAX;
  2572. return NO_ERROR;
  2573. case WQL_TOK_AFTER:
  2574. nReturnedOp = WQL_TOK_NOT_AFTER;
  2575. if (!Next())
  2576. return WBEM_E_INVALID_SYNTAX;
  2577. return NO_ERROR;
  2578. case WQL_TOK_BETWEEN:
  2579. nReturnedOp = WQL_TOK_NOT_BETWEEN;
  2580. if (!Next())
  2581. return WBEM_E_INVALID_SYNTAX;
  2582. return NO_ERROR;
  2583. case WQL_TOK_NULL:
  2584. nReturnedOp = WQL_TOK_NOT_NULL;
  2585. if (!Next())
  2586. return WBEM_E_INVALID_SYNTAX;
  2587. return NO_ERROR;
  2588. case WQL_TOK_IN:
  2589. nReturnedOp = WQL_TOK_NOT_IN;
  2590. if (!Next())
  2591. return WBEM_E_INVALID_SYNTAX;
  2592. return NO_ERROR;
  2593. case WQL_TOK_A:
  2594. nReturnedOp = WQL_TOK_NOT_A;
  2595. if (!Next())
  2596. return WBEM_E_INVALID_SYNTAX;
  2597. return NO_ERROR;
  2598. }
  2599. return WBEM_E_INVALID_SYNTAX;
  2600. }
  2601. //*****************************************************************************************
  2602. //
  2603. // <in_clause> ::= WQL_TOK_OPEN_PAREN <in_type> WQL_TOK_CLOSE_PAREN;
  2604. // <in_type> ::= <subselect_stmt>;
  2605. // <in_type> ::= <const_list>;
  2606. // <in_type> ::= <qualified_name>;
  2607. //
  2608. //*****************************************************************************************
  2609. int CWQLParser::in_clause(IN SWQLTypedExpr *pTE)
  2610. {
  2611. int nRes;
  2612. if (m_nCurrentToken != WQL_TOK_OPEN_PAREN)
  2613. return WBEM_E_INVALID_SYNTAX;
  2614. //int nStPos = m_pLexer->GetCurPos();
  2615. if (!Next())
  2616. return WBEM_E_INVALID_SYNTAX;
  2617. if (m_nCurrentToken == WQL_TOK_SELECT)
  2618. {
  2619. SWQLNode_Select *pSel = 0;
  2620. nRes = subselect_stmt(&pSel);
  2621. if (nRes)
  2622. return nRes;
  2623. // pSel->m_nStPos = nStPos;
  2624. // pSel->m_nEndPos = m_pLexer->GetCurPos() - 1;
  2625. // Translate the IN / NOT IN operator to the specific
  2626. // case of subselects.
  2627. // ==================================================
  2628. if (pTE->m_dwRelOperator == WQL_TOK_IN)
  2629. pTE->m_dwRelOperator = WQL_TOK_IN_SUBSELECT;
  2630. else if (pTE->m_dwRelOperator == WQL_TOK_NOT_IN)
  2631. pTE->m_dwRelOperator = WQL_TOK_NOT_IN_SUBSELECT;
  2632. pTE->m_pSubSelect = pSel;
  2633. }
  2634. else if (m_nCurrentToken == WQL_TOK_IDENT)
  2635. {
  2636. nRes = qualified_name(0);
  2637. if (nRes)
  2638. return nRes;
  2639. }
  2640. // If here, we must have a const-list.
  2641. // ===================================
  2642. else
  2643. {
  2644. SWQLConstList *pCL = 0;
  2645. nRes = const_list(&pCL);
  2646. if (nRes)
  2647. return nRes;
  2648. pTE->m_pConstList = pCL;
  2649. }
  2650. if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN)
  2651. return WBEM_E_INVALID_SYNTAX;
  2652. if (!Next())
  2653. return WBEM_E_INVALID_SYNTAX;
  2654. return NO_ERROR;
  2655. }
  2656. //*****************************************************************************************
  2657. //
  2658. // <const_list> ::= <typed_const> <const_list2>;
  2659. // <const_list2> ::= WQL_TOK_COMMA <typed_const> <const_list2>;
  2660. // <const_list2> ::= <>;
  2661. //
  2662. //*****************************************************************************************
  2663. // done
  2664. int CWQLParser::const_list(SWQLConstList **pRetVal)
  2665. {
  2666. int nRes;
  2667. SWQLConstList *pCL = new SWQLConstList;
  2668. if (!pCL)
  2669. return WBEM_E_OUT_OF_MEMORY;
  2670. *pRetVal = 0;
  2671. while (1)
  2672. {
  2673. if (m_nCurrentToken == WQL_TOK_QSTRING ||
  2674. m_nCurrentToken == WQL_TOK_INT ||
  2675. m_nCurrentToken == WQL_TOK_HEX_CONST ||
  2676. m_nCurrentToken == WQL_TOK_REAL ||
  2677. m_nCurrentToken == WQL_TOK_CHAR ||
  2678. m_nCurrentToken == WQL_TOK_PROMPT ||
  2679. m_nCurrentToken == WQL_TOK_NULL
  2680. )
  2681. {
  2682. SWQLTypedConst *pTC = 0;
  2683. nRes = typed_const(&pTC);
  2684. if (nRes)
  2685. {
  2686. delete pCL;
  2687. return nRes;
  2688. }
  2689. pCL->Add(pTC);
  2690. }
  2691. if (m_nCurrentToken != WQL_TOK_COMMA)
  2692. break;
  2693. // If here, a comma, indicating a following constant.
  2694. // ==================================================
  2695. if (!Next())
  2696. {
  2697. delete pCL;
  2698. return WBEM_E_INVALID_SYNTAX;
  2699. }
  2700. }
  2701. *pRetVal = pCL;
  2702. return NO_ERROR;
  2703. }
  2704. //*****************************************************************************************
  2705. //
  2706. // QUALIFIED_NAME
  2707. //
  2708. // This recognizes a name separated by dots, and recognizes any array references which
  2709. // may occur with those names:
  2710. // a
  2711. // a.b
  2712. // a[n].b[n]
  2713. // a.b.c.d
  2714. // a.b[2].c.d.e[3].f
  2715. // ...etc.
  2716. //
  2717. // <qualified_name> ::= WQL_TOK_IDENT <qualified_name2>;
  2718. // <qualified_name2> ::= WQL_TOK_DOT WQL_TOK_IDENT <qualified_name2>;
  2719. //
  2720. // <qualified_name2> ::=
  2721. // WQL_TOK_OPEN_BRACKET
  2722. // WQL_TOK_INT
  2723. // WQL_TOK_CLOSEBRACKET
  2724. // <qname_becomes_array_ref>
  2725. // <qualified_name2>;
  2726. //
  2727. // <qname_becomes_array_ref> ::= <>; // Dummy to enforce array semantics
  2728. //
  2729. // <qualified_name2> ::= <>;
  2730. //
  2731. //*****************************************************************************************
  2732. // done
  2733. int CWQLParser::qualified_name(OUT SWQLQualifiedName **pRetVal)
  2734. {
  2735. if (pRetVal == 0)
  2736. return WBEM_E_INVALID_PARAMETER;
  2737. *pRetVal = 0;
  2738. if (m_nCurrentToken != WQL_TOK_IDENT && m_nCurrentToken != WQL_TOK_COUNT)
  2739. return WBEM_E_INVALID_SYNTAX;
  2740. SWQLQualifiedName QN;
  2741. SWQLQualifiedNameField *pQNF;
  2742. pQNF = new SWQLQualifiedNameField;
  2743. if (!pQNF)
  2744. return WBEM_E_OUT_OF_MEMORY;
  2745. pQNF->m_pName = CloneLPWSTR(m_pTokenText);
  2746. if (pQNF->m_pName == 0 || QN.Add(pQNF))
  2747. {
  2748. delete pQNF;
  2749. return WBEM_E_OUT_OF_MEMORY;
  2750. }
  2751. if (wbem_wcsicmp(m_pTokenText, L"__CLASS") == 0)
  2752. m_uFeatures |= WMIQ_RPNF_SYSPROP_CLASS_USED;
  2753. if (!Next())
  2754. return WBEM_E_INVALID_SYNTAX;
  2755. while (1)
  2756. {
  2757. if (m_nCurrentToken == WQL_TOK_DOT)
  2758. {
  2759. // Move past dot
  2760. // ==============
  2761. if (!Next())
  2762. return WBEM_E_INVALID_SYNTAX;
  2763. if (!(m_nCurrentToken == WQL_TOK_IDENT || m_nCurrentToken == WQL_TOK_ASTERISK))
  2764. return WBEM_E_INVALID_SYNTAX;
  2765. m_uFeatures |= WMIQ_RPNF_QUALIFIED_NAMES_USED;
  2766. pQNF = new SWQLQualifiedNameField;
  2767. if (!pQNF)
  2768. return WBEM_E_OUT_OF_MEMORY;
  2769. pQNF->m_pName = CloneLPWSTR(m_pTokenText);
  2770. if (!pQNF->m_pName)
  2771. return WBEM_E_OUT_OF_MEMORY;
  2772. QN.Add(pQNF);
  2773. if (wbem_wcsicmp(m_pTokenText, L"__CLASS") == 0)
  2774. m_uFeatures |= WMIQ_RPNF_SYSPROP_CLASS_USED;
  2775. if (!Next())
  2776. return WBEM_E_INVALID_SYNTAX;
  2777. continue;
  2778. }
  2779. if (m_nCurrentToken == WQL_TOK_OPEN_BRACKET)
  2780. {
  2781. if (!Next())
  2782. return WBEM_E_INVALID_SYNTAX;
  2783. if (m_nCurrentToken != WQL_TOK_INT)
  2784. return WBEM_E_INVALID_SYNTAX;
  2785. unsigned __int64 ArrayIndex = 0;
  2786. BOOL bRes, b64Bit, bSigned;
  2787. m_uFeatures |= WMIQ_RPNF_ARRAY_ACCESS_USED;
  2788. bRes = GetIntToken(&bSigned, &b64Bit, &ArrayIndex);
  2789. if (!bRes || b64Bit || bSigned)
  2790. return WBEM_E_INVALID_SYNTAX;
  2791. pQNF->m_bArrayRef = TRUE;
  2792. pQNF->m_dwArrayIndex = (DWORD) ArrayIndex;
  2793. if (!Next())
  2794. return WBEM_E_INVALID_SYNTAX;
  2795. if (m_nCurrentToken != WQL_TOK_CLOSE_BRACKET)
  2796. return WBEM_E_INVALID_SYNTAX;
  2797. if (!Next())
  2798. return WBEM_E_INVALID_SYNTAX;
  2799. continue;
  2800. }
  2801. break;
  2802. }
  2803. // Copy the object and return it. We worked with the copy QN
  2804. // throughout to avoid complicated cleanup problems on errors, since
  2805. // we take advantage of the auto destructor of <QN> in cases
  2806. // above where we return errors.
  2807. // ==================================================================
  2808. SWQLQualifiedName *pRetCopy = new SWQLQualifiedName(QN);
  2809. if (!pRetCopy)
  2810. return WBEM_E_OUT_OF_MEMORY;
  2811. *pRetVal = pRetCopy;
  2812. return NO_ERROR;
  2813. }
  2814. //*****************************************************************************************
  2815. //
  2816. // col_ref
  2817. //
  2818. //*****************************************************************************************
  2819. // done
  2820. int CWQLParser::col_ref(OUT SWQLQualifiedName **pRetVal)
  2821. {
  2822. return qualified_name(pRetVal);
  2823. }
  2824. //*****************************************************************************************
  2825. //
  2826. // <col_list> ::= <col_ref> <col_list_rest>;
  2827. // <col_list_rest> ::= WQL_TOK_COMMA <col_ref> <col_list_rest>;
  2828. // <col_list_rest> ::= <>;
  2829. //
  2830. //*****************************************************************************************
  2831. // <status: SWQLColRef fields to be analyzed and filled in. Testable, though>
  2832. int CWQLParser::col_list(OUT SWQLNode_ColumnList **pRetColList)
  2833. {
  2834. *pRetColList = 0;
  2835. SWQLNode_ColumnList *pColList = new SWQLNode_ColumnList;
  2836. if (!pColList)
  2837. return WBEM_E_OUT_OF_MEMORY;
  2838. while (1)
  2839. {
  2840. SWQLQualifiedName *pColRef = 0;
  2841. int nRes = col_ref(&pColRef);
  2842. if (nRes)
  2843. {
  2844. delete pColList;
  2845. return nRes;
  2846. }
  2847. // If here, we have a legit column to add to the node.
  2848. // ===================================================
  2849. SWQLColRef *pCRef = 0;
  2850. QNameToSWQLColRef(pColRef, &pCRef);
  2851. pColList->m_aColumnRefs.Add(pCRef);
  2852. // Check for sortation indication
  2853. // ==============================
  2854. if (m_nCurrentToken == WQL_TOK_ASC)
  2855. {
  2856. pCRef->m_dwFlags |= WQL_FLAG_SORT_ASC;
  2857. if (!Next())
  2858. {
  2859. delete pColList;
  2860. return WBEM_E_INVALID_SYNTAX;
  2861. }
  2862. }
  2863. else if (m_nCurrentToken == WQL_TOK_DESC)
  2864. {
  2865. pCRef->m_dwFlags |= WQL_FLAG_SORT_DESC;
  2866. if (!Next())
  2867. {
  2868. delete pColList;
  2869. return WBEM_E_INVALID_SYNTAX;
  2870. }
  2871. }
  2872. // Check for a continuation.
  2873. // =========================
  2874. if (m_nCurrentToken != WQL_TOK_COMMA)
  2875. break;
  2876. if (!Next())
  2877. {
  2878. delete pColList;
  2879. return WBEM_E_INVALID_SYNTAX;
  2880. }
  2881. }
  2882. *pRetColList = pColList;
  2883. return NO_ERROR;
  2884. }
  2885. //*****************************************************************************************
  2886. //
  2887. // <subselect_stmt> ::=
  2888. // WQL_TOK_SELECT
  2889. // <select_type>
  2890. // <col_ref> // Must not be an asterisk
  2891. // <from_clause>
  2892. // <where_clause>
  2893. //
  2894. //*****************************************************************************************
  2895. int CWQLParser::subselect_stmt(OUT SWQLNode_Select **pRetSel)
  2896. {
  2897. int nSelType;
  2898. int nRes = 0;
  2899. SWQLNode_FromClause *pFrom = 0;
  2900. SWQLNode_Select *pSel = 0;
  2901. SWQLNode_TableRefs *pTblRefs = 0;
  2902. SWQLNode_WhereClause *pWhere = 0;
  2903. *pRetSel = 0;
  2904. // Verify that we are in a subselect.
  2905. // ==================================
  2906. if (m_nCurrentToken != WQL_TOK_SELECT)
  2907. return WBEM_E_INVALID_SYNTAX;
  2908. if (!Next())
  2909. return WBEM_E_INVALID_SYNTAX;
  2910. // This affects some of the productions, since they behave differently
  2911. // in subselects than in primary selects.
  2912. // ===================================================================
  2913. m_nParseContext = Ctx_Subselect;
  2914. // If here, we are definitely in a subselect, so
  2915. // allocate a new node.
  2916. // ==============================================
  2917. pSel = new SWQLNode_Select;
  2918. if (!pSel)
  2919. return WBEM_E_OUT_OF_MEMORY;
  2920. pTblRefs = new SWQLNode_TableRefs;
  2921. if (!pTblRefs)
  2922. {
  2923. delete pSel;
  2924. return WBEM_E_OUT_OF_MEMORY;
  2925. }
  2926. pSel->m_pLeft = pTblRefs;
  2927. // Find the select type.
  2928. // =====================
  2929. nRes = select_type(nSelType);
  2930. if (nRes)
  2931. return nRes;
  2932. pTblRefs->m_nSelectType = nSelType; // ALL, DISTINCT
  2933. // Get the column list. In this case
  2934. // it must be a single column and not
  2935. // an asterisk.
  2936. // ====================================
  2937. nRes = col_ref_list(pTblRefs);
  2938. if (nRes)
  2939. return nRes;
  2940. // Get the FROM clause and patch it in.
  2941. // =====================================
  2942. nRes = from_clause(&pFrom);
  2943. if (nRes)
  2944. return nRes;
  2945. pTblRefs->m_pRight = pFrom;
  2946. // Get the WHERE clause.
  2947. // =====================
  2948. nRes = where_clause(&pWhere);
  2949. if (nRes)
  2950. return nRes;
  2951. pSel->m_pRight = pWhere;
  2952. *pRetSel = pSel;
  2953. m_nParseContext = Ctx_Default; // No longer in a subselect
  2954. return NO_ERROR;
  2955. }
  2956. /////////////////////////////////////////////////////////////////////////////
  2957. //
  2958. // Containers
  2959. //
  2960. /////////////////////////////////////////////////////////////////////////////
  2961. //***************************************************************************
  2962. //
  2963. // SWQLTypedConst constructor
  2964. //
  2965. //***************************************************************************
  2966. // done
  2967. SWQLTypedConst::SWQLTypedConst()
  2968. {
  2969. m_dwType = VT_NULL;
  2970. m_bPrompt = false;
  2971. memset(&m_Value, 0, sizeof(m_Value));
  2972. }
  2973. //***************************************************************************
  2974. //
  2975. // SWQLTypedConst::operator =
  2976. //
  2977. //***************************************************************************
  2978. // done
  2979. SWQLTypedConst & SWQLTypedConst::operator = (SWQLTypedConst &Src)
  2980. {
  2981. Empty();
  2982. if (Src.m_dwType == VT_LPWSTR)
  2983. {
  2984. m_Value.m_pString = CloneLPWSTR(Src.m_Value.m_pString);
  2985. if (CloneFailed(m_Value.m_pString,Src.m_Value.m_pString))
  2986. throw CX_MemoryException();
  2987. }
  2988. else
  2989. {
  2990. m_Value = Src.m_Value;
  2991. }
  2992. m_dwType = Src.m_dwType;
  2993. m_bPrompt = Src.m_bPrompt;
  2994. return *this;
  2995. }
  2996. //***************************************************************************
  2997. //
  2998. // SWQLTypedConst::Empty()
  2999. //
  3000. //***************************************************************************
  3001. // done
  3002. void SWQLTypedConst::Empty()
  3003. {
  3004. if (m_dwType == VT_LPWSTR)
  3005. delete [] m_Value.m_pString;
  3006. m_bPrompt = false;
  3007. }
  3008. //***************************************************************************
  3009. //
  3010. // SWQLConstList::operator =
  3011. //
  3012. //***************************************************************************
  3013. // done
  3014. SWQLConstList & SWQLConstList::operator = (SWQLConstList & Src)
  3015. {
  3016. Empty();
  3017. for (int i = 0; i < Src.m_aValues.Size(); i++)
  3018. {
  3019. SWQLTypedConst *pC = (SWQLTypedConst *) Src.m_aValues[i];
  3020. m_aValues.Add(new SWQLTypedConst(*pC));
  3021. }
  3022. return *this;
  3023. }
  3024. //***************************************************************************
  3025. //
  3026. // SWQLConstList::Empty
  3027. //
  3028. //***************************************************************************
  3029. // done
  3030. void SWQLConstList::Empty()
  3031. {
  3032. for (int i = 0; i < m_aValues.Size(); i++)
  3033. delete (SWQLTypedConst *) m_aValues[i];
  3034. m_aValues.Empty();
  3035. }
  3036. //***************************************************************************
  3037. //
  3038. // SWQLQualifiedName::operator =
  3039. //
  3040. //***************************************************************************
  3041. // done
  3042. SWQLQualifiedName & SWQLQualifiedName::operator = (SWQLQualifiedName &Src)
  3043. {
  3044. Empty();
  3045. for (int i = 0; i < Src.m_aFields.Size(); i++)
  3046. {
  3047. SWQLQualifiedNameField *pQN = new SWQLQualifiedNameField;
  3048. if (!pQN)
  3049. throw CX_MemoryException();
  3050. *pQN = *(SWQLQualifiedNameField *) Src.m_aFields[i];
  3051. m_aFields.Add(pQN);
  3052. }
  3053. return *this;
  3054. }
  3055. //***************************************************************************
  3056. //
  3057. // SWQLQualifiedNameField::operator =
  3058. //
  3059. //***************************************************************************
  3060. // done
  3061. SWQLQualifiedNameField &
  3062. SWQLQualifiedNameField::operator =(SWQLQualifiedNameField &Src)
  3063. {
  3064. Empty();
  3065. m_bArrayRef = Src.m_bArrayRef;
  3066. m_pName = CloneLPWSTR(Src.m_pName);
  3067. if (CloneFailed(m_pName,Src.m_pName))
  3068. throw CX_MemoryException();
  3069. m_dwArrayIndex = Src.m_dwArrayIndex;
  3070. return *this;
  3071. }
  3072. //***************************************************************************
  3073. //
  3074. // SWQLNode_ColumnList destructor
  3075. //
  3076. //***************************************************************************
  3077. // tbd
  3078. //***************************************************************************
  3079. //
  3080. // QNameToSWQLColRef
  3081. //
  3082. // Translates a qualified name to a SWQLColRef structure and embeds
  3083. // the q-name into the struct (since that is a field).
  3084. //
  3085. //***************************************************************************
  3086. int CWQLParser::QNameToSWQLColRef(
  3087. IN SWQLQualifiedName *pQName,
  3088. OUT SWQLColRef **pRetVal
  3089. )
  3090. {
  3091. *pRetVal = 0;
  3092. if (pQName == 0 || pRetVal == 0)
  3093. return WBEM_E_INVALID_PARAMETER;
  3094. SWQLColRef *pCR = new SWQLColRef;
  3095. if (!pCR)
  3096. return WBEM_E_OUT_OF_MEMORY;
  3097. // Algorithm: With a two name sequence, assume that the first name is
  3098. // the table and that the second name is the column. If multiple
  3099. // names occur, then we set the SWQLColRef type to WQL_FLAG_COMPLEX
  3100. // and just take the last name for the column.
  3101. // ==================================================================
  3102. if (pQName->m_aFields.Size() == 2)
  3103. {
  3104. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pQName->m_aFields[1];
  3105. SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pQName->m_aFields[0];
  3106. pCR->m_pColName = CloneLPWSTR(pCol->m_pName);
  3107. pCR->m_pTableRef = CloneLPWSTR(pTbl->m_pName);
  3108. if (!pCR->m_pColName || !pCR->m_pTableRef)
  3109. return WBEM_E_OUT_OF_MEMORY;
  3110. pCR->m_dwFlags = WQL_FLAG_TABLE | WQL_FLAG_COLUMN;
  3111. if (wbem_wcsicmp(L"*", pCol->m_pName) == 0)
  3112. pCR->m_dwFlags |= WQL_FLAG_ASTERISK;
  3113. if (pCol->m_bArrayRef)
  3114. {
  3115. pCR->m_dwFlags |= WQL_FLAG_ARRAY_REF;
  3116. pCR->m_dwArrayIndex = pCol->m_dwArrayIndex;
  3117. }
  3118. }
  3119. else if (pQName->m_aFields.Size() == 1)
  3120. {
  3121. SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pQName->m_aFields[0];
  3122. pCR->m_pColName = CloneLPWSTR(pCol->m_pName);
  3123. if (!pCR->m_pColName)
  3124. return WBEM_E_OUT_OF_MEMORY;
  3125. pCR->m_dwFlags |= WQL_FLAG_COLUMN;
  3126. if (wbem_wcsicmp(L"*", pCol->m_pName) == 0)
  3127. pCR->m_dwFlags |= WQL_FLAG_ASTERISK;
  3128. if (pCol->m_bArrayRef)
  3129. {
  3130. pCR->m_dwFlags |= WQL_FLAG_ARRAY_REF;
  3131. pCR->m_dwArrayIndex = pCol->m_dwArrayIndex;
  3132. }
  3133. }
  3134. // Complex case.
  3135. // =============
  3136. else
  3137. {
  3138. pCR->m_dwFlags = WQL_FLAG_COMPLEX_NAME;
  3139. }
  3140. // Copy the qualified name.
  3141. // ========================
  3142. pCR->m_pQName = pQName;
  3143. *pRetVal = pCR;
  3144. return NO_ERROR;;
  3145. }
  3146. //***************************************************************************
  3147. //
  3148. // SWQLNode_ColumnList::DebugDump
  3149. //
  3150. //***************************************************************************
  3151. void SWQLNode_ColumnList::DebugDump()
  3152. {
  3153. printf("---SWQLNode_ColumnList---\n");
  3154. for (int i = 0; i < m_aColumnRefs.Size(); i++)
  3155. {
  3156. SWQLColRef *pCR = (SWQLColRef *) m_aColumnRefs[i];
  3157. if (pCR)
  3158. pCR->DebugDump();
  3159. }
  3160. printf("---End SWQLNode_ColumnList---\n");
  3161. }
  3162. //***************************************************************************
  3163. //
  3164. //***************************************************************************
  3165. void SWQLNode_TableRefs::DebugDump()
  3166. {
  3167. printf("********** BEGIN SWQLNode_TableRefs *************\n");
  3168. printf("Select type = ");
  3169. if (m_nSelectType & WQL_FLAG_COUNT)
  3170. printf("WQL_FLAG_COUNT ");
  3171. if (m_nSelectType & WQL_FLAG_ALL)
  3172. printf("WQL_FLAG_ALL ");
  3173. if (m_nSelectType & WQL_FLAG_DISTINCT)
  3174. printf("WQL_FLAG_DISTINCT ");
  3175. printf("\n");
  3176. if (m_pLeft)
  3177. m_pLeft->DebugDump();
  3178. if (m_pRight)
  3179. m_pRight->DebugDump();
  3180. printf("********** END SWQLNode_TableRefs *************\n\n\n");
  3181. }
  3182. //***************************************************************************
  3183. //
  3184. //***************************************************************************
  3185. void SWQLNode_FromClause::DebugDump()
  3186. {
  3187. printf("---SWQLNode_FromClause---\n");
  3188. if (m_pLeft == 0)
  3189. return;
  3190. m_pLeft->DebugDump();
  3191. printf("---End SWQLNode_FromClause---\n");
  3192. }
  3193. //***************************************************************************
  3194. //
  3195. //***************************************************************************
  3196. void SWQLNode_Select::DebugDump()
  3197. {
  3198. printf("********** BEGIN SWQLNode_Select *************\n");
  3199. if (m_pLeft)
  3200. m_pLeft->DebugDump();
  3201. if (m_pRight)
  3202. m_pRight->DebugDump();
  3203. printf("********** END SWQLNode_Select *************\n");
  3204. }
  3205. //***************************************************************************
  3206. //
  3207. //***************************************************************************
  3208. void SWQLNode_WmiScopedSelect::DebugDump()
  3209. {
  3210. printf("********** BEGIN SWQLNode_WmiScopedSelect *************\n");
  3211. printf("Scope = %S\n", m_pszScope);
  3212. for (int i = 0; i < m_aTables.Size(); i++)
  3213. {
  3214. printf("Selected table = %S\n", LPWSTR(m_aTables[i]));
  3215. }
  3216. printf("********** END SWQLNode_WmiScopedSelect *************\n");
  3217. }
  3218. //***************************************************************************
  3219. //
  3220. //***************************************************************************
  3221. void SWQLNode_TableRef::DebugDump()
  3222. {
  3223. printf(" ---TableRef---\n");
  3224. printf(" TableName = %S\n", m_pTableName);
  3225. printf(" Alias = %S\n", m_pAlias);
  3226. printf(" ---End TableRef---\n");
  3227. }
  3228. //***************************************************************************
  3229. //
  3230. //***************************************************************************
  3231. void SWQLNode_Join::DebugDump()
  3232. {
  3233. printf("---SWQLNode_Join---\n");
  3234. printf("Join type = ");
  3235. switch (m_dwJoinType)
  3236. {
  3237. case WQL_FLAG_INNER_JOIN : printf("WQL_FLAG_INNER_JOIN "); break;
  3238. case WQL_FLAG_FULL_OUTER_JOIN : printf("WQL_FLAG_FULL_OUTER_JOIN "); break;
  3239. case WQL_FLAG_LEFT_OUTER_JOIN : printf("WQL_FLAG_LEFT_OUTER_JOIN "); break;
  3240. case WQL_FLAG_RIGHT_OUTER_JOIN : printf("WQL_FLAG_RIGHT_OUTER_JOIN "); break;
  3241. default: printf("<error> ");
  3242. }
  3243. if (m_dwFlags & WQL_FLAG_FIRSTROW)
  3244. printf(" (FIRSTROW)");
  3245. printf("\n");
  3246. if (m_pRight)
  3247. m_pRight->DebugDump();
  3248. if (m_pLeft)
  3249. m_pLeft->DebugDump();
  3250. printf("---End SWQLNode_Join---\n");
  3251. }
  3252. //***************************************************************************
  3253. //
  3254. // SWQLNode_Sql89Join::Empty
  3255. //
  3256. //***************************************************************************
  3257. void SWQLNode_Sql89Join::Empty()
  3258. {
  3259. for (int i = 0; i < m_aValues.Size(); i++)
  3260. delete (SWQLNode_TableRef *) m_aValues[i];
  3261. m_aValues.Empty();
  3262. }
  3263. //***************************************************************************
  3264. //
  3265. // SWQLNode_Sql89Join::DebugDump
  3266. //
  3267. //***************************************************************************
  3268. void SWQLNode_Sql89Join::DebugDump()
  3269. {
  3270. printf("\n========== SQL 89 JOIN =================================\n");
  3271. for (int i = 0; i < m_aValues.Size(); i++)
  3272. {
  3273. SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) m_aValues[i];
  3274. if (pTR)
  3275. pTR->DebugDump();
  3276. }
  3277. printf("\n========== END SQL 89 JOIN =============================\n");
  3278. }
  3279. //***************************************************************************
  3280. //
  3281. // SWQLNode_WhereClause::DebugDump
  3282. //
  3283. //***************************************************************************
  3284. void SWQLNode_WhereClause::DebugDump()
  3285. {
  3286. printf("\n========== WHERE CLAUSE ================================\n");
  3287. if (m_pLeft)
  3288. m_pLeft->DebugDump();
  3289. else
  3290. printf(" <no where clause> \n");
  3291. if (m_pRight)
  3292. m_pRight->DebugDump();
  3293. printf("============= END WHERE CLAUSE ============================\n");
  3294. }
  3295. //***************************************************************************
  3296. //
  3297. // SWQLNode_WhereOptions::DebugDump
  3298. //
  3299. //***************************************************************************
  3300. void SWQLNode_WhereOptions::DebugDump()
  3301. {
  3302. printf("---- Where Options ----\n");
  3303. if (m_pLeft)
  3304. m_pLeft->DebugDump();
  3305. if (m_pRight)
  3306. m_pRight->DebugDump();
  3307. printf("---- End Where Options ----\n");
  3308. }
  3309. //***************************************************************************
  3310. //
  3311. // SWQLNode_Having::DebugDump
  3312. //
  3313. //***************************************************************************
  3314. void SWQLNode_Having::DebugDump()
  3315. {
  3316. printf("---- Having ----\n");
  3317. if (m_pLeft)
  3318. m_pLeft->DebugDump();
  3319. if (m_pRight)
  3320. m_pRight->DebugDump();
  3321. printf("---- End Having ----\n");
  3322. }
  3323. //***************************************************************************
  3324. //
  3325. // SWQLNode_GroupBy::DebugDump
  3326. //
  3327. //***************************************************************************
  3328. void SWQLNode_GroupBy::DebugDump()
  3329. {
  3330. printf("---- Group By ----\n");
  3331. if (m_pLeft)
  3332. m_pLeft->DebugDump();
  3333. if (m_pRight)
  3334. m_pRight->DebugDump();
  3335. printf("---- End Group By ----\n");
  3336. }
  3337. //***************************************************************************
  3338. //
  3339. // SWQLNode_RelExpr::DebugDump
  3340. //
  3341. //***************************************************************************
  3342. void SWQLNode_RelExpr::DebugDump()
  3343. {
  3344. if (m_pRight)
  3345. m_pRight->DebugDump();
  3346. printf(" --- SWQLNode_RelExpr ---\n");
  3347. switch (m_dwExprType)
  3348. {
  3349. case WQL_TOK_OR:
  3350. printf(" <WQL_TOK_OR>\n");
  3351. break;
  3352. case WQL_TOK_AND:
  3353. printf(" <WQL_TOK_AND>\n");
  3354. break;
  3355. case WQL_TOK_NOT:
  3356. printf(" <WQL_TOK_NOT>\n");
  3357. break;
  3358. case WQL_TOK_TYPED_EXPR:
  3359. printf(" <WQL_TOK_TYPED_EXPR>\n");
  3360. m_pTypedExpr->DebugDump();
  3361. break;
  3362. default:
  3363. printf(" <invalid>\n");
  3364. }
  3365. printf(" --- END SWQLNode_RelExpr ---\n\n");
  3366. if (m_pLeft)
  3367. m_pLeft->DebugDump();
  3368. }
  3369. //***************************************************************************
  3370. //
  3371. //***************************************************************************
  3372. static LPWSTR OpToStr(DWORD dwOp)
  3373. {
  3374. LPWSTR pRet = 0;
  3375. switch (dwOp)
  3376. {
  3377. case WQL_TOK_EQ: pRet = L" '=' <WQL_TOK_EQ>"; break;
  3378. case WQL_TOK_NE: pRet = L" '!=' <WQL_TOK_NE>"; break;
  3379. case WQL_TOK_GT: pRet = L" '>' <WQL_TOK_GT>"; break;
  3380. case WQL_TOK_LT: pRet = L" '<' <WQL_TOK_LT>"; break;
  3381. case WQL_TOK_GE: pRet = L" '>=' <WQL_TOK_GE>"; break;
  3382. case WQL_TOK_LE: pRet = L" '<=' <WQL_TOK_LE>"; break;
  3383. case WQL_TOK_IN_CONST_LIST : pRet = L" IN <WQL_TOK_IN_CONST_LIST>"; break;
  3384. case WQL_TOK_NOT_IN_CONST_LIST : pRet = L" NOT IN <WQL_TOK_NOT_IN_CONST_LIST>"; break;
  3385. case WQL_TOK_IN_SUBSELECT : pRet = L" IN <WQL_TOK_IN_SUBSELECT>"; break;
  3386. case WQL_TOK_NOT_IN_SUBSELECT : pRet = L" NOT IN <WQL_TOK_NOT_IN_SUBSELECT>"; break;
  3387. case WQL_TOK_ISNULL: pRet = L"<WQL_TOK_ISNULL>"; break;
  3388. case WQL_TOK_NOT_NULL: pRet = L"<WQL_TOK_NOT_NULL>"; break;
  3389. case WQL_TOK_BETWEEN: pRet = L"<WQL_TOK_BETWEEN>"; break;
  3390. case WQL_TOK_NOT_BETWEEN: pRet = L"<WQL_TOK_NOT_BETWEEN>"; break;
  3391. default: pRet = L" <unknown operator>"; break;
  3392. }
  3393. return pRet;
  3394. }
  3395. //***************************************************************************
  3396. //
  3397. //***************************************************************************
  3398. void SWQLTypedExpr::DebugDump()
  3399. {
  3400. printf(" === BEGIN SWQLTypedExpr ===\n");
  3401. printf(" m_pTableRef = %S\n", m_pTableRef);
  3402. printf(" m_pColRef = %S\n", m_pColRef);
  3403. printf(" m_pJoinTableRef = %S\n", m_pJoinTableRef);
  3404. printf(" m_pJoinColRef = %S\n", m_pJoinColRef);
  3405. printf(" m_dwRelOperator = %S\n", OpToStr(m_dwRelOperator));
  3406. // printf(" m_pSubSelect = 0x%X\n", m_pSubSelect);
  3407. printf(" m_dwLeftArrayIndex = %d\n", m_dwLeftArrayIndex);
  3408. printf(" m_dwRightArrayIndex = %d\n", m_dwRightArrayIndex);
  3409. printf(" m_pConstValue = ");
  3410. if (m_pConstValue)
  3411. m_pConstValue->DebugDump();
  3412. else
  3413. printf(" NULL ptr \n");
  3414. printf(" m_pConstValue2 = ");
  3415. if (m_pConstValue2)
  3416. m_pConstValue2->DebugDump();
  3417. else
  3418. printf(" NULL ptr \n");
  3419. printf(" m_dwLeftFlags = (0x%X)", m_dwLeftFlags);
  3420. if (m_dwLeftFlags & WQL_FLAG_COLUMN)
  3421. printf(" WQL_FLAG_COLUMN");
  3422. if (m_dwLeftFlags & WQL_FLAG_TABLE)
  3423. printf(" WQL_FLAG_TABLE");
  3424. if (m_dwLeftFlags & WQL_FLAG_CONST)
  3425. printf(" WQL_FLAG_CONST");
  3426. if (m_dwLeftFlags & WQL_FLAG_COMPLEX_NAME)
  3427. printf(" WQL_FLAG_COMPLEX_NAME");
  3428. if (m_dwLeftFlags & WQL_FLAG_SORT_ASC)
  3429. printf(" WQL_FLAG_SORT_ASC");
  3430. if (m_dwLeftFlags & WQL_FLAG_SORT_DESC)
  3431. printf(" WQL_FLAG_SORT_DESC");
  3432. if (m_dwLeftFlags & WQL_FLAG_FUNCTIONIZED)
  3433. printf(" WQL_FLAG_FUNCTIONIZED (Function=%S)", m_pIntrinsicFuncOnColRef);
  3434. if (m_dwLeftFlags & WQL_FLAG_ARRAY_REF)
  3435. printf(" WQL_FLAG_ARRAY_REF");
  3436. printf("\n");
  3437. printf(" m_dwRightFlags = (0x%X)", m_dwRightFlags);
  3438. if (m_dwRightFlags & WQL_FLAG_COLUMN)
  3439. printf(" WQL_FLAG_COLUMN");
  3440. if (m_dwRightFlags & WQL_FLAG_TABLE)
  3441. printf(" WQL_FLAG_TABLE");
  3442. if (m_dwRightFlags & WQL_FLAG_CONST)
  3443. printf(" WQL_FLAG_CONST");
  3444. if (m_dwRightFlags & WQL_FLAG_COMPLEX_NAME)
  3445. printf(" WQL_FLAG_COMPLEX_NAME");
  3446. if (m_dwLeftFlags & WQL_FLAG_SORT_ASC)
  3447. printf(" WQL_FLAG_SORT_ASC");
  3448. if (m_dwLeftFlags & WQL_FLAG_SORT_DESC)
  3449. printf(" WQL_FLAG_SORT_DESC");
  3450. if (m_dwRightFlags & WQL_FLAG_FUNCTIONIZED)
  3451. {
  3452. printf(" WQL_FLAG_FUNCTIONIZED");
  3453. if (m_pIntrinsicFuncOnJoinColRef)
  3454. printf("(On join col: Function=%S)", m_pIntrinsicFuncOnJoinColRef);
  3455. if (m_pIntrinsicFuncOnConstValue)
  3456. printf("(On const: Function=%S)", m_pIntrinsicFuncOnConstValue);
  3457. }
  3458. if (m_dwRightFlags & WQL_FLAG_ARRAY_REF)
  3459. printf(" WQL_FLAG_ARRAY_REF");
  3460. if (m_dwRightFlags & WQL_FLAG_CONST_RANGE)
  3461. printf(" WQL_FLAG_CONST_RANGE");
  3462. printf("\n");
  3463. if (m_pLeftFunction)
  3464. {
  3465. printf("m_pLeftFunction: \n");
  3466. m_pLeftFunction->DebugDump();
  3467. }
  3468. if (m_pRightFunction)
  3469. {
  3470. printf("m_pRightFunction: \n");
  3471. m_pRightFunction->DebugDump();
  3472. }
  3473. if (m_pConstList)
  3474. {
  3475. printf(" ---Const List---\n");
  3476. for (int i = 0; i < m_pConstList->m_aValues.Size(); i++)
  3477. {
  3478. SWQLTypedConst *pConst = (SWQLTypedConst *) m_pConstList->m_aValues.GetAt(i);
  3479. printf(" ");
  3480. pConst->DebugDump();
  3481. }
  3482. printf(" ---End Const List---\n");
  3483. }
  3484. // Subselects
  3485. // ==========
  3486. if (m_pSubSelect)
  3487. {
  3488. printf(" ------- Begin Subselect ------\n");
  3489. m_pSubSelect->DebugDump();
  3490. printf(" ------- End Subselect ------\n");
  3491. }
  3492. printf("\n");
  3493. printf(" === END SWQLTypedExpr ===\n");
  3494. }
  3495. //***************************************************************************
  3496. //
  3497. //***************************************************************************
  3498. SWQLTypedExpr::SWQLTypedExpr()
  3499. {
  3500. m_pTableRef = 0;
  3501. m_pColRef = 0;
  3502. m_dwRelOperator = 0;
  3503. m_pConstValue = 0;
  3504. m_pConstValue2 = 0;
  3505. m_pJoinTableRef = 0;
  3506. m_pJoinColRef = 0;
  3507. m_pIntrinsicFuncOnColRef = 0;
  3508. m_pIntrinsicFuncOnJoinColRef = 0;
  3509. m_pIntrinsicFuncOnConstValue = 0;
  3510. m_pLeftFunction = 0;
  3511. m_pRightFunction = 0;
  3512. m_pQNRight = 0;
  3513. m_pQNLeft = 0;
  3514. m_dwLeftFlags = 0;
  3515. m_dwRightFlags = 0;
  3516. m_pSubSelect = 0;
  3517. m_dwLeftArrayIndex = 0;
  3518. m_dwRightArrayIndex = 0;
  3519. m_pConstList = 0;
  3520. }
  3521. //***************************************************************************
  3522. //
  3523. //***************************************************************************
  3524. void SWQLTypedExpr::Empty()
  3525. {
  3526. delete [] m_pTableRef;
  3527. delete [] m_pColRef;
  3528. delete m_pConstValue;
  3529. delete m_pConstValue2;
  3530. delete m_pConstList;
  3531. delete [] m_pJoinTableRef;
  3532. delete [] m_pJoinColRef;
  3533. delete [] m_pIntrinsicFuncOnColRef;
  3534. delete [] m_pIntrinsicFuncOnJoinColRef;
  3535. delete [] m_pIntrinsicFuncOnConstValue;
  3536. delete m_pLeftFunction;
  3537. delete m_pRightFunction;
  3538. delete m_pQNRight;
  3539. delete m_pQNLeft;
  3540. delete m_pSubSelect;
  3541. }
  3542. //***************************************************************************
  3543. //
  3544. //***************************************************************************
  3545. //
  3546. void SWQLNode_Delete::DebugDump()
  3547. {
  3548. printf("Delete Node\n");
  3549. printf("FROM:");
  3550. if (m_pLeft)
  3551. m_pLeft->DebugDump();
  3552. printf("WHERE:");
  3553. if (m_pRight)
  3554. m_pRight->DebugDump();
  3555. }
  3556. //***************************************************************************
  3557. //
  3558. //***************************************************************************
  3559. SWQLNode_Delete::~SWQLNode_Delete()
  3560. {
  3561. // nothing for now
  3562. }
  3563. //***************************************************************************
  3564. //
  3565. //***************************************************************************
  3566. void SWQLTypedConst::DebugDump()
  3567. {
  3568. printf(" Typed Const <");
  3569. switch (m_dwType)
  3570. {
  3571. case VT_LPWSTR:
  3572. printf("%S", m_Value.m_pString);
  3573. break;
  3574. case VT_I4:
  3575. printf("%d (0x%X)", m_Value.m_lValue, m_Value.m_lValue);
  3576. break;
  3577. case VT_R8:
  3578. printf("%f", m_Value.m_dblValue);
  3579. break;
  3580. case VT_BOOL:
  3581. printf("(bool) %d", m_Value.m_bValue);
  3582. break;
  3583. case VT_NULL:
  3584. printf(" NULL");
  3585. break;
  3586. default:
  3587. printf(" unknown");
  3588. }
  3589. printf(">\n");
  3590. }
  3591. //***************************************************************************
  3592. //
  3593. //***************************************************************************
  3594. static DWORD FlipOperator(DWORD dwOp)
  3595. {
  3596. switch (dwOp)
  3597. {
  3598. case WQL_TOK_LT: return WQL_TOK_GT;
  3599. case WQL_TOK_LE: return WQL_TOK_GE;
  3600. case WQL_TOK_GT: return WQL_TOK_LT;
  3601. case WQL_TOK_GE: return WQL_TOK_LE;
  3602. }
  3603. return dwOp; // Echo original
  3604. }
  3605. //***************************************************************************
  3606. //
  3607. //***************************************************************************
  3608. void SWQLNode_JoinPair::DebugDump()
  3609. {
  3610. printf("---SWQLNode_JoinPair---\n");
  3611. if (m_pRight)
  3612. m_pRight->DebugDump();
  3613. if (m_pLeft)
  3614. m_pLeft->DebugDump();
  3615. printf("---End SWQLNode_JoinPair---\n");
  3616. }
  3617. void SWQLNode_OnClause::DebugDump()
  3618. {
  3619. printf("---SWQLNode_OnClause---\n");
  3620. if (m_pLeft)
  3621. m_pLeft->DebugDump();
  3622. printf("---END SWQLNode_OnClause---\n");
  3623. }
  3624. //***************************************************************************
  3625. //
  3626. //***************************************************************************
  3627. void SWQLNode_OrderBy::DebugDump()
  3628. {
  3629. printf("\n\n---- 'ORDER BY' Clause ----\n");
  3630. if (m_pLeft)
  3631. m_pLeft->DebugDump();
  3632. printf("---- End 'ORDER BY' Clause ----\n\n");
  3633. }
  3634. //***************************************************************************
  3635. //
  3636. //***************************************************************************
  3637. const LPWSTR CWQLParser::AliasToTable(IN LPWSTR pAlias)
  3638. {
  3639. const CFlexArray *pAliases = GetSelectedAliases();
  3640. for (int i = 0; i < pAliases->Size(); i++)
  3641. {
  3642. SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) pAliases->GetAt(i);
  3643. if (wbem_wcsicmp(pTR->m_pAlias, pAlias) == 0)
  3644. return pTR->m_pTableName;
  3645. }
  3646. return NULL; // Not found
  3647. }
  3648. //***************************************************************************
  3649. //
  3650. //***************************************************************************
  3651. //
  3652. void SWQLNode_Datepart::DebugDump()
  3653. {
  3654. printf(" ----Begin SWQLNode_Datepart----\n");
  3655. switch (m_nDatepart)
  3656. {
  3657. case WQL_TOK_YEAR: printf(" WQL_TOK_YEAR"); break;
  3658. case WQL_TOK_MONTH: printf(" WQL_TOK_MONTH"); break;
  3659. case WQL_TOK_DAY: printf(" WQL_TOK_DAY"); break;
  3660. case WQL_TOK_HOUR: printf(" WQL_TOK_HOUR"); break;
  3661. case WQL_TOK_MINUTE: printf(" WQL_TOK_MINUTE"); break;
  3662. case WQL_TOK_SECOND: printf(" WQL_TOK_SECOND"); break;
  3663. case WQL_TOK_MILLISECOND: printf(" WQL_TOK_MILLISECOND"); break;
  3664. default:
  3665. printf(" -> No datepart specified\n");
  3666. }
  3667. printf("\n");
  3668. if (m_pColRef)
  3669. m_pColRef->DebugDump();
  3670. printf(" ----End SWQLNode_Datepart----\n");
  3671. }
  3672. //***************************************************************************
  3673. //
  3674. //***************************************************************************
  3675. //
  3676. void SWQLNode_ColumnList::Empty()
  3677. {
  3678. for (int i = 0; i < m_aColumnRefs.Size(); i++)
  3679. delete (SWQLColRef *) m_aColumnRefs[i];
  3680. m_aColumnRefs.Empty();
  3681. }
  3682. //***************************************************************************
  3683. //
  3684. //***************************************************************************
  3685. //
  3686. void StrArrayDelete(
  3687. ULONG uSize,
  3688. LPWSTR *pszArray
  3689. )
  3690. {
  3691. if (!pszArray)
  3692. return;
  3693. for (unsigned u = 0; u < uSize; u++)
  3694. delete pszArray[u];
  3695. delete pszArray;
  3696. }
  3697. //***************************************************************************
  3698. //
  3699. //***************************************************************************
  3700. //
  3701. HRESULT StrArrayCopy(
  3702. ULONG uSize,
  3703. LPWSTR *pSrc,
  3704. LPWSTR **pDest
  3705. )
  3706. {
  3707. HRESULT hr = WBEM_S_NO_ERROR;
  3708. LPWSTR *pFinal = new LPWSTR[uSize];
  3709. if (pFinal)
  3710. {
  3711. for (ULONG u = 0; u < uSize; u++)
  3712. {
  3713. pFinal[u] = CloneLPWSTR(pSrc[u]);
  3714. if (!pFinal[u])
  3715. {
  3716. hr = WBEM_E_OUT_OF_MEMORY;
  3717. break;
  3718. }
  3719. }
  3720. if (SUCCEEDED(hr))
  3721. {
  3722. *pDest = pFinal;
  3723. }
  3724. else
  3725. {
  3726. for (ULONG u2 = 0; u2 < u; u2++)
  3727. {
  3728. delete pFinal[u];
  3729. }
  3730. delete [] pFinal;
  3731. }
  3732. }
  3733. else
  3734. hr = WBEM_E_OUT_OF_MEMORY;
  3735. return hr;
  3736. }
  3737. //***************************************************************************
  3738. //
  3739. //***************************************************************************
  3740. //
  3741. CWbemQueryQualifiedName::CWbemQueryQualifiedName()
  3742. {
  3743. Init();
  3744. }
  3745. //***************************************************************************
  3746. //
  3747. //***************************************************************************
  3748. //
  3749. void CWbemQueryQualifiedName::Init()
  3750. {
  3751. m_uVersion = 1;
  3752. m_uTokenType = 1;
  3753. m_uNameListSize = 0;
  3754. m_ppszNameList = 0;
  3755. m_bArraysUsed = 0;
  3756. m_pbArrayElUsed = 0;
  3757. m_puArrayIndex = 0;
  3758. }
  3759. //////////////////////////////////////////////////////////////////////////////////
  3760. // *
  3761. CWbemQueryQualifiedName::~CWbemQueryQualifiedName() { DeleteAll(); }
  3762. void CWbemQueryQualifiedName::DeleteAll()
  3763. {
  3764. StrArrayDelete(m_uNameListSize, (LPWSTR *) m_ppszNameList);
  3765. delete [] m_pbArrayElUsed;
  3766. delete [] m_puArrayIndex;
  3767. }
  3768. //////////////////////////////////////////////////////////////////////////////////
  3769. //
  3770. CWbemQueryQualifiedName::CWbemQueryQualifiedName(CWbemQueryQualifiedName &Src)
  3771. {
  3772. Init();
  3773. *this = Src;
  3774. }
  3775. //////////////////////////////////////////////////////////////////////////////////
  3776. //
  3777. CWbemQueryQualifiedName& CWbemQueryQualifiedName::operator =(CWbemQueryQualifiedName &Src)
  3778. {
  3779. DeleteAll();
  3780. m_uVersion = Src.m_uVersion;
  3781. m_uTokenType = Src.m_uTokenType;
  3782. m_uNameListSize = Src.m_uNameListSize;
  3783. m_ppszNameList = new LPCWSTR[m_uNameListSize];
  3784. m_pbArrayElUsed = new BOOL[m_uNameListSize];
  3785. m_puArrayIndex = new ULONG[m_uNameListSize];
  3786. if (!m_ppszNameList || !m_pbArrayElUsed || !m_puArrayIndex)
  3787. throw CX_MemoryException();
  3788. for (unsigned u = 0; u < m_uNameListSize; u++)
  3789. {
  3790. m_pbArrayElUsed[u] = Src.m_pbArrayElUsed[u];
  3791. m_puArrayIndex[u] = Src.m_puArrayIndex[u];
  3792. }
  3793. if (FAILED(StrArrayCopy(m_uNameListSize, (LPWSTR *) Src.m_ppszNameList, (LPWSTR **) &m_ppszNameList)))
  3794. throw CX_MemoryException();
  3795. return *this;
  3796. };
  3797. //////////////////////////////////////////////////////////////////////////////////
  3798. //
  3799. void CWbemRpnQueryToken::Init()
  3800. {
  3801. m_uVersion = 1;
  3802. m_uTokenType = 0;
  3803. m_uSubexpressionShape = 0;
  3804. m_uOperator = 0;
  3805. m_pRightIdent = 0;
  3806. m_pLeftIdent = 0;
  3807. m_uConstApparentType = 0; // VT_ type
  3808. m_uConst2ApparentType = 0;
  3809. m_Const.m_uVal64 = 0;
  3810. m_Const2.m_uVal64 = 0;
  3811. m_pszLeftFunc = 0;
  3812. m_pszRightFunc = 0;
  3813. }
  3814. ///////////////////////////////////////////////////////////////////////////////////
  3815. //
  3816. //
  3817. CWbemRpnQueryToken::CWbemRpnQueryToken()
  3818. {
  3819. Init();
  3820. }
  3821. ///////////////////////////////////////////////////////////////////////////////////
  3822. //
  3823. //
  3824. void CWbemRpnEncodedQuery::DeleteAll()
  3825. {
  3826. unsigned u = 0;
  3827. for (u = 0; u < m_uSelectListSize; u++)
  3828. {
  3829. SWbemQueryQualifiedName *pQN = m_ppSelectList[u];
  3830. CWbemQueryQualifiedName *pTmp = (CWbemQueryQualifiedName*) pQN;
  3831. delete pTmp;
  3832. }
  3833. delete [] m_puDetectedFeatures;
  3834. delete [] m_ppSelectList;
  3835. delete LPWSTR(m_pszOptionalFromPath);
  3836. StrArrayDelete(m_uFromListSize, (LPWSTR *) m_ppszFromList);
  3837. for (u = 0; u < m_uWhereClauseSize; u++)
  3838. {
  3839. CWbemRpnQueryToken *pTmp = (CWbemRpnQueryToken *) m_ppRpnWhereClause[u];
  3840. delete pTmp;
  3841. }
  3842. m_uWhereClauseSize = 0;
  3843. delete [] m_ppRpnWhereClause;
  3844. StrArrayDelete(m_uOrderByListSize, (LPWSTR *) m_ppszOrderByList);
  3845. }
  3846. //////////////////////////////////////////////////////////////////////////////////
  3847. //
  3848. CWbemRpnQueryToken::~CWbemRpnQueryToken() { DeleteAll(); }
  3849. void CWbemRpnQueryToken::DeleteAll()
  3850. {
  3851. delete (CWbemQueryQualifiedName *) m_pRightIdent;
  3852. delete (CWbemQueryQualifiedName *) m_pLeftIdent;
  3853. if (m_uConstApparentType == VT_LPWSTR)
  3854. {
  3855. delete (LPWSTR) m_Const.m_pszStrVal;
  3856. }
  3857. if (m_uConst2ApparentType == VT_LPWSTR)
  3858. {
  3859. delete (LPWSTR) m_Const2.m_pszStrVal;
  3860. }
  3861. delete LPWSTR(m_pszLeftFunc);
  3862. delete LPWSTR(m_pszRightFunc);
  3863. }
  3864. //////////////////////////////////////////////////////////////////////////////////
  3865. //
  3866. CWbemRpnQueryToken::CWbemRpnQueryToken(CWbemRpnQueryToken &Src)
  3867. {
  3868. Init();
  3869. *this = Src;
  3870. }
  3871. //////////////////////////////////////////////////////////////////////////////////
  3872. //
  3873. CWbemRpnQueryToken& CWbemRpnQueryToken::operator =(CWbemRpnQueryToken &Src)
  3874. {
  3875. // Kill old stuff.
  3876. DeleteAll();
  3877. // Copy new stuff.
  3878. m_pRightIdent = (SWbemQueryQualifiedName *) new CWbemQueryQualifiedName(
  3879. *(CWbemQueryQualifiedName *) Src.m_pRightIdent
  3880. );
  3881. m_pLeftIdent = (SWbemQueryQualifiedName *) new CWbemQueryQualifiedName(
  3882. *(CWbemQueryQualifiedName *) Src.m_pLeftIdent
  3883. );
  3884. if (!m_pRightIdent || !m_pLeftIdent)
  3885. throw CX_MemoryException();
  3886. m_uConstApparentType = Src.m_uConstApparentType;
  3887. m_uConst2ApparentType = Src.m_uConst2ApparentType;
  3888. if (m_uConstApparentType == VT_LPWSTR)
  3889. {
  3890. m_Const.m_pszStrVal = CloneLPWSTR(Src.m_Const.m_pszStrVal);\
  3891. if (!m_Const.m_pszStrVal)
  3892. throw CX_MemoryException();
  3893. }
  3894. else
  3895. m_Const = Src.m_Const;
  3896. if (m_uConst2ApparentType == VT_LPWSTR)
  3897. {
  3898. m_Const2.m_pszStrVal = CloneLPWSTR(Src.m_Const2.m_pszStrVal);
  3899. if (!m_Const2.m_pszStrVal)
  3900. throw CX_MemoryException();
  3901. }
  3902. else
  3903. m_Const2 = Src.m_Const2;
  3904. m_pszLeftFunc = CloneLPWSTR(Src.m_pszLeftFunc);
  3905. if (CloneFailed(m_pszLeftFunc,Src.m_pszLeftFunc))
  3906. throw CX_MemoryException();
  3907. m_pszRightFunc = CloneLPWSTR(Src.m_pszRightFunc);
  3908. if (CloneFailed(m_pszRightFunc,Src.m_pszRightFunc))
  3909. throw CX_MemoryException();
  3910. return *this;
  3911. };
  3912. //////////////////////////////////////////////////////////////////////////////////
  3913. void CWbemRpnEncodedQuery::Init()
  3914. {
  3915. m_uVersion = 1;
  3916. m_uTokenType = 0;
  3917. m_uParsedFeatureMask = 0I64;
  3918. m_uDetectedArraySize = 0;
  3919. m_puDetectedFeatures = 0;
  3920. m_uSelectListSize = 0;
  3921. m_ppSelectList = 0;
  3922. // FROM clause
  3923. // ===========
  3924. m_uFromTargetType = 0;
  3925. m_pszOptionalFromPath = 0;
  3926. m_uFromListSize = 0;
  3927. m_ppszFromList = 0;
  3928. // Where clause
  3929. // ============
  3930. m_uWhereClauseSize = 0;
  3931. m_ppRpnWhereClause = 0;
  3932. // WITHIN value
  3933. // ============
  3934. m_dblWithinPolling = 0.0;
  3935. m_dblWithinWindow = 0.0;
  3936. // ORDER BY
  3937. // ========
  3938. m_uOrderByListSize = 0;
  3939. m_ppszOrderByList = 0;
  3940. m_uOrderDirectionEl = 0;
  3941. }
  3942. ///////////////////////////////////////////////////////////////////////////////////
  3943. //
  3944. //
  3945. CWbemRpnEncodedQuery::CWbemRpnEncodedQuery()
  3946. {
  3947. Init();
  3948. }
  3949. ///////////////////////////////////////////////////////////////////////////////////
  3950. //
  3951. //
  3952. CWbemRpnEncodedQuery::~CWbemRpnEncodedQuery()
  3953. {
  3954. DeleteAll();
  3955. }
  3956. ///////////////////////////////////////////////////////////////////////////////////
  3957. //
  3958. //
  3959. CWbemRpnEncodedQuery::CWbemRpnEncodedQuery(CWbemRpnEncodedQuery &Src)
  3960. {
  3961. Init();
  3962. *this = Src;
  3963. }
  3964. ///////////////////////////////////////////////////////////////////////////////////
  3965. //
  3966. //
  3967. CWbemRpnEncodedQuery& CWbemRpnEncodedQuery::operator=(CWbemRpnEncodedQuery &Src)
  3968. {
  3969. unsigned u;
  3970. // Kill old stuff.
  3971. DeleteAll();
  3972. // Clone new stuff.
  3973. m_uVersion = Src.m_uVersion;
  3974. m_uTokenType = Src.m_uTokenType;
  3975. // General query features
  3976. // ======================
  3977. m_uParsedFeatureMask = Src.m_uParsedFeatureMask;
  3978. m_uDetectedArraySize = Src.m_uDetectedArraySize;
  3979. m_puDetectedFeatures = new ULONG[Src.m_uDetectedArraySize];
  3980. if (!m_puDetectedFeatures)
  3981. throw CX_MemoryException();
  3982. memcpy(m_puDetectedFeatures, Src.m_puDetectedFeatures, sizeof(ULONG) * Src.m_uDetectedArraySize);
  3983. // Values being selected if WMIQ_RPNF_PROJECTION is set
  3984. // =====================================================
  3985. m_uSelectListSize = Src.m_uSelectListSize;
  3986. m_ppSelectList = (SWbemQueryQualifiedName **) new CWbemQueryQualifiedName *[m_uSelectListSize];
  3987. if (!m_ppSelectList)
  3988. throw CX_MemoryException();
  3989. for (u = 0; u < m_uSelectListSize; u++)
  3990. {
  3991. CWbemQueryQualifiedName *p = new CWbemQueryQualifiedName(*(CWbemQueryQualifiedName *) Src.m_ppSelectList[u]);
  3992. if (!p)
  3993. throw CX_MemoryException();
  3994. m_ppSelectList[u] = (SWbemQueryQualifiedName *) p;
  3995. }
  3996. // FROM
  3997. m_uFromTargetType = Src.m_uFromTargetType;
  3998. m_pszOptionalFromPath = CloneLPWSTR(Src.m_pszOptionalFromPath);// NULL if not used
  3999. if (CloneFailed(m_pszOptionalFromPath,Src.m_pszOptionalFromPath))
  4000. throw CX_MemoryException();
  4001. if (FAILED(StrArrayCopy(Src.m_uFromListSize, (LPWSTR *) Src.m_ppszFromList, (LPWSTR **) &m_ppszFromList)))
  4002. throw CX_MemoryException();
  4003. m_uFromListSize = Src.m_uFromListSize;
  4004. // Where clause
  4005. // ============
  4006. m_uWhereClauseSize = Src.m_uWhereClauseSize;
  4007. m_ppRpnWhereClause = new SWbemRpnQueryToken *[m_uWhereClauseSize];
  4008. if (!m_ppRpnWhereClause)
  4009. throw CX_MemoryException();
  4010. for (u = 0; u < m_uWhereClauseSize; u++)
  4011. {
  4012. CWbemRpnQueryToken *pTmp = new CWbemRpnQueryToken(* (CWbemRpnQueryToken *) Src.m_ppRpnWhereClause[u]);
  4013. if (!pTmp)
  4014. throw CX_MemoryException();
  4015. m_ppRpnWhereClause[u] = (SWbemRpnQueryToken *) pTmp;
  4016. }
  4017. // WITHIN value
  4018. // ============
  4019. m_dblWithinPolling = Src.m_dblWithinPolling;
  4020. m_dblWithinWindow = Src.m_dblWithinWindow;
  4021. // ORDER BY
  4022. // ========
  4023. if (FAILED(StrArrayCopy(Src.m_uOrderByListSize, (LPWSTR *) Src.m_ppszOrderByList, (LPWSTR **) &m_ppszOrderByList)))
  4024. throw CX_MemoryException();
  4025. m_uOrderByListSize = Src.m_uOrderByListSize;
  4026. m_uOrderDirectionEl = new ULONG[m_uOrderByListSize];
  4027. if (!m_uOrderDirectionEl)
  4028. throw CX_MemoryException();
  4029. memcpy(m_uOrderDirectionEl, Src.m_uOrderDirectionEl, sizeof(ULONG) * m_uOrderByListSize);
  4030. return *this;
  4031. }
  4032. ///////////////////////////////////////////////////////////////////////////////////
  4033. //
  4034. // Recursively rearranges the tokens from AST to RPN.
  4035. // Nondestructive to the query itself; only stores the pointers.
  4036. //
  4037. //
  4038. HRESULT CWQLParser::BuildRpnWhereClause(
  4039. SWQLNode *pCurrent,
  4040. CFlexArray &aRpnReorg
  4041. )
  4042. {
  4043. if (pCurrent == 0)
  4044. return WBEM_S_NO_ERROR;
  4045. BuildRpnWhereClause(pCurrent->m_pLeft, aRpnReorg);
  4046. BuildRpnWhereClause(pCurrent->m_pRight, aRpnReorg);
  4047. aRpnReorg.Add(pCurrent);
  4048. return WBEM_S_NO_ERROR;
  4049. }
  4050. //***************************************************************************
  4051. //
  4052. //***************************************************************************
  4053. //
  4054. int CWQLParser::update_stmt(OUT SWQLNode_Update **pUpdStmt)
  4055. {
  4056. return WBEM_E_INVALID_SYNTAX;
  4057. }
  4058. //***************************************************************************
  4059. //
  4060. //***************************************************************************
  4061. //
  4062. int CWQLParser::insert_stmt(OUT SWQLNode_Insert **pInsStmt)
  4063. {
  4064. return WBEM_E_INVALID_SYNTAX;
  4065. }
  4066. //***************************************************************************
  4067. //
  4068. //***************************************************************************
  4069. //
  4070. HRESULT CWQLParser::BuildSelectList(CWbemRpnEncodedQuery *pQuery)
  4071. {
  4072. SWQLNode_ColumnList *pCL = (SWQLNode_ColumnList *) GetColumnList();
  4073. if (pCL == 0)
  4074. return WBEM_E_INVALID_QUERY;
  4075. ULONG uSize = (ULONG) pCL->m_aColumnRefs.Size();
  4076. pQuery->m_uSelectListSize = uSize;
  4077. pQuery->m_ppSelectList = (SWbemQueryQualifiedName **)
  4078. new CWbemQueryQualifiedName *[uSize];
  4079. if (!pQuery->m_ppSelectList)
  4080. {
  4081. throw CX_MemoryException();
  4082. }
  4083. for (ULONG u = 0; u < uSize; u++)
  4084. {
  4085. SWQLColRef *pCol = (SWQLColRef *) pCL->m_aColumnRefs[u];
  4086. SWbemQueryQualifiedName *pTemp = (SWbemQueryQualifiedName *) new CWbemQueryQualifiedName;
  4087. if (!pTemp)
  4088. throw CX_MemoryException();
  4089. unsigned uNameListSize = 1;
  4090. if (pCol->m_pTableRef)
  4091. uNameListSize = 2;
  4092. pTemp->m_uNameListSize = uNameListSize;
  4093. pTemp->m_ppszNameList = (LPCWSTR *) new LPWSTR[uNameListSize];
  4094. if (!pTemp->m_ppszNameList)
  4095. {
  4096. delete pTemp;
  4097. throw CX_MemoryException();
  4098. }
  4099. if (uNameListSize == 1)
  4100. {
  4101. pTemp->m_ppszNameList[0] = CloneLPWSTR(pCol->m_pColName);
  4102. if (!pTemp->m_ppszNameList[0])
  4103. {
  4104. delete pTemp;
  4105. throw CX_MemoryException();
  4106. }
  4107. }
  4108. else
  4109. {
  4110. pTemp->m_ppszNameList[0] = CloneLPWSTR(pCol->m_pTableRef);
  4111. if (!pTemp->m_ppszNameList[0])
  4112. {
  4113. delete pTemp;
  4114. throw CX_MemoryException();
  4115. }
  4116. pTemp->m_ppszNameList[1] = CloneLPWSTR(pCol->m_pColName);
  4117. if (!pTemp->m_ppszNameList[1])
  4118. {
  4119. delete pTemp;
  4120. throw CX_MemoryException();
  4121. }
  4122. }
  4123. pQuery->m_ppSelectList[u] = pTemp;
  4124. }
  4125. return 0;
  4126. }
  4127. //***************************************************************************
  4128. //
  4129. //***************************************************************************
  4130. //
  4131. HRESULT CWQLParser::BuildFromClause(CWbemRpnEncodedQuery *pQuery)
  4132. {
  4133. SWQLNode_FromClause *pFrom = (SWQLNode_FromClause *) GetFromClause();
  4134. if (pFrom == NULL)
  4135. return WBEM_E_INVALID_QUERY;
  4136. // Check left node for traditional SQL
  4137. // Check right node for WMI scoped select
  4138. if (pFrom->m_pLeft)
  4139. {
  4140. SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) pFrom->m_pLeft;
  4141. pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_UNARY;
  4142. pQuery->m_uFromListSize = 1;
  4143. pQuery->m_ppszFromList = (LPCWSTR *) new LPWSTR[1];
  4144. if (!pQuery->m_ppszFromList)
  4145. throw CX_MemoryException();
  4146. pQuery->m_ppszFromList[0] = CloneLPWSTR(pTR->m_pTableName);
  4147. if (!pQuery->m_ppszFromList[0])
  4148. {
  4149. delete pQuery->m_ppszFromList;
  4150. throw CX_MemoryException();
  4151. }
  4152. }
  4153. else if (pFrom->m_pRight)
  4154. {
  4155. SWQLNode_WmiScopedSelect *pSS = (SWQLNode_WmiScopedSelect *) pFrom->m_pRight;
  4156. pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_PATH;
  4157. pQuery->m_pszOptionalFromPath = CloneLPWSTR(pSS->m_pszScope);
  4158. if (pQuery->m_pszOptionalFromPath)
  4159. {
  4160. throw CX_MemoryException();
  4161. }
  4162. int nSz = pSS->m_aTables.Size();
  4163. if (nSz == 1)
  4164. pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_UNARY;
  4165. else if (nSz > 1)
  4166. pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_CLASS_LIST;
  4167. pQuery->m_uFromListSize = (ULONG) nSz;
  4168. pQuery->m_ppszFromList = (LPCWSTR *) new LPWSTR[nSz];
  4169. if (!pQuery->m_ppszFromList)
  4170. throw CX_MemoryException();
  4171. for (int n = 0; n < nSz; n++)
  4172. {
  4173. pQuery->m_ppszFromList[n] = CloneLPWSTR(LPWSTR(pSS->m_aTables[n]));
  4174. if (!pQuery->m_ppszFromList[n])
  4175. throw CX_MemoryException();
  4176. }
  4177. }
  4178. else
  4179. return WBEM_E_INVALID_QUERY;
  4180. return 0;
  4181. }
  4182. //***************************************************************************
  4183. //
  4184. //***************************************************************************
  4185. //
  4186. HRESULT CWQLParser::GetRpnSequence(OUT SWbemRpnEncodedQuery **pRpn)
  4187. {
  4188. HRESULT hRes;
  4189. try
  4190. {
  4191. CWbemRpnEncodedQuery *pNewRpn = new CWbemRpnEncodedQuery;
  4192. if (!pNewRpn)
  4193. return WBEM_E_OUT_OF_MEMORY;
  4194. wmilib::auto_ptr<CWbemRpnEncodedQuery> delNewRpn(pNewRpn);
  4195. // Copy detected features.
  4196. // =======================
  4197. pNewRpn->m_uParsedFeatureMask = m_uFeatures;
  4198. // Do the SELECT LIST.
  4199. // ===================
  4200. BuildSelectList(pNewRpn);
  4201. // Do the FROM list.
  4202. // =================
  4203. BuildFromClause(pNewRpn);
  4204. // Do the WHERE clause.
  4205. // ====================
  4206. CFlexArray aRpn;
  4207. SWQLNode *pWhereRoot = GetWhereClauseRoot();
  4208. SWQLNode_RelExpr *pExprRoot = (SWQLNode_RelExpr *) pWhereRoot->m_pLeft;
  4209. SWQLNode_WhereOptions *pOp = (SWQLNode_WhereOptions *) pWhereRoot->m_pRight; // ORDER BY, etc.
  4210. if (pExprRoot)
  4211. hRes = BuildRpnWhereClause(pExprRoot, aRpn);
  4212. // Now traverse the RPN form of the WHERE clause, if any.
  4213. // ======================================================
  4214. if (aRpn.Size())
  4215. {
  4216. pNewRpn->m_uWhereClauseSize = aRpn.Size();
  4217. pNewRpn->m_ppRpnWhereClause = (SWbemRpnQueryToken **) new CWbemRpnQueryToken*[aRpn.Size()];
  4218. if (!pNewRpn->m_ppRpnWhereClause)
  4219. return WBEM_E_OUT_OF_MEMORY;
  4220. }
  4221. BOOL b_Test_AllEqualityTests = TRUE;
  4222. BOOL b_Test_Disjunctive = FALSE;
  4223. BOOL b_AtLeastOneTest = FALSE;
  4224. for (int i = 0; i < aRpn.Size(); i++)
  4225. {
  4226. SWQLNode_RelExpr *pSrc = (SWQLNode_RelExpr *) aRpn[i];
  4227. SWbemRpnQueryToken *pDest = (SWbemRpnQueryToken *) new CWbemRpnQueryToken;
  4228. if (!pDest)
  4229. return WBEM_E_OUT_OF_MEMORY;
  4230. wmilib::auto_ptr<SWbemRpnQueryToken> delDest(pDest);
  4231. hRes = BuildCurrentWhereToken(pSrc, pDest);
  4232. delDest.release();
  4233. pNewRpn->m_ppRpnWhereClause[i] = pDest;
  4234. // Add in stats.
  4235. // =============
  4236. if (pDest->m_uTokenType == WMIQ_RPN_TOKEN_EXPRESSION)
  4237. {
  4238. if (pDest->m_uOperator != WMIQ_RPN_OP_EQ)
  4239. b_Test_AllEqualityTests = FALSE;
  4240. b_AtLeastOneTest = TRUE;
  4241. }
  4242. else if (pDest->m_uTokenType != WMIQ_RPN_TOKEN_AND)
  4243. {
  4244. b_Test_Disjunctive = TRUE;
  4245. }
  4246. if (pDest->m_pRightIdent != 0 && pDest->m_pLeftIdent != 0)
  4247. {
  4248. pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_PROP_TO_PROP_TESTS;
  4249. }
  4250. }
  4251. if (b_Test_AllEqualityTests && b_AtLeastOneTest)
  4252. pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_EQUALITY_TESTS_ONLY;
  4253. if (b_Test_Disjunctive)
  4254. pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_QUERY_IS_DISJUNCTIVE;
  4255. else
  4256. pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_QUERY_IS_CONJUNCTIVE;
  4257. *pRpn = pNewRpn;
  4258. delNewRpn.release();
  4259. }
  4260. catch (CX_MemoryException)
  4261. {
  4262. return WBEM_E_OUT_OF_MEMORY;
  4263. }
  4264. catch (...)
  4265. {
  4266. return WBEM_E_CRITICAL_ERROR;
  4267. }
  4268. return WBEM_S_NO_ERROR;
  4269. }
  4270. //***************************************************************************
  4271. //
  4272. //***************************************************************************
  4273. //
  4274. ULONG RpnTranslateExprFlags(SWQLTypedExpr *pTE)
  4275. {
  4276. return 0;
  4277. }
  4278. //***************************************************************************
  4279. //
  4280. //***************************************************************************
  4281. //
  4282. ULONG RpnTranslateOperator(SWQLTypedExpr *pTE)
  4283. {
  4284. ULONG uRes = WMIQ_RPN_OP_UNDEFINED;
  4285. switch (pTE->m_dwRelOperator)
  4286. {
  4287. case WQL_TOK_LE: uRes = WMIQ_RPN_OP_LE; break;
  4288. case WQL_TOK_LT: uRes = WMIQ_RPN_OP_LT; break;
  4289. case WQL_TOK_GE: uRes = WMIQ_RPN_OP_GE; break;
  4290. case WQL_TOK_GT: uRes = WMIQ_RPN_OP_GT; break;
  4291. case WQL_TOK_EQ: uRes = WMIQ_RPN_OP_EQ; break;
  4292. case WQL_TOK_NE: uRes = WMIQ_RPN_OP_NE; break;
  4293. case WQL_TOK_LIKE: uRes = WMIQ_RPN_OP_LIKE; break;
  4294. case WQL_TOK_ISA: uRes = WMIQ_RPN_OP_ISA; break;
  4295. case WQL_TOK_ISNULL: uRes = WMIQ_RPN_OP_ISNULL; break;
  4296. case WQL_TOK_NOT_NULL: uRes = WMIQ_RPN_OP_ISNOTNULL; break;
  4297. }
  4298. return uRes;
  4299. }
  4300. //***************************************************************************
  4301. //
  4302. //***************************************************************************
  4303. //
  4304. SWbemQueryQualifiedName *RpnTranslateIdent(ULONG uWhichSide, SWQLTypedExpr *pTE)
  4305. {
  4306. SWQLQualifiedName *pQN = 0;
  4307. if (uWhichSide == WMIQ_RPN_LEFT_PROPERTY_NAME)
  4308. {
  4309. pQN = pTE->m_pQNLeft;
  4310. }
  4311. else
  4312. {
  4313. pQN = pTE->m_pQNRight;
  4314. }
  4315. if (pQN)
  4316. {
  4317. CWbemQueryQualifiedName *pNew = new CWbemQueryQualifiedName;
  4318. if (!pNew)
  4319. throw CX_MemoryException();
  4320. pNew->m_uNameListSize = (ULONG) pQN->m_aFields.Size();
  4321. pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[pNew->m_uNameListSize];
  4322. if (!pNew->m_ppszNameList)
  4323. {
  4324. delete pNew;
  4325. throw CX_MemoryException();
  4326. }
  4327. for (int i = 0; i < pQN->m_aFields.Size(); i++)
  4328. {
  4329. SWQLQualifiedNameField *pField = (SWQLQualifiedNameField *) pQN->m_aFields[i];
  4330. LPWSTR pszNewName = CloneLPWSTR(pField->m_pName);
  4331. if (!pszNewName)
  4332. {
  4333. delete pNew;
  4334. throw CX_MemoryException();
  4335. }
  4336. pNew->m_ppszNameList[i] = pszNewName;
  4337. }
  4338. return (SWbemQueryQualifiedName *) pNew;
  4339. }
  4340. else if (pTE->m_pColRef && WMIQ_RPN_LEFT_PROPERTY_NAME == uWhichSide)
  4341. {
  4342. CWbemQueryQualifiedName *pNew = new CWbemQueryQualifiedName;
  4343. if (!pNew)
  4344. throw CX_MemoryException();
  4345. if (pTE->m_pTableRef)
  4346. {
  4347. pNew->m_uNameListSize = 2;
  4348. pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[2];
  4349. if (!pNew->m_ppszNameList)
  4350. {
  4351. delete pNew;
  4352. throw CX_MemoryException();
  4353. }
  4354. pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pTableRef);
  4355. if (!pNew->m_ppszNameList[0])
  4356. {
  4357. delete pNew;
  4358. throw CX_MemoryException();
  4359. }
  4360. pNew->m_ppszNameList[1] = CloneLPWSTR(pTE->m_pColRef);
  4361. if (!pNew->m_ppszNameList[1])
  4362. {
  4363. delete pNew;
  4364. throw CX_MemoryException();
  4365. }
  4366. }
  4367. else
  4368. {
  4369. pNew->m_uNameListSize = 1;
  4370. pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[1];
  4371. if (!pNew->m_ppszNameList)
  4372. {
  4373. delete pNew;
  4374. throw CX_MemoryException();
  4375. }
  4376. pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pColRef);
  4377. if (!pNew->m_ppszNameList[0])
  4378. {
  4379. delete pNew;
  4380. throw CX_MemoryException();
  4381. }
  4382. }
  4383. return (SWbemQueryQualifiedName *) pNew;
  4384. }
  4385. else if (pTE->m_pJoinColRef && WMIQ_RPN_RIGHT_PROPERTY_NAME == uWhichSide)
  4386. {
  4387. CWbemQueryQualifiedName *pNew = new CWbemQueryQualifiedName;
  4388. if (!pNew)
  4389. throw CX_MemoryException();
  4390. if (pTE->m_pJoinTableRef)
  4391. {
  4392. pNew->m_uNameListSize = 2;
  4393. pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[2];
  4394. if (!pNew->m_ppszNameList)
  4395. {
  4396. delete pNew;
  4397. throw CX_MemoryException();
  4398. }
  4399. pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pJoinTableRef);
  4400. if (!pNew->m_ppszNameList[0])
  4401. {
  4402. delete pNew;
  4403. throw CX_MemoryException();
  4404. }
  4405. pNew->m_ppszNameList[1] = CloneLPWSTR(pTE->m_pJoinColRef);
  4406. if (!pNew->m_ppszNameList[1])
  4407. {
  4408. delete pNew;
  4409. throw CX_MemoryException();
  4410. }
  4411. }
  4412. else
  4413. {
  4414. pNew->m_uNameListSize = 1;
  4415. pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[1];
  4416. if (!pNew->m_ppszNameList)
  4417. {
  4418. delete pNew;
  4419. throw CX_MemoryException();
  4420. }
  4421. pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pJoinColRef);
  4422. if (!pNew->m_ppszNameList[0])
  4423. {
  4424. delete pNew;
  4425. throw CX_MemoryException();
  4426. }
  4427. }
  4428. return (SWbemQueryQualifiedName *) pNew;
  4429. }
  4430. else
  4431. return 0;
  4432. }
  4433. //***************************************************************************
  4434. //
  4435. //***************************************************************************
  4436. //
  4437. SWbemQueryQualifiedName *RpnTranslateRightIdent(SWQLTypedExpr *pTE)
  4438. {
  4439. return 0;
  4440. }
  4441. //***************************************************************************
  4442. //
  4443. //***************************************************************************
  4444. //
  4445. SWbemRpnConst RpnTranslateConst(SWQLTypedConst *pSrc)
  4446. {
  4447. SWbemRpnConst c;
  4448. memset(&c, 0, sizeof(c));
  4449. if (!pSrc)
  4450. return c;
  4451. switch (pSrc->m_dwType)
  4452. {
  4453. case VT_LPWSTR:
  4454. c.m_pszStrVal = CloneLPWSTR(pSrc->m_Value.m_pString);
  4455. // this will fail with an "empty" struct returned
  4456. break;
  4457. case VT_I4:
  4458. c.m_lLongVal = pSrc->m_Value.m_lValue;
  4459. break;
  4460. case VT_R8:
  4461. c.m_dblVal = pSrc->m_Value.m_dblValue;
  4462. break;
  4463. case VT_BOOL:
  4464. c.m_bBoolVal = pSrc->m_Value.m_bValue;
  4465. break;
  4466. case VT_UI4:
  4467. c.m_uLongVal = (unsigned) pSrc->m_Value.m_lValue;
  4468. break;
  4469. case VT_I8:
  4470. c.m_lVal64 = pSrc->m_Value.m_i64Value;
  4471. break;
  4472. case VT_UI8:
  4473. c.m_uVal64 = (unsigned __int64) pSrc->m_Value.m_i64Value;
  4474. break;
  4475. }
  4476. return c;
  4477. }
  4478. //***************************************************************************
  4479. //
  4480. //***************************************************************************
  4481. //
  4482. ULONG RpnTranslateConstType(SWQLTypedConst *pSrc)
  4483. {
  4484. if (pSrc)
  4485. return pSrc->m_dwType;
  4486. else
  4487. return VT_NULL;
  4488. }
  4489. //***************************************************************************
  4490. //
  4491. //***************************************************************************
  4492. //
  4493. LPCWSTR RpnTranslateLeftFunc(SWQLTypedExpr *pTE)
  4494. {
  4495. return Clone(pTE->m_pIntrinsicFuncOnColRef);
  4496. }
  4497. //***************************************************************************
  4498. //
  4499. //***************************************************************************
  4500. //
  4501. LPCWSTR RpnTranslateRightFunc(SWQLTypedExpr *pTE)
  4502. {
  4503. if (pTE->m_pIntrinsicFuncOnJoinColRef == 0)
  4504. return Clone(pTE->m_pIntrinsicFuncOnConstValue);
  4505. else
  4506. return Clone(pTE->m_pIntrinsicFuncOnJoinColRef);
  4507. }
  4508. //***************************************************************************
  4509. //
  4510. //***************************************************************************
  4511. //
  4512. HRESULT CWQLParser::BuildCurrentWhereToken(
  4513. SWQLNode_RelExpr *pSrc,
  4514. SWbemRpnQueryToken *pDest
  4515. )
  4516. {
  4517. HRESULT hRes = WBEM_E_INVALID_QUERY;
  4518. if (pSrc->m_dwExprType == WQL_TOK_OR)
  4519. {
  4520. pDest->m_uTokenType = WMIQ_RPN_TOKEN_OR;
  4521. }
  4522. else if (pSrc->m_dwExprType == WQL_TOK_AND)
  4523. {
  4524. pDest->m_uTokenType = WMIQ_RPN_TOKEN_AND;
  4525. }
  4526. else if (pSrc->m_dwExprType == WQL_TOK_NOT)
  4527. {
  4528. pDest->m_uTokenType = WMIQ_RPN_TOKEN_NOT;
  4529. }
  4530. else if (pSrc->m_dwExprType == WQL_TOK_TYPED_EXPR)
  4531. {
  4532. pDest->m_uTokenType = WMIQ_RPN_TOKEN_EXPRESSION;
  4533. SWQLTypedExpr *pTmp = pSrc->m_pTypedExpr;
  4534. pDest->m_uSubexpressionShape = RpnTranslateExprFlags(pTmp);
  4535. pDest->m_uOperator = RpnTranslateOperator(pTmp);
  4536. pDest->m_pLeftIdent = RpnTranslateIdent(WMIQ_RPN_LEFT_PROPERTY_NAME, pTmp);
  4537. pDest->m_pRightIdent = RpnTranslateIdent(WMIQ_RPN_RIGHT_PROPERTY_NAME, pTmp);
  4538. pDest->m_uConstApparentType = RpnTranslateConstType(pTmp->m_pConstValue);
  4539. pDest->m_Const = RpnTranslateConst(pTmp->m_pConstValue);
  4540. pDest->m_uConst2ApparentType = RpnTranslateConstType(pTmp->m_pConstValue2);
  4541. pDest->m_Const2 = RpnTranslateConst(pTmp->m_pConstValue2);
  4542. pDest->m_pszLeftFunc = RpnTranslateLeftFunc(pTmp);
  4543. pDest->m_pszRightFunc = RpnTranslateRightFunc(pTmp);
  4544. if (pDest->m_pLeftIdent)
  4545. pDest->m_uSubexpressionShape |= WMIQ_RPN_LEFT_PROPERTY_NAME;
  4546. if (pDest->m_pRightIdent)
  4547. pDest->m_uSubexpressionShape |= WMIQ_RPN_RIGHT_PROPERTY_NAME;
  4548. // Special case NULL if there really is a const value with a type of NULL
  4549. if ( (pDest->m_uConstApparentType != VT_NULL) ||
  4550. ( NULL != pTmp->m_pConstValue && pTmp->m_pConstValue->m_dwType == VT_NULL ) )
  4551. pDest->m_uSubexpressionShape |= WMIQ_RPN_CONST;
  4552. // Do the same for CONST2
  4553. if ( (pDest->m_uConst2ApparentType != VT_NULL) ||
  4554. ( NULL != pTmp->m_pConstValue2 && pTmp->m_pConstValue2->m_dwType == VT_NULL ) )
  4555. pDest->m_uSubexpressionShape |= WMIQ_RPN_CONST2;
  4556. if (pDest->m_pszLeftFunc)
  4557. pDest->m_uSubexpressionShape |= WMIQ_RPN_LEFT_FUNCTION;
  4558. if (pDest->m_pszRightFunc)
  4559. pDest->m_uSubexpressionShape |= WMIQ_RPN_RIGHT_FUNCTION;
  4560. if (pDest->m_uOperator != 0)
  4561. pDest->m_uSubexpressionShape |= WMIQ_RPN_RELOP;
  4562. }
  4563. return hRes;
  4564. }
  4565. //***************************************************************************
  4566. //
  4567. //***************************************************************************
  4568. //
  4569. int CWQLParser::assocquery(OUT SWQLNode_AssocQuery **pAssocQuery)
  4570. {
  4571. HRESULT hRes;
  4572. CAssocQueryParser AP;
  4573. *pAssocQuery = 0;
  4574. hRes = AP.Parse(m_pszQueryText);
  4575. if (FAILED(hRes)) return hRes;
  4576. // If here, extract the info and put it into a new node.
  4577. // =====================================================
  4578. wmilib::auto_ptr<SWQLNode_AssocQuery> pTmp(new SWQLNode_AssocQuery);
  4579. if (0 == pTmp.get()) return WBEM_E_OUT_OF_MEMORY;
  4580. pTmp->m_pAQInf = new CWbemAssocQueryInf;
  4581. if (NULL == pTmp->m_pAQInf) return WBEM_E_OUT_OF_MEMORY;
  4582. hRes = pTmp->m_pAQInf->CopyFrom((SWbemAssocQueryInf *) &AP);
  4583. if (FAILED(hRes)) return hRes;
  4584. *pAssocQuery = pTmp.release();
  4585. return S_OK;
  4586. }
  4587. //***************************************************************************
  4588. //
  4589. //***************************************************************************
  4590. //
  4591. void SWQLNode_QueryRoot::DebugDump()
  4592. {
  4593. if (m_pLeft)
  4594. m_pLeft->DebugDump();
  4595. }
  4596. //***************************************************************************
  4597. //
  4598. //***************************************************************************
  4599. //
  4600. void SWQLNode_AssocQuery::DebugDump()
  4601. {
  4602. printf("Association query info\n");
  4603. printf("Version = %u\n", m_pAQInf->m_uVersion);
  4604. printf("Analysis Type = %u\n", m_pAQInf->m_uAnalysisType);
  4605. printf("Feature Mask = 0x%X\n", m_pAQInf->m_uFeatureMask);
  4606. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_ASSOCIATORS)
  4607. printf(" WMIQ_ASSOCQ_ASSOCIATORS\n");
  4608. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_REFERENCES)
  4609. printf(" WMIQ_ASSOCQ_REFERENCES\n");
  4610. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_RESULTCLASS)
  4611. printf(" WMIQ_ASSOCQ_RESULTCLASS\n");
  4612. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_ASSOCCLASS)
  4613. printf(" WMIQ_ASSOCQ_ASSOCCLASS\n");
  4614. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_ROLE)
  4615. printf(" WMIQ_ASSOCQ_ROLE\n");
  4616. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_RESULTROLE)
  4617. printf(" WMIQ_ASSOCQ_RESULTROLE\n");
  4618. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_REQUIREDQUALIFIER)
  4619. printf(" WMIQ_ASSOCQ_REQUIREDQUALIFIER\n");
  4620. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_REQUIREDASSOCQUALIFIER)
  4621. printf(" WMIQ_ASSOCQ_REQUIREDASSOCQUALIFIER\n");
  4622. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_CLASSDEFSONLY)
  4623. printf(" WMIQ_ASSOCQ_CLASSDEFSONLY\n");
  4624. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_KEYSONLY)
  4625. printf(" WMIQ_ASSOCQ_KEYSONLY\n");
  4626. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_SCHEMAONLY)
  4627. printf(" WMIQ_ASSOCQ_SCHEMAONLY\n");
  4628. if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_CLASSREFSONLY)
  4629. printf(" WMIQ_ASSOCQ_CLASSREFSONLY\n");
  4630. printf("IWbemPath pointer = 0x%I64X\n", (unsigned __int64) m_pAQInf->m_pPath);
  4631. if (m_pAQInf->m_pPath)
  4632. {
  4633. printf("Path object has ");
  4634. wchar_t Buf[256];
  4635. ULONG uLen = 256;
  4636. m_pAQInf->m_pPath->GetText(0, &uLen, Buf);
  4637. printf("<%S>\n", Buf);
  4638. }
  4639. printf("m_pszQueryText = %S\n", m_pAQInf->m_pszQueryText);
  4640. printf("m_pszResultClass = %S\n", m_pAQInf->m_pszResultClass);
  4641. printf("m_pszAssocClass = %S\n", m_pAQInf->m_pszAssocClass);
  4642. printf("m_pszRole = %S\n", m_pAQInf->m_pszRole);
  4643. printf("m_pszResultRole = %S\n", m_pAQInf->m_pszResultRole);
  4644. printf("m_pszRequiredQualifier = %S\n", m_pAQInf->m_pszRequiredQualifier);
  4645. printf("m_pszRequiredAssocQualifier = %S\n", m_pAQInf->m_pszRequiredAssocQualifier);
  4646. printf("---end---\n");
  4647. }
  4648. //***************************************************************************
  4649. //
  4650. //***************************************************************************
  4651. //
  4652. CWbemAssocQueryInf::CWbemAssocQueryInf()
  4653. {
  4654. Init();
  4655. }
  4656. //***************************************************************************
  4657. //
  4658. //***************************************************************************
  4659. //
  4660. CWbemAssocQueryInf::~CWbemAssocQueryInf()
  4661. {
  4662. Empty();
  4663. }
  4664. //***************************************************************************
  4665. //
  4666. //***************************************************************************
  4667. //
  4668. void CWbemAssocQueryInf::Empty()
  4669. {
  4670. if (m_pPath)
  4671. m_pPath->Release();
  4672. delete [] m_pszPath;
  4673. delete [] m_pszQueryText;
  4674. delete [] m_pszResultClass;
  4675. delete [] m_pszAssocClass;
  4676. delete [] m_pszRole;
  4677. delete [] m_pszResultRole;
  4678. delete [] m_pszRequiredQualifier;
  4679. delete [] m_pszRequiredAssocQualifier;
  4680. Init();
  4681. }
  4682. //***************************************************************************
  4683. //
  4684. //***************************************************************************
  4685. //
  4686. void CWbemAssocQueryInf::Init()
  4687. {
  4688. m_uVersion = 0;
  4689. m_uAnalysisType = 0;
  4690. m_uFeatureMask = 0;
  4691. m_pPath = 0;
  4692. m_pszPath = 0;
  4693. m_pszQueryText = 0;
  4694. m_pszResultClass = 0;
  4695. m_pszAssocClass = 0;
  4696. m_pszRole = 0;
  4697. m_pszResultRole = 0;
  4698. m_pszRequiredQualifier = 0;
  4699. m_pszRequiredAssocQualifier = 0;
  4700. }
  4701. //***************************************************************************
  4702. //
  4703. //***************************************************************************
  4704. //
  4705. HRESULT CWbemAssocQueryInf::CopyFrom(SWbemAssocQueryInf *pSrc)
  4706. {
  4707. m_uVersion = pSrc->m_uVersion;
  4708. m_uAnalysisType = pSrc->m_uAnalysisType;
  4709. m_uFeatureMask = pSrc->m_uFeatureMask;
  4710. m_pszPath = CloneLPWSTR(pSrc->m_pszPath);
  4711. if (CloneFailed(m_pszPath,pSrc->m_pszPath))
  4712. return WBEM_E_OUT_OF_MEMORY;
  4713. if (m_pszPath)
  4714. {
  4715. HRESULT hRes= CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &m_pPath);
  4716. if (SUCCEEDED(hRes))
  4717. {
  4718. hRes = m_pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, m_pszPath);
  4719. if (FAILED(hRes))
  4720. {
  4721. m_pPath->Release();
  4722. m_pPath = 0;
  4723. return hRes;
  4724. }
  4725. }
  4726. else
  4727. return hRes;
  4728. }
  4729. m_pszQueryText = CloneLPWSTR(pSrc->m_pszQueryText);
  4730. if (CloneFailed(m_pszQueryText,pSrc->m_pszQueryText))
  4731. return WBEM_E_OUT_OF_MEMORY;
  4732. m_pszResultClass = CloneLPWSTR(pSrc->m_pszResultClass);
  4733. if (CloneFailed(m_pszResultClass,pSrc->m_pszResultClass))
  4734. return WBEM_E_OUT_OF_MEMORY;
  4735. m_pszAssocClass = CloneLPWSTR(pSrc->m_pszAssocClass);
  4736. if (CloneFailed(m_pszAssocClass,pSrc->m_pszAssocClass))
  4737. return WBEM_E_OUT_OF_MEMORY;
  4738. m_pszRole = CloneLPWSTR(pSrc->m_pszRole);
  4739. if (CloneFailed(m_pszRole,pSrc->m_pszRole))
  4740. return WBEM_E_OUT_OF_MEMORY;
  4741. m_pszResultRole = CloneLPWSTR(pSrc->m_pszResultRole);
  4742. if (CloneFailed(m_pszResultRole,pSrc->m_pszResultRole))
  4743. return WBEM_E_OUT_OF_MEMORY;
  4744. m_pszRequiredQualifier = CloneLPWSTR(pSrc->m_pszRequiredQualifier);
  4745. if (CloneFailed(m_pszRequiredQualifier,pSrc->m_pszRequiredQualifier))
  4746. return WBEM_E_OUT_OF_MEMORY;
  4747. m_pszRequiredAssocQualifier = CloneLPWSTR(pSrc->m_pszRequiredAssocQualifier);
  4748. if (CloneFailed(m_pszRequiredAssocQualifier,pSrc->m_pszRequiredAssocQualifier))
  4749. return WBEM_E_OUT_OF_MEMORY;
  4750. return WBEM_S_NO_ERROR;
  4751. }