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.

553 lines
13 KiB

  1. //***************************************************************************
  2. //
  3. // WMIQUERY.CPP
  4. //
  5. // Query parser implementation
  6. //
  7. // raymcc 10-Apr-00 Created
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <wbemcli.h>
  14. #include "sync.h"
  15. #include "flexarry.h"
  16. #include <wmiutils.h>
  17. #include <wbemint.h>
  18. #include "wmiquery.h"
  19. #include "helpers.h"
  20. #include <like.h>
  21. #include <wqllex.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #define INVALID 0x3
  25. static CRITICAL_SECTION CS_UserMem;
  26. static CFlexArray *g_pUserMem;
  27. CCritSec g_csQPLock;
  28. class C_SYNC
  29. {
  30. public:
  31. C_SYNC () { g_csQPLock.Enter();}
  32. ~C_SYNC() { g_csQPLock.Leave();}
  33. };
  34. struct SWmiqUserMem
  35. {
  36. DWORD m_dwType;
  37. LPVOID m_pMem;
  38. };
  39. class BoolStack
  40. {
  41. BOOL *m_pValues;
  42. int nPtr;
  43. public:
  44. enum { DefaultSize = 256 };
  45. BoolStack(int nSz)
  46. {
  47. m_pValues = new BOOL[nSz];
  48. nPtr = -1;
  49. }
  50. ~BoolStack() { delete m_pValues; }
  51. void Push(BOOL b){ m_pValues[++nPtr] = b; }
  52. BOOL Pop() { return m_pValues[nPtr--]; }
  53. BOOL Peek() { return m_pValues[nPtr]; }
  54. };
  55. //***************************************************************************
  56. //
  57. //***************************************************************************
  58. //
  59. CWmiQuery::CWmiQuery()
  60. {
  61. m_uRefCount = 1; // Required by helper in MainDLL.CPP.
  62. m_pParser = 0;
  63. m_pAssocParser = 0;
  64. m_pLexerSrc = 0;
  65. InterlockedIncrement(&g_cObj);
  66. }
  67. //***************************************************************************
  68. //
  69. //***************************************************************************
  70. //
  71. CWmiQuery::~CWmiQuery()
  72. {
  73. Empty();
  74. InterlockedDecrement(&g_cObj);
  75. }
  76. //***************************************************************************
  77. //
  78. //***************************************************************************
  79. //
  80. void CWmiQuery::InitEmpty()
  81. {
  82. // Empty();
  83. }
  84. //***************************************************************************
  85. //
  86. //***************************************************************************
  87. //
  88. ULONG CWmiQuery::AddRef()
  89. {
  90. InterlockedIncrement((LONG *) &m_uRefCount);
  91. return m_uRefCount;
  92. }
  93. //***************************************************************************
  94. //
  95. //***************************************************************************
  96. //
  97. ULONG CWmiQuery::Release()
  98. {
  99. ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount);
  100. if (0 != uNewCount)
  101. return uNewCount;
  102. delete this;
  103. return 0;
  104. }
  105. //***************************************************************************
  106. //
  107. // CWmiQuery::QueryInterface
  108. //
  109. // Exports IWbemServices interface.
  110. //
  111. //***************************************************************************
  112. //
  113. HRESULT CWmiQuery::QueryInterface(
  114. IN REFIID riid,
  115. OUT LPVOID *ppvObj
  116. )
  117. {
  118. *ppvObj = 0;
  119. if (IID_IUnknown==riid || IID_IWbemQuery==riid || IID__IWmiQuery==riid )
  120. {
  121. *ppvObj = (IWbemServicesEx*)this;
  122. AddRef();
  123. return S_OK;
  124. }
  125. return E_NOINTERFACE;
  126. }
  127. //***************************************************************************
  128. //
  129. //***************************************************************************
  130. //
  131. HRESULT CWmiQuery::Empty()
  132. {
  133. // if ( CS_Entry.TryEnter () == FALSE )
  134. // return WBEM_E_CRITICAL_ERROR;
  135. C_SYNC cs;
  136. if (m_pParser)
  137. delete m_pParser;
  138. m_pParser = 0;
  139. if (m_pAssocParser)
  140. delete m_pAssocParser;
  141. m_pAssocParser = 0;
  142. if (m_pLexerSrc)
  143. delete m_pLexerSrc;
  144. m_pLexerSrc = 0;
  145. if (m_aClassCache.Size())
  146. {
  147. for (int i = 0; i < m_aClassCache.Size(); i++)
  148. {
  149. _IWmiObject *pObj = (_IWmiObject *) m_aClassCache[i];
  150. pObj->Release();
  151. }
  152. m_aClassCache.Empty();
  153. }
  154. return WBEM_S_NO_ERROR;
  155. }
  156. //***************************************************************************
  157. //
  158. //***************************************************************************
  159. //
  160. // *
  161. HRESULT CWmiQuery::SetLanguageFeatures(
  162. /* [in] */ ULONG uFlags,
  163. /* [in] */ ULONG uArraySize,
  164. /* [in] */ ULONG __RPC_FAR *puFeatures
  165. )
  166. {
  167. // if ( CS_Entry.TryEnter () == FALSE )
  168. // return WBEM_E_CRITICAL_ERROR;
  169. C_SYNC cs;
  170. for (ULONG u = 0; u < uArraySize; u++)
  171. {
  172. m_uRestrictedFeatures[u] = puFeatures[u];
  173. }
  174. m_uRestrictedFeaturesSize = u;
  175. return WBEM_S_NO_ERROR;
  176. }
  177. //***************************************************************************
  178. //
  179. //***************************************************************************
  180. //
  181. HRESULT CWmiQuery::TestLanguageFeatures(
  182. /* [in] */ ULONG uFlags,
  183. /* [out][in] */ ULONG __RPC_FAR *uArraySize,
  184. /* [out] */ ULONG __RPC_FAR *puFeatures
  185. )
  186. {
  187. return E_NOTIMPL;
  188. }
  189. //***************************************************************************
  190. //
  191. //***************************************************************************
  192. //
  193. HRESULT CWmiQuery::Parse(
  194. /* [in] */ LPCWSTR pszLang,
  195. /* [in] */ LPCWSTR pszQuery,
  196. /* [in] */ ULONG uFlags
  197. )
  198. {
  199. if (_wcsicmp(pszLang, L"WQL") != 0 && _wcsicmp(pszLang, L"SQL") != 0)
  200. {
  201. return WBEM_E_INVALID_PARAMETER;
  202. }
  203. if (pszQuery == 0 || wcslen(pszQuery) == 0)
  204. {
  205. return WBEM_E_INVALID_PARAMETER;
  206. }
  207. // if ( CS_Entry.TryEnter () == FALSE )
  208. // return WBEM_E_CRITICAL_ERROR;
  209. C_SYNC cs;
  210. HRESULT hRes;
  211. int nRes;
  212. Empty();
  213. try
  214. {
  215. // Get a text source bound to the query.
  216. // =====================================
  217. m_pLexerSrc = new CTextLexSource(pszQuery);
  218. if (!m_pLexerSrc)
  219. return WBEM_E_OUT_OF_MEMORY;
  220. // Check the first token and see which way to branch.
  221. // ==================================================
  222. m_pParser = new CWQLParser(LPWSTR(pszQuery), m_pLexerSrc);
  223. if (!m_pParser)
  224. return WBEM_E_OUT_OF_MEMORY;
  225. hRes = m_pParser->Parse();
  226. }
  227. catch(...)
  228. {
  229. return WBEM_E_CRITICAL_ERROR;
  230. }
  231. return hRes;
  232. }
  233. //***************************************************************************
  234. //
  235. //***************************************************************************
  236. //
  237. HRESULT CWmiQuery::GetAnalysis(
  238. /* [in] */ ULONG uAnalysisType,
  239. /* [in] */ ULONG uFlags,
  240. /* [out] */ LPVOID __RPC_FAR *pAnalysis
  241. )
  242. {
  243. // if ( CS_Entry.TryEnter () == FALSE )
  244. // return WBEM_E_CRITICAL_ERROR;
  245. C_SYNC cs;
  246. int nRes;
  247. if (!m_pParser)
  248. return WBEM_E_INVALID_OPERATION;
  249. if (uAnalysisType == WMIQ_ANALYSIS_RPN_SEQUENCE)
  250. {
  251. // Verify it was a select clause.
  252. // ==============================
  253. SWQLNode_QueryRoot *pRoot = m_pParser->GetParseRoot();
  254. if (pRoot->m_dwQueryType != SWQLNode_QueryRoot::eSelect)
  255. return WBEM_E_INVALID_OPERATION;
  256. // Encode and record it.
  257. // =====================
  258. nRes = m_pParser->GetRpnSequence((SWbemRpnEncodedQuery **) pAnalysis);
  259. if (nRes != 0)
  260. return WBEM_E_FAILED;
  261. SWmiqUserMem *pUM = new SWmiqUserMem;
  262. if (!pUM)
  263. return WBEM_E_OUT_OF_MEMORY;
  264. pUM->m_pMem = *pAnalysis;
  265. pUM->m_dwType = WMIQ_ANALYSIS_RPN_SEQUENCE;
  266. EnterCriticalSection(&CS_UserMem);
  267. g_pUserMem->Add(pUM);
  268. LeaveCriticalSection(&CS_UserMem);
  269. return WBEM_S_NO_ERROR;
  270. }
  271. else if (uAnalysisType == WMIQ_ANALYSIS_RESERVED)
  272. {
  273. SWQLNode *p = m_pParser->GetParseRoot();
  274. *pAnalysis = p;
  275. return WBEM_S_NO_ERROR;
  276. }
  277. else if (uAnalysisType == WMIQ_ANALYSIS_ASSOC_QUERY)
  278. {
  279. SWQLNode_QueryRoot *pRoot = m_pParser->GetParseRoot();
  280. if (pRoot->m_dwQueryType != SWQLNode_QueryRoot::eAssoc)
  281. return WBEM_E_INVALID_OPERATION;
  282. SWQLNode_AssocQuery *pAssocNode = (SWQLNode_AssocQuery *) pRoot->m_pLeft;
  283. if (!pAssocNode)
  284. return WBEM_E_INVALID_QUERY;
  285. SWbemAssocQueryInf *pAssocInf = (SWbemAssocQueryInf *) pAssocNode->m_pAQInf;
  286. if (!pAssocInf)
  287. return WBEM_E_INVALID_QUERY;
  288. *pAnalysis = pAssocInf;
  289. SWmiqUserMem *pUM = new SWmiqUserMem;
  290. if (!pUM)
  291. return WBEM_E_OUT_OF_MEMORY;
  292. pUM->m_pMem = *pAnalysis;
  293. pUM->m_dwType = WMIQ_ANALYSIS_ASSOC_QUERY;
  294. EnterCriticalSection(&CS_UserMem);
  295. g_pUserMem->Add(pUM);
  296. LeaveCriticalSection(&CS_UserMem);
  297. return WBEM_S_NO_ERROR;
  298. }
  299. else if (uAnalysisType == WMIQ_ANALYSIS_QUERY_TEXT)
  300. {
  301. LPWSTR pszQuery = Macro_CloneLPWSTR(m_pParser->GetQueryText());
  302. if (!pszQuery)
  303. return WBEM_E_OUT_OF_MEMORY;
  304. SWmiqUserMem *pUM = new SWmiqUserMem;
  305. if (!pUM)
  306. return WBEM_E_OUT_OF_MEMORY;
  307. pUM->m_pMem = pszQuery;
  308. pUM->m_dwType = WMIQ_ANALYSIS_QUERY_TEXT;
  309. EnterCriticalSection(&CS_UserMem);
  310. g_pUserMem->Add(pUM);
  311. LeaveCriticalSection(&CS_UserMem);
  312. *pAnalysis = pszQuery;
  313. return WBEM_S_NO_ERROR;
  314. }
  315. return WBEM_E_INVALID_PARAMETER;
  316. }
  317. //***************************************************************************
  318. //
  319. //***************************************************************************
  320. //
  321. HRESULT CWmiQuery::GetQueryInfo(
  322. /* [in] */ ULONG uAnalysisType,
  323. /* [in] */ ULONG uInfoId,
  324. /* [in] */ ULONG uBufSize,
  325. /* [out] */ LPVOID pDestBuf
  326. )
  327. {
  328. return E_NOTIMPL;
  329. }
  330. //***************************************************************************
  331. //
  332. //***************************************************************************
  333. //
  334. #ifdef _OLD_
  335. HRESULT CWmiQuery::StringTest(
  336. /* [in] */ ULONG uTestType,
  337. /* [in] */ LPCWSTR pszTestStr,
  338. /* [in] */ LPCWSTR pszExpr
  339. )
  340. {
  341. HRESULT hr = WBEM_S_NO_ERROR;
  342. if (uTestType == WQL_TOK_LIKE)
  343. {
  344. CLike l (pszTestStr);
  345. BOOL bRet = l.Match(pszExpr);
  346. if(bRet)
  347. hr = S_OK;
  348. else
  349. hr = S_FALSE;
  350. }
  351. else
  352. hr = E_NOTIMPL;
  353. return hr;
  354. }
  355. #endif
  356. //***************************************************************************
  357. //
  358. //***************************************************************************
  359. //
  360. HRESULT CWmiQuery::FreeMemory(
  361. LPVOID pMem
  362. )
  363. {
  364. // if ( CS_Entry.TryEnter () == FALSE )
  365. // return WBEM_E_CRITICAL_ERROR;
  366. C_SYNC cs;
  367. // Check to ensure that query root isn't freed.
  368. // Allow a pass-through as if it succeeded.
  369. // ============================================
  370. SWQLNode *p = m_pParser->GetParseRoot();
  371. if (pMem == p)
  372. return WBEM_S_NO_ERROR;
  373. // Find and free the memory.
  374. // =========================
  375. HRESULT hRes = WBEM_E_NOT_FOUND;
  376. EnterCriticalSection(&CS_UserMem);
  377. for (int i = 0; i < g_pUserMem->Size(); i++)
  378. {
  379. SWmiqUserMem *pUM = (SWmiqUserMem *) (*g_pUserMem)[i];
  380. if (pUM->m_pMem == pMem)
  381. {
  382. switch (pUM->m_dwType)
  383. {
  384. case WMIQ_ANALYSIS_RPN_SEQUENCE:
  385. delete (CWbemRpnEncodedQuery *) pMem;
  386. break;
  387. case WMIQ_ANALYSIS_ASSOC_QUERY:
  388. break;
  389. case WMIQ_ANALYSIS_PROP_ANALYSIS_MATRIX:
  390. break;
  391. case WMIQ_ANALYSIS_QUERY_TEXT:
  392. delete LPWSTR(pMem);
  393. break;
  394. case WMIQ_ANALYSIS_RESERVED:
  395. // A copy of the internal parser tree pointer.
  396. // Leave it alone! Don't delete it! If you do, I will hunt you down.
  397. break;
  398. default:
  399. break;
  400. }
  401. delete pUM;
  402. g_pUserMem->RemoveAt(i);
  403. hRes = WBEM_S_NO_ERROR;
  404. break;
  405. }
  406. }
  407. LeaveCriticalSection(&CS_UserMem);
  408. return hRes;
  409. }
  410. //***************************************************************************
  411. //
  412. //***************************************************************************
  413. //
  414. HRESULT CWmiQuery::Dump(
  415. LPSTR pszFile
  416. )
  417. {
  418. return WBEM_S_NO_ERROR;
  419. }
  420. //***************************************************************************
  421. //
  422. //***************************************************************************
  423. //
  424. HRESULT CWmiQuery::Startup()
  425. {
  426. InitializeCriticalSection(&CS_UserMem);
  427. g_pUserMem = new CFlexArray;
  428. return S_OK;
  429. }
  430. //***************************************************************************
  431. //
  432. //***************************************************************************
  433. //
  434. HRESULT CWmiQuery::Shutdown()
  435. {
  436. DeleteCriticalSection(&CS_UserMem);
  437. delete g_pUserMem;
  438. return S_OK;
  439. }
  440. //***************************************************************************
  441. //
  442. //***************************************************************************
  443. //
  444. HRESULT CWmiQuery::CanUnload()
  445. {
  446. // Later, track outstanding analysis pointers
  447. return S_OK;
  448. }