Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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