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.

1408 lines
39 KiB

  1. // object.cpp: implementation of the CObjSecurity class.
  2. //
  3. // Copyright (c)1997-1999 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "object.h"
  8. #include "persistmgr.h"
  9. #include <io.h>
  10. #include "requestobject.h"
  11. /*
  12. Routine Description:
  13. Name:
  14. CObjSecurity::CObjSecurity
  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. type - determines whether it is a Sce_FileObject or Sce_KeyObject.
  25. pCtx - Pointer to WMI context object (COM interface). Passed along
  26. by the caller. It's up to WMI whether this interface pointer is NULL or not.
  27. Return Value:
  28. None as any constructor
  29. Notes:
  30. if you create any local members, think about initialize them here
  31. */
  32. CObjSecurity::CObjSecurity (
  33. IN ISceKeyChain *pKeyChain,
  34. IN IWbemServices *pNamespace,
  35. IN int type,
  36. IN IWbemContext *pCtx
  37. )
  38. :
  39. CGenericClass(pKeyChain, pNamespace, pCtx),
  40. m_Type(type)
  41. {
  42. }
  43. /*
  44. Routine Description:
  45. Name:
  46. CObjSecurity::~CObjSecurity
  47. Functionality:
  48. Destructor. Necessary as good C++ discipline since we have virtual functions.
  49. Virtual:
  50. Yes.
  51. Arguments:
  52. none as any destructor
  53. Return Value:
  54. None as any destructor
  55. Notes:
  56. if you create any local members, think about whether
  57. there is any need for a non-trivial destructor
  58. */
  59. CObjSecurity::~CObjSecurity()
  60. {
  61. }
  62. /*
  63. Routine Description:
  64. Name:
  65. CObjSecurity::CreateObject
  66. Functionality:
  67. Create WMI objects (Sce_FileObject/Sce_KeyObject). Depending on parameter atAction,
  68. this creation may mean:
  69. (a) Get a single instance (atAction == ACTIONTYPE_GET)
  70. (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY)
  71. (c) Delete an instance (atAction == ACTIONTYPE_DELETE)
  72. Virtual:
  73. Yes.
  74. Arguments:
  75. pHandler - COM interface pointer for notifying WMI for creation result.
  76. atAction - Get single instance ACTIONTYPE_GET
  77. Get several instances ACTIONTYPE_QUERY
  78. Delete a single instance ACTIONTYPE_DELETE
  79. Return Value:
  80. Success: it must return success code (use SUCCEEDED to test). It is
  81. not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI,
  82. not directly passed back via parameters.
  83. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate
  84. the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying
  85. situations, this may not be an error depending on caller's intention.
  86. Notes:
  87. */
  88. HRESULT
  89. CObjSecurity::CreateObject (
  90. IN IWbemObjectSink * pHandler,
  91. IN ACTIONTYPE atAction
  92. )
  93. {
  94. //
  95. // we know how to:
  96. // Get single instance ACTIONTYPE_GET
  97. // Delete a single instance ACTIONTYPE_DELETE
  98. // Get several instances ACTIONTYPE_QUERY
  99. //
  100. if ( ACTIONTYPE_GET != atAction &&
  101. ACTIONTYPE_DELETE != atAction &&
  102. ACTIONTYPE_QUERY != atAction )
  103. {
  104. return WBEM_E_NOT_SUPPORTED;
  105. }
  106. HRESULT hr = WBEM_S_NO_ERROR;
  107. //
  108. // We must have the pStorePath property because that is where
  109. // our instance is stored.
  110. // m_srpKeyChain->GetKeyPropertyValue WBEM_S_FALSE if the key is not recognized
  111. // So, we need to test against WBEM_S_FALSE if the property is mandatory
  112. //
  113. CComVariant varStorePath;
  114. hr = m_srpKeyChain->GetKeyPropertyValue(pStorePath, &varStorePath);
  115. CComVariant varPath;
  116. if (SUCCEEDED(hr) && hr != WBEM_S_FALSE)
  117. {
  118. hr = m_srpKeyChain->GetKeyPropertyValue(pPath, &varPath);
  119. if (FAILED(hr))
  120. {
  121. return hr;
  122. }
  123. else if (hr == WBEM_S_FALSE && (ACTIONTYPE_QUERY != atAction) )
  124. {
  125. return WBEM_E_NOT_FOUND;
  126. }
  127. }
  128. else if (hr == WBEM_S_FALSE)
  129. {
  130. return WBEM_E_NOT_FOUND;
  131. }
  132. else
  133. {
  134. return hr;
  135. }
  136. //
  137. // if we have a valid store path
  138. //
  139. if (varStorePath.vt == VT_BSTR)
  140. {
  141. //
  142. // Prepare a store (for persistence) for this store path (file)
  143. //
  144. CSceStore SceStore;
  145. hr = SceStore.SetPersistPath(varStorePath.bstrVal);
  146. if ( SUCCEEDED(hr) ) {
  147. //
  148. // make sure the store (just a file) really exists. The raw path
  149. // may contain env variables, so we need the expanded path
  150. //
  151. DWORD dwAttrib = GetFileAttributes(SceStore.GetExpandedPath());
  152. if ( dwAttrib != -1 )
  153. {
  154. //
  155. // make sure the store type is not mismatching
  156. //
  157. if ( SceStore.GetStoreType() < SCE_INF_FORMAT ||
  158. SceStore.GetStoreType() > SCE_JET_ANALYSIS_REQUIRED )
  159. {
  160. hr = WBEM_E_INVALID_PARAMETER;
  161. }
  162. int objType = m_Type;
  163. if ( SUCCEEDED(hr) )
  164. {
  165. BOOL bPostFilter=TRUE;
  166. DWORD dwCount = 0;
  167. m_srpKeyChain->GetKeyPropertyCount(&dwCount);
  168. if ( varPath.vt == VT_BSTR )
  169. {
  170. //
  171. // get one instance or delete one instance
  172. //
  173. if ( ACTIONTYPE_DELETE == atAction )
  174. {
  175. hr = DeleteInstance(pHandler, &SceStore, objType, varPath.bstrVal);
  176. }
  177. else
  178. {
  179. if (dwCount == 2 )
  180. {
  181. bPostFilter = FALSE;
  182. }
  183. hr = ConstructInstance(pHandler,
  184. &SceStore,
  185. varStorePath.bstrVal,
  186. objType,
  187. (varPath.vt == VT_BSTR) ? varPath.bstrVal : NULL,
  188. bPostFilter);
  189. }
  190. }
  191. else if ( ACTIONTYPE_QUERY == atAction )
  192. {
  193. //
  194. // query support
  195. //
  196. if ( dwCount == 1 )
  197. {
  198. bPostFilter = FALSE;
  199. }
  200. hr = ConstructQueryInstances(pHandler, &SceStore, varStorePath.bstrVal, objType, bPostFilter);
  201. }
  202. else
  203. {
  204. hr = WBEM_E_INVALID_OBJECT_PATH;
  205. }
  206. }
  207. }
  208. else
  209. {
  210. hr = WBEM_E_NOT_FOUND;
  211. }
  212. }
  213. }
  214. return hr;
  215. }
  216. /*
  217. Routine Description:
  218. Name:
  219. CObjSecurity::PutInst
  220. Functionality:
  221. Put an instance as instructed by WMI. Since this class implements Sce_FileObject/Sce_KeyObject,
  222. which is persistence oriented, this will cause the Sce_FileObject/Sce_KeyObject object's property
  223. information to be saved in our store.
  224. Virtual:
  225. Yes.
  226. Arguments:
  227. pInst - COM interface pointer to the WMI class (Sce_FileObject/Sce_KeyObject) object.
  228. pHandler - COM interface pointer for notifying WMI of any events.
  229. pCtx - COM interface pointer. This interface is just something we pass around.
  230. WMI may mandate it (not now) in the future. But we never construct
  231. such an interface and so, we just pass around for various WMI API's
  232. Return Value:
  233. Success: it must return success code (use SUCCEEDED to test). It is
  234. not guaranteed to return WBEM_NO_ERROR.
  235. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  236. the instance.
  237. Notes:
  238. Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  239. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  240. to test for the result of retrieving a property.
  241. */
  242. HRESULT
  243. CObjSecurity::PutInst (
  244. IN IWbemClassObject * pInst,
  245. IN IWbemObjectSink * pHandler,
  246. IN IWbemContext * pCtx
  247. )
  248. {
  249. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  250. CComBSTR bstrObjConvert;
  251. CComBSTR bstrObjPath;
  252. CComBSTR bstrSDDL;
  253. //
  254. // SCE_NO_VALUE means the property is not available
  255. //
  256. DWORD mode = SCE_NO_VALUE;
  257. CSceStore SceStore;
  258. //
  259. // CScePropertyMgr helps us to access WMI object's properties
  260. // create an instance and attach the WMI object to it.
  261. // This will always succeed.
  262. //
  263. CScePropertyMgr ScePropMgr;
  264. ScePropMgr.Attach(pInst);
  265. //
  266. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  267. // a "goto CleanUp;" with hr set to the return value from
  268. // the function (macro parameter)
  269. //
  270. //
  271. // get object path, can't be NULL
  272. //
  273. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pPath, &bstrObjPath));
  274. if ( hr == WBEM_S_RESET_TO_DEFAULT)
  275. {
  276. hr = WBEM_E_ILLEGAL_NULL;
  277. goto CleanUp;
  278. }
  279. SCE_PROV_IfErrorGotoCleanup(MakeSingleBackSlashPath(bstrObjPath, L'\\', &bstrObjConvert));
  280. //
  281. // get mode, default to 0
  282. //
  283. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pMode, &mode));
  284. //
  285. // get SDDLString, can't be NULL
  286. //
  287. if (WBEM_S_RESET_TO_DEFAULT == ScePropMgr.GetProperty(pSDDLString, &bstrSDDL))
  288. {
  289. hr = WBEM_E_ILLEGAL_NULL;
  290. goto CleanUp;
  291. }
  292. //
  293. // Attach the WMI object instance to the store and let the store know that
  294. // it's store is given by the pStorePath property of the instance.
  295. //
  296. SceStore.SetPersistProperties(pInst, pStorePath);
  297. //
  298. // now save the info to file
  299. //
  300. hr = SaveSettingsToStore(&SceStore,
  301. m_Type,
  302. bstrObjConvert,
  303. mode,
  304. bstrSDDL
  305. );
  306. CleanUp:
  307. return hr;
  308. }
  309. /*
  310. Routine Description:
  311. Name:
  312. CObjSecurity::ConstructInstance
  313. Functionality:
  314. This is private function to create an instance of Sce_FileObject/Sce_KeyObject.
  315. Virtual:
  316. No.
  317. Arguments:
  318. pHandler - COM interface pointer for notifying WMI of any events.
  319. pSceStore - Pointer to our store. It must have been appropriately set up.
  320. wszLogStorePath - store path, a key property of Sce_FileObject/Sce_KeyObject class.
  321. ObjType - a corresponding key property of Sce_FileObject/Sce_KeyObject class.
  322. wszObjName - object name.
  323. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  324. Return Value:
  325. Success: it must return success code (use SUCCEEDED to test). It is
  326. not guaranteed to return WBEM_NO_ERROR.
  327. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  328. Notes:
  329. */
  330. HRESULT CObjSecurity::ConstructInstance (
  331. IN IWbemObjectSink * pHandler,
  332. IN CSceStore * pSceStore,
  333. IN LPCWSTR wszLogStorePath,
  334. IN int ObjType,
  335. IN LPCWSTR wszObjName OPTIONAL,
  336. IN BOOL bPostFilter
  337. )
  338. {
  339. //
  340. // parameters are checked before it's called
  341. //
  342. HRESULT hr=WBEM_S_NO_ERROR;
  343. //
  344. // ask SCE to read a gigantic structure out from the store. Only SCE
  345. // knows now to release the memory. Don't just delete it! Use our CSceStore
  346. // to do the releasing (FreeSecurityProfileInfo)
  347. //
  348. //
  349. // for INT format store
  350. //
  351. PSCE_PROFILE_INFO pInfo = NULL;
  352. //
  353. // for database format store
  354. //
  355. PSCE_OBJECT_SECURITY pObjSecurity = NULL;
  356. AREA_INFORMATION Area;
  357. if ( ObjType == SCE_OBJECT_TYPE_FILE ) {
  358. Area = AREA_FILE_SECURITY;
  359. } else {
  360. Area = AREA_REGISTRY_SECURITY;
  361. }
  362. //
  363. // for INF format store
  364. //
  365. if ( pSceStore->GetStoreType() == SCE_INF_FORMAT )
  366. {
  367. hr = pSceStore->GetSecurityProfileInfo(
  368. Area,
  369. &pInfo,
  370. NULL
  371. );
  372. }
  373. else
  374. {
  375. //
  376. // for database format store
  377. //
  378. hr = pSceStore->GetObjectSecurity (
  379. Area,
  380. wszObjName,
  381. &pObjSecurity
  382. );
  383. }
  384. if ( pSceStore->GetStoreType() == SCE_INF_FORMAT )
  385. {
  386. if ( pInfo == NULL )
  387. {
  388. hr = WBEM_E_NOT_FOUND;
  389. }
  390. if ( SUCCEEDED(hr) )
  391. {
  392. //
  393. // for INF format, we have to search for the object name in the returned array
  394. //
  395. PSCE_OBJECT_ARRAY pObjArr = (ObjType == SCE_OBJECT_TYPE_FILE) ? pInfo->pFiles.pAllNodes : pInfo->pRegistryKeys.pAllNodes;
  396. if ( pObjArr && pObjArr->pObjectArray )
  397. {
  398. for ( DWORD i=0; i<pObjArr->Count; i++)
  399. {
  400. if ( (pObjArr->pObjectArray)[i]->Name == NULL )
  401. {
  402. continue;
  403. }
  404. if ( _wcsicmp((pObjArr->pObjectArray)[i]->Name, wszObjName)== 0 )
  405. {
  406. break;
  407. }
  408. }
  409. //
  410. // find it
  411. //
  412. if ( i < pObjArr->Count )
  413. {
  414. pObjSecurity = (pObjArr->pObjectArray)[i];
  415. }
  416. }
  417. }
  418. }
  419. //
  420. // if the object's security information buffer is empty, treat it as "not found"
  421. //
  422. if ( pObjSecurity == NULL )
  423. {
  424. hr = WBEM_E_NOT_FOUND;
  425. }
  426. CComBSTR bstrLogOut;
  427. if ( SUCCEEDED(hr) )
  428. {
  429. hr = MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut);
  430. if (SUCCEEDED(hr))
  431. {
  432. hr = PutDataInstance(pHandler,
  433. bstrLogOut,
  434. ObjType,
  435. wszObjName,
  436. (int)(pObjSecurity->Status),
  437. pObjSecurity->pSecurityDescriptor,
  438. pObjSecurity->SeInfo,
  439. bPostFilter);
  440. }
  441. }
  442. pSceStore->FreeSecurityProfileInfo(pInfo);
  443. if ( pSceStore->GetStoreType() != SCE_INF_FORMAT && pObjSecurity )
  444. {
  445. pSceStore->FreeObjectSecurity(pObjSecurity);
  446. }
  447. return hr;
  448. }
  449. /*
  450. Routine Description:
  451. Name:
  452. CObjSecurity::ConstructQueryInstances
  453. Functionality:
  454. Querying instances of Sce_FileObject/Sce_KeyObject whose key properties meet the specified parameters.
  455. Virtual:
  456. No.
  457. Arguments:
  458. pHandler - COM interface pointer used to notify WMI when instances are created.
  459. pSceStore - Pointer to our store. It must have been appropriately set up.
  460. wszLogStorePath - Log's store path.
  461. ObjType - may be NULL.
  462. bPostFilter - controls how pHandler->SetStatus is called.
  463. Return Value:
  464. Success: it must return success code (use SUCCEEDED to test). It is
  465. not guaranteed to return WBEM_NO_ERROR.
  466. Failure: Various errors may occurs. Any such error should indicate the operation is not carried out
  467. Notes:
  468. */
  469. HRESULT
  470. CObjSecurity::ConstructQueryInstances (
  471. IN IWbemObjectSink * pHandler,
  472. IN CSceStore * pSceStore,
  473. IN LPCWSTR wszLogStorePath,
  474. IN int ObjType,
  475. IN BOOL bPostFilter
  476. )
  477. {
  478. //
  479. // parameters are checked before it's called
  480. //
  481. HRESULT hr = WBEM_S_NO_ERROR;
  482. CComBSTR bstrLogOut;
  483. hr = MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut);
  484. if (FAILED(hr))
  485. {
  486. return hr;
  487. }
  488. //
  489. // query object information from the profile
  490. //
  491. if ( pSceStore->GetStoreType() == SCE_INF_FORMAT )
  492. {
  493. //
  494. // ask SCE to read a gigantic structure out from the store. Only SCE
  495. // knows now to release the memory. Don't just delete it! Use our CSceStore
  496. // to do the releasing (FreeSecurityProfileInfo)
  497. //
  498. PSCE_PROFILE_INFO pInfo = NULL;
  499. hr = pSceStore->GetSecurityProfileInfo(
  500. (ObjType == SCE_OBJECT_TYPE_FILE) ? AREA_FILE_SECURITY : AREA_REGISTRY_SECURITY,
  501. &pInfo,
  502. NULL
  503. );
  504. if ( SUCCEEDED(hr) )
  505. {
  506. //
  507. // for INF format, we have to search for the object name in the returned array
  508. //
  509. PSCE_OBJECT_ARRAY pObjArr = (ObjType == SCE_OBJECT_TYPE_FILE) ? pInfo->pFiles.pAllNodes : pInfo->pRegistryKeys.pAllNodes;
  510. if ( pObjArr && pObjArr->pObjectArray )
  511. {
  512. for ( DWORD i=0; SUCCEEDED(hr) && i < pObjArr->Count; i++)
  513. {
  514. if ( (pObjArr->pObjectArray)[i]->Name == NULL )
  515. {
  516. continue;
  517. }
  518. //
  519. // create instance of this one
  520. //
  521. hr = PutDataInstance(pHandler,
  522. bstrLogOut,
  523. ObjType,
  524. (pObjArr->pObjectArray)[i]->Name,
  525. (int)((pObjArr->pObjectArray)[i]->Status),
  526. (pObjArr->pObjectArray)[i]->pSecurityDescriptor,
  527. (pObjArr->pObjectArray)[i]->SeInfo,
  528. bPostFilter
  529. );
  530. }
  531. }
  532. }
  533. pSceStore->FreeSecurityProfileInfo(pInfo);
  534. }
  535. else
  536. {
  537. //
  538. // the original design of the sce algorithms prevents a clean redesign of this access
  539. // because it relies on a continuing enumeration of the open profile file
  540. //
  541. PVOID hProfile=NULL;
  542. PSCESVC_CONFIGURATION_INFO pObjInfo=NULL;
  543. SCESTATUS rc = SceOpenProfile(pSceStore->GetExpandedPath(), (SCE_FORMAT_TYPE)pSceStore->GetStoreType(), &hProfile);
  544. if ( rc != SCESTATUS_SUCCESS )
  545. {
  546. //
  547. // SCE returned errors needs to be translated to HRESULT.
  548. //
  549. return ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  550. }
  551. SCEP_HANDLE scepHandle;
  552. scepHandle.hProfile = hProfile;
  553. scepHandle.SectionName = (ObjType == SCE_OBJECT_TYPE_FILE ) ? (PWSTR)szFileSecurity : (PWSTR)szRegistryKeys;
  554. SCE_ENUMERATION_CONTEXT EnumHandle=0;
  555. DWORD CountReturned;
  556. do {
  557. //
  558. // enumerate the info
  559. //
  560. CountReturned = 0;
  561. rc = SceSvcQueryInfo((SCE_HANDLE)&scepHandle,
  562. SceSvcConfigurationInfo,
  563. NULL,
  564. FALSE,
  565. (PVOID *)&pObjInfo,
  566. &EnumHandle
  567. );
  568. //
  569. // SCE returned errors needs to be translated to HRESULT.
  570. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  571. //
  572. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  573. if ( SUCCEEDED(hr) && pObjInfo && pObjInfo->Count > 0 && pObjInfo->Lines )
  574. {
  575. //
  576. // got something
  577. //
  578. CountReturned = pObjInfo->Count;
  579. int mode;
  580. for ( DWORD i=0; SUCCEEDED(hr) && i<pObjInfo->Count; i++ )
  581. {
  582. //
  583. // create instance for each one
  584. //
  585. if ( SUCCEEDED(hr) )
  586. {
  587. //
  588. // prefast will complain about the following line of code
  589. // first wchar of Value is mode?
  590. //
  591. mode = *((BYTE *)(pObjInfo->Lines[i].Value));
  592. hr = PutDataInstance(pHandler,
  593. bstrLogOut,
  594. ObjType,
  595. pObjInfo->Lines[i].Key,
  596. mode,
  597. pObjInfo->Lines[i].Value + 1,
  598. bPostFilter
  599. );
  600. }
  601. }
  602. }
  603. if ( pObjInfo )
  604. {
  605. SceSvcFree(pObjInfo);
  606. pObjInfo = NULL;
  607. }
  608. } while ( SUCCEEDED(hr) && CountReturned >= SCESVC_ENUMERATION_MAX );
  609. SceCloseProfile( &hProfile );
  610. }
  611. return hr;
  612. }
  613. /*
  614. Routine Description:
  615. Name:
  616. CObjSecurity::PutDataInstance
  617. Functionality:
  618. With all the properties of a Sce_FileObject/Sce_KeyObject, this function just creates a new
  619. instance and populate the properties and then hand it back to WMI.
  620. Virtual:
  621. No.
  622. Arguments:
  623. pHandler - COM interface pointer for notifying WMI of any events.
  624. wszStoreName - store path, a key property of Sce_FileObject/Sce_KeyObject class.
  625. ObjType - Sce_FileObject/Sce_KeyObject
  626. wszObjName - the name
  627. mode - a property of the Sce_FileObject/Sce_KeyObject class
  628. pSD - Security Descriptor
  629. SeInfo - SECURITY_INFORMATION
  630. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  631. Return Value:
  632. Success: it must return success code (use SUCCEEDED to test). It is
  633. not guaranteed to return WBEM_NO_ERROR.
  634. Failure: Various errors may occurs. Any error indicates the failure to create the instance.
  635. Notes:
  636. */
  637. HRESULT CObjSecurity::PutDataInstance (
  638. IN IWbemObjectSink * pHandler,
  639. IN LPCWSTR wszStoreName,
  640. IN int ObjType,
  641. IN LPCWSTR wszObjName,
  642. IN int mode,
  643. IN PSECURITY_DESCRIPTOR pSD,
  644. IN SECURITY_INFORMATION SeInfo,
  645. IN BOOL bPostFilter
  646. )
  647. {
  648. PWSTR strSD=NULL;
  649. HRESULT hr=WBEM_S_NO_ERROR;
  650. if ( pSD )
  651. {
  652. //
  653. // convert security descriptor to string
  654. //
  655. DWORD dSize=0;
  656. SCESTATUS rc = SceSvcConvertSDToText(
  657. pSD,
  658. SeInfo,
  659. &strSD,
  660. &dSize
  661. );
  662. if ( rc != SCESTATUS_SUCCESS )
  663. {
  664. //
  665. // SCE returned errors needs to be translated to HRESULT.
  666. //
  667. return ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  668. }
  669. }
  670. hr = PutDataInstance(pHandler, wszStoreName, ObjType, wszObjName, mode, strSD, bPostFilter);
  671. if ( strSD )
  672. {
  673. LocalFree(strSD);
  674. }
  675. return hr;
  676. }
  677. /*
  678. Routine Description:
  679. Name:
  680. CObjSecurity::PutDataInstance
  681. Functionality:
  682. With all the properties of a Sce_FileObject/Sce_KeyObject, this function just creates a new
  683. instance and populate the properties and then hand it back to WMI.
  684. Virtual:
  685. No.
  686. Arguments:
  687. pHandler - COM interface pointer for notifying WMI of any events.
  688. wszStoreName - store path, a key property of Sce_AuditPolicy class.
  689. ObjType - Sce_FileObject/Sce_KeyObject
  690. wszObjName - the name
  691. mode - a property of the Sce_FileObject/Sce_KeyObject class
  692. strSD - string format of a Security Descriptor
  693. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  694. Return Value:
  695. Success: it must return success code (use SUCCEEDED to test). It is
  696. not guaranteed to return WBEM_NO_ERROR.
  697. Failure: Various errors may occurs. Any error indicates the failure to create the instance.
  698. Notes:
  699. */
  700. HRESULT CObjSecurity::PutDataInstance (
  701. IN IWbemObjectSink * pHandler,
  702. IN LPCWSTR wszStoreName,
  703. IN int ObjType,
  704. IN LPCWSTR wszObjName,
  705. IN int mode,
  706. IN LPCWSTR strSD,
  707. IN BOOL bPostFilter
  708. )
  709. {
  710. //
  711. // create a blank object to fill in the properties
  712. //
  713. CComPtr<IWbemClassObject> srpObj;
  714. HRESULT hr = SpawnAnInstance(&srpObj);
  715. if (SUCCEEDED(hr))
  716. {
  717. //
  718. // CScePropertyMgr helps us to access WMI object's properties
  719. // create an instance and attach the WMI object to it.
  720. // This will always succeed.
  721. //
  722. CScePropertyMgr ScePropMgr;
  723. ScePropMgr.Attach(srpObj);
  724. //
  725. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  726. // a "goto CleanUp;" with hr set to the return value from
  727. // the function (macro parameter)
  728. //
  729. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pStorePath, wszStoreName));
  730. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pPath, wszObjName));
  731. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pMode, (DWORD)mode));
  732. if ( strSD )
  733. {
  734. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pSDDLString, strSD));
  735. }
  736. //
  737. // do the necessary gestures to WMI.
  738. // the use of WBEM_STATUS_REQUIREMENTS in SetStatus is not documented by WMI
  739. // at this point. Consult WMI team for detail if you suspect problems with
  740. // the use of WBEM_STATUS_REQUIREMENTS
  741. //
  742. if ( !bPostFilter ) {
  743. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_FALSE, NULL, NULL);
  744. } else {
  745. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_OK, NULL, NULL);
  746. }
  747. //
  748. // pass the new instance to WMI
  749. //
  750. hr = pHandler->Indicate(1, &srpObj);
  751. }
  752. CleanUp:
  753. return hr;
  754. }
  755. /*
  756. Routine Description:
  757. Name:
  758. CObjSecurity::DeleteInstance
  759. Functionality:
  760. remove an instance of Sce_FileObject/Sce_KeyObject from the specified store.
  761. Virtual:
  762. No.
  763. Arguments:
  764. pHandler - COM interface pointer for notifying WMI of any events.
  765. pSceStore - Pointer to our store. It must have been appropriately set up.
  766. ObjType - Sce_FileObject or Sce_KeyObject
  767. wszObjName - a corresponding property of the Sce_FileObject/Sce_KeyObject class.
  768. Return Value:
  769. whatever SaveSettingsToStore function returns.
  770. Notes:
  771. */
  772. HRESULT
  773. CObjSecurity::DeleteInstance (
  774. IN IWbemObjectSink * pHandler,
  775. IN CSceStore * pSceStore,
  776. IN int ObjType,
  777. IN LPCWSTR wszObjName
  778. )
  779. {
  780. return SaveSettingsToStore(pSceStore, ObjType, wszObjName, SCE_NO_VALUE, NULL);
  781. }
  782. /*
  783. Routine Description:
  784. Name:
  785. CObjSecurity::DeleteInstance
  786. Functionality:
  787. remove an instance of Sce_FileObject/Sce_KeyObject from the specified store.
  788. Virtual:
  789. No.
  790. Arguments:
  791. pHandler - COM interface pointer for notifying WMI of any events.
  792. pSceStore - Pointer to our store. It must have been appropriately set up.
  793. ObjType - Sce_FileObject or Sce_KeyObject
  794. wszObjName - a corresponding property of the Sce_FileObject/Sce_KeyObject class.
  795. Return Value:
  796. whatever SaveSettingsToStore function returns.
  797. Notes:
  798. */
  799. HRESULT CObjSecurity::SaveSettingsToStore (
  800. IN CSceStore * pSceStore,
  801. IN int ObjType,
  802. IN PCWSTR wszObjName,
  803. IN DWORD mode,
  804. IN PCWSTR wszSDDL
  805. )
  806. {
  807. HRESULT hr = WBEM_S_NO_ERROR;
  808. DWORD dwDump;
  809. //
  810. // For a new .inf file. Write an empty buffer to the file
  811. // will creates the file with right header/signature/unicode format
  812. // this is harmless for existing files.
  813. // For database store, this is a no-op.
  814. //
  815. hr = pSceStore->WriteSecurityProfileInfo(
  816. AreaBogus,
  817. (PSCE_PROFILE_INFO)&dwDump,
  818. NULL,
  819. false
  820. );
  821. if (SUCCEEDED(hr))
  822. {
  823. AREA_INFORMATION Area;
  824. //
  825. // ask SCE to read a gigantic structure out from the store. Only SCE
  826. // knows now to release the memory. Don't just delete it! Use our CSceStore
  827. // to do the releasing (FreeSecurityProfileInfo)
  828. //
  829. PSCE_PROFILE_INFO pInfo=NULL;
  830. if ( ObjType == SCE_OBJECT_TYPE_FILE ) {
  831. Area = AREA_FILE_SECURITY;
  832. } else {
  833. Area = AREA_REGISTRY_SECURITY;
  834. }
  835. //
  836. // query object information from the profile
  837. //
  838. hr = pSceStore->GetSecurityProfileInfo(
  839. Area,
  840. &pInfo,
  841. NULL
  842. );
  843. if ( SUCCEEDED(hr) ) {
  844. //
  845. // for INF format, we have to search for the object name in the returned array
  846. //
  847. SCE_OBJECTS pObjects= (ObjType == SCE_OBJECT_TYPE_FILE) ? pInfo->pFiles : pInfo->pRegistryKeys;
  848. PSCE_OBJECT_ARRAY pObjArr = pObjects.pAllNodes;
  849. DWORD i=0;
  850. if ( pObjArr && pObjArr->pObjectArray )
  851. {
  852. for ( i=0; i<pObjArr->Count; i++)
  853. {
  854. if ( (pObjArr->pObjectArray[i])->Name == NULL )
  855. {
  856. continue;
  857. }
  858. if ( _wcsicmp((pObjArr->pObjectArray[i])->Name, wszObjName) == 0 )
  859. {
  860. break;
  861. }
  862. }
  863. }
  864. if ( pObjArr && pObjArr->pObjectArray && i<pObjArr->Count )
  865. {
  866. //
  867. // find it
  868. //
  869. if ( mode == SCE_NO_VALUE || wszSDDL == NULL )
  870. {
  871. //
  872. // delete it
  873. // free buffer first
  874. //
  875. if ( (pObjArr->pObjectArray[i])->pSecurityDescriptor )
  876. {
  877. LocalFree((pObjArr->pObjectArray[i])->pSecurityDescriptor);
  878. }
  879. LocalFree((pObjArr->pObjectArray[i])->Name);
  880. //
  881. // shift everything else up
  882. //
  883. for (DWORD j=i; j<pObjArr->Count-1; j++)
  884. {
  885. (pObjArr->pObjectArray[j])->Name = pObjArr->pObjectArray[j+1]->Name;
  886. (pObjArr->pObjectArray[j])->Status = pObjArr->pObjectArray[j+1]->Status;
  887. (pObjArr->pObjectArray[j])->IsContainer = pObjArr->pObjectArray[j+1]->IsContainer;
  888. (pObjArr->pObjectArray[j])->pSecurityDescriptor = pObjArr->pObjectArray[j+1]->pSecurityDescriptor;
  889. (pObjArr->pObjectArray[j])->SeInfo = pObjArr->pObjectArray[j+1]->SeInfo;
  890. }
  891. //
  892. // empty the last one
  893. //
  894. (pObjArr->pObjectArray[j])->Name = NULL;
  895. (pObjArr->pObjectArray[j])->Status = 0;
  896. (pObjArr->pObjectArray[j])->IsContainer = 0;
  897. (pObjArr->pObjectArray[j])->pSecurityDescriptor = NULL;
  898. (pObjArr->pObjectArray[j])->SeInfo = 0;
  899. //
  900. // decrement the count
  901. //
  902. pObjArr->Count--;
  903. }
  904. else
  905. {
  906. //
  907. // modify it
  908. //
  909. (pObjArr->pObjectArray[i])->Status = (BYTE)mode;
  910. SECURITY_INFORMATION SeInfo=0;
  911. PSECURITY_DESCRIPTOR pSD=NULL;
  912. DWORD dSize=0;
  913. SCESTATUS rc = SceSvcConvertTextToSD ((PWSTR)wszSDDL, &pSD, &dSize, &SeInfo);
  914. if ( rc == SCESTATUS_SUCCESS && pSD )
  915. {
  916. if ( (pObjArr->pObjectArray[i])->pSecurityDescriptor )
  917. {
  918. LocalFree((pObjArr->pObjectArray[i])->pSecurityDescriptor);
  919. }
  920. (pObjArr->pObjectArray[i])->pSecurityDescriptor = pSD;
  921. pSD = NULL;
  922. (pObjArr->pObjectArray[i])->SeInfo = SeInfo;
  923. }
  924. else
  925. {
  926. //
  927. // SCE returned errors needs to be translated to HRESULT.
  928. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  929. //
  930. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  931. }
  932. }
  933. if ( SUCCEEDED(hr) )
  934. {
  935. hr = pSceStore->WriteSecurityProfileInfo(
  936. Area,
  937. pInfo,
  938. NULL,
  939. false
  940. );
  941. }
  942. }
  943. else
  944. {
  945. //
  946. // not found
  947. //
  948. if ( mode == SCE_NO_VALUE || wszSDDL == NULL )
  949. {
  950. //
  951. // try to delete non exist object
  952. //
  953. hr = WBEM_E_NOT_FOUND;
  954. }
  955. else
  956. {
  957. //
  958. // add this one in
  959. // pInfo->pFiles or pRegistryKeys is already saved in pObjects
  960. //
  961. SCE_OBJECT_SECURITY ObjSec;
  962. PSCE_OBJECT_SECURITY pObjSec = &ObjSec;
  963. SCE_OBJECT_ARRAY ObjArray;
  964. ObjArray.Count = 1;
  965. ObjArray.pObjectArray = &pObjSec;
  966. pObjArr = &ObjArray;
  967. SECURITY_INFORMATION SeInfo=0;
  968. PSECURITY_DESCRIPTOR pSD=NULL;
  969. DWORD dSize=0;
  970. SCESTATUS rc = SceSvcConvertTextToSD((PWSTR)wszSDDL, &pSD, &dSize, &SeInfo);
  971. if ( rc == SCESTATUS_SUCCESS && pSD )
  972. {
  973. ObjSec.Name = (PWSTR)wszObjName;
  974. ObjSec.Status = (BYTE)mode;
  975. ObjSec.IsContainer = 0;
  976. ObjSec.pSecurityDescriptor = pSD;
  977. ObjSec.SeInfo = SeInfo;
  978. //
  979. // set the temp buffer pointer to pInfo to set to the store
  980. //
  981. SCE_OBJECTS sceObj;
  982. sceObj.pAllNodes = pObjArr;
  983. if ( ObjType == SCE_OBJECT_TYPE_FILE )
  984. {
  985. pInfo->pFiles = sceObj;
  986. }
  987. else pInfo->pRegistryKeys = sceObj;
  988. //
  989. // append this item to the section
  990. //
  991. hr = pSceStore->WriteSecurityProfileInfo (
  992. Area,
  993. pInfo,
  994. NULL,
  995. true
  996. );
  997. //
  998. // reset the buffer pointer
  999. //
  1000. if ( ObjType == SCE_OBJECT_TYPE_FILE )
  1001. {
  1002. pInfo->pFiles = pObjects;
  1003. }
  1004. else
  1005. {
  1006. pInfo->pRegistryKeys = pObjects;
  1007. }
  1008. }
  1009. else
  1010. {
  1011. //
  1012. // SCE returned errors needs to be translated to HRESULT.
  1013. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  1014. //
  1015. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  1016. }
  1017. if ( pSD )
  1018. {
  1019. LocalFree(pSD);
  1020. }
  1021. }
  1022. }
  1023. }
  1024. pSceStore->FreeSecurityProfileInfo(pInfo);
  1025. }
  1026. return hr;
  1027. }