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.

2235 lines
66 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. DataCollection.cpp
  5. Abstract:
  6. This file contains the implementation of the CSAFDataCollection class,
  7. which implements the data collection functionality.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 07/22/99
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. #include "wmixmlt.h"
  14. #include <wbemcli.h>
  15. /////////////////////////////////////////////////////////////////////////////
  16. #define CHECK_MODIFY() __MPC_EXIT_IF_METHOD_FAILS(hr, CanModifyProperties())
  17. #define CHECK_ABORTED() __MPC_EXIT_IF_METHOD_FAILS(hr, IsCollectionAborted())
  18. #define DATASPEC_DEFAULT L"<systemdataspec>"
  19. #define DATASPEC_CONFIG HC_ROOT_HELPSVC_CONFIG L"\\Dataspec.xml"
  20. #define DATASPEC_LOCATION HC_ROOT_HELPSVC_DATACOLL
  21. #define DATASPEC_TEMP HC_ROOT_HELPSVC_TEMP
  22. #define SAFETY_MARGIN__MEMORY (4*1024*1024)
  23. /////////////////////////////////////////////////////////////////////////////
  24. #define TEXT_TAG_DATACOLLECTION L"DataCollection"
  25. #define TEXT_TAG_SNAPSHOT L"Snapshot"
  26. #define TEXT_ATTR_TIMESTAMP L"Timestamp"
  27. #define TEXT_ATTR_TIMEZONE L"TimeZone"
  28. #define TEXT_TAG_DELTA L"Delta"
  29. #define TEXT_ATTR_TIMESTAMP_T0 L"Timestamp_T0"
  30. #define TEXT_ATTR_TIMESTAMP_T1 L"Timestamp_T1"
  31. /////////////////////////////////////////////////////////////////////////////
  32. static WCHAR l_CIM_header [] = L"<?xml version=\"1.0\" encoding=\"unicode\"?><CIM CIMVERSION=\"2.0\" DTDVERSION=\"2.0\"><DECLARATION><DECLGROUP.WITHPATH>";
  33. static WCHAR l_CIM_trailer[] = L"</DECLGROUP.WITHPATH></DECLARATION></CIM>";
  34. static WCHAR l_Select_Pattern[] = L"Select";
  35. static CComVariant l_vPathLevel ( 3 );
  36. static CComVariant l_vExcludeSystemProperties ( (bool)true );
  37. static CComBSTR l_bstrQueryLang ( L"WQL" );
  38. static CComBSTR l_bstrPathLevel ( L"PathLevel" );
  39. static CComBSTR l_bstrExcludeSystemProperties( L"ExcludeSystemProperties" );
  40. /////////////////////////////////////////////////////////////////////////////
  41. void CSAFDataCollection::CleanQueryResult( QueryResults& qr )
  42. {
  43. MPC::CallDestructorForAll( qr );
  44. }
  45. HRESULT CSAFDataCollection::StreamFromXML( /*[in]*/ IXMLDOMDocument* xdd ,
  46. /*[in]*/ bool fDelete ,
  47. /*[in/out]*/ CComPtr<IStream>& val )
  48. {
  49. __HCP_FUNC_ENTRY( "CSAFDataCollection::StreamFromXML" );
  50. HRESULT hr;
  51. CComPtr<MPC::FileStream> stream;
  52. MPC::wstring strTempFile;
  53. //
  54. // No XML document, so no stream...
  55. //
  56. if(xdd)
  57. {
  58. MPC::wstring strTempPath;
  59. LARGE_INTEGER li;
  60. //
  61. // Generate a unique file name.
  62. //
  63. strTempPath = DATASPEC_TEMP; MPC::SubstituteEnvVariables( strTempPath );
  64. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetTemporaryFileName( strTempFile, strTempPath.c_str() ));
  65. //
  66. // Create a stream for a file.
  67. //
  68. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &stream ));
  69. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->InitForReadWrite( strTempFile.c_str() ));
  70. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->DeleteOnRelease ( fDelete ));
  71. //
  72. // Write the XML DOM to the stream.
  73. //
  74. __MPC_EXIT_IF_METHOD_FAILS(hr, xdd->save( CComVariant( stream ) ));
  75. //
  76. // Reset stream to beginning.
  77. //
  78. li.LowPart = 0;
  79. li.HighPart = 0;
  80. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->Seek( li, STREAM_SEEK_SET, NULL ));
  81. }
  82. val = stream;
  83. hr = S_OK;
  84. __HCP_FUNC_CLEANUP;
  85. if(FAILED(hr))
  86. {
  87. stream.Release();
  88. (void)MPC::RemoveTemporaryFile( strTempFile );
  89. }
  90. __HCP_FUNC_EXIT(hr);
  91. }
  92. /////////////////////////////////////////////////////////////////////////////
  93. CSAFDataCollection::CSAFDataCollection()
  94. {
  95. __HCP_FUNC_ENTRY( "CSAFDataCollection::CSAFDataCollection" );
  96. // MPC::Impersonation m_imp;
  97. //
  98. m_dsStatus = DC_NOTACTIVE; // DC_STATUS m_dsStatus;
  99. m_lPercent = 0; // long m_lPercent;
  100. m_dwErrorCode = S_OK; // DWORD m_dwErrorCode;
  101. m_fScheduled = false; // bool m_fScheduled;
  102. m_fCompleted = false; // bool m_fCompleted;
  103. m_fWorking = false; // bool m_fWorking;
  104. // List m_lstReports;
  105. m_hcpdcrcCurrentReport = NULL; // CSAFDataCollectionReport* m_hcpdcrcCurrentReport;
  106. //
  107. // CComBSTR m_bstrMachineData;
  108. // CComBSTR m_bstrHistory;
  109. m_lHistory = 0; // long m_lHistory;
  110. //
  111. // CComPtr<IStream> m_streamMachineData;
  112. // CComPtr<IStream> m_streamHistory;
  113. //
  114. //
  115. // CComBSTR m_bstrFilenameT0;
  116. // CComBSTR m_bstrFilenameT1;
  117. // CComBSTR m_bstrFilenameDiff;
  118. //
  119. //
  120. // CComPtrThreadNeutral<IDispatch> m_sink_onStatusChange;
  121. // CComPtrThreadNeutral<IDispatch> m_sink_onProgress;
  122. // CComPtrThreadNeutral<IDispatch> m_sink_onComplete;
  123. //
  124. m_lQueries_Done = 0; // long m_lQueries_Done;
  125. m_lQueries_Total = 0; // long m_lQueries_Total;
  126. }
  127. HRESULT CSAFDataCollection::FinalConstruct()
  128. {
  129. __HCP_FUNC_ENTRY( "CSAFDataCollection::FinalConstruct" );
  130. __HCP_FUNC_EXIT(S_OK);
  131. }
  132. void CSAFDataCollection::FinalRelease()
  133. {
  134. __HCP_FUNC_ENTRY( "CSAFDataCollection::FinalRelease" );
  135. (void)Abort();
  136. Thread_Wait();
  137. EraseReports();
  138. }
  139. void CSAFDataCollection::EraseReports()
  140. {
  141. __HCP_FUNC_ENTRY( "CSAFDataCollection::EraseReports" );
  142. IterConst it;
  143. MPC::SmartLock<_ThreadModel> lock( this );
  144. //
  145. // Release all the items.
  146. //
  147. MPC::ReleaseAll( m_lstReports );
  148. m_hcpdcrcCurrentReport = NULL;
  149. m_streamMachineData = NULL;
  150. m_streamHistory = NULL;
  151. }
  152. void CSAFDataCollection::StartOperations()
  153. {
  154. __HCP_FUNC_ENTRY( "CSAFDataCollection::StartOperation" );
  155. MPC::SmartLock<_ThreadModel> lock( this );
  156. EraseReports();
  157. m_fWorking = true;
  158. m_fCompleted = false;
  159. }
  160. void CSAFDataCollection::StopOperations()
  161. {
  162. __HCP_FUNC_ENTRY( "CSAFDataCollection::StartOperation" );
  163. MPC::SmartLock<_ThreadModel> lock( this );
  164. m_fWorking = false;
  165. }
  166. HRESULT CSAFDataCollection::ImpersonateCaller()
  167. {
  168. return m_imp.Impersonate();
  169. }
  170. HRESULT CSAFDataCollection::EndImpersonation()
  171. {
  172. return m_imp.RevertToSelf();
  173. }
  174. /////////////////////////////////////////////////////////////////////////////
  175. /////////////////////////////////////////////////////////////////////////////
  176. HRESULT CSAFDataCollection::ExecLoopCollect()
  177. {
  178. __HCP_FUNC_ENTRY( "CSAFDataCollection::ExecLoopCollect" );
  179. HRESULT hr;
  180. QueryResults qr;
  181. WMIHistory::Database wmihd;
  182. WMIHistory::Database wmihd_MachineData;
  183. WMIHistory::Database wmihd_History;
  184. WMIHistory::Database::ProvList lstQueries_MachineData;
  185. WMIHistory::Database::ProvList lstQueries_History;
  186. DC_STATUS dcLastState;
  187. ::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST );
  188. __MPC_TRY_BEGIN();
  189. __MPC_EXIT_IF_METHOD_FAILS(hr, put_Status( DC_COLLECTING )); dcLastState = DC_COLLECTING;
  190. CHECK_ABORTED();
  191. //
  192. // First of all, load and validate the dataspec.
  193. //
  194. if(m_bstrMachineData.Length())
  195. {
  196. if(MPC::StrICmp( m_bstrMachineData, DATASPEC_DEFAULT ) == 0)
  197. {
  198. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihd_MachineData.Init( NULL, DATASPEC_CONFIG ));
  199. }
  200. else
  201. {
  202. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
  203. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihd_MachineData.Init( NULL, m_bstrMachineData ));
  204. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
  205. }
  206. //
  207. // Filter and count the queries.
  208. //
  209. __MPC_EXIT_IF_METHOD_FAILS(hr, FilterDataSpec( wmihd_MachineData, NULL, lstQueries_MachineData ));
  210. }
  211. if(m_bstrHistory.Length())
  212. {
  213. //
  214. // Try to lock the database and load the data spec file.
  215. //
  216. while(1)
  217. {
  218. if(SUCCEEDED(hr = wmihd.Init( DATASPEC_LOCATION, DATASPEC_CONFIG )))
  219. {
  220. break;
  221. }
  222. if(hr != HRESULT_FROM_WIN32( WAIT_TIMEOUT ))
  223. {
  224. __MPC_FUNC_LEAVE;
  225. }
  226. CHECK_ABORTED();
  227. }
  228. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihd.Load());
  229. //
  230. // Filter and count the queries.
  231. //
  232. if(MPC::StrICmp( m_bstrHistory, DATASPEC_DEFAULT ) == 0)
  233. {
  234. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihd_History.Init( NULL, DATASPEC_CONFIG ));
  235. }
  236. else
  237. {
  238. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
  239. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihd_History.Init( NULL, m_bstrHistory ));
  240. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
  241. }
  242. __MPC_EXIT_IF_METHOD_FAILS(hr, FilterDataSpec( wmihd, &wmihd_History, lstQueries_History ));
  243. }
  244. //
  245. // Then count the number of queries to be executed.
  246. //
  247. m_lQueries_Done = 0;
  248. m_lQueries_Total = lstQueries_MachineData.size() + lstQueries_History.size();
  249. CHECK_ABORTED();
  250. //
  251. // Execute the collection of Machine Data.
  252. //
  253. if(m_bstrMachineData.Length())
  254. {
  255. WMIParser::ClusterByClassMap cluster;
  256. CComPtr<IXMLDOMDocument> xdd;
  257. //
  258. // Collect data from WMI.
  259. //
  260. __MPC_EXIT_IF_METHOD_FAILS(hr, ExecDataSpec( qr, cluster, lstQueries_MachineData, true ));
  261. //
  262. // Collate all the different streams into only one XML document.
  263. //
  264. __MPC_EXIT_IF_METHOD_FAILS(hr, CollateMachineDataWithTimestamp( qr, cluster, NULL, NULL, &xdd ));
  265. __MPC_EXIT_IF_METHOD_FAILS(hr, StreamFromXML( xdd, true, m_streamMachineData ));
  266. //
  267. // Cleanup everything.
  268. //
  269. cluster.clear();
  270. CleanQueryResult( qr );
  271. }
  272. CHECK_ABORTED();
  273. if(m_bstrHistory.Length())
  274. {
  275. WMIParser::ClusterByClassMap cluster;
  276. CComPtr<IXMLDOMDocument> xdd;
  277. //
  278. // Collect data from WMI.
  279. //
  280. // We actually use the queries in our data spec and do only those specified in the history list.
  281. //
  282. __MPC_EXIT_IF_METHOD_FAILS(hr, ExecDataSpec( qr, cluster, lstQueries_History, false ));
  283. //
  284. // Compute deltas, but don't persist them! (fPersist == false)
  285. //
  286. __MPC_EXIT_IF_METHOD_FAILS(hr, ComputeDelta( qr, cluster, lstQueries_History, false ));
  287. //
  288. // Cleanup everything (the data is already stored in files...)
  289. //
  290. cluster.clear();
  291. CleanQueryResult( qr );
  292. __MPC_EXIT_IF_METHOD_FAILS(hr, try_Status( dcLastState, DC_COMPARING )); dcLastState = DC_COMPARING;
  293. //
  294. // Collate all the different snapshots and deltas into only one XML document.
  295. //
  296. __MPC_EXIT_IF_METHOD_FAILS(hr, CollateHistory( wmihd, wmihd_History, &xdd ));
  297. __MPC_EXIT_IF_METHOD_FAILS(hr, StreamFromXML( xdd, true, m_streamHistory ));
  298. }
  299. CHECK_ABORTED();
  300. Fire_onProgress( this, m_lQueries_Done, m_lQueries_Total );
  301. __MPC_EXIT_IF_METHOD_FAILS(hr, try_Status( dcLastState, DC_COMPLETED )); dcLastState = DC_COMPLETED;
  302. hr = S_OK;
  303. __HCP_FUNC_CLEANUP;
  304. __MPC_TRY_CATCHALL(hr);
  305. (void)EndImpersonation();
  306. //
  307. //
  308. //
  309. if(FAILED(hr))
  310. {
  311. (void)put_ErrorCode( hr );
  312. (void)put_Status ( DC_FAILED );
  313. }
  314. //
  315. // Make sure to delete the temporary WMIParser:Snapshot objects.
  316. //
  317. CleanQueryResult( qr );
  318. //
  319. // In any case, fire the "onComplete" event, so all the clients exit from loops.
  320. //
  321. Fire_onComplete( this, hr );
  322. Thread_Abort(); // To tell the MPC:Thread object to close the worker thread...
  323. //
  324. // Anyway, always return a success.
  325. //
  326. StopOperations();
  327. hr = S_OK;
  328. __HCP_FUNC_EXIT(hr);
  329. }
  330. HRESULT CSAFDataCollection::ExecLoopCompare()
  331. {
  332. __HCP_FUNC_ENTRY( "CSAFDataCollection::ExecLoopCompare" );
  333. HRESULT hr;
  334. VARIANT_BOOL fRes;
  335. DC_STATUS dcLastState;
  336. ::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST );
  337. __MPC_TRY_BEGIN();
  338. __MPC_EXIT_IF_METHOD_FAILS(hr, put_Status( DC_COMPARING )); dcLastState = DC_COMPARING;
  339. CHECK_ABORTED();
  340. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
  341. __MPC_EXIT_IF_METHOD_FAILS(hr, WMIParser::CompareSnapshots( m_bstrFilenameT0, m_bstrFilenameT1, m_bstrFilenameDiff, &fRes ));
  342. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
  343. if(fRes == VARIANT_FALSE)
  344. {
  345. __MPC_EXIT_IF_METHOD_FAILS(hr, try_Status( dcLastState, DC_NODELTA )); dcLastState = DC_NODELTA;
  346. }
  347. else
  348. {
  349. __MPC_EXIT_IF_METHOD_FAILS(hr, try_Status( dcLastState, DC_COMPLETED )); dcLastState = DC_COMPLETED;
  350. }
  351. hr = S_OK;
  352. __HCP_FUNC_CLEANUP;
  353. __MPC_TRY_CATCHALL(hr);
  354. (void)EndImpersonation();
  355. //
  356. //
  357. //
  358. if(FAILED(hr))
  359. {
  360. (void)put_ErrorCode( hr );
  361. (void)put_Status ( DC_FAILED );
  362. }
  363. //
  364. // In any case, fire the "onComplete" event, so all the clients exit from loops.
  365. //
  366. Fire_onComplete( this, hr );
  367. Thread_Abort(); // To tell the MPC:Thread object to close the worker thread...
  368. //
  369. // Anyway, always return a success.
  370. //
  371. StopOperations();
  372. hr = S_OK;
  373. __HCP_FUNC_EXIT(hr);
  374. }
  375. /////////////////////////////////////////////////////////////////////////////
  376. /////////////////////////////////////////////////////////////////////////////
  377. HRESULT CSAFDataCollection::FilterDataSpec( /*[in]*/ WMIHistory::Database& wmihdQuery ,
  378. /*[in]*/ WMIHistory::Database* wmihdFilter ,
  379. /*[in]*/ WMIHistory::Database::ProvList& lstQueries )
  380. {
  381. __HCP_FUNC_ENTRY( "CSAFDataCollection::FilterDataSpec" );
  382. HRESULT hr;
  383. WMIHistory::Database::ProvIterConst itBegin;
  384. WMIHistory::Database::ProvIterConst itEnd;
  385. WMIHistory::Database::ProvIterConst it;
  386. //
  387. // Exec each query.
  388. //
  389. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihdQuery.get_Providers( itBegin, itEnd ));
  390. for(it=itBegin; it!=itEnd; it++)
  391. {
  392. WMIHistory::Provider* wmihp = *it;
  393. MPC::wstring szNamespace;
  394. MPC::wstring szClass;
  395. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Namespace( szNamespace ));
  396. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Class ( szClass ));
  397. if(wmihdFilter)
  398. {
  399. WMIHistory::Provider* wmihpFilter;
  400. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihdFilter->find_Provider( NULL, &szNamespace, &szClass, wmihpFilter ));
  401. //
  402. // The namespace/class is unknown, skip it.
  403. //
  404. if(wmihpFilter == NULL) continue;
  405. }
  406. lstQueries.push_back( wmihp );
  407. }
  408. hr = S_OK;
  409. __HCP_FUNC_CLEANUP;
  410. __HCP_FUNC_EXIT(hr);
  411. }
  412. HRESULT CSAFDataCollection::ExecDataSpec( /*[in/out]*/ QueryResults& qr ,
  413. /*[in/out]*/ WMIParser::ClusterByClassMap& cluster ,
  414. /*[in]*/ WMIHistory::Database::ProvList& lstQueries ,
  415. /*[in]*/ bool fImpersonate )
  416. {
  417. __HCP_FUNC_ENTRY( "CSAFDataCollection::ExecDataSpec" );
  418. HRESULT hr;
  419. WMIHistory::Database::ProvIterConst itBegin = lstQueries.begin();
  420. WMIHistory::Database::ProvIterConst itEnd = lstQueries.end();
  421. WMIHistory::Database::ProvIterConst it;
  422. //
  423. // Exec each query.
  424. //
  425. for(it=itBegin; it!=itEnd; it++)
  426. {
  427. CComPtr<IXMLDOMDocument> xddCollected;
  428. WMIHistory::Provider* wmihp = *it;
  429. MPC::wstring szNamespace;
  430. MPC::wstring szClass;
  431. MPC::wstring szWQL;
  432. Fire_onProgress( this, m_lQueries_Done++, m_lQueries_Total );
  433. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Namespace( szNamespace ));
  434. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Class ( szClass ));
  435. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_WQL ( szWQL ));
  436. if(szWQL.length() == 0)
  437. {
  438. szWQL = L"select * from ";
  439. szWQL += szClass;
  440. }
  441. //
  442. // Create a new item and link it to the system.
  443. //
  444. {
  445. CSAFDataCollectionReport* dcr;
  446. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &dcr ));
  447. m_lstReports.push_back( dcr );
  448. dcr->m_bstrNamespace = szNamespace.c_str();
  449. dcr->m_bstrClass = szClass .c_str();
  450. dcr->m_bstrWQL = szWQL .c_str();
  451. m_hcpdcrcCurrentReport = dcr;
  452. }
  453. //
  454. // Fix for a problem in WMI: namespaces with "/" are not recognized...
  455. //
  456. {
  457. MPC::wstring::size_type pos;
  458. while((pos = szNamespace.find( '/' )) != szNamespace.npos) szNamespace[pos] = '\\';
  459. }
  460. //////////////////////////////////////////////////////////////////////////////////
  461. //
  462. // Execute the query, impersonating if requested.
  463. //
  464. if(fImpersonate)
  465. {
  466. __MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
  467. }
  468. hr = CollectUsingEncoder( szNamespace, szWQL, &xddCollected );
  469. if(FAILED(hr))
  470. {
  471. xddCollected = NULL;
  472. __MPC_EXIT_IF_METHOD_FAILS(hr, CollectUsingTranslator( szNamespace, szWQL, &xddCollected ));
  473. }
  474. if(fImpersonate)
  475. {
  476. __MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
  477. }
  478. //
  479. //
  480. //
  481. //////////////////////////////////////////////////////////////////////////////////
  482. if(xddCollected)
  483. {
  484. __MPC_EXIT_IF_METHOD_FAILS(hr, Distribute( xddCollected, qr, cluster ));
  485. }
  486. }
  487. hr = S_OK;
  488. __HCP_FUNC_CLEANUP;
  489. (void)EndImpersonation();
  490. __HCP_FUNC_EXIT(hr);
  491. }
  492. HRESULT CSAFDataCollection::CollectUsingTranslator( /*[in] */ MPC::wstring& szNamespace ,
  493. /*[in] */ MPC::wstring& szWQL ,
  494. /*[out]*/ IXMLDOMDocument* *ppxddDoc )
  495. {
  496. __HCP_FUNC_ENTRY( "CSAFDataCollection::CollectUsingTranslator" );
  497. HRESULT hr;
  498. HRESULT hrXML;
  499. CComBSTR bstrNamespace = szNamespace.c_str();
  500. CComBSTR bstrWQL = szWQL .c_str();
  501. CComPtr<IWmiXMLTranslator> pTrans;
  502. CComPtr<IXMLDOMDocument> xddDoc;
  503. CComBSTR bstrXML;
  504. VARIANT_BOOL fSuccessful;
  505. *ppxddDoc = NULL;
  506. CHECK_ABORTED();
  507. //
  508. // Create the WMI->XML translator.
  509. //
  510. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstance( CLSID_WmiXMLTranslator, NULL, CLSCTX_INPROC_SERVER, IID_IWmiXMLTranslator, (void**)&pTrans ));
  511. // Set to truncate Qualifiers and have full identity information.
  512. __MPC_EXIT_IF_METHOD_FAILS(hr, pTrans->put_DeclGroupType ( wmiXMLDeclGroupWithPath ));
  513. __MPC_EXIT_IF_METHOD_FAILS(hr, pTrans->put_QualifierFilter( wmiXMLFilterNone ));
  514. __MPC_EXIT_IF_METHOD_FAILS(hr, pTrans->put_HostFilter ( VARIANT_TRUE ));
  515. //
  516. // Execute the query.
  517. //
  518. hrXML = pTrans->ExecQuery( bstrNamespace, bstrWQL, &bstrXML );
  519. if(FAILED(hrXML))
  520. {
  521. CComQIPtr<ISupportErrorInfo> sei = pTrans;
  522. if(sei && SUCCEEDED(sei->InterfaceSupportsErrorInfo( IID_IWmiXMLTranslator )))
  523. {
  524. CComPtr<IErrorInfo> ei;
  525. if(SUCCEEDED(GetErrorInfo( 0, &ei )) && ei)
  526. {
  527. ei->GetDescription( &m_hcpdcrcCurrentReport->m_bstrDescription );
  528. }
  529. }
  530. m_hcpdcrcCurrentReport->m_dwErrorCode = hrXML;
  531. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  532. }
  533. //
  534. // Load the result into an XML DOM object.
  535. //
  536. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstance( CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&xddDoc ));
  537. __MPC_EXIT_IF_METHOD_FAILS(hr, xddDoc->loadXML( bstrXML, &fSuccessful ));
  538. if(fSuccessful == VARIANT_FALSE)
  539. {
  540. CComQIPtr<ISupportErrorInfo> sei = xddDoc;
  541. if(sei && SUCCEEDED(sei->InterfaceSupportsErrorInfo( IID_IXMLDOMDocument )))
  542. {
  543. CComPtr<IErrorInfo> ei;
  544. if(SUCCEEDED(GetErrorInfo( 0, &ei )))
  545. {
  546. ei->GetDescription( &m_hcpdcrcCurrentReport->m_bstrDescription );
  547. }
  548. }
  549. m_hcpdcrcCurrentReport->m_dwErrorCode = ERROR_BAD_FORMAT;
  550. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  551. }
  552. // __MPC_EXIT_IF_METHOD_FAILS(hr, xddDoc->save( CComVariant( "C:\\dump.xml" ) ));
  553. // __MPC_EXIT_IF_METHOD_FAILS(hr, xddDoc->load( CComVariant( "C:\\dump.xml" ), &fSuccessful ));
  554. // if(fSuccessful == VARIANT_FALSE)
  555. // {
  556. // __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BAD_FORMAT);
  557. // }
  558. //
  559. // Return the pointer to the XML document.
  560. //
  561. *ppxddDoc = xddDoc.Detach();
  562. hr = S_OK;
  563. __HCP_FUNC_CLEANUP;
  564. __HCP_FUNC_EXIT(hr);
  565. }
  566. HRESULT CSAFDataCollection::CollectUsingEncoder( /*[in] */ MPC::wstring& szNamespace ,
  567. /*[in] */ MPC::wstring& szWQL ,
  568. /*[out]*/ IXMLDOMDocument* *ppxddDoc )
  569. {
  570. __HCP_FUNC_ENTRY( "CSAFDataCollection::CollectUsingEncoder" );
  571. HRESULT hr;
  572. HRESULT hrXML;
  573. HRESULT hrConnect;
  574. CComBSTR bstrNamespace( szNamespace.c_str() );
  575. CComBSTR bstrWQL ( szWQL .c_str() );
  576. CComPtr<IXMLDOMDocument> xddDoc;
  577. CComBSTR bstrXML;
  578. VARIANT_BOOL fSuccessful;
  579. // Additional Declarations/Definitions for XMLE Usage.
  580. CComPtr<IWbemContext> pWbemContext;
  581. CComPtr<IWbemServices> pWbemServices;
  582. CComPtr<IWbemObjectTextSrc> pWbemTextSrc;
  583. CComPtr<IEnumWbemClassObject> pWbemEnum;
  584. CComPtr<IWbemLocator> pWbemLocator;
  585. LPWSTR szSelect;
  586. LPWSTR szWQLCopy;
  587. CComBSTR bstrModWQL;
  588. *ppxddDoc = NULL;
  589. CHECK_ABORTED();
  590. // Create an instance of WbemObjectTextSrc class (this would fails if the Encoder functionality is not present).
  591. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstance( CLSID_WbemObjectTextSrc, NULL, CLSCTX_INPROC_SERVER, IID_IWbemObjectTextSrc, (void**)&pWbemTextSrc ));
  592. // Create an instance of the IWbemLocator Interface.
  593. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pWbemLocator ));
  594. //
  595. // Got the pointer to the IWbemLocator Service.
  596. //
  597. // Connect to the required Namespace using the Locator Service.
  598. //
  599. hrConnect = pWbemLocator->ConnectServer( CComBSTR( szNamespace.c_str() ),
  600. NULL , //using current account for simplicity
  601. NULL , //using current password for simplicity
  602. 0L , // locale
  603. 0L , // securityFlags
  604. NULL , // authority (domain for NTLM)
  605. NULL , // context
  606. &pWbemServices );
  607. if(FAILED(hrConnect))
  608. {
  609. CComQIPtr<ISupportErrorInfo> sei = pWbemLocator;
  610. if(sei && SUCCEEDED(sei->InterfaceSupportsErrorInfo( IID_IWbemLocator )))
  611. {
  612. CComPtr<IErrorInfo> ei;
  613. if(SUCCEEDED(GetErrorInfo( 0, &ei )) && ei)
  614. {
  615. ei->GetDescription( &m_hcpdcrcCurrentReport->m_bstrDescription );
  616. }
  617. }
  618. m_hcpdcrcCurrentReport->m_dwErrorCode = hrConnect;
  619. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  620. }
  621. //
  622. // Adjust the security level to IMPERSONATE, to satisfy the flawed WMI requirements....
  623. //
  624. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SetInterfaceSecurity_ImpLevel( pWbemServices, RPC_C_IMP_LEVEL_IMPERSONATE ));
  625. //
  626. // Connected To Namespace.
  627. //
  628. // Now execute the query to get EnumObjects.
  629. // This is the instances got against the query.
  630. // WBEM_FLAG_FORWARD_ONLY Flag to be used?
  631. //
  632. // Append __Path to the WQL query.
  633. szWQLCopy = bstrWQL;
  634. // Search for Select pattern.
  635. szSelect = StrStrIW(szWQLCopy,l_Select_Pattern);
  636. if(szSelect != NULL)
  637. {
  638. // Select Pattern Found
  639. // Advance the pointer to the end of the pattern so the pointer is
  640. // positioned at end of the word "select"
  641. szSelect += wcslen(l_Select_Pattern);
  642. bstrModWQL = L"Select __Path, ";
  643. bstrModWQL.Append(szSelect);
  644. bstrWQL = bstrModWQL;
  645. }
  646. hrXML = pWbemServices->ExecQuery( l_bstrQueryLang, bstrWQL, 0, 0, &pWbemEnum );
  647. if(FAILED(hrXML))
  648. {
  649. CComQIPtr<ISupportErrorInfo> sei = pWbemServices;
  650. if(sei && SUCCEEDED(sei->InterfaceSupportsErrorInfo( IID_IWbemServices )))
  651. {
  652. CComPtr<IErrorInfo> ei;
  653. if(SUCCEEDED(GetErrorInfo( 0, &ei )) && ei)
  654. {
  655. ei->GetDescription( &m_hcpdcrcCurrentReport->m_bstrDescription );
  656. }
  657. }
  658. m_hcpdcrcCurrentReport->m_dwErrorCode = hrXML;
  659. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  660. }
  661. //
  662. // Adjust the security level to IMPERSONATE, to satisfy the flawed WMI requirements....
  663. //
  664. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SetInterfaceSecurity_ImpLevel( pWbemEnum, RPC_C_IMP_LEVEL_IMPERSONATE ));
  665. ////////////////////////////////////////////////////////////////////////////////
  666. // Create a new WbemContext object.
  667. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstance( CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER, IID_IWbemContext, (void**)&pWbemContext ));
  668. //
  669. // For the XML to be conformant with the earlier XMLT format,
  670. // we need VALUE.OBJECTWITHPATH.
  671. //
  672. __MPC_EXIT_IF_METHOD_FAILS(hr, pWbemContext->SetValue( l_bstrPathLevel, 0, &l_vPathLevel ));
  673. //
  674. // We don't need the system properties that are returned by
  675. // default. Hence Exclude them from the output.
  676. //
  677. __MPC_EXIT_IF_METHOD_FAILS(hr, pWbemContext->SetValue( l_bstrExcludeSystemProperties, 0, &l_vExcludeSystemProperties ));
  678. ////////////////////////////////////////////////////////////////////////////////
  679. //
  680. // Collate all the instances.
  681. //
  682. bstrXML = l_CIM_header;
  683. while(1)
  684. {
  685. CComPtr<IWbemClassObject> pObj;
  686. CComBSTR bstrXMLCurrent;
  687. ULONG uReturned;
  688. bool fProceed;
  689. __MPC_EXIT_IF_METHOD_FAILS(hr, pWbemEnum->Next( WBEM_INFINITE, 1, &pObj, &uReturned ));
  690. if(hr == WBEM_S_FALSE || uReturned == 0) break;
  691. hrXML = pWbemTextSrc->GetText( 0, pObj, WMI_OBJ_TEXT_WMI_DTD_2_0, pWbemContext, &bstrXMLCurrent );
  692. if(FAILED(hrXML))
  693. {
  694. CComQIPtr<ISupportErrorInfo> sei = pWbemTextSrc;
  695. if(sei && SUCCEEDED(sei->InterfaceSupportsErrorInfo( IID_IWbemObjectTextSrc )))
  696. {
  697. CComPtr<IErrorInfo> ei;
  698. if(SUCCEEDED(GetErrorInfo( 0, &ei )) && ei)
  699. {
  700. ei->GetDescription( &m_hcpdcrcCurrentReport->m_bstrDescription );
  701. }
  702. }
  703. m_hcpdcrcCurrentReport->m_dwErrorCode = hrXML;
  704. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  705. }
  706. // Append the individual instance XMLs
  707. //
  708. bstrXML.Append( bstrXMLCurrent );
  709. }
  710. bstrXML.Append( l_CIM_trailer );
  711. //
  712. // Load the result into an XML DOM object.
  713. //
  714. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstance( CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&xddDoc ));
  715. __MPC_EXIT_IF_METHOD_FAILS(hr, xddDoc->loadXML( bstrXML, &fSuccessful ));
  716. if(fSuccessful == VARIANT_FALSE)
  717. {
  718. CComQIPtr<ISupportErrorInfo> sei = xddDoc;
  719. if(sei && SUCCEEDED(sei->InterfaceSupportsErrorInfo( IID_IXMLDOMDocument )))
  720. {
  721. CComPtr<IErrorInfo> ei;
  722. if(SUCCEEDED(GetErrorInfo( 0, &ei )))
  723. {
  724. ei->GetDescription( &m_hcpdcrcCurrentReport->m_bstrDescription );
  725. }
  726. }
  727. m_hcpdcrcCurrentReport->m_dwErrorCode = ERROR_BAD_FORMAT;
  728. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  729. }
  730. // __MPC_EXIT_IF_METHOD_FAILS(hr, xddDoc->save( CComVariant( "C:\\dump.xml" ) ));
  731. //
  732. // Return the pointer to the XML document.
  733. //
  734. *ppxddDoc = xddDoc.Detach();
  735. hr = S_OK;
  736. __HCP_FUNC_CLEANUP;
  737. __HCP_FUNC_EXIT(hr);
  738. }
  739. HRESULT CSAFDataCollection::Distribute( /*[in] */ IXMLDOMDocument* pxddDoc ,
  740. /*[in/out]*/ QueryResults& qr ,
  741. /*[in/out]*/ WMIParser::ClusterByClassMap& cluster )
  742. {
  743. __HCP_FUNC_ENTRY( "CSAFDataCollection::Distribute" );
  744. HRESULT hr;
  745. MPC::XmlUtil xml( pxddDoc );
  746. CComPtr<IXMLDOMNode> xdnRoot;
  747. WMIParser::Snapshot *pwmips = NULL;
  748. __MPC_EXIT_IF_ALLOC_FAILS(hr, pwmips, new WMIParser::Snapshot());
  749. qr.push_back( pwmips );
  750. //
  751. // Quick fix for broken Incident object: force UNICODE encoding.
  752. //
  753. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.SetVersionAndEncoding( L"1.0", L"unicode" ));
  754. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetRoot ( &xdnRoot ));
  755. __MPC_EXIT_IF_METHOD_FAILS(hr, pwmips->put_Node ( xdnRoot ));
  756. __MPC_EXIT_IF_METHOD_FAILS(hr, WMIParser::DistributeOnCluster( cluster, *pwmips ));
  757. hr = S_OK;
  758. __HCP_FUNC_CLEANUP;
  759. __HCP_FUNC_EXIT(hr);
  760. }
  761. HRESULT CSAFDataCollection::ComputeDelta( /*[in]*/ QueryResults& qr ,
  762. /*[in]*/ WMIParser::ClusterByClassMap& cluster ,
  763. /*[in]*/ WMIHistory::Database::ProvList& lstQueries ,
  764. /*[in]*/ bool fPersist )
  765. {
  766. __HCP_FUNC_ENTRY( "CSAFDataCollection::ComputeDelta" );
  767. HRESULT hr;
  768. WMIHistory::Database::ProvIterConst it;
  769. for(it=lstQueries.begin(); it!=lstQueries.end(); it++)
  770. {
  771. WMIHistory::Provider* wmihp = *it;
  772. WMIHistory::Data* wmihpd_T0;
  773. WMIHistory::Data* wmihpd_T1;
  774. WMIHistory::Data* wmihpd_D1;
  775. CComPtr<IXMLDOMDocument> xddDoc;
  776. MPC::wstring szNamespace;
  777. MPC::wstring szClass;
  778. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Namespace( szNamespace ));
  779. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Class ( szClass ));
  780. //
  781. // Collate only the data from current cluster.
  782. //
  783. __MPC_EXIT_IF_METHOD_FAILS(hr, CollateMachineData( qr, cluster, &szNamespace, &szClass, true, &xddDoc ));
  784. //
  785. // Save it to a file.
  786. //
  787. {
  788. MPC::XmlUtil xml( xddDoc );
  789. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->alloc_Snapshot( xml, wmihpd_T1 ));
  790. }
  791. //
  792. // If two snapshots are present, compute the delta.
  793. //
  794. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Snapshot( wmihpd_T0 ));
  795. if(wmihpd_T0 == NULL)
  796. {
  797. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->insert_Snapshot( wmihpd_T1, fPersist ));
  798. }
  799. else
  800. {
  801. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->ComputeDiff( wmihpd_T0, wmihpd_T1, wmihpd_D1 ));
  802. if(wmihpd_D1)
  803. {
  804. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->insert_Snapshot( wmihpd_D1, fPersist ));
  805. }
  806. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->insert_Snapshot( wmihpd_T1, fPersist ));
  807. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->remove_Snapshot( wmihpd_T0, fPersist ));
  808. }
  809. }
  810. hr = S_OK;
  811. __HCP_FUNC_CLEANUP;
  812. __HCP_FUNC_EXIT(hr);
  813. }
  814. HRESULT CSAFDataCollection::CollateMachineData( /*[in] */ QueryResults& qr ,
  815. /*[in] */ WMIParser::ClusterByClassMap& cluster ,
  816. /*[in] */ MPC::wstring* pszNamespace ,
  817. /*[in] */ MPC::wstring* pszClass ,
  818. /*[in] */ bool fGenerate ,
  819. /*[out]*/ IXMLDOMDocument* *ppxddDoc )
  820. {
  821. __HCP_FUNC_ENTRY( "CSAFDataCollection::CollateMachineData" );
  822. HRESULT hr;
  823. WMIParser::Snapshot wmips;
  824. *ppxddDoc = NULL;
  825. CHECK_ABORTED();
  826. __MPC_EXIT_IF_METHOD_FAILS(hr, wmips.New());
  827. if(qr.begin() != qr.end())
  828. {
  829. WMIParser::ClusterByClassIter itCluster;
  830. //
  831. // For each cluster, enumerate all the instances in it and copy to the new snapshot.
  832. //
  833. for(itCluster = cluster.begin(); itCluster != cluster.end(); itCluster++)
  834. {
  835. MPC::NocaseCompare cmp;
  836. WMIParser::Instance* inst = (*itCluster).first;
  837. WMIParser::Cluster& subcluster = (*itCluster).second;
  838. WMIParser::ClusterByKeyIter itSubBegin;
  839. WMIParser::ClusterByKeyIter itSubEnd;
  840. //
  841. // Filter only some classes or namespaces.
  842. //
  843. if(pszNamespace)
  844. {
  845. MPC::wstring szNamespace;
  846. __MPC_EXIT_IF_METHOD_FAILS(hr, inst->get_Namespace( szNamespace ));
  847. //
  848. // NOTICE: if the namespace is "<UNKNOWN>", then assume a match.
  849. //
  850. if(szNamespace != L"<UNKNOWN>")
  851. {
  852. if(!cmp( szNamespace, *pszNamespace )) continue;
  853. }
  854. }
  855. if(pszClass)
  856. {
  857. MPC::wstring szClass;
  858. __MPC_EXIT_IF_METHOD_FAILS(hr, inst->get_Class( szClass ));
  859. if(!cmp( szClass, *pszClass )) continue;
  860. }
  861. //
  862. // Copy all the instances into the new document.
  863. //
  864. __MPC_EXIT_IF_METHOD_FAILS(hr, subcluster.Enum( itSubBegin, itSubEnd ));
  865. while(itSubBegin != itSubEnd)
  866. {
  867. WMIParser::Instance* pwmipiInst;
  868. __MPC_EXIT_IF_METHOD_FAILS(hr, wmips.clone_Instance( (*itSubBegin).first, pwmipiInst ));
  869. fGenerate = true;
  870. CHECK_ABORTED();
  871. itSubBegin++;
  872. }
  873. }
  874. }
  875. //
  876. // Only return the document if at least one instance is present.
  877. //
  878. if(fGenerate)
  879. {
  880. CComPtr<IXMLDOMNode> xdnRoot;
  881. __MPC_EXIT_IF_METHOD_FAILS(hr, wmips.get_Node( &xdnRoot ));
  882. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRoot->get_ownerDocument( ppxddDoc ));
  883. }
  884. hr = S_OK;
  885. __HCP_FUNC_CLEANUP;
  886. __HCP_FUNC_EXIT(hr);
  887. }
  888. HRESULT CSAFDataCollection::CollateMachineDataWithTimestamp( /*[in] */ QueryResults& qr ,
  889. /*[in] */ WMIParser::ClusterByClassMap& cluster ,
  890. /*[in] */ MPC::wstring* pszNamespace ,
  891. /*[in] */ MPC::wstring* pszClass ,
  892. /*[out]*/ IXMLDOMDocument* *ppxddDoc )
  893. {
  894. __HCP_FUNC_ENTRY( "CSAFDataCollection::CollateMachineDataWithTimestamp" );
  895. HRESULT hr;
  896. CComPtr<IXMLDOMDocument> xdd;
  897. *ppxddDoc = NULL;
  898. CHECK_ABORTED();
  899. __MPC_EXIT_IF_METHOD_FAILS(hr, CollateMachineData( qr, cluster, NULL, NULL, false, &xdd ));
  900. if(xdd)
  901. {
  902. MPC::XmlUtil xml;
  903. CComPtr<IXMLDOMNode> xdnNodeSnapshot;
  904. //
  905. // Create the document.
  906. //
  907. {
  908. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.New( TEXT_TAG_DATACOLLECTION ));
  909. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.CreateNode( TEXT_TAG_SNAPSHOT, &xdnNodeSnapshot ));
  910. }
  911. //
  912. // Set the date.
  913. //
  914. {
  915. DATE dTimestamp = MPC::GetLocalTime();
  916. TIME_ZONE_INFORMATION tzi;
  917. MPC::wstring szValue;
  918. bool fFound;
  919. if(::GetTimeZoneInformation( &tzi ) == TIME_ZONE_ID_DAYLIGHT)
  920. {
  921. tzi.Bias += tzi.DaylightBias;
  922. }
  923. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertDateToString( dTimestamp, szValue, /*fGMT*/true, /*fCIM*/true, 0 ));
  924. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, TEXT_ATTR_TIMESTAMP, szValue, fFound, xdnNodeSnapshot ));
  925. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, TEXT_ATTR_TIMEZONE, (LONG)tzi.Bias, fFound, xdnNodeSnapshot ));
  926. }
  927. //
  928. // Insert the CIM tree into the document.
  929. //
  930. {
  931. CComPtr<IXMLDOMNode> xdnNodeToInsert;
  932. CComPtr<IXMLDOMNode> xdnNodeReplaced;
  933. __MPC_EXIT_IF_METHOD_FAILS(hr, xdd->get_documentElement( (IXMLDOMElement**)&xdnNodeToInsert ));
  934. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnNodeSnapshot->appendChild( xdnNodeToInsert, &xdnNodeReplaced ));
  935. }
  936. //
  937. // Return the XML blob to the caller.
  938. //
  939. {
  940. CComPtr<IXMLDOMNode> xdnRoot;
  941. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetRoot ( &xdnRoot ));
  942. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRoot->get_ownerDocument( ppxddDoc ));
  943. }
  944. }
  945. hr = S_OK;
  946. __HCP_FUNC_CLEANUP;
  947. __HCP_FUNC_EXIT(hr);
  948. }
  949. HRESULT CSAFDataCollection::CollateHistory( /*[in] */ WMIHistory::Database& wmihdQuery ,
  950. /*[in] */ WMIHistory::Database& wmihdFilter ,
  951. /*[out]*/ IXMLDOMDocument* *ppxddDoc )
  952. {
  953. __HCP_FUNC_ENTRY( "CSAFDataCollection::CollateHistory" );
  954. typedef std::vector< LONG > SeqVector;
  955. typedef SeqVector::iterator SeqIter;
  956. typedef SeqVector::const_iterator SeqIterConst;
  957. HRESULT hr;
  958. QueryResults qr;
  959. WMIParser::ClusterByClassMap cluster;
  960. WMIHistory::Database::ProvList prov_lst;
  961. WMIHistory::Database::ProvIterConst prov_itBegin;
  962. WMIHistory::Database::ProvIterConst prov_itEnd;
  963. WMIHistory::Database::ProvIterConst prov_it;
  964. SeqVector seq_vec;
  965. SeqIterConst seq_it;
  966. MPC::XmlUtil xml;
  967. MPC::wstring szValue;
  968. bool fFound;
  969. long lHistory = m_lHistory; // Number of deltas to collect.
  970. DATE dTimestampCurrent;
  971. DATE dTimestampNext;
  972. TIME_ZONE_INFORMATION tzi;
  973. *ppxddDoc = NULL;
  974. CHECK_ABORTED();
  975. if(::GetTimeZoneInformation( &tzi ) == TIME_ZONE_ID_DAYLIGHT)
  976. {
  977. tzi.Bias += tzi.DaylightBias;
  978. }
  979. //
  980. // Form the list of providers to collate.
  981. //
  982. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihdQuery.get_Providers( prov_itBegin, prov_itEnd ));
  983. for(prov_it=prov_itBegin; prov_it!=prov_itEnd; prov_it++)
  984. {
  985. WMIHistory::Provider* wmihp = *prov_it;
  986. WMIHistory::Provider* wmihpFilter;
  987. MPC::wstring szNamespace;
  988. MPC::wstring szClass;
  989. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Namespace ( szNamespace ));
  990. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->get_Class ( szClass ));
  991. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihdFilter.find_Provider( NULL, &szNamespace, &szClass, wmihpFilter ));
  992. //
  993. // The namespace/class is known, add it to the list.
  994. //
  995. if(wmihpFilter)
  996. {
  997. WMIHistory::Provider::DataIterConst itBegin;
  998. WMIHistory::Provider::DataIterConst itEnd;
  999. LONG lSequence;
  1000. //
  1001. // For each delta, extract the sequence info and add it to a list of UNIQUE sequence numbers.
  1002. //
  1003. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihp->enum_Data( itBegin, itEnd ));
  1004. while(itBegin != itEnd)
  1005. {
  1006. __MPC_EXIT_IF_METHOD_FAILS(hr, (*itBegin++)->get_Sequence( lSequence ));
  1007. if(std::find( seq_vec.begin(), seq_vec.end(), lSequence ) == seq_vec.end())
  1008. {
  1009. seq_vec.push_back( lSequence );
  1010. }
  1011. }
  1012. prov_lst.push_back( wmihp );
  1013. }
  1014. }
  1015. //
  1016. // The list of dates is empty, so no data is available.
  1017. //
  1018. if(seq_vec.begin() == seq_vec.end())
  1019. {
  1020. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  1021. }
  1022. //
  1023. // Sort the dates from the newest to the oldest.
  1024. //
  1025. std::sort< SeqIter >( seq_vec.begin(), seq_vec.end(), std::greater<LONG>() );
  1026. CHECK_ABORTED();
  1027. //
  1028. // Create the document.
  1029. //
  1030. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.New( TEXT_TAG_DATACOLLECTION ));
  1031. //
  1032. // First of all, collate the snapshots.
  1033. //
  1034. {
  1035. CComPtr<IXMLDOMDocument> xdd;
  1036. CComPtr<IXMLDOMNode> xdnNode;
  1037. CComPtr<IXMLDOMNode> xdnNodeToInsert;
  1038. CComPtr<IXMLDOMNode> xdnNodeReplaced;
  1039. //
  1040. // Walk through all the providers and load the snapshots.
  1041. //
  1042. for(prov_it=prov_lst.begin(); prov_it!=prov_lst.end(); prov_it++)
  1043. {
  1044. WMIHistory::Data* wmihpd;
  1045. MPC::XmlUtil xmlData;
  1046. CComPtr<IXMLDOMDocument> xddData;
  1047. __MPC_EXIT_IF_METHOD_FAILS(hr, (*prov_it)->get_Snapshot( wmihpd ));
  1048. if(wmihpd == NULL) continue;
  1049. //
  1050. // If it's the first provider we see in this round, create the proper element, "Snapshot".
  1051. //
  1052. // As its date, we pick the latest date in the list of dates. This is because not all the snapshots have the
  1053. // same date, when two snapshots are identical, no delta is created and the new snapshot is not stored.
  1054. // But it's guarantee that, if there's a snapshot, its date is greater than any delta's date.
  1055. //
  1056. if(xdnNode == NULL)
  1057. {
  1058. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihpd->get_TimestampT0( dTimestampCurrent ));
  1059. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.CreateNode( TEXT_TAG_SNAPSHOT, &xdnNode ));
  1060. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertDateToString( dTimestampCurrent, szValue, /*fGMT*/true, /*fCIM*/true, 0 ));
  1061. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, TEXT_ATTR_TIMESTAMP, szValue, fFound, xdnNode ));
  1062. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, TEXT_ATTR_TIMEZONE, (LONG)tzi.Bias, fFound, xdnNode ));
  1063. }
  1064. //
  1065. // Load the data and distribuite among clusters.
  1066. //
  1067. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihpd->LoadCIM ( xmlData ));
  1068. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlData.GetDocument( &xddData ));
  1069. __MPC_EXIT_IF_METHOD_FAILS(hr, Distribute ( xddData, qr, cluster ));
  1070. }
  1071. __MPC_EXIT_IF_METHOD_FAILS(hr, CollateMachineData( qr, cluster, NULL, NULL, false, &xdd ));
  1072. if(xdd)
  1073. {
  1074. __MPC_EXIT_IF_METHOD_FAILS(hr, xdd->get_documentElement( (IXMLDOMElement**)&xdnNodeToInsert ));
  1075. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnNode->appendChild( xdnNodeToInsert, &xdnNodeReplaced ));
  1076. }
  1077. //
  1078. // Cleanup everything.
  1079. //
  1080. cluster.clear();
  1081. CleanQueryResult( qr );
  1082. }
  1083. //
  1084. // Them, for each date, collate all its deltas.
  1085. //
  1086. for(seq_it=seq_vec.begin(); seq_it!=seq_vec.end(); seq_it++)
  1087. {
  1088. CComPtr<IXMLDOMDocument> xdd;
  1089. CComPtr<IXMLDOMNode> xdnNode;
  1090. CComPtr<IXMLDOMNode> xdnNodeToInsert;
  1091. CComPtr<IXMLDOMNode> xdnNodeReplaced;
  1092. //
  1093. // Walk through all the providers and load data about the current date.
  1094. //
  1095. for(prov_it=prov_lst.begin(); prov_it!=prov_lst.end(); prov_it++)
  1096. {
  1097. WMIHistory::Data* wmihpd;
  1098. MPC::XmlUtil xmlData;
  1099. CComPtr<IXMLDOMDocument> xddData;
  1100. __MPC_EXIT_IF_METHOD_FAILS(hr, (*prov_it)->get_Sequence( *seq_it, wmihpd ));
  1101. if(wmihpd == NULL ) continue;
  1102. if(wmihpd->IsSnapshot()) continue;
  1103. //
  1104. // If it's the first provider we see in this round, create the proper element, "Snapshot" or "Delta".
  1105. //
  1106. if(xdnNode == NULL)
  1107. {
  1108. dTimestampNext = dTimestampCurrent;
  1109. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihpd->get_TimestampT0( dTimestampCurrent ));
  1110. //
  1111. // Check if we have reached the requested number of deltas.
  1112. //
  1113. if(lHistory-- <= 0) break;
  1114. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.CreateNode( TEXT_TAG_DELTA, &xdnNode ));
  1115. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertDateToString( dTimestampCurrent, szValue, /*fGMT*/true, /*fCIM*/true, 0 ));
  1116. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, TEXT_ATTR_TIMESTAMP_T0, szValue, fFound, xdnNode ));
  1117. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertDateToString( dTimestampNext, szValue, /*fGMT*/true, /*fCIM*/true, 0 ));
  1118. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, TEXT_ATTR_TIMESTAMP_T1, szValue, fFound, xdnNode ));
  1119. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, TEXT_ATTR_TIMEZONE, (LONG)tzi.Bias, fFound, xdnNode ));
  1120. }
  1121. //
  1122. // Load the data and distribuite among clusters.
  1123. //
  1124. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihpd->LoadCIM ( xmlData ));
  1125. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlData.GetDocument( &xddData ));
  1126. __MPC_EXIT_IF_METHOD_FAILS(hr, Distribute ( xddData, qr, cluster ));
  1127. }
  1128. __MPC_EXIT_IF_METHOD_FAILS(hr, CollateMachineData( qr, cluster, NULL, NULL, false, &xdd ));
  1129. if(xdd)
  1130. {
  1131. __MPC_EXIT_IF_METHOD_FAILS(hr, xdd->get_documentElement( (IXMLDOMElement**)&xdnNodeToInsert ));
  1132. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnNode->appendChild( xdnNodeToInsert, &xdnNodeReplaced ));
  1133. }
  1134. //
  1135. // Cleanup everything.
  1136. //
  1137. cluster.clear();
  1138. CleanQueryResult( qr );
  1139. }
  1140. //
  1141. // Return the XML blob to the caller.
  1142. //
  1143. {
  1144. CComPtr<IXMLDOMNode> xdnRoot;
  1145. __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetRoot( &xdnRoot ));
  1146. __MPC_EXIT_IF_METHOD_FAILS(hr, xdnRoot->get_ownerDocument( ppxddDoc ));
  1147. }
  1148. hr = S_OK;
  1149. __HCP_FUNC_CLEANUP;
  1150. //
  1151. // Make sure to delete the temporary WMIParser:Snapshot objects.
  1152. //
  1153. CleanQueryResult( qr );
  1154. __HCP_FUNC_EXIT(hr);
  1155. }
  1156. /////////////////////////////////////////////////////////////////////////////
  1157. /////////////////////////////////////////////////////////////////////////////
  1158. //////////////////////////
  1159. // //
  1160. // Event Firing Methods //
  1161. // //
  1162. //////////////////////////
  1163. HRESULT CSAFDataCollection::Fire_onStatusChange( ISAFDataCollection* hcpdc, tagDC_STATUS dsStatus )
  1164. {
  1165. CComVariant pvars[2];
  1166. //
  1167. // Only this part should be inside a critical section, otherwise deadlocks could occur.
  1168. //
  1169. {
  1170. MPC::SmartLock<_ThreadModel> lock( this );
  1171. //
  1172. // Disable events if the "onComplete" event has already been sent.
  1173. //
  1174. if(m_fCompleted) return S_OK;
  1175. }
  1176. pvars[1] = hcpdc;
  1177. pvars[0] = dsStatus;
  1178. return FireAsync_Generic( DISPID_SAF_DCE__ONSTATUSCHANGE, pvars, ARRAYSIZE( pvars ), m_sink_onStatusChange );
  1179. }
  1180. HRESULT CSAFDataCollection::Fire_onProgress( ISAFDataCollection* hcpdc, LONG lDone, LONG lTotal )
  1181. {
  1182. CComVariant pvars[3];
  1183. //
  1184. // Only this part should be inside a critical section, otherwise deadlocks could occur.
  1185. //
  1186. {
  1187. MPC::SmartLock<_ThreadModel> lock( this );
  1188. //
  1189. // Disable events if the "onComplete" event has already been sent.
  1190. //
  1191. if(m_fCompleted) return S_OK;
  1192. m_lPercent = lTotal ? (lDone * 100.0 / lTotal) : 0;
  1193. }
  1194. pvars[2] = hcpdc;
  1195. pvars[1] = lDone;
  1196. pvars[0] = lTotal;
  1197. return FireAsync_Generic( DISPID_SAF_DCE__ONPROGRESS, pvars, ARRAYSIZE( pvars ), m_sink_onProgress );
  1198. }
  1199. HRESULT CSAFDataCollection::Fire_onComplete( ISAFDataCollection* hcpdc, HRESULT hrRes )
  1200. {
  1201. CComVariant pvars[2];
  1202. //
  1203. // Only this part should be inside a critical section, otherwise deadlocks could occur.
  1204. //
  1205. {
  1206. MPC::SmartLock<_ThreadModel> lock( this );
  1207. //
  1208. // Disable events if the "onComplete" event has already been sent.
  1209. //
  1210. if(m_fCompleted) return S_OK;
  1211. m_fCompleted = true;
  1212. }
  1213. pvars[1] = hcpdc;
  1214. pvars[0] = hrRes;
  1215. return FireAsync_Generic( DISPID_SAF_DCE__ONCOMPLETE, pvars, ARRAYSIZE( pvars ), m_sink_onComplete );
  1216. }
  1217. /////////////////////////////////////////////////////////////////////////////
  1218. /////////////////////////////////////////////////////////////////////////////
  1219. /////////////////////
  1220. // //
  1221. // Utility Methods //
  1222. // //
  1223. /////////////////////
  1224. HRESULT CSAFDataCollection::CanModifyProperties()
  1225. {
  1226. __HCP_FUNC_ENTRY( "CSAFDataCollection::CanModifyProperties" );
  1227. HRESULT hr = E_ACCESSDENIED;
  1228. if(m_fWorking == false ||
  1229. m_fCompleted == true )
  1230. {
  1231. hr = S_OK;
  1232. }
  1233. __HCP_FUNC_EXIT(hr);
  1234. }
  1235. HRESULT CSAFDataCollection::IsCollectionAborted()
  1236. {
  1237. __HCP_FUNC_ENTRY( "CSAFDataCollection::IsCollectionAborted" );
  1238. HRESULT hr;
  1239. //
  1240. // We not only check for explicit abortion, but also for low memory situations.
  1241. // Our code is almost safe, but we have seen that other parts of the system
  1242. // tend to crash on no-memory scenarios.
  1243. //
  1244. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::FailOnLowMemory( SAFETY_MARGIN__MEMORY ));
  1245. if(Thread_IsAborted() == true)
  1246. {
  1247. __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT);
  1248. }
  1249. hr = S_OK;
  1250. __HCP_FUNC_CLEANUP;
  1251. __HCP_FUNC_EXIT(hr);
  1252. }
  1253. /////////////////////////////////////////////////////////////////////////////
  1254. ////////////////////////////////////////////
  1255. // //
  1256. // Internal Property Manipulation Methods //
  1257. // //
  1258. ////////////////////////////////////////////
  1259. HRESULT CSAFDataCollection::put_Status( /*[in]*/ DC_STATUS newVal )
  1260. {
  1261. __HCP_FUNC_ENTRY( "CSAFDataCollection::put_Status" );
  1262. HRESULT hr = try_Status( (DC_STATUS)-1, newVal );
  1263. __HCP_FUNC_EXIT(hr);
  1264. }
  1265. HRESULT CSAFDataCollection::try_Status( /*[in]*/ DC_STATUS preVal ,
  1266. /*[in]*/ DC_STATUS postVal )
  1267. {
  1268. __HCP_FUNC_ENTRY( "CSAFDataCollection::try_Status" );
  1269. HRESULT hr;
  1270. bool fChanged = false;
  1271. DC_STATUS dsStatus;
  1272. MPC::SmartLock<_ThreadModel> lock( this );
  1273. if(preVal == m_dsStatus ||
  1274. preVal == -1 )
  1275. {
  1276. fChanged = (m_dsStatus != postVal);
  1277. m_dsStatus = postVal;
  1278. dsStatus = m_dsStatus;
  1279. //
  1280. // Clean error at start of data collection.
  1281. //
  1282. switch(m_dsStatus)
  1283. {
  1284. case DC_COLLECTING:
  1285. case DC_COMPARING:
  1286. m_dwErrorCode = 0;
  1287. break;
  1288. }
  1289. }
  1290. else
  1291. {
  1292. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  1293. }
  1294. hr = S_OK;
  1295. __HCP_FUNC_CLEANUP;
  1296. lock = NULL; // Release the lock before firing the event.
  1297. //
  1298. // Important, leave these calls outside Locked Sections!!
  1299. //
  1300. if(SUCCEEDED(hr) && fChanged)
  1301. {
  1302. Fire_onStatusChange( this, dsStatus );
  1303. }
  1304. __HCP_FUNC_EXIT(hr);
  1305. }
  1306. HRESULT CSAFDataCollection::put_ErrorCode( /*[in]*/ DWORD newVal )
  1307. {
  1308. __HCP_FUNC_ENTRY( "CSAFDataCollection::put_ErrorCode" );
  1309. HRESULT hr;
  1310. MPC::SmartLock<_ThreadModel> lock( this );
  1311. m_dwErrorCode = newVal;
  1312. hr = S_OK;
  1313. __HCP_FUNC_EXIT(hr);
  1314. }
  1315. /////////////////////////////////////////////////////////////////////////////
  1316. ////////////////
  1317. // //
  1318. // Properties //
  1319. // //
  1320. ////////////////
  1321. STDMETHODIMP CSAFDataCollection::get_Status( /*[out]*/ DC_STATUS *pVal )
  1322. {
  1323. __HCP_BEGIN_PROPERTY_GET2("CSAFDataCollection::get_Status",hr,pVal,m_dsStatus);
  1324. __HCP_END_PROPERTY(hr);
  1325. }
  1326. STDMETHODIMP CSAFDataCollection::get_PercentDone( /*[out]*/ long *pVal )
  1327. {
  1328. __HCP_BEGIN_PROPERTY_GET2("CSAFDataCollection::get_PercentDone",hr,pVal,m_lPercent);
  1329. __HCP_END_PROPERTY(hr);
  1330. }
  1331. STDMETHODIMP CSAFDataCollection::get_ErrorCode( /*[out]*/ long *pVal )
  1332. {
  1333. __HCP_BEGIN_PROPERTY_GET2("CSAFDataCollection::get_ErrorCode",hr,pVal,(long)m_dwErrorCode);
  1334. __HCP_END_PROPERTY(hr);
  1335. }
  1336. /////////////////////////////////////////////////////////////////////////////
  1337. STDMETHODIMP CSAFDataCollection::get_MachineData_DataSpec( /*[out]*/ BSTR *pVal )
  1338. {
  1339. MPC::SmartLock<_ThreadModel> lock( this );
  1340. return MPC::GetBSTR( m_bstrMachineData, pVal );
  1341. }
  1342. STDMETHODIMP CSAFDataCollection::put_MachineData_DataSpec( /*[in]*/ BSTR newVal )
  1343. {
  1344. __HCP_BEGIN_PROPERTY_PUT("CSAFDataCollection::put_MachineData_DataSpec",hr);
  1345. CHECK_MODIFY();
  1346. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::PutBSTR( m_bstrMachineData, newVal ));
  1347. __HCP_END_PROPERTY(hr);
  1348. }
  1349. STDMETHODIMP CSAFDataCollection::get_History_DataSpec( /*[out]*/ BSTR *pVal )
  1350. {
  1351. MPC::SmartLock<_ThreadModel> lock( this );
  1352. return MPC::GetBSTR( m_bstrHistory, pVal );
  1353. }
  1354. STDMETHODIMP CSAFDataCollection::put_History_DataSpec( /*[in]*/ BSTR newVal )
  1355. {
  1356. __HCP_BEGIN_PROPERTY_PUT("CSAFDataCollection::put_History_DataSpec",hr);
  1357. CHECK_MODIFY();
  1358. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::PutBSTR( m_bstrHistory, newVal ));
  1359. __HCP_END_PROPERTY(hr);
  1360. }
  1361. STDMETHODIMP CSAFDataCollection::get_History_MaxDeltas( /*[out]*/ long *pVal )
  1362. {
  1363. __HCP_BEGIN_PROPERTY_GET2("CSAFDataCollection::get_History_MaxDeltas",hr,pVal,m_lHistory);
  1364. __HCP_END_PROPERTY(hr);
  1365. }
  1366. STDMETHODIMP CSAFDataCollection::put_History_MaxDeltas( /*[in]*/ long newVal )
  1367. {
  1368. __HCP_BEGIN_PROPERTY_PUT("CSAFDataCollection::put_History_MaxDeltas",hr);
  1369. //
  1370. // Check validity range.
  1371. //
  1372. if(newVal < 0 ||
  1373. newVal > WMIHISTORY_MAX_NUMBER_OF_DELTAS )
  1374. {
  1375. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  1376. }
  1377. m_lHistory = newVal;
  1378. __HCP_END_PROPERTY(hr);
  1379. }
  1380. STDMETHODIMP CSAFDataCollection::get_History_MaxSupportedDeltas( /*[out]*/ long *pVal )
  1381. {
  1382. __HCP_BEGIN_PROPERTY_GET2("CSAFDataCollection::get_History_MaxSupportedDeltas",hr,pVal,WMIHISTORY_MAX_NUMBER_OF_DELTAS);
  1383. __HCP_END_PROPERTY(hr);
  1384. }
  1385. /////////////////////////////////////////////////////////////////////////////
  1386. STDMETHODIMP CSAFDataCollection::put_onStatusChange( /*[in]*/ IDispatch* function )
  1387. {
  1388. __HCP_FUNC_ENTRY( "CSAFDataCollection::put_onStatusChange" );
  1389. m_sink_onStatusChange = function;
  1390. __HCP_FUNC_EXIT(S_OK);
  1391. }
  1392. STDMETHODIMP CSAFDataCollection::put_onProgress( /*[in]*/ IDispatch* function )
  1393. {
  1394. __HCP_FUNC_ENTRY( "CSAFDataCollection::put_onProgress" );
  1395. m_sink_onProgress = function;
  1396. __HCP_FUNC_EXIT(S_OK);
  1397. }
  1398. STDMETHODIMP CSAFDataCollection::put_onComplete( /*[in]*/ IDispatch* function )
  1399. {
  1400. __HCP_FUNC_ENTRY( "CSAFDataCollection::put_onComplete" );
  1401. m_sink_onComplete = function;
  1402. __HCP_FUNC_EXIT(S_OK);
  1403. }
  1404. STDMETHODIMP CSAFDataCollection::get_Reports( /*[out]*/ IPCHCollection* *ppC )
  1405. {
  1406. __HCP_FUNC_ENTRY( "CSAFDataCollection::get_Reports" );
  1407. HRESULT hr;
  1408. IterConst it;
  1409. CComPtr<CPCHCollection> pColl;
  1410. MPC::SmartLock<_ThreadModel> lock( this );
  1411. __MPC_PARAMCHECK_BEGIN(hr)
  1412. __MPC_PARAMCHECK_POINTER_AND_SET(ppC,NULL);
  1413. __MPC_PARAMCHECK_END();
  1414. CHECK_MODIFY();
  1415. //
  1416. // Create the Enumerator and fill it with jobs.
  1417. //
  1418. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
  1419. for(it = m_lstReports.begin(); it != m_lstReports.end(); it++)
  1420. {
  1421. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( *it ));
  1422. }
  1423. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppC ));
  1424. hr = S_OK;
  1425. __HCP_FUNC_CLEANUP;
  1426. __HCP_FUNC_EXIT(hr);
  1427. }
  1428. /////////////////////////////////////////////////////////////////////////////
  1429. /////////////
  1430. // Methods //
  1431. /////////////
  1432. STDMETHODIMP CSAFDataCollection::ExecuteSync()
  1433. {
  1434. __HCP_FUNC_ENTRY( "CSAFDataCollection::ExecuteSync" );
  1435. HRESULT hr;
  1436. CComPtr<CSAFDataCollectionEvents> hcpdceEvent;
  1437. CComPtr<ISAFDataCollection> hcpdc;
  1438. //
  1439. // Create the Wait object.
  1440. //
  1441. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hcpdceEvent ));
  1442. __MPC_EXIT_IF_METHOD_FAILS(hr, QueryInterface( IID_ISAFDataCollection, (void**)&hcpdc ));
  1443. __MPC_EXIT_IF_METHOD_FAILS(hr, hcpdceEvent->WaitForCompletion( hcpdc ));
  1444. hr = S_OK;
  1445. __HCP_FUNC_CLEANUP;
  1446. __HCP_FUNC_EXIT(hr);
  1447. }
  1448. STDMETHODIMP CSAFDataCollection::ExecuteAsync()
  1449. {
  1450. __HCP_FUNC_ENTRY( "CSAFDataCollection::ExecuteAsync" );
  1451. HRESULT hr;
  1452. MPC::SmartLock<_ThreadModel> lock( this );
  1453. CHECK_MODIFY();
  1454. //
  1455. // At least a data spec file should be supplied.
  1456. //
  1457. if(m_bstrMachineData.Length() == 0 &&
  1458. m_bstrHistory .Length() == 0 )
  1459. {
  1460. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  1461. }
  1462. //
  1463. // Release the lock on current object, otherwise a deadlock could occur.
  1464. //
  1465. __MPC_EXIT_IF_METHOD_FAILS(hr, m_imp.Initialize());
  1466. //
  1467. // Let's go into read-only mode.
  1468. //
  1469. StartOperations();
  1470. lock = NULL;
  1471. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, ExecLoopCollect, NULL ));
  1472. hr = S_OK;
  1473. __HCP_FUNC_CLEANUP;
  1474. __HCP_FUNC_EXIT(hr);
  1475. }
  1476. STDMETHODIMP CSAFDataCollection::Abort()
  1477. {
  1478. __HCP_FUNC_ENTRY( "CSAFDataCollection::Abort" );
  1479. MPC::SmartLock<_ThreadModel> lock( this );
  1480. if(FAILED(CanModifyProperties()))
  1481. {
  1482. Thread_Abort();
  1483. }
  1484. __HCP_FUNC_EXIT(S_OK);
  1485. }
  1486. STDMETHODIMP CSAFDataCollection::MachineData_GetStream( /*[in]*/ IUnknown* *stream )
  1487. {
  1488. __HCP_FUNC_ENTRY( "CSAFDataCollection::MachineData_GetStream" );
  1489. HRESULT hr;
  1490. __MPC_PARAMCHECK_BEGIN(hr)
  1491. __MPC_PARAMCHECK_POINTER_AND_SET(stream,NULL);
  1492. __MPC_PARAMCHECK_END();
  1493. if(m_streamMachineData)
  1494. {
  1495. __MPC_EXIT_IF_METHOD_FAILS(hr, m_streamMachineData.QueryInterface( stream ));
  1496. }
  1497. hr = S_OK;
  1498. __HCP_FUNC_CLEANUP;
  1499. __HCP_FUNC_EXIT(hr);
  1500. }
  1501. STDMETHODIMP CSAFDataCollection::History_GetStream( /*[in]*/ IUnknown* *stream )
  1502. {
  1503. __HCP_FUNC_ENTRY( "CSAFDataCollection::History_GetStream" );
  1504. HRESULT hr;
  1505. __MPC_PARAMCHECK_BEGIN(hr)
  1506. __MPC_PARAMCHECK_POINTER_AND_SET(stream,NULL);
  1507. __MPC_PARAMCHECK_END();
  1508. if(m_streamHistory)
  1509. {
  1510. __MPC_EXIT_IF_METHOD_FAILS(hr, m_streamHistory.QueryInterface( stream ));
  1511. }
  1512. hr = S_OK;
  1513. __HCP_FUNC_CLEANUP;
  1514. __HCP_FUNC_EXIT(hr);
  1515. }
  1516. STDMETHODIMP CSAFDataCollection::CompareSnapshots( /*[in] */ BSTR bstrFilenameT0 ,
  1517. /*[in] */ BSTR bstrFilenameT1 ,
  1518. /*[in] */ BSTR bstrFilenameDiff )
  1519. {
  1520. __HCP_FUNC_ENTRY( "CSAFDataCollection::CompareSnapshots" );
  1521. HRESULT hr;
  1522. MPC::SmartLock<_ThreadModel> lock( this );
  1523. __MPC_PARAMCHECK_BEGIN(hr)
  1524. __MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrFilenameT0);
  1525. __MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrFilenameT1);
  1526. __MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrFilenameDiff);
  1527. __MPC_PARAMCHECK_END();
  1528. CHECK_MODIFY();
  1529. m_bstrFilenameT0 = bstrFilenameT0;
  1530. m_bstrFilenameT1 = bstrFilenameT1;
  1531. m_bstrFilenameDiff = bstrFilenameDiff;
  1532. //
  1533. // Release the lock on current object, otherwise a deadlock could occur.
  1534. //
  1535. __MPC_EXIT_IF_METHOD_FAILS(hr, m_imp.Initialize());
  1536. //
  1537. // Let's go into read-only mode.
  1538. //
  1539. StartOperations();
  1540. lock = NULL;
  1541. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, ExecLoopCompare, NULL ));
  1542. hr = S_OK;
  1543. __HCP_FUNC_CLEANUP;
  1544. __HCP_FUNC_EXIT(hr);
  1545. }
  1546. /////////////////////////////////////////////////////////////////////////////
  1547. HRESULT CSAFDataCollection::ExecScheduledCollection()
  1548. {
  1549. __HCP_FUNC_ENTRY( "CSAFDataCollection::ExecScheduledCollection" );
  1550. HRESULT hr;
  1551. QueryResults qr;
  1552. WMIParser::ClusterByClassMap cluster;
  1553. WMIHistory::Database wmihd;
  1554. WMIHistory::Database::ProvList lstQueries;
  1555. HANDLE hThread;
  1556. int iPriority;
  1557. hThread = ::GetCurrentThread();
  1558. iPriority = ::GetThreadPriority( hThread );
  1559. ::SetThreadPriority( hThread, THREAD_PRIORITY_LOWEST );
  1560. //
  1561. // Try to lock the database and load the data spec file.
  1562. //
  1563. while(1)
  1564. {
  1565. if(SUCCEEDED(hr = wmihd.Init( DATASPEC_LOCATION, DATASPEC_CONFIG )))
  1566. {
  1567. break;
  1568. }
  1569. if(hr != HRESULT_FROM_WIN32( WAIT_TIMEOUT ))
  1570. {
  1571. __MPC_FUNC_LEAVE;
  1572. }
  1573. }
  1574. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihd.Load());
  1575. //
  1576. // Check if enough time has past between two data collections.
  1577. //
  1578. {
  1579. SYSTEMTIME stNow;
  1580. SYSTEMTIME stLatest;
  1581. ::GetLocalTime ( &stNow );
  1582. ::VariantTimeToSystemTime( wmihd.LastTime(), &stLatest );
  1583. if(stNow.wYear == stLatest.wYear &&
  1584. stNow.wMonth == stLatest.wMonth &&
  1585. stNow.wDay == stLatest.wDay )
  1586. {
  1587. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  1588. }
  1589. }
  1590. m_fScheduled = true;
  1591. //
  1592. // Filter and count the queries.
  1593. //
  1594. __MPC_EXIT_IF_METHOD_FAILS(hr, FilterDataSpec( wmihd, NULL, lstQueries ));
  1595. //
  1596. // Collect data from WMI.
  1597. //
  1598. __MPC_EXIT_IF_METHOD_FAILS(hr, ExecDataSpec( qr, cluster, lstQueries, false ));
  1599. //
  1600. // Compute deltas.
  1601. //
  1602. __MPC_EXIT_IF_METHOD_FAILS(hr, ComputeDelta( qr, cluster, lstQueries, true ));
  1603. //
  1604. // Persiste the changes to the database.
  1605. //
  1606. __MPC_EXIT_IF_METHOD_FAILS(hr, wmihd.Save());
  1607. hr = S_OK;
  1608. __HCP_FUNC_CLEANUP;
  1609. CleanQueryResult( qr );
  1610. ::SetThreadPriority( hThread, iPriority );
  1611. __HCP_FUNC_EXIT(hr);
  1612. }