Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

466 lines
14 KiB

  1. /*++
  2. // Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. ASSOCQP.CPP
  5. Abstract:
  6. Association query parser
  7. History:
  8. raymcc 04-Jul-99 Created.
  9. raymcc 14-Aug-99 Resubmit due to VSS problem.
  10. raymcc 11-Apr-00 Reworked for WMIUTILS
  11. --*/
  12. #include "precomp.h"
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <wmiutils.h>
  16. #include <genlex.h>
  17. #include <assocqp.h>
  18. #include <wbemcli.h>
  19. #include <helpers.h>
  20. #define ASSOC_QUERY_VERSION 2
  21. // ==========================================================================
  22. // ASSOCIATION QUERY PARSER.
  23. // ==========================================================================
  24. #define QASSOC_TOK_STRING 101
  25. #define QASSOC_TOK_IDENT 102
  26. #define QASSOC_TOK_DOT 103
  27. #define QASSOC_TOK_EQU 104
  28. #define QASSOC_TOK_COLON 105
  29. #define QASSOC_TOK_ERROR 1
  30. #define QASSOC_TOK_EOF 0
  31. #define ST_IDENT 13
  32. #define ST_STRING 19
  33. #define ST_QSTRING 26
  34. #define ST_QSTRING_ESC 30
  35. // DFA State Table for Assoc query tokens.
  36. // =======================================
  37. LexEl AssocQuery_LexTable[] =
  38. {
  39. // State First Last New state, Return tok, Instructions
  40. // =======================================================================
  41. /* 0 */ L'A', L'Z', ST_IDENT, 0, GLEX_ACCEPT,
  42. /* 1 */ L'a', L'z', ST_IDENT, 0, GLEX_ACCEPT,
  43. /* 2 */ L'_', GLEX_EMPTY, ST_IDENT, 0, GLEX_ACCEPT,
  44. /* 3 */ L'{', GLEX_EMPTY, ST_STRING, 0, GLEX_CONSUME,
  45. /* 4 */ L'=', GLEX_EMPTY, 0, QASSOC_TOK_EQU, GLEX_ACCEPT|GLEX_RETURN,
  46. /* 5 */ L'.', GLEX_EMPTY, 0, QASSOC_TOK_DOT, GLEX_ACCEPT|GLEX_RETURN,
  47. /* 6 */ L':', GLEX_EMPTY, 0, QASSOC_TOK_COLON, GLEX_ACCEPT|GLEX_RETURN,
  48. /* 7 */ L' ', GLEX_EMPTY, 0, 0, GLEX_CONSUME,
  49. /* 8 */ L'\t', GLEX_EMPTY, 0, 0, GLEX_CONSUME,
  50. /* 9 */ L'\n', GLEX_EMPTY, 0, 0, GLEX_CONSUME|GLEX_LINEFEED,
  51. /* 10 */ L'\r', GLEX_EMPTY, 0, 0, GLEX_CONSUME,
  52. /* 11 */ 0, GLEX_EMPTY, 0, QASSOC_TOK_EOF, GLEX_CONSUME|GLEX_RETURN, // Note forced return
  53. /* 12 */ GLEX_ANY, GLEX_EMPTY, 0, QASSOC_TOK_ERROR, GLEX_ACCEPT|GLEX_RETURN,
  54. /* ST_IDENT */
  55. /* 13 */ L'a', L'z', ST_IDENT, 0, GLEX_ACCEPT,
  56. /* 14 */ L'A', L'Z', ST_IDENT, 0, GLEX_ACCEPT,
  57. /* 15 */ L'_', GLEX_EMPTY, ST_IDENT, 0, GLEX_ACCEPT,
  58. /* 16 */ L'0', L'9', ST_IDENT, 0, GLEX_ACCEPT,
  59. /* 17 */ GLEX_ANY, GLEX_EMPTY, 0, QASSOC_TOK_IDENT, GLEX_PUSHBACK|GLEX_RETURN,
  60. /* ST_STRING */
  61. /* 18 */ 0, GLEX_EMPTY, 0, QASSOC_TOK_ERROR, GLEX_ACCEPT|GLEX_RETURN,
  62. /* 19 */ L'"', GLEX_EMPTY, ST_QSTRING, 0, GLEX_ACCEPT,
  63. /* 20 */ L'}', GLEX_EMPTY, 0, QASSOC_TOK_STRING, GLEX_RETURN,
  64. /* 21 */ L' ', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT,
  65. /* 22 */ L'\r', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT,
  66. /* 23 */ L'\n', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT,
  67. /* 24 */ L'\t', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT,
  68. /* 25 */ GLEX_ANY, GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT,
  69. /* ST_QSTRING */
  70. /* 26 */ 0, GLEX_EMPTY, 0, QASSOC_TOK_ERROR, GLEX_ACCEPT|GLEX_RETURN,
  71. /* 27 */ L'"', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT,
  72. /* 28 */ L'\\', GLEX_EMPTY, ST_QSTRING_ESC, 0, GLEX_ACCEPT,
  73. /* 29 */ GLEX_ANY, GLEX_EMPTY, ST_QSTRING, 0, GLEX_ACCEPT,
  74. /* ST_QSTRING_ESC */
  75. /* 30 */ GLEX_ANY, GLEX_EMPTY, ST_QSTRING, 0, GLEX_ACCEPT,
  76. };
  77. /*----------------------------------------------------
  78. References of {objpath} where
  79. ResultClass=XXX
  80. Role=YYY
  81. RequiredQualifier=QualifierName
  82. ClassDefsOnly
  83. Associators of {objpath} where
  84. ResultClass=XXX
  85. AssocClass=YYY
  86. Role=PPP
  87. RequiredQualifier=QualifierName
  88. RequiredAssocQualifier=QualifierName
  89. ClassDefsOnly
  90. ------------------------------------------------------*/
  91. static HRESULT ParseAssocQuery(
  92. IN LPWSTR Query,
  93. OUT LPWSTR *pTargetObj,
  94. OUT LPWSTR *pResultClass,
  95. OUT LPWSTR *pAssocClass,
  96. OUT LPWSTR *pRole,
  97. OUT LPWSTR *pResultRole,
  98. OUT LPWSTR *pRequiredQualifier,
  99. OUT LPWSTR *pRequiredAssocQualifier,
  100. OUT DWORD *pdwQueryType
  101. )
  102. {
  103. *pTargetObj = 0;
  104. *pResultClass = 0;
  105. *pAssocClass = 0;
  106. *pRole = 0;
  107. *pResultRole = 0;
  108. *pRequiredQualifier = 0;
  109. *pRequiredAssocQualifier = 0;
  110. *pdwQueryType = 0;
  111. CTextLexSource src(Query);
  112. CGenLexer Lexer(AssocQuery_LexTable, &src);
  113. if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) return WBEM_E_OUT_OF_MEMORY;
  114. int nTok = 0;
  115. BOOL bHadTokens = FALSE;
  116. // Get first token.
  117. // TBD: Check for out-of-memory
  118. // =============================
  119. nTok = Lexer.NextToken();
  120. if (nTok != QASSOC_TOK_IDENT)
  121. goto Error;
  122. // REFERENCES or ASSOCIATORS
  123. // =========================
  124. if (wbem_wcsicmp(L"References", Lexer.GetTokenText()) == 0)
  125. *pdwQueryType |= WMIQ_ASSOCQ_REFERENCES;
  126. else if (wbem_wcsicmp(L"Associators", Lexer.GetTokenText()) == 0)
  127. *pdwQueryType |= WMIQ_ASSOCQ_ASSOCIATORS;
  128. else
  129. goto Error;
  130. // OF
  131. // ==
  132. nTok = Lexer.NextToken();
  133. if (nTok != QASSOC_TOK_IDENT)
  134. goto Error;
  135. if (wbem_wcsicmp(L"of", Lexer.GetTokenText()) != 0)
  136. goto Error;
  137. // {OBJECTPATH}
  138. // ============
  139. nTok = Lexer.NextToken();
  140. if (nTok != QASSOC_TOK_STRING)
  141. goto Error;
  142. *pTargetObj = Macro_CloneLPWSTR(Lexer.GetTokenText());
  143. if (!(*pTargetObj))
  144. goto Error;
  145. // WHERE
  146. // =====
  147. nTok = Lexer.NextToken();
  148. if (nTok == QASSOC_TOK_EOF)
  149. goto Completed;
  150. if (nTok != QASSOC_TOK_IDENT)
  151. goto Error;
  152. if (wbem_wcsicmp(L"where", Lexer.GetTokenText()) != 0)
  153. goto Error;
  154. // Check for RESULTCLASS, ROLE, ASSOCCLASS, CLASSDEFSONLY,
  155. // REQUIREDQUALIFIER, REQUIREDASSOCQUALIFIER
  156. // ======================================================
  157. for (;;)
  158. {
  159. nTok = Lexer.NextToken();
  160. if (nTok == QASSOC_TOK_ERROR)
  161. goto Error;
  162. if (nTok == QASSOC_TOK_EOF)
  163. {
  164. if(!bHadTokens)
  165. goto Error;
  166. else
  167. goto Completed;
  168. }
  169. if (nTok != QASSOC_TOK_IDENT)
  170. goto Error;
  171. bHadTokens = TRUE;
  172. if (wbem_wcsicmp(L"RESULTCLASS", Lexer.GetTokenText()) == 0)
  173. {
  174. if(*pResultClass)
  175. goto Error;
  176. nTok = Lexer.NextToken();
  177. if (nTok != QASSOC_TOK_EQU)
  178. goto Error;
  179. nTok = Lexer.NextToken();
  180. if (nTok != QASSOC_TOK_IDENT)
  181. goto Error;
  182. *pResultClass = Macro_CloneLPWSTR(Lexer.GetTokenText());
  183. if (!(*pResultClass))
  184. goto Error;
  185. *pdwQueryType |= WMIQ_ASSOCQ_RESULTCLASS;
  186. }
  187. else if (wbem_wcsicmp(L"ROLE", Lexer.GetTokenText()) == 0)
  188. {
  189. if(*pRole)
  190. goto Error;
  191. nTok = Lexer.NextToken();
  192. if (nTok != QASSOC_TOK_EQU)
  193. goto Error;
  194. nTok = Lexer.NextToken();
  195. if (nTok != QASSOC_TOK_IDENT)
  196. goto Error;
  197. *pRole = Macro_CloneLPWSTR(Lexer.GetTokenText());
  198. if (!(*pRole))
  199. goto Error;
  200. *pdwQueryType |= WMIQ_ASSOCQ_ROLE;
  201. }
  202. else if (wbem_wcsicmp(L"RESULTROLE", Lexer.GetTokenText()) == 0)
  203. {
  204. if(*pResultRole)
  205. goto Error;
  206. if(*pdwQueryType & WMIQ_ASSOCQ_REFERENCES)
  207. goto Error;
  208. nTok = Lexer.NextToken();
  209. if (nTok != QASSOC_TOK_EQU)
  210. goto Error;
  211. nTok = Lexer.NextToken();
  212. if (nTok != QASSOC_TOK_IDENT)
  213. goto Error;
  214. *pResultRole = Macro_CloneLPWSTR(Lexer.GetTokenText());
  215. if (!(*pResultRole))
  216. goto Error;
  217. *pdwQueryType |= WMIQ_ASSOCQ_RESULTROLE;
  218. }
  219. else if (wbem_wcsicmp(L"ASSOCCLASS", Lexer.GetTokenText()) == 0)
  220. {
  221. if(*pAssocClass)
  222. goto Error;
  223. if(*pdwQueryType & WMIQ_ASSOCQ_REFERENCES)
  224. goto Error;
  225. nTok = Lexer.NextToken();
  226. if (nTok != QASSOC_TOK_EQU)
  227. goto Error;
  228. nTok = Lexer.NextToken();
  229. if (nTok != QASSOC_TOK_IDENT)
  230. goto Error;
  231. *pAssocClass = Macro_CloneLPWSTR(Lexer.GetTokenText());
  232. if (!(*pAssocClass))
  233. goto Error;
  234. *pdwQueryType |= WMIQ_ASSOCQ_ASSOCCLASS;
  235. }
  236. else if (wbem_wcsicmp(L"REQUIREDQUALIFIER", Lexer.GetTokenText()) == 0)
  237. {
  238. if(*pRequiredQualifier)
  239. goto Error;
  240. nTok = Lexer.NextToken();
  241. if (nTok != QASSOC_TOK_EQU)
  242. goto Error;
  243. nTok = Lexer.NextToken();
  244. if (nTok != QASSOC_TOK_IDENT)
  245. goto Error;
  246. *pRequiredQualifier = Macro_CloneLPWSTR(Lexer.GetTokenText());
  247. if (!(*pRequiredQualifier))
  248. goto Error;
  249. *pdwQueryType |= WMIQ_ASSOCQ_REQUIREDQUALIFIER;
  250. }
  251. else if (wbem_wcsicmp(L"REQUIREDASSOCQUALIFIER", Lexer.GetTokenText()) == 0)
  252. {
  253. if(*pRequiredAssocQualifier)
  254. goto Error;
  255. if(*pdwQueryType & WMIQ_ASSOCQ_REFERENCES)
  256. goto Error;
  257. nTok = Lexer.NextToken();
  258. if (nTok != QASSOC_TOK_EQU)
  259. goto Error;
  260. nTok = Lexer.NextToken();
  261. if (nTok != QASSOC_TOK_IDENT)
  262. goto Error;
  263. *pRequiredAssocQualifier = Macro_CloneLPWSTR(Lexer.GetTokenText());
  264. if (!(*pRequiredAssocQualifier))
  265. goto Error;
  266. *pdwQueryType |= WMIQ_ASSOCQ_REQUIREDASSOCQUALIFIER;
  267. }
  268. else if (wbem_wcsicmp(L"CLASSDEFSONLY", Lexer.GetTokenText()) == 0)
  269. {
  270. *pdwQueryType |= WMIQ_ASSOCQ_CLASSDEFSONLY;
  271. }
  272. else if (wbem_wcsicmp(L"KEYSONLY", Lexer.GetTokenText()) == 0)
  273. {
  274. *pdwQueryType |= WMIQ_ASSOCQ_KEYSONLY;
  275. }
  276. else if (wbem_wcsicmp(L"SCHEMAONLY", Lexer.GetTokenText()) == 0)
  277. {
  278. *pdwQueryType |= WMIQ_ASSOCQ_SCHEMAONLY;
  279. }
  280. else if (wbem_wcsicmp(L"CLASSREFSONLY", Lexer.GetTokenText()) == 0)
  281. {
  282. *pdwQueryType |= WMIQ_ASSOCQ_CLASSREFSONLY;
  283. }
  284. else
  285. {
  286. goto Error;
  287. }
  288. }
  289. Completed:
  290. if( (*pdwQueryType & WMIQ_ASSOCQ_SCHEMAONLY) &&
  291. (*pdwQueryType & WMIQ_ASSOCQ_CLASSDEFSONLY))
  292. {
  293. goto Error;
  294. }
  295. return S_OK;
  296. Error:
  297. delete *pTargetObj;
  298. delete *pResultClass;
  299. delete *pAssocClass;
  300. delete *pRole;
  301. delete *pResultRole;
  302. delete *pRequiredQualifier;
  303. delete *pRequiredAssocQualifier;
  304. *pTargetObj = 0;
  305. *pResultClass = 0;
  306. *pAssocClass = 0;
  307. *pRole = 0;
  308. *pResultRole = 0;
  309. *pdwQueryType = 0;
  310. *pRequiredQualifier = 0;
  311. *pRequiredAssocQualifier = 0;
  312. return WBEM_E_INVALID_QUERY;
  313. }
  314. //***************************************************************************
  315. //
  316. //***************************************************************************
  317. CAssocQueryParser::CAssocQueryParser()
  318. {
  319. m_uVersion = ASSOC_QUERY_VERSION;
  320. m_uFeatureMask = 0;
  321. m_uAnalysisType = WMIQ_ANALYSIS_ASSOC_QUERY;
  322. m_pPath = 0;
  323. m_pszPath = 0;
  324. m_pszQueryText = 0;
  325. m_pszResultClass = 0;
  326. m_pszAssocClass = 0;
  327. m_pszRole = 0;
  328. m_pszResultRole = 0;
  329. m_pszRequiredQualifier = 0;
  330. m_pszRequiredAssocQualifier = 0;
  331. }
  332. //***************************************************************************
  333. //
  334. //***************************************************************************
  335. CAssocQueryParser::~CAssocQueryParser()
  336. {
  337. delete m_pszPath;
  338. delete m_pszQueryText;
  339. delete m_pszResultClass;
  340. delete m_pszAssocClass;
  341. delete m_pszRole;
  342. delete m_pszResultRole;
  343. delete m_pszRequiredQualifier;
  344. delete m_pszRequiredAssocQualifier;
  345. if (m_pPath)
  346. m_pPath->Release();
  347. }
  348. //***************************************************************************
  349. //
  350. //***************************************************************************
  351. HRESULT CAssocQueryParser::Parse(LPCWSTR pszQuery)
  352. {
  353. if (pszQuery == NULL)
  354. return WBEM_E_INVALID_QUERY;
  355. // Clone the query text for debugging.
  356. // ===================================
  357. int nLen = wcslen(pszQuery) + 1;
  358. m_pszQueryText = new wchar_t[nLen];
  359. if (m_pszQueryText == NULL)
  360. return WBEM_E_OUT_OF_MEMORY;
  361. StringCchCopyW(m_pszQueryText,nLen, pszQuery);
  362. // Parse it.
  363. // =========
  364. HRESULT res = ParseAssocQuery(
  365. m_pszQueryText,
  366. &m_pszPath,
  367. &m_pszResultClass,
  368. &m_pszAssocClass,
  369. &m_pszRole,
  370. &m_pszResultRole,
  371. &m_pszRequiredQualifier,
  372. &m_pszRequiredAssocQualifier,
  373. &m_uFeatureMask
  374. );
  375. if ( FAILED(res))
  376. return res;
  377. // Parse the object path.
  378. // ======================
  379. if (m_pszPath)
  380. {
  381. HRESULT hRes= CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &m_pPath);
  382. if (FAILED(hRes))
  383. return WBEM_E_FAILED;
  384. hRes = m_pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, m_pszPath);
  385. if (FAILED(hRes))
  386. return WBEM_E_FAILED;
  387. }
  388. else
  389. return WBEM_E_INVALID_QUERY;
  390. return WBEM_S_NO_ERROR;
  391. }