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.

995 lines
24 KiB

  1. // Rights.cpp: implementation of the CUserPrivilegeRights class.
  2. //
  3. // Copyright (c)1997-1999 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "rights.h"
  8. #include "persistmgr.h"
  9. #include <io.h>
  10. #include "requestobject.h"
  11. /*
  12. Routine Description:
  13. Name:
  14. CUserPrivilegeRights::CUserPrivilegeRights
  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. CUserPrivilegeRights::CUserPrivilegeRights (
  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. CUserPrivilegeRights::~CUserPrivilegeRights
  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. CUserPrivilegeRights::~CUserPrivilegeRights ()
  57. {
  58. }
  59. /*
  60. Routine Description:
  61. Name:
  62. CUserPrivilegeRights::CreateObject
  63. Functionality:
  64. Create WMI objects (Sce_UserPrivilegeRight). 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. CUserPrivilegeRights::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. {
  101. return WBEM_E_NOT_SUPPORTED;
  102. }
  103. int idxStorePath=-1, idxRight=-1;
  104. //
  105. // We must have the pStorePath property because that is where
  106. // our instance is stored.
  107. // m_srpKeyChain->GetKeyPropertyValue WBEM_S_FALSE if the key is not recognized
  108. // So, we need to test against WBEM_S_FALSE if the property is mandatory
  109. //
  110. CComVariant varStorePath;
  111. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(pStorePath, &varStorePath);
  112. CComVariant varUserRight;
  113. if (SUCCEEDED(hr) && WBEM_S_FALSE != hr)
  114. {
  115. hr = m_srpKeyChain->GetKeyPropertyValue(pUserRight, &varUserRight);
  116. if (FAILED(hr))
  117. {
  118. return hr;
  119. }
  120. else if (hr == WBEM_S_FALSE && (ACTIONTYPE_QUERY != atAction) )
  121. {
  122. return WBEM_E_NOT_FOUND;
  123. }
  124. }
  125. if (SUCCEEDED(hr))
  126. {
  127. //
  128. // Prepare a store (for persistence) for this store path (file)
  129. //
  130. CSceStore SceStore;
  131. hr = SceStore.SetPersistPath(varStorePath.bstrVal);
  132. if ( SUCCEEDED(hr) ) {
  133. //
  134. // make sure the store (just a file) really exists. The raw path
  135. // may contain env variables, so we need the expanded path
  136. //
  137. DWORD dwAttrib = GetFileAttributes(SceStore.GetExpandedPath());
  138. if ( dwAttrib != -1 )
  139. {
  140. //
  141. // make sure our store is valid
  142. //
  143. if ( SceStore.GetStoreType() < SCE_INF_FORMAT ||
  144. SceStore.GetStoreType() > SCE_JET_ANALYSIS_REQUIRED )
  145. {
  146. hr = WBEM_E_INVALID_PARAMETER;
  147. }
  148. if ( SUCCEEDED(hr) )
  149. {
  150. if ( ACTIONTYPE_DELETE == atAction )
  151. {
  152. hr = DeleteInstance(pHandler, &SceStore, varUserRight.bstrVal);
  153. }
  154. else
  155. {
  156. //
  157. // get the key property count to determin how we should be construct the instance(s)
  158. //
  159. BOOL bPostFilter=TRUE;
  160. DWORD dwCount = 0;
  161. m_srpKeyChain->GetKeyPropertyCount(&dwCount);
  162. if ( varUserRight.vt == VT_EMPTY && dwCount == 1 )
  163. {
  164. //
  165. // something else is specified in the path
  166. // have filter on
  167. //
  168. bPostFilter = FALSE;
  169. }
  170. hr = ConstructInstance(
  171. pHandler,
  172. &SceStore,
  173. varStorePath.bstrVal,
  174. (varUserRight.vt == VT_BSTR) ? varUserRight.bstrVal : NULL,
  175. bPostFilter
  176. );
  177. }
  178. }
  179. }
  180. else
  181. {
  182. hr = WBEM_E_NOT_FOUND;
  183. }
  184. }
  185. }
  186. return hr;
  187. }
  188. /*
  189. Routine Description:
  190. Name:
  191. CUserPrivilegeRights::PutInst
  192. Functionality:
  193. Put an instance as instructed by WMI. Since this class implements Sce_UserPrivilegeRight,
  194. which is persistence oriented, this will cause the Sce_UserPrivilegeRight object's property
  195. information to be saved in our store.
  196. Virtual:
  197. Yes.
  198. Arguments:
  199. pInst - COM interface pointer to the WMI class (Sce_UserPrivilegeRight) object.
  200. pHandler - COM interface pointer for notifying WMI of any events.
  201. pCtx - COM interface pointer. This interface is just something we pass around.
  202. WMI may mandate it (not now) in the future. But we never construct
  203. such an interface and so, we just pass around for various WMI API's
  204. Return Value:
  205. Success: it must return success code (use SUCCEEDED to test). It is
  206. not guaranteed to return WBEM_NO_ERROR.
  207. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  208. the instance.
  209. Notes:
  210. Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  211. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  212. to test for the result of retrieving a property.
  213. */
  214. HRESULT
  215. CUserPrivilegeRights::PutInst (
  216. IN IWbemClassObject * pInst,
  217. IN IWbemObjectSink * pHandler,
  218. IN IWbemContext * pCtx
  219. )
  220. {
  221. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  222. CComBSTR bstrRight = NULL;
  223. PSCE_NAME_LIST pnlAdd = NULL;
  224. DWORD mode;
  225. CSceStore SceStore;
  226. //
  227. // CScePropertyMgr helps us to access WMI object's properties
  228. // create an instance and attach the WMI object to it.
  229. // This will always succeed.
  230. //
  231. CScePropertyMgr ScePropMgr;
  232. ScePropMgr.Attach(pInst);
  233. //
  234. // get user right name, can't be NULL
  235. // user right name should be validated
  236. //
  237. //
  238. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  239. // a "goto CleanUp;" with hr set to the return value from
  240. // the function (macro parameter)
  241. //
  242. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pUserRight, &bstrRight));
  243. if ( hr == WBEM_S_RESET_TO_DEFAULT)
  244. {
  245. hr = WBEM_E_ILLEGAL_NULL;
  246. goto CleanUp;
  247. }
  248. //
  249. // validate the privilege right
  250. //
  251. SCE_PROV_IfErrorGotoCleanup(ValidatePrivilegeRight(bstrRight));
  252. //
  253. // get mode
  254. //
  255. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pMode, &mode));
  256. if ( hr == WBEM_S_RESET_TO_DEFAULT)
  257. {
  258. hr = WBEM_E_ILLEGAL_NULL;
  259. goto CleanUp;
  260. }
  261. //
  262. // get AddList
  263. //
  264. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pAddList, &pnlAdd));
  265. //
  266. // ignore RemoveList for now (since we don't support the mode)
  267. //
  268. //
  269. // Attach the WMI object instance to the store and let the store know that
  270. // it's store is given by the pStorePath property of the instance.
  271. //
  272. SceStore.SetPersistProperties(pInst, pStorePath);
  273. //
  274. // now save the info to file
  275. //
  276. hr = SaveSettingsToStore(&SceStore,
  277. bstrRight,
  278. mode,
  279. pnlAdd,
  280. NULL
  281. );
  282. CleanUp:
  283. if ( pnlAdd )
  284. {
  285. SceFreeMemory(pnlAdd, SCE_STRUCT_NAME_LIST);
  286. }
  287. return hr;
  288. }
  289. /*
  290. Routine Description:
  291. Name:
  292. CUserPrivilegeRights::ConstructInstance
  293. Functionality:
  294. This is private function to create an instance of Sce_UserPrivilegeRight.
  295. Virtual:
  296. No.
  297. Arguments:
  298. pHandler - COM interface pointer for notifying WMI of any events.
  299. pSceStore - Pointer to our store. It must have been appropriately set up.
  300. wszLogStorePath - store path, a key property of Sce_UserPrivilegeRight class.
  301. wszRightName - a corresponding key property of Sce_UserPrivilegeRight class.
  302. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  303. Return Value:
  304. Success: it must return success code (use SUCCEEDED to test). It is
  305. not guaranteed to return WBEM_NO_ERROR.
  306. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  307. Notes:
  308. */
  309. HRESULT
  310. CUserPrivilegeRights::ConstructInstance (
  311. IN IWbemObjectSink * pHandler,
  312. IN CSceStore * pSceStore,
  313. IN LPCWSTR wszLogStorePath,
  314. IN LPCWSTR wszRightName OPTIONAL,
  315. IN BOOL bPostFilter
  316. )
  317. {
  318. //
  319. // ask SCE to read a gigantic structure out from the store. Only SCE
  320. // knows now to release the memory. Don't just delete it! Use our CSceStore
  321. // to do the releasing (FreeSecurityProfileInfo)
  322. //
  323. PSCE_PROFILE_INFO pInfo=NULL;
  324. HRESULT hr = pSceStore->GetSecurityProfileInfo(
  325. AREA_PRIVILEGES,
  326. &pInfo,
  327. NULL
  328. );
  329. //
  330. // nothing is read from the store
  331. //
  332. if ( pInfo == NULL )
  333. {
  334. if ( wszRightName )
  335. {
  336. hr = WBEM_E_NOT_FOUND;
  337. }
  338. else
  339. {
  340. hr = WBEM_S_NO_ERROR;
  341. }
  342. return hr;
  343. }
  344. //
  345. // we have to search for the user right name in the returned list
  346. //
  347. PSCE_PRIVILEGE_ASSIGNMENT pPrivileges = pInfo->OtherInfo.smp.pPrivilegeAssignedTo;
  348. if ( wszRightName )
  349. {
  350. while ( pPrivileges )
  351. {
  352. if ( pPrivileges->Name == NULL )
  353. {
  354. continue;
  355. }
  356. if ( _wcsicmp(pPrivileges->Name, wszRightName)== 0 )
  357. {
  358. break;
  359. }
  360. pPrivileges = pPrivileges->Next;
  361. }
  362. //
  363. // if the service information buffer is empty, treat it as "not found"
  364. //
  365. if ( pPrivileges == NULL )
  366. {
  367. hr = WBEM_E_NOT_FOUND;
  368. }
  369. }
  370. CComBSTR bstrLogOut;
  371. //
  372. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  373. // a "goto CleanUp;" with hr set to the return value from
  374. // the function (macro parameter)
  375. //
  376. if ( SUCCEEDED(hr) )
  377. {
  378. PSCE_PRIVILEGE_ASSIGNMENT pTmp = pPrivileges;
  379. SCE_PROV_IfErrorGotoCleanup(MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut));
  380. while ( pTmp )
  381. {
  382. CComPtr<IWbemClassObject> srpObj;
  383. SCE_PROV_IfErrorGotoCleanup(SpawnAnInstance(&srpObj));
  384. //
  385. // CScePropertyMgr helps us to access WMI object's properties
  386. // create an instance and attach the WMI object to it.
  387. // This will always succeed.
  388. //
  389. CScePropertyMgr ScePropMgr;
  390. ScePropMgr.Attach(srpObj);
  391. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pStorePath, bstrLogOut));
  392. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pUserRight, pTmp->Name));
  393. //
  394. // hardcode the mode for now
  395. //
  396. DWORD mode = 1;
  397. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pMode, mode));
  398. if ( pPrivileges->AssignedTo )
  399. {
  400. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pAddList, pPrivileges->AssignedTo));
  401. }
  402. //
  403. // ignore RemoveList for now
  404. //
  405. //
  406. // do the necessary gestures to WMI.
  407. // the use of WBEM_STATUS_REQUIREMENTS in SetStatus is not documented by WMI
  408. // at this point. Consult WMI team for detail if you suspect problems with
  409. // the use of WBEM_STATUS_REQUIREMENTS
  410. //
  411. if ( !bPostFilter ) {
  412. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_FALSE, NULL, NULL);
  413. } else {
  414. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_OK, NULL, NULL);
  415. }
  416. //
  417. // pass the new instance to WMI
  418. //
  419. hr = pHandler->Indicate(1, &srpObj);
  420. if ( wszRightName )
  421. {
  422. // get the single instance
  423. break;
  424. }
  425. //
  426. // go to the next item
  427. //
  428. pTmp = pTmp->Next;
  429. }
  430. }
  431. CleanUp:
  432. pSceStore->FreeSecurityProfileInfo(pInfo);
  433. return hr;
  434. }
  435. /*
  436. Routine Description:
  437. Name:
  438. CUserPrivilegeRights::DeleteInstance
  439. Functionality:
  440. remove an instance of Sce_UserPrivilegeRight from the specified store.
  441. Virtual:
  442. No.
  443. Arguments:
  444. pHandler - COM interface pointer for notifying WMI of any events.
  445. pSceStore - Pointer to our store. It must have been appropriately set up.
  446. wszRightName - property of the Sce_UserPrivilegeRight class.
  447. Return Value:
  448. See SaveSettingsToStore.
  449. Notes:
  450. */
  451. HRESULT CUserPrivilegeRights::DeleteInstance (
  452. IN IWbemObjectSink * pHandler,
  453. IN CSceStore * pSceStore,
  454. IN LPCWSTR wszRightName
  455. )
  456. {
  457. //
  458. // SCE_NO_VALUE and NULL pointers indicate to SaveSettingsToStore that this is a delete
  459. //
  460. return SaveSettingsToStore(pSceStore, wszRightName, SCE_NO_VALUE, NULL, NULL);
  461. }
  462. /*
  463. Routine Description:
  464. Name:
  465. CUserPrivilegeRights::SaveSettingsToStore
  466. Functionality:
  467. With all the properties of a Sce_UserPrivilegeRight, this function just saves
  468. the instance properties to our store.
  469. Virtual:
  470. No.
  471. Arguments:
  472. pSceStore - the store.
  473. wszGroupName - a corresponding key property of Sce_UserPrivilegeRight class.
  474. mode - another corresponding property of the Sce_UserPrivilegeRight class.
  475. pnlAdd - another corresponding property of the Sce_UserPrivilegeRight class.
  476. pnlRemove - another corresponding property of the Sce_UserPrivilegeRight class.
  477. Return Value:
  478. Success: it must return success code (use SUCCEEDED to test). It is
  479. not guaranteed to return WBEM_NO_ERROR.
  480. Failure: Various errors may occurs. Any error indicates the failure to save the instance.
  481. Notes:
  482. */
  483. HRESULT CUserPrivilegeRights::SaveSettingsToStore (
  484. IN CSceStore * pSceStore,
  485. IN PCWSTR wszRightName,
  486. IN DWORD mode,
  487. IN PSCE_NAME_LIST pnlAdd,
  488. IN PSCE_NAME_LIST pnlRemove
  489. )
  490. {
  491. //
  492. // ask SCE to read a gigantic structure out from the store. Only SCE
  493. // knows now to release the memory. Don't just delete it! Use our CSceStore
  494. // to do the releasing (FreeSecurityProfileInfo)
  495. //
  496. PSCE_PROFILE_INFO pInfo=NULL;
  497. HRESULT hr = pSceStore->GetSecurityProfileInfo(
  498. AREA_PRIVILEGES,
  499. &pInfo,
  500. NULL
  501. );
  502. if (FAILED(hr))
  503. {
  504. return hr;
  505. }
  506. //
  507. // if it is INF template, then the following function will do the job as commented below
  508. //
  509. DWORD dwDump;
  510. //
  511. // For a new .inf file. Write an empty buffer to the file
  512. // will creates the file with right header/signature/unicode format
  513. // this is harmless for existing files.
  514. // For database store, this is a no-op.
  515. //
  516. hr = pSceStore->WriteSecurityProfileInfo(AreaBogus, (PSCE_PROFILE_INFO)&dwDump, NULL, false);
  517. if (FAILED(hr))
  518. {
  519. return hr;
  520. }
  521. //
  522. // for INF format, we have to search for the servic name in the returned array
  523. //
  524. PSCE_PRIVILEGE_ASSIGNMENT pRight = pInfo->OtherInfo.smp.pPrivilegeAssignedTo;
  525. PSCE_PRIVILEGE_ASSIGNMENT pParent = NULL;
  526. DWORD i = 0;
  527. while ( pRight )
  528. {
  529. if ( pRight->Name == NULL )
  530. {
  531. continue;
  532. }
  533. if ( _wcsicmp(pRight->Name, wszRightName)== 0 )
  534. {
  535. break;
  536. }
  537. pParent = pRight;
  538. pRight = pRight->Next;
  539. }
  540. if ( pRight )
  541. {
  542. //
  543. // find it
  544. //
  545. if ( mode == SCE_NO_VALUE )
  546. {
  547. //
  548. // delete it
  549. //
  550. if ( pParent )
  551. {
  552. pParent->Next = pRight->Next;
  553. }
  554. else
  555. {
  556. pInfo->OtherInfo.smp.pPrivilegeAssignedTo = pRight->Next;
  557. }
  558. //
  559. // free buffer
  560. //
  561. pRight->Next = NULL;
  562. SceFreeMemory(pRight, SCE_STRUCT_PRIVILEGE);
  563. }
  564. else
  565. {
  566. //
  567. // modify it
  568. //
  569. if ( pRight->AssignedTo )
  570. {
  571. SceFreeMemory(pRight->AssignedTo, SCE_STRUCT_NAME_LIST);
  572. }
  573. pRight->AssignedTo = pnlAdd;
  574. }
  575. //
  576. // write the section header
  577. //
  578. if ( SUCCEEDED(hr) )
  579. {
  580. hr = pSceStore->WriteSecurityProfileInfo(AREA_PRIVILEGES, pInfo, NULL, false);
  581. }
  582. if ( mode != SCE_NO_VALUE )
  583. {
  584. //
  585. // reset the buffer pointer
  586. //
  587. pRight->AssignedTo = NULL;
  588. }
  589. }
  590. else
  591. {
  592. //
  593. // not found
  594. //
  595. if ( mode == SCE_NO_VALUE )
  596. {
  597. //
  598. // try to delete non exist object
  599. //
  600. hr = WBEM_E_NOT_FOUND;
  601. }
  602. else
  603. {
  604. //
  605. // add this one in
  606. //
  607. SCE_PRIVILEGE_ASSIGNMENT addRight;
  608. addRight.Name = (PWSTR)wszRightName;
  609. addRight.Value = 0;
  610. addRight.AssignedTo = pnlAdd;
  611. addRight.Status = 0;
  612. addRight.Next = NULL;
  613. //
  614. // set the temp buffer pointer to pInfo to set to the store
  615. //
  616. pRight = pInfo->OtherInfo.smp.pPrivilegeAssignedTo;
  617. pInfo->OtherInfo.smp.pPrivilegeAssignedTo = &addRight;
  618. //
  619. // append this item to the section
  620. //
  621. hr = pSceStore->WriteSecurityProfileInfo(
  622. AREA_PRIVILEGES,
  623. pInfo,
  624. NULL,
  625. true // appending
  626. );
  627. //
  628. // reset the buffer pointer
  629. //
  630. pInfo->OtherInfo.smp.pPrivilegeAssignedTo = pRight;
  631. }
  632. }
  633. //
  634. // Free the profile buffer
  635. //
  636. pSceStore->FreeSecurityProfileInfo(pInfo);
  637. return hr;
  638. }
  639. /*
  640. Routine Description:
  641. Name:
  642. CUserPrivilegeRights::ValidatePrivilegeRight
  643. Functionality:
  644. Private helper to verify that the given right is valid. Will query all
  645. supported user rights (Sce_SupportedUserRights) to see if this is one of them.
  646. Virtual:
  647. No.
  648. Arguments:
  649. bstrRight - a corresponding key property of Sce_UserPrivilegeRight class.
  650. Return Value:
  651. Success: it must return success code (use SUCCEEDED to test). It is
  652. not guaranteed to return WBEM_NO_ERROR.
  653. Failure: Various errors may occurs. Any error indicates the failure to save the instance.
  654. Notes:
  655. */
  656. HRESULT CUserPrivilegeRights::ValidatePrivilegeRight (
  657. IN BSTR bstrRight
  658. )
  659. {
  660. if ( bstrRight == NULL )
  661. {
  662. return WBEM_E_INVALID_PARAMETER;
  663. }
  664. DWORD Len = SysStringLen(bstrRight);
  665. //
  666. // memory allocated for this BSTR strQueryCategories will be automatically released by CComBSTR
  667. //
  668. //
  669. // prepare the query
  670. //
  671. LPCWSTR pQuery = L"SELECT * FROM Sce_SupportedUserRights WHERE RightName=\"";
  672. //
  673. // 1 for closing quote and 1 for 0 terminator
  674. //
  675. CComBSTR strQueryCategories;
  676. strQueryCategories.m_str = ::SysAllocStringLen(NULL, Len + wcslen(pQuery) + 2);
  677. if ( strQueryCategories.m_str == NULL )
  678. {
  679. return WBEM_E_OUT_OF_MEMORY;
  680. }
  681. //
  682. // this won't overrun. See allocation size above
  683. //
  684. wcscpy(strQueryCategories.m_str, pQuery);
  685. wcscat(strQueryCategories.m_str, bstrRight);
  686. wcscat(strQueryCategories.m_str, L"\"");
  687. //
  688. // execute the query
  689. //
  690. CComPtr<IEnumWbemClassObject> srpEnum;
  691. CComPtr<IWbemClassObject> srpObj;
  692. ULONG n = 0;
  693. HRESULT hr = m_srpNamespace->ExecQuery(L"WQL",
  694. strQueryCategories,
  695. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  696. NULL,
  697. &srpEnum
  698. );
  699. if (SUCCEEDED(hr))
  700. {
  701. //
  702. // should get one and only one instance
  703. //
  704. hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &n);
  705. if ( hr == WBEM_S_FALSE )
  706. {
  707. hr = WBEM_E_INVALID_PARAMETER;
  708. }
  709. if ( SUCCEEDED(hr) )
  710. {
  711. if (n > 0)
  712. {
  713. //
  714. // find the instance
  715. //
  716. hr = WBEM_S_NO_ERROR;
  717. }
  718. else
  719. {
  720. hr = WBEM_E_INVALID_PARAMETER;
  721. }
  722. }
  723. }
  724. return hr;
  725. }