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.

1038 lines
26 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. BOOL bStatusSet = FALSE;
  499. if (!m_JoinOnArray.IsValid() || m_EnumerateClasses.IsEmpty())
  500. {
  501. return TRUE;
  502. }
  503. ModifySourceQueriesWithEnumResults();
  504. //reset number of queries asked and answered
  505. m_iQueriesAsked = 1;
  506. m_iQueriesAnswered = 0;
  507. for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
  508. {
  509. int dummyInt;
  510. if (!m_EnumerateClasses.Lookup(m_SourceArray[x]->GetClassName(), dummyInt))
  511. {
  512. CStringW queryStr = GetStringFromRPN(m_SourceArray[x]->GetRPNExpression(), 0, NULL);
  513. CWbemServerWrap** nsPtrs = m_NSpaceArray[x]->GetServerPtrs();
  514. if (queryStr.GetLength() > 0)
  515. {
  516. for (int m = 0; m < m_NSpaceArray[x]->GetCount(); m++)
  517. {
  518. if (nsPtrs[m] != NULL)
  519. {
  520. CViewProvObjectSink* pSnk = new CViewProvObjectSink(m_ObjSinkArray[x], nsPtrs[m], m);
  521. pSnk->AddRef();
  522. BSTR queryBStr = queryStr.AllocSysString();
  523. BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
  524. IWbemObjectSink* pQuerySink = pSnk;
  525. IWbemContext * t_pCtx = m_Ctx;
  526. if (nsPtrs[m]->IsRemote())
  527. {
  528. #if 0
  529. #if _NT_TARGET_VERSION < 500
  530. pQuerySink = pSnk->Associate();
  531. #endif
  532. #endif
  533. t_pCtx = NULL; //don't use context for remote cimoms
  534. }
  535. IWbemServices *ptmpServ = nsPtrs[m]->GetServerOrProxy();
  536. if (ptmpServ)
  537. {
  538. if ( pQuerySink )
  539. {
  540. HRESULT t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  541. if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && nsPtrs[m]->IsRemote())
  542. {
  543. if ( SUCCEEDED(UpdateConnection(&(nsPtrs[m]), &ptmpServ)) )
  544. {
  545. if (ptmpServ)
  546. {
  547. t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  548. }
  549. }
  550. }
  551. if (SUCCEEDED(t_hr))
  552. {
  553. if (m_ArrayLock.Lock())
  554. {
  555. m_iQueriesAsked++;
  556. m_ArrayLock.Unlock();
  557. }
  558. else
  559. {
  560. pSnk->DisAssociate();
  561. }
  562. }
  563. else
  564. {
  565. pSnk->DisAssociate();
  566. }
  567. }
  568. else
  569. {
  570. pSnk->DisAssociate();
  571. }
  572. if (ptmpServ)
  573. {
  574. nsPtrs[m]->ReturnServerOrProxy(ptmpServ);
  575. }
  576. }
  577. else
  578. {
  579. pSnk->DisAssociate();
  580. }
  581. SysFreeString(queryLBStr);
  582. SysFreeString(queryBStr);
  583. pSnk->Release();
  584. }
  585. else
  586. {
  587. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_NAMESPACE ) ;
  588. a_ErrorObject.SetWbemStatus ( ( WBEMSTATUS ) m_NSpaceArray[x]->GetServerCreationError () ) ;
  589. a_ErrorObject.SetMessage ( L"Failed to send query, invalid or inaccessible namespace" ) ;
  590. bStatusSet = TRUE;
  591. }
  592. }
  593. }
  594. }
  595. }
  596. if (m_ArrayLock.Lock())
  597. {
  598. m_iQueriesAsked--;
  599. if (m_iQueriesAsked != m_iQueriesAnswered)
  600. {
  601. //just in case this was triggerred while we had yet to ask some queries
  602. ResetEvent(m_StatusHandle);
  603. }
  604. else
  605. {
  606. //just in case this wasn't triggerred while we were asking queries
  607. SetEvent(m_StatusHandle);
  608. }
  609. m_ArrayLock.Unlock();
  610. }
  611. if (m_iQueriesAsked == 0)
  612. {
  613. if ( ! bStatusSet )
  614. {
  615. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  616. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  617. a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), invalid source namespace(s)" ) ;
  618. }
  619. return FALSE;
  620. }
  621. else
  622. {
  623. bWait = TRUE;
  624. }
  625. return TRUE;
  626. }
  627. BOOL ExecQueryTaskObject::PerformEnumQueries(WbemProvErrorObject &a_ErrorObject)
  628. {
  629. m_iQueriesAsked++;
  630. ModifySourceQueriesForUserQuery();
  631. m_ObjSinkArray.SetSize(0, m_NSpaceArray.GetSize());
  632. BOOL bStatusSet = FALSE;
  633. for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
  634. {
  635. BOOL bDone = FALSE;
  636. int dummyInt;
  637. CObjectSinkResults * objSnk = new CObjectSinkResults(this, x);
  638. objSnk->AddRef();
  639. m_ObjSinkArray.SetAtGrow(x, objSnk);
  640. if (!m_JoinOnArray.IsValid() || m_EnumerateClasses.IsEmpty() ||
  641. m_EnumerateClasses.Lookup(m_SourceArray[x]->GetClassName(), dummyInt) )
  642. {
  643. CStringW queryStr = GetStringFromRPN(m_SourceArray[x]->GetRPNExpression(), 0, NULL);
  644. if (queryStr.GetLength() > 0)
  645. {
  646. CWbemServerWrap** nsPtrs = m_NSpaceArray[x]->GetServerPtrs();
  647. for (int m = 0; m < m_NSpaceArray[x]->GetCount(); m++)
  648. {
  649. if (nsPtrs[m] != NULL)
  650. {
  651. CViewProvObjectSink* pSnk = new CViewProvObjectSink(objSnk, nsPtrs[m], m);
  652. pSnk->AddRef();
  653. BSTR queryBStr = queryStr.AllocSysString();
  654. BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
  655. IWbemObjectSink* pQuerySink = pSnk;
  656. IWbemContext * t_pCtx = m_Ctx;
  657. if (nsPtrs[m]->IsRemote())
  658. {
  659. #if 0
  660. #if _NT_TARGET_VERSION < 500
  661. pQuerySink = pSnk->Associate();
  662. #endif
  663. #endif
  664. t_pCtx = NULL; //don't use context for remote cimoms
  665. }
  666. IWbemServices *ptmpServ = nsPtrs[m]->GetServerOrProxy();
  667. if (ptmpServ)
  668. {
  669. if ( pQuerySink )
  670. {
  671. HRESULT t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  672. if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && nsPtrs[m]->IsRemote())
  673. {
  674. if ( SUCCEEDED(UpdateConnection(&(nsPtrs[m]), &ptmpServ)) )
  675. {
  676. if (ptmpServ)
  677. {
  678. t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
  679. }
  680. }
  681. }
  682. if (SUCCEEDED(t_hr))
  683. {
  684. if (m_ArrayLock.Lock())
  685. {
  686. m_iQueriesAsked++;
  687. m_ArrayLock.Unlock();
  688. }
  689. else
  690. {
  691. pSnk->DisAssociate();
  692. }
  693. }
  694. else
  695. {
  696. pSnk->DisAssociate();
  697. }
  698. }
  699. else
  700. {
  701. pSnk->DisAssociate();
  702. }
  703. if (ptmpServ)
  704. {
  705. nsPtrs[m]->ReturnServerOrProxy(ptmpServ);
  706. }
  707. }
  708. else
  709. {
  710. pSnk->DisAssociate();
  711. }
  712. pSnk->Release();
  713. SysFreeString(queryBStr);
  714. SysFreeString(queryLBStr);
  715. }
  716. else
  717. {
  718. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_NAMESPACE ) ;
  719. a_ErrorObject.SetWbemStatus ( ( WBEMSTATUS ) m_NSpaceArray[x]->GetServerCreationError () ) ;
  720. a_ErrorObject.SetMessage ( L"Failed to send query, invalid or inaccessible namespace" ) ;
  721. bStatusSet = TRUE;
  722. }
  723. }
  724. }
  725. }
  726. }
  727. if (m_ArrayLock.Lock())
  728. {
  729. m_iQueriesAsked--;
  730. if (m_iQueriesAsked != m_iQueriesAnswered)
  731. {
  732. //just in case this was triggerred while we had yet to ask some queries
  733. ResetEvent(m_StatusHandle);
  734. }
  735. else
  736. {
  737. //just in case this wasn't triggerred while we were asking queries
  738. SetEvent(m_StatusHandle);
  739. }
  740. m_ArrayLock.Unlock();
  741. }
  742. if (m_iQueriesAsked == 0)
  743. {
  744. if ( ! bStatusSet )
  745. {
  746. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  747. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  748. a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), invalid source namespace(s)" ) ;
  749. }
  750. return FALSE;
  751. }
  752. return TRUE;
  753. }
  754. BOOL ExecQueryTaskObject::ProcessResults(WbemProvErrorObject &a_ErrorObject)
  755. {
  756. BOOL retVal = TRUE;
  757. int indexCnt = 0;
  758. for (int x = 0; retVal && (x < m_ObjSinkArray.GetSize()); x++)
  759. {
  760. if (m_ObjSinkArray[x]->IsSet())
  761. {
  762. if (SUCCEEDED(m_ObjSinkArray[x]->GetResult()))
  763. {
  764. DWORD dwCount = m_ObjSinkArray[x]->m_ObjArray.GetSize();
  765. if (0 < dwCount)
  766. {
  767. indexCnt++;
  768. }
  769. }
  770. else
  771. {
  772. retVal = FALSE;
  773. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  774. a_ErrorObject.SetWbemStatus ( ( WBEMSTATUS ) m_ObjSinkArray[x]->GetResult() ) ;
  775. a_ErrorObject.SetMessage ( L"Object path and Class qualifiers resulted in a failed query." ) ;
  776. }
  777. }
  778. else
  779. {
  780. retVal = FALSE;
  781. a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  782. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  783. a_ErrorObject.SetMessage ( L"Invalid source namespace path OR object path and Class qualifiers resulted in a failed query." ) ;
  784. }
  785. }
  786. if (0 == indexCnt)
  787. {
  788. if (retVal)
  789. {
  790. retVal = FALSE;
  791. a_ErrorObject.SetStatus ( WBEM_PROV_E_NOT_FOUND ) ;
  792. a_ErrorObject.SetWbemStatus ( WBEM_E_NOT_FOUND ) ;
  793. a_ErrorObject.SetMessage ( L"No source objects found to support view object path." ) ;
  794. }
  795. CleanUpObjSinks();
  796. }
  797. else
  798. {
  799. if (m_JoinOnArray.IsValid())
  800. {
  801. #ifdef VP_PERFORMANT_JOINS
  802. BOOL t_bRes = CreateAndIndicateJoinsPerf(a_ErrorObject, m_bSingleton);
  803. #else
  804. BOOL t_bRes = CreateAndIndicateJoins(a_ErrorObject, m_bSingleton);
  805. #endif
  806. retVal = retVal && t_bRes;
  807. }
  808. else //union or association
  809. {
  810. if ((m_bSingleton) && (indexCnt > 1))
  811. {
  812. retVal = FALSE;
  813. a_ErrorObject.SetStatus ( WBEM_PROV_E_TOOMANYRESULTSRETURNED ) ;
  814. a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
  815. a_ErrorObject.SetMessage ( L"Too many view instances can be created." ) ;
  816. CleanUpObjSinks();
  817. }
  818. else
  819. {
  820. BOOL t_bRes = CreateAndIndicateUnions(a_ErrorObject, -1);
  821. retVal = retVal && t_bRes;
  822. }
  823. }
  824. }
  825. return retVal;
  826. }
  827. BOOL ExecQueryTaskObject :: ExecQuery ()
  828. {
  829. BOOL t_Status ;
  830. DebugOut2(
  831. CViewProvServ::sm_debugLog->WriteFileAndLine (
  832. _T(__FILE__),__LINE__,
  833. _T("ExecQueryTaskObject :: ExecQuery\r\n")
  834. ) ;
  835. )
  836. if ( _wcsicmp ( m_QueryFormat , WBEM_QUERY_LANGUAGE_SQL1 ) == 0 )
  837. {
  838. CTextLexSource querySource(m_Query);
  839. SQL1_Parser sqlParser(&querySource) ;
  840. t_Status = ! sqlParser.Parse ( & m_RPNExpression ) ;
  841. if ( t_Status )
  842. {
  843. t_Status = SetClass(m_RPNExpression->bsClassName) ;
  844. if ( t_Status )
  845. {
  846. t_Status = ParseAndProcessClassQualifiers(m_ErrorObject);
  847. if (t_Status)
  848. {
  849. t_Status = PerformQuery(m_ErrorObject);
  850. }
  851. }
  852. else
  853. {
  854. t_Status = FALSE ;
  855. m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
  856. m_ErrorObject.SetWbemStatus ( WBEM_E_INVALID_CLASS ) ;
  857. m_ErrorObject.SetMessage ( L"Unknown Class" ) ;
  858. DebugOut2(
  859. CViewProvServ::sm_debugLog->WriteFileAndLine (
  860. _T(__FILE__),__LINE__,
  861. _T("ExecQueryTaskObject :: ExecQuery:Unknown Class\r\n")
  862. ) ;
  863. )
  864. }
  865. }
  866. else
  867. {
  868. t_Status = FALSE ;
  869. m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_QUERY ) ;
  870. m_ErrorObject.SetWbemStatus ( WBEM_E_PROVIDER_NOT_CAPABLE ) ;
  871. m_ErrorObject.SetMessage ( L"WQL query was invalid for this provider" ) ;
  872. DebugOut2(
  873. CViewProvServ::sm_debugLog->WriteFileAndLine (
  874. _T(__FILE__),__LINE__,
  875. _T("ExecQueryTaskObject :: ExecQuery:WQL query was invalid for this provider\r\n")
  876. ) ;
  877. )
  878. }
  879. }
  880. else
  881. {
  882. t_Status = FALSE ;
  883. m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_QUERY_TYPE ) ;
  884. m_ErrorObject.SetWbemStatus ( WBEM_E_INVALID_QUERY_TYPE ) ;
  885. m_ErrorObject.SetMessage ( L"Query Language not supported" ) ;
  886. DebugOut2(
  887. CViewProvServ::sm_debugLog->WriteFileAndLine (
  888. _T(__FILE__),__LINE__,
  889. _T("ExecQueryTaskObject :: ExecQuery:Query Language not supported\r\n")
  890. ) ;
  891. )
  892. }
  893. DebugOut2(
  894. CViewProvServ::sm_debugLog->WriteFileAndLine (
  895. _T(__FILE__),__LINE__,
  896. _T("ExecQueryTaskObject :: ExecQuery:Returning %lx\r\n"),
  897. t_Status
  898. ) ;
  899. )
  900. return t_Status ;
  901. }