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.

1151 lines
27 KiB

  1. // sequence.cpp: implementation of the various classes related to sequencing
  2. //
  3. // Copyright (c)1997-2001 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "sequence.h"
  7. #include "persistmgr.h"
  8. #include "requestobject.h"
  9. /*
  10. Routine Description:
  11. Name:
  12. CNameList::~CNameList
  13. Functionality:
  14. Destructor. Simply cleans up the vector, which contains heap allocated strings.
  15. Virtual:
  16. No
  17. Arguments:
  18. None.
  19. Return Value:
  20. None as any destructor
  21. Notes:
  22. if you create any local members, think about releasing them here.
  23. */
  24. CNameList::~CNameList()
  25. {
  26. int iCount = m_vList.size();
  27. for (int i = 0; i < iCount; ++i)
  28. {
  29. delete [] m_vList[i];
  30. }
  31. m_vList.clear();
  32. }
  33. /*
  34. Routine Description:
  35. Name:
  36. COrderNameList::COrderNameList
  37. Functionality:
  38. Contructor. Simple initialization.
  39. Virtual:
  40. No
  41. Arguments:
  42. None.
  43. Return Value:
  44. None as any constructor
  45. Notes:
  46. if you create any local members, think about initializing them here.
  47. */
  48. COrderNameList::COrderNameList() : m_ppList(NULL)
  49. {
  50. }
  51. /*
  52. Routine Description:
  53. Name:
  54. COrderNameList::~COrderNameList
  55. Functionality:
  56. Detructor. Simple Cleanup.
  57. Virtual:
  58. No
  59. Arguments:
  60. None.
  61. Return Value:
  62. None as any destructor
  63. Notes:
  64. if you create any local members, think about releasing them in Cleanup method.
  65. */
  66. COrderNameList::~COrderNameList()
  67. {
  68. Cleanup();
  69. }
  70. /*
  71. Routine Description:
  72. Name:
  73. COrderNameList::Cleanup
  74. Functionality:
  75. Clean up the map and the vector, both of which hold heap memory resources.
  76. Virtual:
  77. No
  78. Arguments:
  79. None.
  80. Return Value:
  81. None.
  82. Notes:
  83. if you create any local members, think about initializing them here.
  84. */
  85. void
  86. COrderNameList::Cleanup()
  87. {
  88. PriToNamesIter it = m_mapPriNames.begin();
  89. PriToNamesIter itEnd = m_mapPriNames.end();
  90. while (it != itEnd)
  91. {
  92. delete (*it).second;
  93. ++it;
  94. }
  95. m_mapPriNames.clear();
  96. m_listPriority.clear();
  97. delete [] m_ppList;
  98. m_ppList = NULL;
  99. }
  100. /*
  101. Routine Description:
  102. Name:
  103. COrderNameList::EndCreation
  104. Functionality:
  105. As name lists are added, we don't sort them (by priority). This function
  106. is the trigger for such sorting. You must call this function after all names
  107. lists are added.
  108. Virtual:
  109. No
  110. Arguments:
  111. None.
  112. Return Value:
  113. Success: various success code. No guarantee it will be WBEM_NO_ERROR. Use SUCCEEDED(hr) to test.
  114. Failure: various failure code. It means the sorting effort has failed.
  115. Notes:
  116. */
  117. HRESULT
  118. COrderNameList::EndCreation ()
  119. {
  120. m_listPriority.sort();
  121. //
  122. // now we are going to create an array for easy management.
  123. // Memory resource is not managed by m_ppList. It's managed by the map and the m_listPriority.
  124. // m_ppList is merely a array (of size m_listPriority.size()) of pointers.
  125. //
  126. delete [] m_ppList;
  127. m_ppList = new CNameList*[m_listPriority.size()];
  128. if (m_ppList == NULL)
  129. {
  130. return WBEM_E_OUT_OF_MEMORY;
  131. }
  132. //
  133. // now build the list. Since we have sorted the priority list,
  134. // it has the natural order!
  135. //
  136. ListIter it = m_listPriority.begin();
  137. ListIter itEnd = m_listPriority.end();
  138. int iIndex = 0;
  139. while (it != itEnd)
  140. {
  141. PriToNamesIter itList = m_mapPriNames.find(*it);
  142. if (itList != m_mapPriNames.end())
  143. {
  144. m_ppList[iIndex] = (*itList).second;
  145. }
  146. else
  147. {
  148. m_ppList[iIndex] = NULL;
  149. }
  150. ++it;
  151. ++iIndex;
  152. }
  153. return WBEM_NO_ERROR;
  154. }
  155. /*
  156. Routine Description:
  157. Name:
  158. COrderNameList::CreateOrderList
  159. Functionality:
  160. Given a priority, together with its list information string, this will add
  161. a CNameList object to our map.
  162. Virtual:
  163. No
  164. Arguments:
  165. dwPriority - The priority value.
  166. pszListInfo - string containing the order information. The names are separated by
  167. wchCookieSep (colon char ':').
  168. Return Value:
  169. Success: WBEM_NO_ERROR.
  170. Failure: various failure code. It means the creation has failed.
  171. Notes:
  172. (1) This function merely pushes the created CNameList to the map and the priority
  173. to the list. It doesn't sort the list. So, this is a function a caller calls
  174. amid its creation. EndCreation does that sorting.
  175. */
  176. HRESULT
  177. COrderNameList::CreateOrderList (
  178. IN DWORD dwPriority,
  179. IN LPCWSTR pszListInfo
  180. )
  181. {
  182. if (pszListInfo == NULL || *pszListInfo == L'\0')
  183. {
  184. return WBEM_S_FALSE;
  185. }
  186. HRESULT hr = WBEM_S_FALSE;
  187. CNameList* pTheList = new CNameList;
  188. if (pTheList == NULL)
  189. {
  190. return WBEM_E_OUT_OF_MEMORY;
  191. }
  192. //
  193. // pszCur is the current point of parsing
  194. //
  195. LPCWSTR pszCur = pszListInfo;
  196. //
  197. // pszNext is the next token's point of the current parsing
  198. //
  199. LPCWSTR pszNext = pszCur;
  200. while (*pszNext != L'\0')
  201. {
  202. //
  203. // seek to the separater
  204. //
  205. while (*pszNext != L'\0' && *pszNext != wchCookieSep)
  206. {
  207. ++pszNext;
  208. }
  209. int iLen = pszNext - pszCur;
  210. if (iLen > 0)
  211. {
  212. LPWSTR pszName = new WCHAR[iLen + 1];
  213. if (pszName == NULL)
  214. {
  215. hr = WBEM_E_OUT_OF_MEMORY;
  216. break;
  217. }
  218. //
  219. // copy, but no white spaces
  220. //
  221. ::TrimCopy(pszName, pszCur, iLen);
  222. //
  223. // if we have a non-empty name, then add to our list
  224. //
  225. if (*pszName == L'\0')
  226. {
  227. delete [] pszName;
  228. }
  229. else
  230. {
  231. //
  232. // give it to the list and the list manages the memory from this point
  233. //
  234. pTheList->m_vList.push_back(pszName);
  235. }
  236. }
  237. //
  238. // either skip wchNameSep or stop
  239. //
  240. if (*pszNext == wchCookieSep)
  241. {
  242. ++pszNext;
  243. }
  244. else if (*pszNext == L'\0')
  245. {
  246. //
  247. // end
  248. //
  249. break;
  250. }
  251. else
  252. {
  253. hr = WBEM_E_INVALID_SYNTAX;
  254. break;
  255. }
  256. pszCur = pszNext;
  257. }
  258. //
  259. // if failed
  260. //
  261. if (FAILED(hr))
  262. {
  263. delete pTheList;
  264. }
  265. else if (pTheList->m_vList.size() == 0)
  266. {
  267. //
  268. // nothing ahs been added
  269. //
  270. hr = WBEM_S_FALSE;
  271. }
  272. else
  273. {
  274. //
  275. // we need to push this to our map and list
  276. //
  277. hr = WBEM_NO_ERROR;
  278. m_mapPriNames.insert(MapPriorityToNames::value_type(dwPriority, pTheList));
  279. m_listPriority.insert(m_listPriority.end(), dwPriority);
  280. }
  281. return hr;
  282. }
  283. /*
  284. Routine Description:
  285. Name:
  286. COrderNameList::GetNext
  287. Functionality:
  288. Enumerating what is managed by the class.
  289. Virtual:
  290. No
  291. Arguments:
  292. ppList - Receives the CNameList of the enumeration.
  293. pdwEnumHandle - in-bound value == where to start the enumeration. Out-bound value ==
  294. where to start for the caller's next enumeration.
  295. Return Value:
  296. Success: (1) WBEM_NO_ERROR if the enumeration is successful.
  297. (2) WBEM_S_NO_MORE_DATA if there is no more data.
  298. Failure: WBEM_E_INVALID_PARAMETER.
  299. Notes:
  300. (1) Internally, the pdwEnumHandle is used as the index. But it is an opaque data to caller.
  301. (2) For maximum robustness, you should also check against *ppList == NULL.
  302. (3) As the parameter indicates, the returned *ppList must not be deleted by caller.
  303. */
  304. HRESULT
  305. COrderNameList::GetNext (
  306. IN const CNameList ** ppList,
  307. IN OUT DWORD * pdwEnumHandle
  308. )const
  309. {
  310. if (ppList == NULL || pdwEnumHandle == NULL)
  311. {
  312. return WBEM_E_INVALID_PARAMETER;
  313. }
  314. *ppList = NULL;
  315. HRESULT hr = WBEM_NO_ERROR;
  316. if (m_ppList && *pdwEnumHandle < m_listPriority.size())
  317. {
  318. *ppList = m_ppList[*pdwEnumHandle];
  319. ++(*pdwEnumHandle);
  320. }
  321. else
  322. {
  323. *ppList = NULL;
  324. hr = WBEM_S_NO_MORE_DATA;
  325. }
  326. return hr;
  327. }
  328. /*
  329. Routine Description:
  330. Name:
  331. CSequencer::GetOrderList
  332. Functionality:
  333. Access to the COrderNameList object. Caller will use this object directly.
  334. Virtual:
  335. No
  336. Arguments:
  337. pList - Receives the COrderNameList.
  338. Return Value:
  339. WBEM_NO_ERROR.
  340. Notes:
  341. (1) As the parameter indicates, the returned *pList must not be deleted by caller.
  342. */
  343. HRESULT
  344. CSequencer::GetOrderList (
  345. OUT const COrderNameList** pList
  346. )
  347. {
  348. *pList = &m_ClassList;
  349. return WBEM_NO_ERROR;
  350. }
  351. /*
  352. Routine Description:
  353. Name:
  354. CSequencer::Create
  355. Functionality:
  356. This creates the SCE namespace-wise sequencing order for embedding classes, plus
  357. template (pszStore) wise class ordering.
  358. As indicated before, template-wise class ordering takes precedence over namespace-wise
  359. class ordering.
  360. Virtual:
  361. No
  362. Arguments:
  363. pNamespace - The namespace pointer we rely on to query Sce_Sequence instances.
  364. pszStore - the store's path
  365. Return Value:
  366. Success: various success code. Use SUCCEEDED(hr) to test.
  367. Failure: various failure code. All means that the sequencer can't be created.
  368. Notes:
  369. (1) As the parameter indicates, the returned *pList must not be deleted by caller.
  370. */
  371. //--------------------------------------------------------------------
  372. // we need to query all instances of Sce_Sequence class and then
  373. // build our class list for each namespace. The ordering of
  374. // classes is determined by Sce_Sequence's priority member,
  375. // The smaller of priority value, the higher its priority
  376. //--------------------------------------------------------------------
  377. HRESULT
  378. CSequencer::Create (
  379. IN IWbemServices * pNamespace,
  380. IN LPCWSTR pszStore,
  381. IN LPCWSTR pszMethod
  382. )
  383. {
  384. if (pNamespace == NULL || pszMethod == NULL || *pszMethod == L'\0')
  385. {
  386. return WBEM_E_INVALID_PARAMETER;
  387. }
  388. //
  389. // need the template sequencing first. This sequencing order, if present, will take precedence
  390. // over the template independent sequencing.
  391. //
  392. //
  393. // Prepare a store (for persistence) for this store path (file)
  394. //
  395. CSceStore SceStore;
  396. HRESULT hr = SceStore.SetPersistPath(pszStore);
  397. if (FAILED(hr))
  398. {
  399. return hr;
  400. }
  401. // we just need to read ClassOrder string out.
  402. LPWSTR pszTemplateClassOrder = NULL;
  403. DWORD dwRead = 0;
  404. //
  405. // try to create a template-wise class order. Since such an order may not exist,
  406. // we will tolerate WBEM_E_NOT_FOUND.
  407. // Need to free the pszTemplateClassOrder.
  408. //
  409. hr = SceStore.GetPropertyFromStore(SCEWMI_CLASSORDER_CLASS, pClassOrder, &pszTemplateClassOrder, &dwRead);
  410. if (hr == WBEM_E_NOT_FOUND)
  411. {
  412. hr = WBEM_NO_ERROR;
  413. }
  414. else if (FAILED(hr))
  415. {
  416. return hr;
  417. }
  418. //
  419. // try to get all sequencing instances.
  420. //
  421. LPCWSTR pszQueryFmt = L"SELECT * FROM Sce_Sequence WHERE Method=\"%s\"";
  422. DWORD dwFmtLen = wcslen(pszQueryFmt);
  423. DWORD dwClassLen = wcslen(pszMethod);
  424. //
  425. // don't forget to ::SysFreeString of this bstrQuery
  426. //
  427. BSTR bstrQuery= ::SysAllocStringLen(NULL, dwClassLen + dwFmtLen + 1);
  428. if ( bstrQuery == NULL )
  429. {
  430. hr = WBEM_E_OUT_OF_MEMORY;
  431. }
  432. CComPtr<IEnumWbemClassObject> srpEnum;
  433. if (SUCCEEDED(hr))
  434. {
  435. //
  436. // this won't overrun the buffer, total length allocated is greater than needed
  437. //
  438. wsprintf(bstrQuery, pszQueryFmt, pszMethod);
  439. hr = pNamespace->ExecQuery(L"WQL", bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &srpEnum);
  440. //
  441. // free the bstr
  442. //
  443. ::SysFreeString(bstrQuery);
  444. }
  445. //
  446. // the previous query will allow us to enumerate through all Sce_Sequence instances
  447. //
  448. if (SUCCEEDED(hr))
  449. {
  450. //
  451. // ready to create the list. We will follow the usage of COrderNameList
  452. // to call BeginCreation first and end all creation by EndCreation.
  453. //
  454. m_ClassList.BeginCreation();
  455. //
  456. // now, if there is a template-wise sequencing, then, use it
  457. // we use absolute priority 0 for this sequencing list. All other
  458. // sequencing list is 1 lower than what they claimed themselves
  459. //
  460. if (pszTemplateClassOrder != NULL)
  461. {
  462. //
  463. // we will allow this to fail
  464. //
  465. m_ClassList.CreateOrderList(0, pszTemplateClassOrder);
  466. }
  467. //
  468. // CScePropertyMgr helps us to access WMI object's properties.
  469. //
  470. CScePropertyMgr ScePropMgr;
  471. DWORD dwPriority;
  472. //
  473. // this will hold the individual Sce_Sequence instance.
  474. //
  475. CComPtr<IWbemClassObject> srpObj;
  476. ULONG nEnum = 0;
  477. hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &nEnum);
  478. //
  479. // for each Sce_Sequence, let's parse its order property to build a list
  480. //
  481. while (SUCCEEDED(hr) && hr != WBEM_S_NO_MORE_DATA && srpObj)
  482. {
  483. CComBSTR bstrSeq;
  484. //
  485. // attach a different WMI object to the property mgr.
  486. // This will always succeed.
  487. //
  488. ScePropMgr.Attach(srpObj);
  489. dwPriority = 0;
  490. //
  491. // we must have priority property, it's a key property
  492. //
  493. hr = ScePropMgr.GetProperty(L"Priority", &dwPriority);
  494. if (SUCCEEDED(hr))
  495. {
  496. //
  497. // we will ignore those instances that has no "sequence" property
  498. //
  499. if (SUCCEEDED(ScePropMgr.GetProperty(L"Order", &bstrSeq)))
  500. {
  501. //
  502. // ask the list to add the names encoded in this string. Don't cleanup the existing ones.
  503. // add 1 more to the claimed priority so that no Sce_Sequence instance can really have
  504. // 0 (highest) priority. We reserve 0 for the template's sequencing list.
  505. //
  506. dwPriority = (dwPriority + 1 == 0) ? dwPriority : dwPriority + 1;
  507. hr = m_ClassList.CreateOrderList(dwPriority, bstrSeq);
  508. }
  509. }
  510. if (SUCCEEDED(hr))
  511. {
  512. //
  513. // get it ready to be reused
  514. //
  515. srpObj.Release();
  516. //
  517. // ready to loop to the next item
  518. //
  519. hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &nEnum);
  520. }
  521. }
  522. //
  523. // this is the good result
  524. //
  525. if (hr == WBEM_S_NO_MORE_DATA)
  526. {
  527. hr = WBEM_NO_ERROR;
  528. }
  529. //
  530. // EndCreation will only return WBEM_E_OUT_OF_MEMORY or WBEM_NO_ERROR
  531. //
  532. if (WBEM_E_OUT_OF_MEMORY == m_ClassList.EndCreation())
  533. {
  534. hr = WBEM_E_OUT_OF_MEMORY;
  535. }
  536. }
  537. delete [] pszTemplateClassOrder;
  538. return hr;
  539. }
  540. //=========================================================================
  541. // implementation for template-wise class sequencing
  542. //=========================================================================
  543. /*
  544. Routine Description:
  545. Name:
  546. CClassOrder::CClassOrder
  547. Functionality:
  548. This is the constructor. Pass along the parameters to the base class
  549. Virtual:
  550. No (you know that, constructor won't be virtual!)
  551. Arguments:
  552. pKeyChain - Pointer to the ISceKeyChain COM interface which is prepared
  553. by the caller who constructs this instance.
  554. pNamespace - Pointer to WMI namespace of our provider (COM interface).
  555. Passed along by the caller. Must not be NULL.
  556. pCtx - Pointer to WMI context object (COM interface). Passed along
  557. by the caller. It's up to WMI whether this interface pointer is NULL or not.
  558. Return Value:
  559. None as any constructor
  560. Notes:
  561. if you create any local members, think about initialize them here
  562. */
  563. CClassOrder::CClassOrder (
  564. IN ISceKeyChain *pKeyChain,
  565. IN IWbemServices *pNamespace,
  566. IN IWbemContext *pCtx
  567. )
  568. :
  569. CGenericClass(pKeyChain, pNamespace, pCtx)
  570. {
  571. }
  572. /*
  573. Routine Description:
  574. Name:
  575. CClassOrder::~CClassOrder
  576. Functionality:
  577. Destructor. Necessary as good C++ discipline since we have virtual functions.
  578. Virtual:
  579. Yes.
  580. Arguments:
  581. none as any destructor
  582. Return Value:
  583. None as any destructor
  584. Notes:
  585. if you create any local members, think about whether
  586. there is any need for a non-trivial destructor
  587. */
  588. CClassOrder::~CClassOrder()
  589. {
  590. }
  591. /*
  592. Routine Description:
  593. Name:
  594. CClassOrder::PutInst
  595. Functionality:
  596. Put an instance as instructed by WMI. Since this class implements Sce_ClassOrder,
  597. which is persistence oriented, this will cause the Sce_ClassOrder object's property
  598. information to be saved in our store.
  599. Virtual:
  600. Yes.
  601. Arguments:
  602. pInst - COM interface pointer to the WMI class (Sce_ClassOrder) object.
  603. pHandler - COM interface pointer for notifying WMI of any events.
  604. pCtx - COM interface pointer. This interface is just something we pass around.
  605. WMI may mandate it (not now) in the future. But we never construct
  606. such an interface and so, we just pass around for various WMI API's
  607. Return Value:
  608. Success: it must return success code (use SUCCEEDED to test). It is
  609. not guaranteed to return WBEM_NO_ERROR.
  610. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  611. the instance.
  612. Notes:
  613. Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  614. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  615. to test for the result of retrieving a property.
  616. */
  617. HRESULT CClassOrder::PutInst (
  618. IN IWbemClassObject * pInst,
  619. IN IWbemObjectSink * pHandler,
  620. IN IWbemContext * pCtx
  621. )
  622. {
  623. //
  624. // CScePropertyMgr helps us to access WMI object's properties
  625. // create an instance and attach the WMI object to it.
  626. // This will always succeed.
  627. //
  628. CScePropertyMgr ScePropMgr;
  629. ScePropMgr.Attach(pInst);
  630. //
  631. // must have a store path
  632. //
  633. CComBSTR vbstrStorePath;
  634. HRESULT hr = ScePropMgr.GetProperty(pStorePath, &vbstrStorePath);
  635. if (SUCCEEDED(hr))
  636. {
  637. CComBSTR bstrOrder;
  638. hr = ScePropMgr.GetProperty(pClassOrder, &bstrOrder);
  639. //
  640. // if everything is fine, we need to save it
  641. //
  642. if (SUCCEEDED(hr))
  643. {
  644. //
  645. // Attach the WMI object instance to the store and let the store know that
  646. // it's store is given by the pStorePath property of the instance.
  647. //
  648. CSceStore SceStore;
  649. SceStore.SetPersistProperties(pInst, pStorePath);
  650. DWORD dwDump;
  651. //
  652. // For a new .inf file. Write an empty buffer to the file
  653. // will creates the file with right header/signature/unicode format
  654. // this is harmless for existing files.
  655. // For database store, this is a no-op.
  656. //
  657. hr = SceStore.WriteSecurityProfileInfo(AreaBogus, (PSCE_PROFILE_INFO)&dwDump, NULL, false);
  658. //
  659. // also, we need to write it to attachment section because it's not a native core object
  660. // without an entry in the attachment section, inf file tempalte can't be imported to
  661. // database stores. For database store, this is no-op
  662. //
  663. if (SUCCEEDED(hr))
  664. {
  665. hr = SceStore.WriteAttachmentSection(SCEWMI_CLASSORDER_CLASS, pszAttachSectionValue);
  666. }
  667. //
  668. // final save
  669. //
  670. if (SUCCEEDED(hr))
  671. {
  672. hr = SceStore.SavePropertyToStore(SCEWMI_CLASSORDER_CLASS, pClassOrder, (LPCWSTR)bstrOrder);
  673. }
  674. }
  675. }
  676. return hr;
  677. }
  678. /*
  679. Routine Description:
  680. Name:
  681. CClassOrder::CreateObject
  682. Functionality:
  683. Create WMI objects (Sce_ClassOrder). Depending on parameter atAction,
  684. this creation may mean:
  685. (a) Get a single instance (atAction == ACTIONTYPE_GET)
  686. (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY)
  687. (c) Delete an instance (atAction == ACTIONTYPE_DELETE)
  688. Virtual:
  689. Yes.
  690. Arguments:
  691. pHandler - COM interface pointer for notifying WMI for creation result.
  692. atAction - Get single instance ACTIONTYPE_GET
  693. Get several instances ACTIONTYPE_QUERY
  694. Delete a single instance ACTIONTYPE_DELETE
  695. Return Value:
  696. Success: it must return success code (use SUCCEEDED to test). It is
  697. not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI,
  698. not directly passed back via parameters.
  699. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate
  700. the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying
  701. situations, this may not be an error depending on caller's intention.
  702. Notes:
  703. */
  704. HRESULT CClassOrder::CreateObject (
  705. IN IWbemObjectSink * pHandler,
  706. IN ACTIONTYPE atAction
  707. )
  708. {
  709. //
  710. // we know how to:
  711. // Get single instance ACTIONTYPE_GET
  712. // Delete a single instance ACTIONTYPE_DELETE
  713. // Get several instances ACTIONTYPE_QUERY
  714. //
  715. if ( ACTIONTYPE_GET != atAction &&
  716. ACTIONTYPE_DELETE != atAction &&
  717. ACTIONTYPE_QUERY != atAction )
  718. {
  719. return WBEM_E_NOT_SUPPORTED;
  720. }
  721. //
  722. // We must have the pStorePath property because that is where
  723. // our instance is stored.
  724. // m_srpKeyChain->GetKeyPropertyValue WBEM_S_FALSE if the key is not recognized
  725. // So, we need to test against WBEM_S_FALSE if the property is mandatory
  726. //
  727. CComVariant varStorePath;
  728. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(pStorePath, &varStorePath);
  729. if (SUCCEEDED(hr) && hr != WBEM_S_FALSE && varStorePath.vt == VT_BSTR)
  730. {
  731. //
  732. // Prepare a store (for persistence) for this store path (file)
  733. //
  734. CSceStore SceStore;
  735. hr = SceStore.SetPersistPath(varStorePath.bstrVal);
  736. if ( SUCCEEDED(hr) )
  737. {
  738. //
  739. // make sure the store (just a file) really exists. The raw path
  740. // may contain env variables, so we need the expanded path
  741. //
  742. DWORD dwAttrib = GetFileAttributes(SceStore.GetExpandedPath());
  743. //
  744. // if the file exist
  745. //
  746. if ( dwAttrib != -1 )
  747. {
  748. if ( ACTIONTYPE_DELETE == atAction )
  749. {
  750. //
  751. // just save a blank section because we only has one instance
  752. //
  753. hr = SceStore.SavePropertyToStore(SCEWMI_CLASSORDER_CLASS, (LPCWSTR)NULL, (LPCWSTR)NULL);
  754. }
  755. else
  756. {
  757. //
  758. // we need to read out the ClassOrder property
  759. //
  760. LPWSTR pszClassOrder = NULL;
  761. DWORD dwRead = 0;
  762. //
  763. // need to free pszClassOrder!
  764. //
  765. hr = SceStore.GetPropertyFromStore(SCEWMI_CLASSORDER_CLASS, pClassOrder, &pszClassOrder, &dwRead);
  766. //
  767. // read is successful
  768. //
  769. if (SUCCEEDED(hr) && dwRead > 0)
  770. {
  771. //
  772. // create a blank new instance to fill in properties
  773. //
  774. CComPtr<IWbemClassObject> srpObj;
  775. hr = SpawnAnInstance(&srpObj);
  776. //
  777. // if successful, then ready to fill in the properties
  778. //
  779. if (SUCCEEDED(hr))
  780. {
  781. //
  782. // CScePropertyMgr helps us to access WMI object's properties
  783. // create an instance and attach the WMI object to it.
  784. // This will always succeed.
  785. //
  786. CScePropertyMgr ScePropMgr;
  787. ScePropMgr.Attach(srpObj);
  788. hr = ScePropMgr.PutProperty(pStorePath, SceStore.GetExpandedPath());
  789. if (SUCCEEDED(hr))
  790. {
  791. hr = ScePropMgr.PutProperty(pClassOrder, pszClassOrder);
  792. }
  793. }
  794. //
  795. // pass the new instance to WMI if we are successful
  796. //
  797. if (SUCCEEDED(hr))
  798. {
  799. hr = pHandler->Indicate(1, &srpObj);
  800. }
  801. delete [] pszClassOrder;
  802. }
  803. }
  804. }
  805. else
  806. {
  807. hr = WBEM_E_NOT_FOUND;
  808. }
  809. }
  810. }
  811. if (SUCCEEDED(hr))
  812. {
  813. //
  814. // do the necessary gestures to WMI.
  815. // the use of WBEM_STATUS_REQUIREMENTS in SetStatus is not documented by WMI
  816. // at this point. Consult WMI team for detail if you suspect problems with
  817. // the use of WBEM_STATUS_REQUIREMENTS
  818. //
  819. if ( ACTIONTYPE_QUERY == atAction )
  820. {
  821. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_FALSE, NULL, NULL);
  822. }
  823. else if (ACTIONTYPE_GET == atAction)
  824. {
  825. pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, S_OK, NULL, NULL);
  826. }
  827. }
  828. return hr;
  829. }