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.

890 lines
24 KiB

  1. // audit.cpp: implementation of the CAuditSettings class.
  2. //
  3. // Copyright (c)1997-1999 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "audit.h"
  8. #include "persistmgr.h"
  9. #include <io.h>
  10. #include "requestobject.h"
  11. /*
  12. Routine Description:
  13. Name:
  14. CAuditSettings::CAuditSettings
  15. Functionality:
  16. This is the constructor. Pass along the parameters to the base class
  17. Virtual:
  18. No (you know that, constructor won't be virtual!)
  19. Arguments:
  20. pKeyChain - Pointer to the ISceKeyChain COM interface which is prepared
  21. by the caller who constructs this instance.
  22. pNamespace - Pointer to WMI namespace of our provider (COM interface).
  23. Passed along by the caller. Must not be NULL.
  24. pCtx - Pointer to WMI context object (COM interface). Passed along
  25. by the caller. It's up to WMI whether this interface pointer is NULL or not.
  26. Return Value:
  27. None as any constructor
  28. Notes:
  29. if you create any local members, think about initialize them here
  30. */
  31. CAuditSettings::CAuditSettings (
  32. IN ISceKeyChain *pKeyChain,
  33. IN IWbemServices *pNamespace,
  34. IN IWbemContext *pCtx
  35. )
  36. :
  37. CGenericClass(pKeyChain, pNamespace, pCtx)
  38. {
  39. }
  40. /*
  41. Routine Description:
  42. Name:
  43. CAuditSettings::~CAuditSettings
  44. Functionality:
  45. Destructor. Necessary as good C++ discipline since we have virtual functions.
  46. Virtual:
  47. Yes.
  48. Arguments:
  49. none as any destructor
  50. Return Value:
  51. None as any destructor
  52. Notes:
  53. if you create any local members, think about whether
  54. there is any need for a non-trivial destructor
  55. */
  56. CAuditSettings::~CAuditSettings()
  57. {
  58. }
  59. /*
  60. Routine Description:
  61. Name:
  62. CAuditSettings::CreateObject
  63. Functionality:
  64. Create WMI objects (Sce_AuditPolicy). Depending on parameter atAction,
  65. this creation may mean:
  66. (a) Get a single instance (atAction == ACTIONTYPE_GET)
  67. (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY)
  68. (c) Delete an instance (atAction == ACTIONTYPE_DELETE)
  69. Virtual:
  70. Yes.
  71. Arguments:
  72. pHandler - COM interface pointer for notifying WMI for creation result.
  73. atAction - Get single instance ACTIONTYPE_GET
  74. Get several instances ACTIONTYPE_QUERY
  75. Delete a single instance ACTIONTYPE_DELETE
  76. Return Value:
  77. Success: it must return success code (use SUCCEEDED to test). It is
  78. not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI,
  79. not directly passed back via parameters.
  80. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate
  81. the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying
  82. situations, this may not be an error depending on caller's intention.
  83. Notes:
  84. */
  85. HRESULT
  86. CAuditSettings::CreateObject (
  87. IN IWbemObjectSink * pHandler,
  88. IN ACTIONTYPE atAction
  89. )
  90. {
  91. //
  92. // we know how to:
  93. // Get single instance ACTIONTYPE_GET
  94. // Delete a single instance ACTIONTYPE_DELETE
  95. // Get several instances ACTIONTYPE_QUERY
  96. //
  97. if ( ACTIONTYPE_GET != atAction &&
  98. ACTIONTYPE_DELETE != atAction &&
  99. ACTIONTYPE_QUERY != atAction ) {
  100. return WBEM_E_NOT_SUPPORTED;
  101. }
  102. //
  103. // We must have the pStorePath property because that is where
  104. // our instance is stored.
  105. // m_srpKeyChain->GetKeyPropertyValue WBEM_S_FALSE if the key is not recognized
  106. // So, we need to test against WBEM_S_FALSE if the property is mandatory
  107. //
  108. CComVariant varStorePath;
  109. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(pStorePath, &varStorePath);
  110. if (SUCCEEDED(hr) && hr != WBEM_S_FALSE && varStorePath.vt == VT_BSTR)
  111. {
  112. //
  113. // we must also have category property unless we are querying
  114. //
  115. CComVariant varCategory;
  116. hr = m_srpKeyChain->GetKeyPropertyValue(pCategory, &varCategory);
  117. if (FAILED(hr))
  118. {
  119. return hr;
  120. }
  121. else if (hr == WBEM_S_FALSE && (ACTIONTYPE_QUERY != atAction) )
  122. {
  123. return WBEM_E_NOT_FOUND;
  124. }
  125. //
  126. // prepare a store to read the properties
  127. //
  128. CSceStore SceStore;
  129. hr = SceStore.SetPersistPath(varStorePath.bstrVal);
  130. if ( SUCCEEDED(hr) ) {
  131. //
  132. // make sure the store (just a file) really exists. The raw path
  133. // may contain env variables, so we need the expanded path
  134. //
  135. DWORD dwAttrib = GetFileAttributes(SceStore.GetExpandedPath());
  136. if ( dwAttrib != -1 ) {
  137. //
  138. // this file exists
  139. //
  140. //
  141. // the key property count determines the post filter
  142. //
  143. BOOL bPostFilter=TRUE;
  144. DWORD dwCount = 0;
  145. m_srpKeyChain->GetKeyPropertyCount(&dwCount);
  146. //
  147. // if we have a valid category
  148. //
  149. if ( varCategory.vt == VT_BSTR && varCategory.bstrVal )
  150. {
  151. if ( ACTIONTYPE_DELETE == atAction )
  152. {
  153. hr = DeleteInstance(pHandler, &SceStore,varCategory.bstrVal);
  154. }
  155. else
  156. {
  157. if ( ACTIONTYPE_QUERY == atAction && dwCount == 2 )
  158. {
  159. bPostFilter = FALSE;
  160. }
  161. hr = ConstructInstance(pHandler,
  162. &SceStore,
  163. varStorePath.bstrVal,
  164. (varStorePath.vt == VT_BSTR) ? varCategory.bstrVal : NULL,
  165. bPostFilter);
  166. }
  167. }
  168. //
  169. // if not valid category, we will do a query
  170. //
  171. else
  172. {
  173. if ( dwCount == 1 )
  174. {
  175. bPostFilter = FALSE;
  176. }
  177. //
  178. // query support
  179. //
  180. hr = ConstructInstance(pHandler, &SceStore, varStorePath.bstrVal, NULL, bPostFilter);
  181. }
  182. }
  183. else
  184. {
  185. hr = WBEM_E_NOT_FOUND;
  186. }
  187. }
  188. }
  189. return hr;
  190. }
  191. /*
  192. Routine Description:
  193. Name:
  194. CAuditSettings::PutInst
  195. Functionality:
  196. Put an instance as instructed by WMI. Since this class implements Sce_AuditPolicy,
  197. which is persistence oriented, this will cause the Sce_AuditPolicy object's property
  198. information to be saved in our store.
  199. Virtual:
  200. Yes.
  201. Arguments:
  202. pInst - COM interface pointer to the WMI class (Sce_AuditPolicy) object.
  203. pHandler - COM interface pointer for notifying WMI of any events.
  204. pCtx - COM interface pointer. This interface is just something we pass around.
  205. WMI may mandate it (not now) in the future. But we never construct
  206. such an interface and so, we just pass around for various WMI API's
  207. Return Value:
  208. Success: it must return success code (use SUCCEEDED to test). It is
  209. not guaranteed to return WBEM_NO_ERROR.
  210. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  211. the instance.
  212. Notes:
  213. Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  214. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  215. to test for the result of retrieving a property.
  216. */
  217. HRESULT
  218. CAuditSettings::PutInst (
  219. IN IWbemClassObject * pInst,
  220. IN IWbemObjectSink * pHandler,
  221. IN IWbemContext * pCtx
  222. )
  223. {
  224. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  225. CComBSTR bstrCategory;
  226. DWORD *pAddress=NULL;
  227. bool bValue=FALSE;
  228. DWORD dwValue = 0;
  229. //
  230. // This is our store for saving information
  231. //
  232. CSceStore SceStore;
  233. //
  234. // this is our property manager for easy access to properties
  235. //
  236. CScePropertyMgr ScePropMgr;
  237. //
  238. // attach the property manager to this WMI object
  239. //
  240. ScePropMgr.Attach(pInst);
  241. //
  242. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  243. // a "goto CleanUp;" with hr set to the return value from
  244. // the function (macro parameter)
  245. //
  246. //
  247. // we don't support an object without the category proeprty
  248. //
  249. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pCategory, &bstrCategory));
  250. //
  251. // check if the category is valid
  252. //
  253. SCE_PROV_IfErrorGotoCleanup(ValidateCategory(bstrCategory, NULL, &pAddress));
  254. //
  255. // We can tolerate the Success property to be missing. In that
  256. // case, we just don't set the bit (take it as FALSE)
  257. //
  258. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pSuccess, &bValue));
  259. if ( hr != WBEM_S_RESET_TO_DEFAULT)
  260. {
  261. dwValue |= bValue ? SCE_AUDIT_EVENT_SUCCESS : 0;
  262. }
  263. //
  264. // we want to re-use bValue, set it to FALSE - our default
  265. //
  266. bValue = FALSE;
  267. //
  268. // We can tolerate the Failure property to be missing. In that
  269. // case, we just don't set the bit (take it as FALSE)
  270. //
  271. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pFailure, &bValue));
  272. if ( hr != WBEM_S_RESET_TO_DEFAULT)
  273. {
  274. dwValue |= bValue? SCE_AUDIT_EVENT_FAILURE : 0;
  275. }
  276. //
  277. // Attach the WMI object instance to the store and let the store know that
  278. // it's store is given by the pStorePath property of the instance.
  279. //
  280. SceStore.SetPersistProperties(pInst, pStorePath);
  281. //
  282. // For a new .inf file. Write an empty buffer to the file
  283. // will creates the file with right header/signature/unicode format
  284. // this is harmless for existing files.
  285. // For database store, this is a no-op.
  286. //
  287. DWORD dwDump;
  288. hr = SceStore.WriteSecurityProfileInfo(
  289. AreaBogus, // a bogus area info
  290. (PSCE_PROFILE_INFO)&dwDump, // a dump buffer
  291. NULL,
  292. false
  293. );
  294. //
  295. // now save the info to file
  296. //
  297. if (SUCCEEDED(hr))
  298. {
  299. hr = SceStore.SavePropertyToStore(
  300. szAuditEvent,
  301. bstrCategory,
  302. dwValue
  303. );
  304. }
  305. CleanUp:
  306. return hr;
  307. }
  308. /*
  309. Routine Description:
  310. Name:
  311. CAuditSettings::ConstructInstance
  312. Functionality:
  313. This is private function to create an instance of Sce_AuditPolicy.
  314. Virtual:
  315. No.
  316. Arguments:
  317. pHandler - COM interface pointer for notifying WMI of any events.
  318. pSceStore - Pointer to our store. It must have been appropriately set up.
  319. wszLogStorePath - store path, a key property of Sce_AuditPolicy class.
  320. wszCategory - a property of Sce_AuditPolicy class.
  321. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  322. Return Value:
  323. Success: it must return success code (use SUCCEEDED to test). It is
  324. not guaranteed to return WBEM_NO_ERROR.
  325. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  326. Notes:
  327. */
  328. HRESULT
  329. CAuditSettings::ConstructInstance (
  330. IN IWbemObjectSink * pHandler,
  331. IN CSceStore * pSceStore,
  332. IN LPWSTR wszLogStorePath,
  333. IN LPCWSTR wszCategory OPTIONAL,
  334. IN BOOL bPostFilter
  335. )
  336. {
  337. //
  338. // make sure that our store is valid
  339. //
  340. if ( pSceStore == NULL || pSceStore->GetStoreType() < SCE_INF_FORMAT ||
  341. pSceStore->GetStoreType() > SCE_JET_ANALYSIS_REQUIRED ) {
  342. return WBEM_E_INVALID_PARAMETER;
  343. }
  344. //
  345. // ask SCE to read a gigantic structure out from the store. Only SCE
  346. // knows now to release the memory. Don't just delete it! Use our CSceStore
  347. // to do the releasing (FreeSecurityProfileInfo)
  348. //
  349. PSCE_PROFILE_INFO pInfo=NULL;
  350. HRESULT hr = pSceStore->GetSecurityProfileInfo(
  351. AREA_SECURITY_POLICY,
  352. &pInfo,
  353. NULL
  354. );
  355. if (SUCCEEDED(hr))
  356. {
  357. //
  358. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  359. // a "goto CleanUp;" with hr set to the return value from
  360. // the function (macro parameter)
  361. //
  362. CComBSTR bstrLogOut;
  363. SCE_PROV_IfErrorGotoCleanup(MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut));
  364. if ( wszCategory )
  365. {
  366. //
  367. // make sure that the category is valid
  368. //
  369. DWORD *pdwValue = NULL;
  370. hr = ValidateCategory(wszCategory, pInfo, &pdwValue);
  371. if (FAILED(hr) || pdwValue == NULL || *pdwValue == SCE_NO_VALUE )
  372. {
  373. goto CleanUp;
  374. }
  375. //
  376. // ask our helper to create it
  377. //
  378. hr = PutDataInstance(pHandler,
  379. bstrLogOut,
  380. wszCategory,
  381. *pdwValue,
  382. bPostFilter
  383. );
  384. }
  385. else
  386. {
  387. //
  388. // query support, create all instances for audit policy
  389. //
  390. if ( pInfo->AuditSystemEvents != SCE_NO_VALUE )
  391. {
  392. hr = PutDataInstance(pHandler,
  393. bstrLogOut,
  394. pwAuditSystemEvents,
  395. pInfo->AuditSystemEvents,
  396. bPostFilter
  397. );
  398. }
  399. if ( SUCCEEDED(hr) && pInfo->AuditLogonEvents != SCE_NO_VALUE )
  400. {
  401. hr = PutDataInstance(pHandler,
  402. bstrLogOut,
  403. pwAuditLogonEvents,
  404. pInfo->AuditLogonEvents,
  405. bPostFilter
  406. );
  407. }
  408. if ( SUCCEEDED(hr) && pInfo->AuditObjectAccess != SCE_NO_VALUE )
  409. {
  410. hr = PutDataInstance(pHandler,
  411. bstrLogOut,
  412. pwAuditObjectAccess,
  413. pInfo->AuditObjectAccess,
  414. bPostFilter
  415. );
  416. }
  417. if ( SUCCEEDED(hr) && pInfo->AuditPrivilegeUse != SCE_NO_VALUE )
  418. {
  419. hr = PutDataInstance(pHandler,
  420. bstrLogOut,
  421. pwAuditPrivilegeUse,
  422. pInfo->AuditPrivilegeUse,
  423. bPostFilter
  424. );
  425. }
  426. if ( SUCCEEDED(hr) && pInfo->AuditPolicyChange != SCE_NO_VALUE )
  427. {
  428. hr = PutDataInstance(pHandler,
  429. bstrLogOut,
  430. pwAuditPolicyChange,
  431. pInfo->AuditPolicyChange,
  432. bPostFilter
  433. );
  434. }
  435. if ( SUCCEEDED(hr) && pInfo->AuditAccountManage != SCE_NO_VALUE )
  436. {
  437. hr = PutDataInstance(pHandler,
  438. bstrLogOut,
  439. pwAuditAccountManage,
  440. pInfo->AuditAccountManage,
  441. bPostFilter
  442. );
  443. }
  444. if ( SUCCEEDED(hr) && pInfo->AuditProcessTracking != SCE_NO_VALUE )
  445. {
  446. hr = PutDataInstance(pHandler,
  447. bstrLogOut,
  448. pwAuditProcessTracking,
  449. pInfo->AuditProcessTracking,
  450. bPostFilter
  451. );
  452. }
  453. if ( SUCCEEDED(hr) && pInfo->AuditDSAccess != SCE_NO_VALUE )
  454. {
  455. hr = PutDataInstance(pHandler,
  456. bstrLogOut,
  457. pwAuditDSAccess,
  458. pInfo->AuditDSAccess,
  459. bPostFilter
  460. );
  461. }
  462. if ( SUCCEEDED(hr) && pInfo->AuditAccountLogon != SCE_NO_VALUE )
  463. {
  464. hr = PutDataInstance(pHandler,
  465. bstrLogOut,
  466. pwAuditAccountLogon,
  467. pInfo->AuditAccountLogon,
  468. bPostFilter
  469. );
  470. }
  471. }
  472. }
  473. CleanUp:
  474. pSceStore->FreeSecurityProfileInfo(pInfo);
  475. return hr;
  476. }
  477. /*
  478. Routine Description:
  479. Name:
  480. CAuditSettings::PutDataInstance
  481. Functionality:
  482. With all the properties of a Sce_AuditPolicy, this function just creates a new
  483. instance and populate the properties and then hand it back to WMI.
  484. Virtual:
  485. No.
  486. Arguments:
  487. pHandler - COM interface pointer for notifying WMI of any events.
  488. wszStoreName - store path, a key property of Sce_AuditPolicy class.
  489. wszCategory - a corresponding key property of Sce_AuditPolicy class.
  490. dwValue - DWORD that encodes both other boolean members of
  491. Sce_AuditPolicy: "Success" and "Failure".
  492. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  493. Return Value:
  494. Success: it must return success code (use SUCCEEDED to test). It is
  495. not guaranteed to return WBEM_NO_ERROR.
  496. Failure: Various errors may occurs. Any error indicates the failure to create the instance.
  497. Notes:
  498. */
  499. HRESULT
  500. CAuditSettings::PutDataInstance (
  501. IN IWbemObjectSink * pHandler,
  502. IN PWSTR wszStoreName,
  503. IN PCWSTR wszCategory,
  504. IN DWORD dwValue,
  505. IN BOOL bPostFilter
  506. )
  507. {
  508. HRESULT hr=WBEM_S_NO_ERROR;
  509. CScePropertyMgr ScePropMgr;
  510. CComPtr<IWbemClassObject> srpObj;
  511. //
  512. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  513. // a "goto CleanUp;" with hr set to the return value from
  514. // the function (macro parameter)
  515. //
  516. SCE_PROV_IfErrorGotoCleanup(SpawnAnInstance(&srpObj));
  517. ScePropMgr.Attach(srpObj);
  518. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pStorePath, wszStoreName));
  519. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pCategory, wszCategory));
  520. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pSuccess, ( dwValue & SCE_AUDIT_EVENT_SUCCESS ) ? true : false));
  521. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pFailure, (dwValue & SCE_AUDIT_EVENT_FAILURE) ? true: false));
  522. //
  523. // do the necessary gestures to WMI.
  524. // the use of WBEM_STATUS_REQUIREMENTS in SetStatus is not documented by WMI
  525. // at this point. Consult WMI team for detail if you suspect problems with
  526. // the use of WBEM_STATUS_REQUIREMENTS
  527. //
  528. if ( !bPostFilter ) {
  529. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_FALSE, NULL, NULL);
  530. } else {
  531. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_OK, NULL, NULL);
  532. }
  533. //
  534. // pass the new instance to WMI
  535. //
  536. hr = pHandler->Indicate(1, &srpObj);
  537. CleanUp:
  538. return hr;
  539. }
  540. /*
  541. Routine Description:
  542. Name:
  543. CAuditSettings::DeleteInstance
  544. Functionality:
  545. remove an instance of Sce_AuditPolicy from the specified store.
  546. Virtual:
  547. No.
  548. Arguments:
  549. pHandler - COM interface pointer for notifying WMI of any events.
  550. pSceStore - Pointer to our store. It must have been appropriately set up.
  551. wszCategory - a corresponding property of the Sce_AuditPolicy class.
  552. Return Value:
  553. Success: it must return success code (use SUCCEEDED to test). It is
  554. not guaranteed to return WBEM_NO_ERROR.
  555. Failure: Various errors may occurs. Any such error should indicate the operation is not carried out
  556. Notes:
  557. */
  558. HRESULT
  559. CAuditSettings::DeleteInstance (
  560. IN IWbemObjectSink * pHandler,
  561. IN CSceStore * pSceStore,
  562. IN LPCWSTR wszCategory
  563. )
  564. {
  565. //
  566. // make sure that we have a valid store
  567. //
  568. if ( pSceStore == NULL ||
  569. pSceStore->GetStoreType() < SCE_INF_FORMAT ||
  570. pSceStore->GetStoreType() > SCE_JET_ANALYSIS_REQUIRED ) {
  571. return WBEM_E_INVALID_PARAMETER;
  572. }
  573. //
  574. // our store knows how to delete
  575. //
  576. return pSceStore->SavePropertyToStore(szAuditEvent, wszCategory, (LPCWSTR)NULL);
  577. }
  578. /*
  579. Routine Description:
  580. Name:
  581. CAuditSettings::ValidateCategory
  582. Functionality:
  583. Validate the auditing category.
  584. Virtual:
  585. No.
  586. Arguments:
  587. wszCategory - string representing category to be verified.
  588. Return Value:
  589. Success: it must return WBEM_NO_ERROR if the category is recognized.
  590. Failure: Various errors may occurs:
  591. (1) WBEM_E_INVALID_PARAMETER if we successfully carry out the validation task and confirmed
  592. that we don't recognize the Category (wszCategory).
  593. (2) Other errors means that we can't carry out the validation at all. This doesn't mean
  594. that the category is invalid. It's just that the means to verify is not available.
  595. Notes:
  596. */
  597. HRESULT
  598. CAuditSettings::ValidateCategory (
  599. IN LPCWSTR wszCategory,
  600. IN PSCE_PROFILE_INFO pInfo OPTIONAL,
  601. OUT DWORD ** pReturn
  602. )
  603. {
  604. if ( wszCategory == NULL || pReturn == NULL )
  605. {
  606. return WBEM_E_INVALID_PARAMETER;
  607. }
  608. else if ( pInfo == NULL )
  609. {
  610. *pReturn = NULL;
  611. return WBEM_NO_ERROR;
  612. }
  613. HRESULT hr = WBEM_NO_ERROR;
  614. if ( _wcsicmp(wszCategory, pwAuditSystemEvents) == 0 )
  615. {
  616. *pReturn = &(pInfo->AuditSystemEvents);
  617. }
  618. else if ( _wcsicmp(wszCategory, pwAuditLogonEvents) == 0 )
  619. {
  620. *pReturn = &(pInfo->AuditLogonEvents);
  621. }
  622. else if ( _wcsicmp(wszCategory, pwAuditObjectAccess) == 0 )
  623. {
  624. *pReturn = &(pInfo->AuditObjectAccess);
  625. }
  626. else if ( _wcsicmp(wszCategory, pwAuditPrivilegeUse) == 0 )
  627. {
  628. *pReturn = &(pInfo->AuditPrivilegeUse);
  629. }
  630. else if ( _wcsicmp(wszCategory, pwAuditPolicyChange) == 0 )
  631. {
  632. *pReturn = &(pInfo->AuditPolicyChange);
  633. }
  634. else if ( _wcsicmp(wszCategory, pwAuditAccountManage) == 0 )
  635. {
  636. *pReturn = &(pInfo->AuditAccountManage);
  637. }
  638. else if ( _wcsicmp(wszCategory, pwAuditProcessTracking) == 0 )
  639. {
  640. *pReturn = &(pInfo->AuditProcessTracking);
  641. }
  642. else if ( _wcsicmp(wszCategory, pwAuditDSAccess) == 0 )
  643. {
  644. *pReturn = &(pInfo->AuditDSAccess);
  645. }
  646. else if ( _wcsicmp(wszCategory, pwAuditAccountLogon) == 0 )
  647. {
  648. *pReturn = &(pInfo->AuditAccountLogon);
  649. }
  650. else
  651. {
  652. *pReturn = NULL;
  653. hr = WBEM_E_INVALID_PARAMETER;
  654. }
  655. return hr;
  656. }