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.

1004 lines
24 KiB

  1. //***************************************************************************
  2. //
  3. // VPGET.CPP
  4. //
  5. // Module: WBEM VIEW PROVIDER
  6. //
  7. // Purpose: Contains the ExecQuery implementation
  8. //
  9. // Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include <provexpt.h>
  14. #include <provcoll.h>
  15. #include <provtempl.h>
  16. #include <provmt.h>
  17. #include <typeinfo.h>
  18. #include <process.h>
  19. #include <objbase.h>
  20. #include <stdio.h>
  21. #include <wbemidl.h>
  22. #include <provcont.h>
  23. #include <provevt.h>
  24. #include <provthrd.h>
  25. #include <provlog.h>
  26. #include <cominit.h>
  27. #include <dsgetdc.h>
  28. #include <lmcons.h>
  29. #include <instpath.h>
  30. #include <genlex.h>
  31. #include <sql_1.h>
  32. #include <objpath.h>
  33. #include <vpdefs.h>
  34. #include <vpquals.h>
  35. #include <vpserv.h>
  36. #include <vptasks.h>
  37. //for association work-around
  38. struct MY_SQL_LEVEL_1_TOKEN
  39. {
  40. BOOL m_bSpecial;
  41. SQL_LEVEL_1_TOKEN m_Tok;
  42. MY_SQL_LEVEL_1_TOKEN() { m_bSpecial = FALSE; }
  43. //assignment operators
  44. MY_SQL_LEVEL_1_TOKEN& operator=(SQL_LEVEL_1_TOKEN &Src)
  45. {
  46. m_bSpecial = FALSE;
  47. this->m_Tok = Src;
  48. return *this;
  49. }
  50. MY_SQL_LEVEL_1_TOKEN& operator=(MY_SQL_LEVEL_1_TOKEN &Src)
  51. {
  52. *this = Src.m_Tok;
  53. m_bSpecial = Src.m_bSpecial;
  54. return *this;
  55. }
  56. //copy constructors match the operators
  57. MY_SQL_LEVEL_1_TOKEN(MY_SQL_LEVEL_1_TOKEN &Src) { *this = Src; }
  58. MY_SQL_LEVEL_1_TOKEN(SQL_LEVEL_1_TOKEN &Src) { *this = Src; }
  59. };
  60. ExecQueryTaskObject::ExecQueryTaskObject(CViewProvServ *a_Provider ,
  61. BSTR a_QueryFormat, BSTR a_Query, ULONG a_Flag,
  62. IWbemObjectSink *a_NotificationHandler, IWbemContext *pCtx
  63. )
  64. : WbemTaskObject(a_Provider, a_NotificationHandler, a_Flag, pCtx),
  65. m_Query(NULL),
  66. m_QueryFormat(NULL),
  67. m_RPNExpression(NULL)
  68. {
  69. m_Query = UnicodeStringDuplicate(a_Query);
  70. m_QueryFormat = UnicodeStringDuplicate(a_QueryFormat);
  71. }
  72. ExecQueryTaskObject::~ExecQueryTaskObject ()
  73. {
  74. BOOL t_Status = TRUE;
  75. IWbemClassObject *t_NotifyStatus = NULL ;
  76. if (WBEM_NO_ERROR != m_ErrorObject.GetWbemStatus ())
  77. {
  78. t_Status = GetExtendedNotifyStatusObject ( &t_NotifyStatus ) ;
  79. }
  80. if ( t_Status )
  81. {
  82. m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetWbemStatus () , 0 , t_NotifyStatus ) ;
  83. if (t_NotifyStatus)
  84. {
  85. t_NotifyStatus->Release () ;
  86. }
  87. }
  88. else
  89. {
  90. m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetWbemStatus () , 0 , NULL ) ;
  91. }
  92. if (m_Query != NULL)
  93. {
  94. delete [] m_Query;
  95. }
  96. if (m_QueryFormat != NULL)
  97. {
  98. delete [] m_QueryFormat;
  99. }
  100. if (m_RPNExpression != NULL)
  101. {
  102. delete m_RPNExpression;
  103. }
  104. if (m_StatusHandle != NULL)
  105. {
  106. CloseHandle(m_StatusHandle);
  107. }
  108. }
  109. BOOL ExecQueryTaskObject::PerformQuery(WbemProvErrorObject &a_ErrorObject)
  110. {
  111. BOOL retVal = FALSE;
  112. m_StatusHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
  113. retVal = PerformEnumQueries(a_ErrorObject);
  114. if (retVal)
  115. {
  116. BOOL bWait = TRUE;
  117. while (bWait)
  118. {
  119. DWORD dwWait = WbemWaitForSingleObject(m_StatusHandle, VP_QUERY_TIMEOUT);
  120. switch (dwWait)
  121. {
  122. case WAIT_OBJECT_0:
  123. {
  124. if (ResetEvent(m_StatusHandle))
  125. {
  126. m_ResultReceived = FALSE;
  127. retVal = PerformSelectQueries(a_ErrorObject, bWait);
  128. if (retVal)
  129. {
  130. if (bWait)
  131. {
  132. while (bWait)
  133. {
  134. dwWait = WbemWaitForSingleObject(m_StatusHandle, VP_QUERY_TIMEOUT);
  135. switch (dwWait)
  136. {
  137. case WAIT_OBJECT_0 :
  138. {
  139. retVal = ProcessResults(a_ErrorObject);
  140. bWait = FALSE;
  141. }
  142. break;
  143. case WAIT_TIMEOUT:
  144. {
  145. BOOL bCleanup = TRUE;
  146. if (m_ArrayLock.Lock())
  147. {
  148. if (m_ResultReceived)
  149. {
  150. m_ResultReceived = FALSE;
  151. bCleanup = FALSE;
  152. }
  153. m_ArrayLock.Unlock();
  154. }
  155. if (bCleanup)
  156. {
  157. CleanUpObjSinks(TRUE);
  158. a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
  159. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  160. a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed, or query timed out" ) ;
  161. retVal = FALSE;
  162. bWait = FALSE;
  163. }
  164. }
  165. break;
  166. default:
  167. {
  168. //Cancel outstanding requests and delete object sinks...
  169. //======================================================
  170. CleanUpObjSinks(TRUE);
  171. a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
  172. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  173. a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed" ) ;
  174. retVal = FALSE;
  175. bWait = FALSE;
  176. }
  177. }
  178. }
  179. }
  180. else
  181. {
  182. retVal = ProcessResults(a_ErrorObject);
  183. }
  184. }
  185. else
  186. {
  187. ProcessResults(a_ErrorObject);
  188. }
  189. }
  190. else
  191. {
  192. retVal = FALSE;
  193. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  194. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  195. a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), a WIN32 API failed" ) ;
  196. ProcessResults(a_ErrorObject);
  197. }
  198. bWait = FALSE;
  199. }
  200. break;
  201. case WAIT_TIMEOUT:
  202. {
  203. BOOL bCleanup = TRUE;
  204. if (m_ArrayLock.Lock())
  205. {
  206. if (m_ResultReceived)
  207. {
  208. m_ResultReceived = FALSE;
  209. bCleanup = FALSE;
  210. }
  211. m_ArrayLock.Unlock();
  212. }
  213. if (bCleanup)
  214. {
  215. CleanUpObjSinks(TRUE);
  216. a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
  217. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  218. a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed, or query timed out" ) ;
  219. retVal = FALSE;
  220. bWait = FALSE;
  221. }
  222. }
  223. break;
  224. default:
  225. {
  226. //Cancel outstanding requests and delete object sinks...
  227. //======================================================
  228. CleanUpObjSinks(TRUE);
  229. a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
  230. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  231. a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed" ) ;
  232. retVal = FALSE;
  233. bWait = FALSE;
  234. }
  235. }
  236. }
  237. }
  238. else
  239. {
  240. //no outstanding requests, just delete object sinks...
  241. //====================================================
  242. CleanUpObjSinks();
  243. }
  244. return retVal;
  245. }
  246. //The following function does 'simple' analysis of the current
  247. //query and modifies the source queries accordingly...
  248. //============================================================
  249. void ExecQueryTaskObject::ModifySourceQueriesForUserQuery()
  250. {
  251. MY_SQL_LEVEL_1_TOKEN* pExtraToks = new MY_SQL_LEVEL_1_TOKEN[m_RPNExpression->nNumTokens + 1];
  252. for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
  253. {
  254. DWORD dwToks = 0;
  255. BOOL bOptimize = TRUE;
  256. for (int i = 0; bOptimize && (i < m_RPNExpression->nNumTokens); i++)
  257. {
  258. switch (m_RPNExpression->pArrayOfTokens[i].nTokenType)
  259. {
  260. case SQL_LEVEL_1_TOKEN::TOKEN_AND:
  261. {
  262. pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  263. }
  264. break;
  265. case SQL_LEVEL_1_TOKEN::TOKEN_OR:
  266. {
  267. pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  268. }
  269. break;
  270. case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
  271. {
  272. pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_NOT;
  273. }
  274. break;
  275. case SQL_LEVEL_1_TOKEN::OP_EXPRESSION:
  276. {
  277. CPropertyQualifierItem* propItem;
  278. if (m_PropertyMap.Lookup(m_RPNExpression->pArrayOfTokens[i].pPropertyName, propItem))
  279. {
  280. if (!propItem->m_SrcPropertyNames[x].IsEmpty())
  281. {
  282. //TransposeReference if necessary
  283. //=================================
  284. MY_SQL_LEVEL_1_TOKEN tmpToken = m_RPNExpression->pArrayOfTokens[i];
  285. BOOL bCont = TRUE;
  286. if (m_bAssoc && (propItem->GetCimType() == CIM_REFERENCE))
  287. {
  288. bCont = TransposeReference(propItem, m_RPNExpression->pArrayOfTokens[i].vConstValue,
  289. &(tmpToken.m_Tok.vConstValue), FALSE, NULL);
  290. if (bCont)
  291. {
  292. //mark the token as special
  293. //for the association work-around
  294. tmpToken.m_bSpecial = TRUE;
  295. }
  296. }
  297. if (bCont)
  298. {
  299. pExtraToks[dwToks] = tmpToken;
  300. SysFreeString(pExtraToks[dwToks].m_Tok.pPropertyName);
  301. pExtraToks[dwToks++].m_Tok.pPropertyName = propItem->m_SrcPropertyNames[x].AllocSysString();
  302. }
  303. else
  304. {
  305. //can't "simply" optimize this query!
  306. dwToks = 0;
  307. bOptimize = FALSE;
  308. }
  309. }
  310. else
  311. {
  312. //can't "simply" optimize this query!
  313. dwToks = 0;
  314. bOptimize = FALSE;
  315. }
  316. }
  317. else
  318. {
  319. //can't "simply" optimize this query!
  320. dwToks = 0;
  321. bOptimize = FALSE;
  322. }
  323. }
  324. break;
  325. default:
  326. {
  327. }
  328. }
  329. }
  330. if (dwToks != 0)
  331. {
  332. if (m_SourceArray[x]->GetRPNExpression()->nNumTokens > 0)
  333. {
  334. pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  335. }
  336. for (i = 0; i < dwToks; i++)
  337. {
  338. m_SourceArray[x]->GetRPNExpression()->AddToken(pExtraToks[i].m_Tok);
  339. if (pExtraToks[i].m_bSpecial)
  340. {
  341. //add the extra tokens if neccessary
  342. //for the association work-around
  343. wchar_t *t_pChar = pExtraToks[i].m_Tok.vConstValue.bstrVal;
  344. //must be \\server\namespace and not \\.\namespace or relpath
  345. if ( (*t_pChar == L'\\') && (*(t_pChar+1) == L'\\') && (*(t_pChar+2) != L'.') )
  346. {
  347. //add the dotted version
  348. SQL_LEVEL_1_TOKEN t_Tok = pExtraToks[i].m_Tok;
  349. t_pChar = t_Tok.vConstValue.bstrVal + 2;
  350. while (*t_pChar != L'\\')
  351. {
  352. t_pChar++;
  353. }
  354. --t_pChar;
  355. *t_pChar = L'.';
  356. --t_pChar;
  357. *t_pChar = L'\\';
  358. --t_pChar;
  359. *t_pChar = L'\\';
  360. BSTR t_strtmp = SysAllocString(t_pChar);
  361. VariantClear(&(t_Tok.vConstValue));
  362. VariantInit(&(t_Tok.vConstValue));
  363. t_Tok.vConstValue.vt = VT_BSTR;
  364. t_Tok.vConstValue.bstrVal = t_strtmp;
  365. m_SourceArray[x]->GetRPNExpression()->AddToken(t_Tok);
  366. //add an Or token
  367. SQL_LEVEL_1_TOKEN t_OrTok;
  368. t_OrTok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  369. m_SourceArray[x]->GetRPNExpression()->AddToken(t_OrTok);
  370. //add the relpath version
  371. t_pChar = t_Tok.vConstValue.bstrVal + 4;
  372. while (*t_pChar != L':')
  373. {
  374. t_pChar++;
  375. }
  376. //exclude the ':'
  377. t_pChar++;
  378. t_strtmp = SysAllocString(t_pChar);
  379. VariantClear(&(t_Tok.vConstValue));
  380. VariantInit(&(t_Tok.vConstValue));
  381. t_Tok.vConstValue.vt = VT_BSTR;
  382. t_Tok.vConstValue.bstrVal = t_strtmp;
  383. m_SourceArray[x]->GetRPNExpression()->AddToken(t_Tok);
  384. //add the last OR
  385. m_SourceArray[x]->GetRPNExpression()->AddToken(t_OrTok);
  386. }
  387. }
  388. }
  389. }
  390. }
  391. delete [] pExtraToks;
  392. }
  393. //This function does 'simple' analysis of the join and modifies the
  394. //unexecuted source queries accordingly for the results received so far...
  395. //=========================================================================
  396. void ExecQueryTaskObject::ModifySourceQueriesWithEnumResults()
  397. {
  398. wchar_t** classA = m_JoinOnArray.GetAClasses();
  399. wchar_t** propsA = m_JoinOnArray.GetAProperties();
  400. wchar_t** classB = m_JoinOnArray.GetBClasses();
  401. wchar_t** propsB = m_JoinOnArray.GetBProperties();
  402. UINT* ops = m_JoinOnArray.GetOperators();
  403. int iEnum; //the index of the enumerated class
  404. int iMod; //the index of the source query to be modified
  405. for (int x = 0; x < m_JoinOnArray.GetCount(); x++)
  406. {
  407. BOOL bIsAEnum = m_EnumerateClasses.Lookup(classA[x], iEnum);
  408. BOOL bIsBEnum = m_EnumerateClasses.Lookup(classB[x], iEnum);
  409. wchar_t* propEnum;
  410. wchar_t* propMod;
  411. if ( (bIsAEnum && !bIsBEnum) || (!bIsAEnum && bIsBEnum) )
  412. {
  413. if (bIsAEnum)
  414. {
  415. if (!m_ClassToIndexMap.Lookup(classA[x], iEnum))
  416. {
  417. //an error forget this case!
  418. continue;
  419. }
  420. else
  421. {
  422. if (!m_ClassToIndexMap.Lookup(classB[x], iMod))
  423. {
  424. //an error forget this case!
  425. continue;
  426. }
  427. else
  428. {
  429. propEnum = propsA[x];
  430. propMod = propsB[x];
  431. }
  432. }
  433. }
  434. else
  435. {
  436. if (!m_ClassToIndexMap.Lookup(classB[x], iEnum))
  437. {
  438. //an error forget this case!
  439. continue;
  440. }
  441. else
  442. {
  443. if (!m_ClassToIndexMap.Lookup(classA[x], iMod))
  444. {
  445. //an error forget this case!
  446. continue;
  447. }
  448. else
  449. {
  450. propEnum = propsB[x];
  451. propMod = propsA[x];
  452. }
  453. }
  454. }
  455. //don't transpose references as
  456. //they are already in source format.
  457. int m = 0;
  458. SQL_LEVEL_1_TOKEN opToken;
  459. opToken.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  460. SQL_LEVEL_1_TOKEN token;
  461. token.nTokenType = SQL_LEVEL_1_TOKEN::OP_EXPRESSION;
  462. token.pPropertyName = SysAllocString(propMod);
  463. if (ops[x] == CJoinOnQualifierArray::NOT_EQUALS_OPERATOR)
  464. {
  465. token.nOperator = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
  466. }
  467. else if (ops[x] == CJoinOnQualifierArray::EQUALS_OPERATOR)
  468. {
  469. token.nOperator = SQL_LEVEL_1_TOKEN::OP_EQUAL;
  470. }
  471. BOOL bAddAnd = m_SourceArray[iMod]->GetRPNExpression()->nNumTokens > 0;
  472. for (int n = 0; n < m_ObjSinkArray[iEnum]->m_ObjArray.GetSize(); n++)
  473. {
  474. VariantInit(&token.vConstValue);
  475. IWbemClassObject* pObj = m_ObjSinkArray[iEnum]->m_ObjArray[n]->GetWrappedObject();
  476. if ( SUCCEEDED(pObj->Get(propEnum, 0, &token.vConstValue, NULL, NULL)) )
  477. {
  478. m_SourceArray[iMod]->GetRPNExpression()->AddToken(token);
  479. m++;
  480. if (m > 1)
  481. {
  482. m_SourceArray[iMod]->GetRPNExpression()->AddToken(opToken);
  483. }
  484. }
  485. VariantClear(&token.vConstValue);
  486. }
  487. if ((bAddAnd) && (m != 0))
  488. {
  489. opToken.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  490. m_SourceArray[iMod]->GetRPNExpression()->AddToken(opToken);
  491. }
  492. }
  493. }
  494. }
  495. BOOL ExecQueryTaskObject::PerformSelectQueries(WbemProvErrorObject &a_ErrorObject, BOOL &bWait)
  496. {
  497. bWait = FALSE;
  498. if (!m_JoinOnArray.IsValid() || m_EnumerateClasses.IsEmpty())
  499. {
  500. return TRUE;
  501. }
  502. ModifySourceQueriesWithEnumResults();
  503. //reset number of queries asked and answered
  504. m_iQueriesAsked = 1;
  505. m_iQueriesAnswered = 0;
  506. for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
  507. {
  508. int dummyInt;
  509. if (!m_EnumerateClasses.Lookup(m_SourceArray[x]->GetClassName(), dummyInt))
  510. {
  511. CStringW queryStr = GetStringFromRPN(m_SourceArray[x]->GetRPNExpression(), 0, NULL);
  512. CWbemServerWrap** nsPtrs = m_NSpaceArray[x]->GetServerPtrs();
  513. if (queryStr.GetLength() > 0)
  514. {
  515. for (int m = 0; m < m_NSpaceArray[x]->GetCount(); m++)
  516. {
  517. if (nsPtrs[m] != NULL)
  518. {
  519. CViewProvObjectSink* pSnk = new CViewProvObjectSink(m_ObjSinkArray[x], nsPtrs[m], m);
  520. pSnk->AddRef();
  521. BSTR queryBStr = queryStr.AllocSysString();
  522. BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
  523. IWbemObjectSink* pQuerySink = pSnk;
  524. IWbemContext * t_pCtx = m_Ctx;
  525. if (nsPtrs[m]->IsRemote())
  526. {
  527. pQuerySink = pSnk->Associate();
  528. t_pCtx = NULL; //don't use context for remote cimoms
  529. }
  530. IWbemServices *ptmpServ = nsPtrs[m]->GetServerOrProxy();
  531. if (ptmpServ)
  532. {
  533. if ( pQuerySink )
  534. {
  535. HRESULT t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  536. if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && nsPtrs[m]->IsRemote())
  537. {
  538. if ( SUCCEEDED(UpdateConnection(&(nsPtrs[m]), &ptmpServ)) )
  539. {
  540. if (ptmpServ)
  541. {
  542. t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  543. }
  544. }
  545. }
  546. if (SUCCEEDED(t_hr))
  547. {
  548. if (m_ArrayLock.Lock())
  549. {
  550. m_iQueriesAsked++;
  551. m_ArrayLock.Unlock();
  552. }
  553. else
  554. {
  555. pSnk->DisAssociate();
  556. }
  557. }
  558. else
  559. {
  560. pSnk->DisAssociate();
  561. }
  562. }
  563. else
  564. {
  565. pSnk->DisAssociate();
  566. }
  567. if (ptmpServ)
  568. {
  569. nsPtrs[m]->ReturnServerOrProxy(ptmpServ);
  570. }
  571. }
  572. else
  573. {
  574. pSnk->DisAssociate();
  575. }
  576. SysFreeString(queryLBStr);
  577. SysFreeString(queryBStr);
  578. pSnk->Release();
  579. }
  580. }
  581. }
  582. }
  583. }
  584. if (m_ArrayLock.Lock())
  585. {
  586. m_iQueriesAsked--;
  587. if (m_iQueriesAsked != m_iQueriesAnswered)
  588. {
  589. //just in case this was triggerred while we had yet to ask some queries
  590. ResetEvent(m_StatusHandle);
  591. }
  592. else
  593. {
  594. //just in case this wasn't triggerred while we were asking queries
  595. SetEvent(m_StatusHandle);
  596. }
  597. m_ArrayLock.Unlock();
  598. }
  599. if (m_iQueriesAsked == 0)
  600. {
  601. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  602. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  603. a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), invalid source namespace(s)" ) ;
  604. return FALSE;
  605. }
  606. else
  607. {
  608. bWait = TRUE;
  609. }
  610. return TRUE;
  611. }
  612. BOOL ExecQueryTaskObject::PerformEnumQueries(WbemProvErrorObject &a_ErrorObject)
  613. {
  614. m_iQueriesAsked++;
  615. ModifySourceQueriesForUserQuery();
  616. m_ObjSinkArray.SetSize(0, m_NSpaceArray.GetSize());
  617. for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
  618. {
  619. BOOL bDone = FALSE;
  620. int dummyInt;
  621. CObjectSinkResults * objSnk = new CObjectSinkResults(this, x);
  622. objSnk->AddRef();
  623. m_ObjSinkArray.SetAtGrow(x, objSnk);
  624. if (!m_JoinOnArray.IsValid() || m_EnumerateClasses.IsEmpty() ||
  625. m_EnumerateClasses.Lookup(m_SourceArray[x]->GetClassName(), dummyInt) )
  626. {
  627. CStringW queryStr = GetStringFromRPN(m_SourceArray[x]->GetRPNExpression(), 0, NULL);
  628. if (queryStr.GetLength() > 0)
  629. {
  630. CWbemServerWrap** nsPtrs = m_NSpaceArray[x]->GetServerPtrs();
  631. for (int m = 0; m < m_NSpaceArray[x]->GetCount(); m++)
  632. {
  633. if (nsPtrs[m] != NULL)
  634. {
  635. CViewProvObjectSink* pSnk = new CViewProvObjectSink(objSnk, nsPtrs[m], m);
  636. pSnk->AddRef();
  637. BSTR queryBStr = queryStr.AllocSysString();
  638. BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
  639. IWbemObjectSink* pQuerySink = pSnk;
  640. IWbemContext * t_pCtx = m_Ctx;
  641. if (nsPtrs[m]->IsRemote())
  642. {
  643. pQuerySink = pSnk->Associate();
  644. t_pCtx = NULL; //don't use context for remote cimoms
  645. }
  646. IWbemServices *ptmpServ = nsPtrs[m]->GetServerOrProxy();
  647. if (ptmpServ)
  648. {
  649. if ( pQuerySink )
  650. {
  651. HRESULT t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  652. if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && nsPtrs[m]->IsRemote())
  653. {
  654. if ( SUCCEEDED(UpdateConnection(&(nsPtrs[m]), &ptmpServ)) )
  655. {
  656. if (ptmpServ)
  657. {
  658. t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  659. }
  660. }
  661. }
  662. if (SUCCEEDED(t_hr))
  663. {
  664. if (m_ArrayLock.Lock())
  665. {
  666. m_iQueriesAsked++;
  667. m_ArrayLock.Unlock();
  668. }
  669. else
  670. {
  671. pSnk->DisAssociate();
  672. }
  673. }
  674. else
  675. {
  676. pSnk->DisAssociate();
  677. }
  678. }
  679. else
  680. {
  681. pSnk->DisAssociate();
  682. }
  683. if (ptmpServ)
  684. {
  685. nsPtrs[m]->ReturnServerOrProxy(ptmpServ);
  686. }
  687. }
  688. else
  689. {
  690. pSnk->DisAssociate();
  691. }
  692. pSnk->Release();
  693. SysFreeString(queryBStr);
  694. SysFreeString(queryLBStr);
  695. }
  696. }
  697. }
  698. }
  699. }
  700. if (m_ArrayLock.Lock())
  701. {
  702. m_iQueriesAsked--;
  703. if (m_iQueriesAsked != m_iQueriesAnswered)
  704. {
  705. //just in case this was triggerred while we had yet to ask some queries
  706. ResetEvent(m_StatusHandle);
  707. }
  708. else
  709. {
  710. //just in case this wasn't triggerred while we were asking queries
  711. SetEvent(m_StatusHandle);
  712. }
  713. m_ArrayLock.Unlock();
  714. }
  715. if (m_iQueriesAsked == 0)
  716. {
  717. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  718. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  719. a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), invalid source namespace(s)" ) ;
  720. return FALSE;
  721. }
  722. return TRUE;
  723. }
  724. BOOL ExecQueryTaskObject::ProcessResults(WbemProvErrorObject &a_ErrorObject)
  725. {
  726. BOOL retVal = TRUE;
  727. int indexCnt = 0;
  728. for (int x = 0; retVal && (x < m_ObjSinkArray.GetSize()); x++)
  729. {
  730. if (m_ObjSinkArray[x]->IsSet())
  731. {
  732. if (SUCCEEDED(m_ObjSinkArray[x]->GetResult()))
  733. {
  734. DWORD dwCount = m_ObjSinkArray[x]->m_ObjArray.GetSize();
  735. if (0 < dwCount)
  736. {
  737. indexCnt++;
  738. }
  739. }
  740. else
  741. {
  742. retVal = FALSE;
  743. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  744. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  745. a_ErrorObject.SetMessage ( L"Object path and Class qualifiers resulted in a failed query." ) ;
  746. }
  747. }
  748. else
  749. {
  750. retVal = FALSE;
  751. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  752. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  753. a_ErrorObject.SetMessage ( L"Invalid source namespace path OR object path and Class qualifiers resulted in a failed query." ) ;
  754. }
  755. }
  756. if (0 == indexCnt)
  757. {
  758. if (retVal)
  759. {
  760. retVal = FALSE;
  761. a_ErrorObject.SetStatus ( WBEM_PROV_E_NOT_FOUND ) ;
  762. a_ErrorObject.SetWbemStatus ( WBEM_E_NOT_FOUND ) ;
  763. a_ErrorObject.SetMessage ( L"No source objects found to support view object path." ) ;
  764. }
  765. CleanUpObjSinks();
  766. }
  767. else
  768. {
  769. if (m_JoinOnArray.IsValid())
  770. {
  771. #ifdef VP_PERFORMANT_JOINS
  772. BOOL t_bRes = CreateAndIndicateJoinsPerf(a_ErrorObject, m_bSingleton);
  773. #else
  774. BOOL t_bRes = CreateAndIndicateJoins(a_ErrorObject, m_bSingleton);
  775. #endif
  776. retVal = retVal && t_bRes;
  777. }
  778. else //union or association
  779. {
  780. if ((m_bSingleton) && (indexCnt > 1))
  781. {
  782. retVal = FALSE;
  783. a_ErrorObject.SetStatus ( WBEM_PROV_E_TOOMANYRESULTSRETURNED ) ;
  784. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  785. a_ErrorObject.SetMessage ( L"Too many view instances can be created." ) ;
  786. CleanUpObjSinks();
  787. }
  788. else
  789. {
  790. BOOL t_bRes = CreateAndIndicateUnions(a_ErrorObject, -1);
  791. retVal = retVal && t_bRes;
  792. }
  793. }
  794. }
  795. return retVal;
  796. }
  797. BOOL ExecQueryTaskObject :: ExecQuery ()
  798. {
  799. BOOL t_Status ;
  800. DebugOut2(
  801. CViewProvServ::sm_debugLog->WriteFileAndLine (
  802. _T(__FILE__),__LINE__,
  803. _T("ExecQueryTaskObject :: ExecQuery\r\n")
  804. ) ;
  805. )
  806. if ( _wcsicmp ( m_QueryFormat , WBEM_QUERY_LANGUAGE_SQL1 ) == 0 )
  807. {
  808. CTextLexSource querySource(m_Query);
  809. SQL1_Parser sqlParser(&querySource) ;
  810. t_Status = ! sqlParser.Parse ( & m_RPNExpression ) ;
  811. if ( t_Status )
  812. {
  813. t_Status = SetClass(m_RPNExpression->bsClassName) ;
  814. if ( t_Status )
  815. {
  816. t_Status = ParseAndProcessClassQualifiers(m_ErrorObject);
  817. if (t_Status)
  818. {
  819. t_Status = PerformQuery(m_ErrorObject);
  820. }
  821. }
  822. else
  823. {
  824. t_Status = FALSE ;
  825. m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  826. m_ErrorObject.SetWbemStatus ( WBEM_E_INVALID_CLASS ) ;
  827. m_ErrorObject.SetMessage ( L"Unknown Class" ) ;
  828. DebugOut2(
  829. CViewProvServ::sm_debugLog->WriteFileAndLine (
  830. _T(__FILE__),__LINE__,
  831. _T("ExecQueryTaskObject :: ExecQuery:Unknown Class\r\n")
  832. ) ;
  833. )
  834. }
  835. }
  836. else
  837. {
  838. t_Status = FALSE ;
  839. m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_QUERY ) ;
  840. m_ErrorObject.SetWbemStatus ( WBEM_E_PROVIDER_NOT_CAPABLE ) ;
  841. m_ErrorObject.SetMessage ( L"WQL query was invalid for this provider" ) ;
  842. DebugOut2(
  843. CViewProvServ::sm_debugLog->WriteFileAndLine (
  844. _T(__FILE__),__LINE__,
  845. _T("ExecQueryTaskObject :: ExecQuery:WQL query was invalid for this provider\r\n")
  846. ) ;
  847. )
  848. }
  849. }
  850. else
  851. {
  852. t_Status = FALSE ;
  853. m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_QUERY_TYPE ) ;
  854. m_ErrorObject.SetWbemStatus ( WBEM_E_INVALID_QUERY_TYPE ) ;
  855. m_ErrorObject.SetMessage ( L"Query Language not supported" ) ;
  856. DebugOut2(
  857. CViewProvServ::sm_debugLog->WriteFileAndLine (
  858. _T(__FILE__),__LINE__,
  859. _T("ExecQueryTaskObject :: ExecQuery:Query Language not supported\r\n")
  860. ) ;
  861. )
  862. }
  863. DebugOut2(
  864. CViewProvServ::sm_debugLog->WriteFileAndLine (
  865. _T(__FILE__),__LINE__,
  866. _T("ExecQueryTaskObject :: ExecQuery:Returning %lx\r\n"),
  867. t_Status
  868. ) ;
  869. )
  870. return t_Status ;
  871. }