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.

768 lines
17 KiB

  1. //*************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation 1999 - 2000
  4. // All rights reserved
  5. //
  6. // pollog.cxx
  7. //
  8. //*************************************************************
  9. #include "rsop.hxx"
  10. #include <strsafe.h>
  11. #define RECORD_ENUMERATION_TIMEOUT -1
  12. #define WQL_LANGUAGE L"WQL"
  13. #define WSZGENERAL_CRITERIA_TEMPLATE L"select * from %s"
  14. #define WSZSPECIFIC_CRITERIA_TEMPLATE WSZGENERAL_CRITERIA_TEMPLATE L" where %s"
  15. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  16. //
  17. // Function: CPolicyLog::CPolicyLog
  18. //
  19. // Purpose: Constructor for CPolicyLog class
  20. //
  21. // Params: none
  22. //
  23. // Return value: none
  24. //
  25. // Notes:
  26. //
  27. //------------------------------------------------------------
  28. CPolicyLog::CPolicyLog() :
  29. _pRsopContext(NULL )
  30. {}
  31. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  32. //
  33. // Function: CPolicyRecord::InitLog
  34. //
  35. // Purpose: Initializes the logging class so that it
  36. // can create / delete / edit record in the database
  37. //
  38. // Params:
  39. // pRsopContext -- context used to bind to the namespace
  40. // wszPolicyType -- string corresponding to the record
  41. // (policy) type -- this is the name of a class defined
  42. // in the database schema.
  43. //
  44. // Return value: S_OK if success, error otherwise
  45. //
  46. // Notes:
  47. //
  48. //------------------------------------------------------------
  49. HRESULT CPolicyLog::InitLog(
  50. CRsopContext* pRsopContext,
  51. WCHAR* wszPolicyType)
  52. {
  53. HRESULT hr;
  54. _pRsopContext = pRsopContext;
  55. if ( ! _pRsopContext->IsRsopEnabled() )
  56. {
  57. return S_OK;
  58. }
  59. //
  60. // Set our internal automation compatible version
  61. // of the policy type with the caller's specification --
  62. // return if we cannot set this value
  63. //
  64. _wszClass = wszPolicyType;
  65. XBStr xbstrClass;
  66. xbstrClass = wszPolicyType;
  67. if ( ! xbstrClass )
  68. {
  69. return E_OUTOFMEMORY;
  70. }
  71. //
  72. // Now, bind the context to get the correct namespace
  73. //
  74. hr = pRsopContext->Bind( &_xWbemServices );
  75. if ( FAILED(hr) )
  76. {
  77. return hr;
  78. }
  79. //
  80. // Be sure to AddRef it, since we don't want it to
  81. // go away when we're done
  82. //
  83. _xWbemServices->AddRef();
  84. //
  85. // Now we attempt to get an interface to the class of policy
  86. // requested by the caller
  87. //
  88. hr = GetRecordCreator(
  89. &xbstrClass,
  90. &_xRecordCreator);
  91. if (FAILED(hr))
  92. {
  93. return hr;
  94. }
  95. return hr;
  96. }
  97. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  98. //
  99. // Function: CPolicyRecord::UninitLog
  100. //
  101. // Purpose: Uninitializes the logging class so that all
  102. // its resources are freed
  103. //
  104. // Params: none
  105. //
  106. // Return value: none
  107. //
  108. // Notes:
  109. //
  110. //------------------------------------------------------------
  111. void CPolicyLog::UninitLog()
  112. {
  113. _xEnum = NULL;
  114. _xWbemServices = NULL;
  115. _xRecordCreator = NULL;
  116. }
  117. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  118. //
  119. // Function: CPolicyLog::AddBlankRecord
  120. //
  121. // Purpose: Creates a blank record in the policy database,
  122. // and connects the supplied CPolicyRecord with the
  123. // newly created record
  124. //
  125. // Params: pRecord -- reference to a CPolicyRecord which will
  126. // be associated with the new record if this funciton
  127. // succeeds.
  128. //
  129. // Return S_OK if success, error otherwise
  130. //
  131. // Notes:
  132. //
  133. //------------------------------------------------------------
  134. HRESULT CPolicyLog::AddBlankRecord(CPolicyRecord* pRecord)
  135. {
  136. HRESULT hr;
  137. IWbemClassObject* pRecordInterface;
  138. if ( ! _pRsopContext->IsRsopEnabled() )
  139. {
  140. return S_OK;
  141. }
  142. pRecordInterface = NULL;
  143. //
  144. // Use the record creator interface to create
  145. // an instance of the class of record associated
  146. // with this log
  147. //
  148. hr = _xRecordCreator->SpawnInstance(
  149. 0,
  150. &pRecordInterface);
  151. if (FAILED(hr))
  152. {
  153. return hr;
  154. }
  155. //
  156. // Initialize the CPolicyRecord so that it is
  157. // associated with the newly created record
  158. //
  159. pRecord->InitRecord(pRecordInterface);
  160. return S_OK;
  161. }
  162. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  163. //
  164. // Function: CPolicyLog::CommitRecord
  165. //
  166. // Purpose: Commits an edited policy record to the database
  167. //
  168. // Params: pRecord -- the record to commit
  169. //
  170. // Return value: S_OK if successful, other error if not
  171. //
  172. // Notes:
  173. //
  174. //------------------------------------------------------------
  175. HRESULT CPolicyLog::CommitRecord(CPolicyRecord* pRecord)
  176. {
  177. return _xWbemServices->PutInstance(
  178. pRecord->GetRecordInterface(),
  179. WBEM_FLAG_CREATE_OR_UPDATE,
  180. NULL,
  181. NULL);
  182. }
  183. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  184. //
  185. // Function: CPolicyRecord::WriteNewRecord
  186. //
  187. // Purpose: Creates a new record in the database, populates
  188. // that record with information specific to the CPolicyRecord
  189. // object, and commits the record.
  190. //
  191. // Params: pRecord -- reference to a CPolicyRecord which contains
  192. // information that should be written to the database
  193. //
  194. // Return S_OK if success, error otherwise
  195. //
  196. // Notes: The pRecord object may not be passed to this
  197. // method more than once
  198. //
  199. //------------------------------------------------------------
  200. HRESULT CPolicyLog::WriteNewRecord(CPolicyRecord* pRecord)
  201. {
  202. HRESULT hr;
  203. if ( ! _pRsopContext->IsRsopEnabled() )
  204. {
  205. return S_OK;
  206. }
  207. //
  208. // Now, let's attempt to add a blank entry for this record to the database
  209. //
  210. hr = AddBlankRecord( pRecord );
  211. if (FAILED(hr))
  212. {
  213. return hr;
  214. }
  215. //
  216. // Write the information for this record into the blank log record
  217. //
  218. hr = pRecord->Write();
  219. if (FAILED(hr))
  220. {
  221. return hr;
  222. }
  223. //
  224. // We've written the record, now commit it permanently to the log
  225. // in the database
  226. //
  227. hr = CommitRecord( pRecord );
  228. return hr;
  229. }
  230. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  231. //
  232. // Function: CPolicyRecord::GetRecordCreator
  233. //
  234. // Purpose: Returns an interface that allows for the creation
  235. // of records of a specified class in the database
  236. //
  237. // Params: pStrClass -- a string named with a class as defined
  238. // by the database schema that indicates the class for
  239. // which we require an interface
  240. //
  241. // ppClass -- out param returning an interface to the
  242. // record creator for a given class
  243. //
  244. // Return S_OK if success, error otherwise
  245. //
  246. // Notes:
  247. //
  248. //------------------------------------------------------------
  249. HRESULT CPolicyLog::GetRecordCreator(
  250. XBStr* pxStrClass,
  251. IWbemClassObject** ppClass)
  252. {
  253. HRESULT hr;
  254. //
  255. // Call the method of the namespace interface to return
  256. // an instance of the specified class defined in that namespace
  257. //
  258. hr = _xWbemServices->GetObject(
  259. *pxStrClass,
  260. 0L,
  261. NULL,
  262. ppClass,
  263. NULL );
  264. return hr;
  265. }
  266. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  267. //
  268. // Function: CPolicyRecord::GetNextRecord
  269. //
  270. // Purpose: Associates a CPolicyRecord with a database
  271. // record that's next in the current enumeration
  272. //
  273. // Params: pRecord -- CPolicyRecord to be associated with
  274. // the next db record in the enumeration
  275. //
  276. // Return S_OK if success, error otherwise
  277. //
  278. // Notes:
  279. //
  280. //------------------------------------------------------------
  281. HRESULT CPolicyLog::GetNextRecord( CPolicyRecord* pRecord )
  282. {
  283. ULONG ulReturned;
  284. IWbemClassObject* pInstance;
  285. HRESULT hr;
  286. ulReturned = 1;
  287. //
  288. // Use the enumeration interface to return a record interface
  289. // to the next item in the enumeration -- we choose
  290. // here to enumerate one at a time as this is not
  291. // optimzed for speed currently.
  292. //
  293. hr = _xEnum->Next(
  294. RECORD_ENUMERATION_TIMEOUT,
  295. 1,
  296. &pInstance,
  297. &ulReturned );
  298. //
  299. // If we received one item back with a success code,
  300. // we have retrieved an interface -- associate
  301. // the retrieved interface with the caller-specified
  302. // pRecord
  303. //
  304. if ( (S_OK == hr) && (1 == ulReturned) )
  305. {
  306. pRecord->InitRecord( pInstance );
  307. }
  308. else
  309. {
  310. ASSERT(FAILED(hr) || (S_FALSE == hr));
  311. }
  312. return hr;
  313. }
  314. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  315. //
  316. // Function: CPolicyLog::OpenExistingRecord
  317. //
  318. // Purpose: Associates a CPolicyRecord with a database
  319. // record that corresponds to a path emitted by
  320. // CPolicyRecord's GetPath method
  321. //
  322. // Params: pRecord -- CPolicyRecord to be associated with
  323. // the existing database item
  324. //
  325. // Return S_OK if success, error otherwise
  326. //
  327. // Notes:
  328. //
  329. //------------------------------------------------------------
  330. HRESULT
  331. CPolicyLog::OpenExistingRecord( CPolicyRecord* pRecord )
  332. {
  333. HRESULT hr;
  334. WCHAR* wszPath = NULL;
  335. DWORD cchLength = MAX_PATH;
  336. BSTR PathName = NULL;
  337. wszPath = (WCHAR*)LocalAlloc(LPTR, cchLength*sizeof(WCHAR));
  338. if ( wszPath == NULL )
  339. {
  340. return E_OUTOFMEMORY;
  341. }
  342. hr = pRecord->GetPath( wszPath, &cchLength );
  343. if ( FAILED( hr ) )
  344. {
  345. LocalFree( wszPath );
  346. return hr;
  347. }
  348. if ( S_OK == hr )
  349. {
  350. PathName = SysAllocString( wszPath );
  351. LocalFree( wszPath );
  352. wszPath = NULL;
  353. }
  354. else
  355. {
  356. LocalFree( wszPath );
  357. wszPath = (WCHAR*)LocalAlloc(LPTR, cchLength*sizeof(WCHAR));
  358. if ( wszPath != NULL )
  359. {
  360. hr = pRecord->GetPath( wszPath, &cchLength );
  361. if ( FAILED(hr) )
  362. {
  363. LocalFree( wszPath );
  364. return hr;
  365. }
  366. PathName = SysAllocString( wszPath );
  367. LocalFree( wszPath );
  368. wszPath = NULL;
  369. }
  370. }
  371. if ( ! PathName )
  372. {
  373. return E_OUTOFMEMORY;
  374. }
  375. if ( SUCCEEDED( hr ) )
  376. {
  377. IWbemClassObject* pInstance;
  378. pInstance = NULL;
  379. if ( _xWbemServices )
  380. {
  381. hr = _xWbemServices->GetObject(
  382. PathName,
  383. WBEM_FLAG_RETURN_WBEM_COMPLETE,
  384. NULL,
  385. &pInstance,
  386. NULL);
  387. }
  388. else
  389. {
  390. hr = E_OUTOFMEMORY;
  391. }
  392. if ( SUCCEEDED( hr ) )
  393. {
  394. pRecord->InitRecord( pInstance );
  395. }
  396. }
  397. SysFreeString( PathName );
  398. if ( SUCCEEDED( hr ) )
  399. {
  400. pRecord->_bNewRecord = FALSE;
  401. }
  402. return hr;
  403. }
  404. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  405. //
  406. // Function: CPolicyRecord::DeleteRecord
  407. //
  408. // Purpose: Deletes the record associated with this CPolicyRecord
  409. // from the database
  410. //
  411. // Params: pRecord -- CPolicyRecord associated with
  412. // the record to delete
  413. //
  414. // Return S_OK if success, error otherwise
  415. //
  416. // Notes:
  417. //
  418. //------------------------------------------------------------
  419. HRESULT CPolicyLog::DeleteRecord(
  420. CPolicyRecord* pRecord,
  421. BOOL bDeleteStatus)
  422. {
  423. CVariant var;
  424. HRESULT hr;
  425. //
  426. // If specified by the caller, delete any associated status records
  427. //
  428. if ( bDeleteStatus )
  429. {
  430. hr = DeleteStatusRecords( pRecord );
  431. if ( FAILED(hr) )
  432. {
  433. return hr;
  434. }
  435. }
  436. //
  437. // Retrieve the database path of the record to delete
  438. //
  439. hr = pRecord->GetRecordInterface()->Get(
  440. WMI_PATH_PROPERTY,
  441. 0L,
  442. (VARIANT*) &var,
  443. NULL,
  444. NULL);
  445. if ( FAILED(hr) )
  446. {
  447. return hr;
  448. }
  449. //
  450. // Now that we have the path, we can use it to delete the record
  451. // by supplying it to the namespace's delete instance method --
  452. // this will delete the record from the namespace
  453. //
  454. hr = _xWbemServices->DeleteInstance(
  455. ((VARIANT*) &var)->bstrVal,
  456. 0L,
  457. NULL,
  458. NULL );
  459. return hr;
  460. }
  461. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  462. //
  463. // Function: CPolicyRecord::DeleteRecord
  464. //
  465. // Purpose: Deletes the record associated with this CPolicyRecord
  466. // from the database
  467. //
  468. // Params: pRecord -- CPolicyRecord associated with
  469. // the record to delete
  470. //
  471. // Return S_OK if success, error otherwise
  472. //
  473. // Notes:
  474. //
  475. //------------------------------------------------------------
  476. HRESULT CPolicyLog::DeleteStatusRecords( CPolicyRecord* pRecord )
  477. {
  478. HRESULT hr;
  479. //
  480. // If there is a setting status associated with
  481. // this error, delete it
  482. //
  483. hr = RsopResetPolicySettingStatus(
  484. 0,
  485. _xWbemServices,
  486. pRecord->GetRecordInterface());
  487. return hr;
  488. }
  489. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  490. //
  491. // Function: CPolicyRecord::ClearLog
  492. //
  493. // Purpose: Clears all records of this log's class (policy type)
  494. // from the log's associated namespace
  495. //
  496. // Params: none
  497. //
  498. // Return S_OK if success, error otherwise
  499. //
  500. // Notes:
  501. //
  502. //------------------------------------------------------------
  503. HRESULT CPolicyLog::ClearLog(
  504. WCHAR* wszSpecifiedCriteria,
  505. BOOL bDeleteStatus)
  506. {
  507. HRESULT hr;
  508. if ( ! _pRsopContext->IsRsopEnabled() )
  509. {
  510. return S_OK;
  511. }
  512. //
  513. // Retrieve an enumerator for the specified criteria
  514. //
  515. hr = GetEnum( wszSpecifiedCriteria );
  516. if (FAILED(hr))
  517. {
  518. return hr;
  519. }
  520. //
  521. // We will iterate through all existing records
  522. //
  523. for (;;)
  524. {
  525. CPolicyRecord CurrentRecord;
  526. //
  527. // Retrieve the current record from the
  528. // namespace
  529. //
  530. hr = GetNextRecord(&CurrentRecord);
  531. if (FAILED(hr))
  532. {
  533. return hr;
  534. }
  535. //
  536. // If there are no more records to retrieve,
  537. // we are done and can exit the loop.
  538. //
  539. if (S_FALSE == hr)
  540. {
  541. break;
  542. }
  543. //
  544. // Delete the current record from the namespace
  545. //
  546. hr = DeleteRecord( &CurrentRecord, bDeleteStatus );
  547. }
  548. FreeEnum();
  549. return S_OK;
  550. }
  551. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  552. //
  553. // Function: CPolicyRecord::ClearLog
  554. //
  555. // Purpose: Deletes all instances of this class from the namespace
  556. //
  557. // Params: none
  558. //
  559. // Return S_OK if success, error otherwise
  560. //
  561. // Notes:
  562. //
  563. //------------------------------------------------------------
  564. HRESULT CPolicyLog::GetEnum( WCHAR* wszSpecifiedCriteria )
  565. {
  566. HRESULT hr;
  567. if ( _xEnum )
  568. {
  569. return E_FAIL;
  570. }
  571. //
  572. // Generate criteria from the caller's specification
  573. //
  574. WCHAR* wszCriteria;
  575. DWORD dwCritLength = ( wszSpecifiedCriteria ? lstrlen(wszSpecifiedCriteria) : 0 ) +
  576. sizeof( WSZSPECIFIC_CRITERIA_TEMPLATE ) / sizeof(WCHAR) +
  577. lstrlen( _wszClass ) + 1;
  578. wszCriteria = new WCHAR [ dwCritLength ];
  579. if ( ! wszCriteria )
  580. {
  581. return E_OUTOFMEMORY;
  582. }
  583. //
  584. // This creates a query for instances of the class supported by this log
  585. // that adhere to the caller's specifications (usually asserts the value of some property)
  586. //
  587. if ( wszSpecifiedCriteria )
  588. {
  589. //
  590. // Include the user's criteria if specified
  591. //
  592. hr = StringCchPrintf(wszCriteria,
  593. dwCritLength,
  594. WSZSPECIFIC_CRITERIA_TEMPLATE,
  595. _wszClass,
  596. wszSpecifiedCriteria);
  597. ASSERT(SUCCEEDED(hr));
  598. }
  599. else
  600. {
  601. //
  602. // If the user specified no criteria, do not attempt to include it
  603. //
  604. hr = StringCchPrintf(wszCriteria,
  605. dwCritLength,
  606. WSZGENERAL_CRITERIA_TEMPLATE,
  607. _wszClass);
  608. ASSERT(SUCCEEDED(hr));
  609. }
  610. hr = E_OUTOFMEMORY;
  611. XBStr Query( wszCriteria );
  612. XBStr QueryLanguage( WQL_LANGUAGE );
  613. if ( Query && QueryLanguage )
  614. {
  615. //
  616. // Use this method to obtain an enumerator for instances
  617. // satisfying the specified criteria
  618. //
  619. hr = _xWbemServices->ExecQuery(
  620. QueryLanguage,
  621. Query,
  622. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  623. NULL,
  624. &_xEnum );
  625. }
  626. delete [] wszCriteria;
  627. if ( FAILED(hr) )
  628. {
  629. return hr;
  630. }
  631. return S_OK;
  632. }
  633. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  634. //
  635. // Function: CPolicyRecord::ClearLog
  636. //
  637. // Purpose: Deletes all instances of this class from the namespace
  638. //
  639. // Params: none
  640. //
  641. // Return S_OK if success, error otherwise
  642. //
  643. // Notes:
  644. //
  645. //------------------------------------------------------------
  646. void CPolicyLog::FreeEnum()
  647. {
  648. //
  649. // This will release the interface and set it to NULL so
  650. // that we know that it is released;
  651. //
  652. _xEnum = 0;
  653. }