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.

1269 lines
33 KiB

  1. // attachment.cpp: implementation of the Sce_PodData class.
  2. //
  3. // Copyright (c)1997-1999 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "attachment.h"
  8. #include "persistmgr.h"
  9. #include <io.h>
  10. #include "requestobject.h"
  11. /*
  12. Routine Description:
  13. Name:
  14. CPodData::CPodData
  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. CPodData::CPodData (
  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. CPodData::~CPodData
  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. CPodData::~CPodData()
  57. {
  58. }
  59. /*
  60. Routine Description:
  61. Name:
  62. CPodData::CreateObject
  63. Functionality:
  64. Create WMI objects (Sce_PodData). 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. CPodData::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. HRESULT hr = WBEM_S_NO_ERROR;
  103. //
  104. // enumerate all properties
  105. //
  106. //
  107. // We must have a store to get/delete an Sce_PodData object(s).
  108. // Note: GetKeyPropertyValue will return WBEM_S_FALSE if the key is not recognized.
  109. // That is why we check against it and return failure as long as it is not querying.
  110. //
  111. CComVariant varStorePath;
  112. hr = m_srpKeyChain->GetKeyPropertyValue(pStorePath, &varStorePath);
  113. if (FAILED(hr))
  114. {
  115. return hr;
  116. }
  117. else if (hr == WBEM_S_FALSE)
  118. {
  119. return WBEM_E_NOT_FOUND;
  120. }
  121. //
  122. // Pod ID is a key property. We must also have Pod ID, unless we are querying.
  123. //
  124. CComVariant varPodID;
  125. hr = m_srpKeyChain->GetKeyPropertyValue(pPodID, &varPodID);
  126. if (FAILED(hr))
  127. {
  128. return hr;
  129. }
  130. else if (hr == WBEM_S_FALSE && (ACTIONTYPE_QUERY != atAction) )
  131. {
  132. return WBEM_E_NOT_FOUND;
  133. }
  134. CComVariant varPodSection;
  135. hr = m_srpKeyChain->GetKeyPropertyValue(pPodSection, &varPodSection);
  136. if (FAILED(hr))
  137. {
  138. return hr;
  139. }
  140. else if (hr == WBEM_S_FALSE && (ACTIONTYPE_QUERY != atAction) )
  141. {
  142. return WBEM_E_NOT_FOUND;
  143. }
  144. CComVariant varKey;
  145. hr = m_srpKeyChain->GetKeyPropertyValue(pKey, &varKey);
  146. if (FAILED(hr))
  147. {
  148. return hr;
  149. }
  150. else if (hr == WBEM_S_FALSE && (ACTIONTYPE_QUERY != atAction) )
  151. {
  152. return WBEM_E_NOT_FOUND;
  153. }
  154. if (SUCCEEDED(hr))
  155. {
  156. //
  157. // Prepare a store (for persistence) for this store path (file)
  158. //
  159. CSceStore SceStore;
  160. hr = SceStore.SetPersistPath(varStorePath.bstrVal);
  161. if ( SUCCEEDED(hr) ) {
  162. //
  163. // make sure the store (just a file) really exists. The raw path
  164. // may contain env variables, so we need the expanded path
  165. //
  166. DWORD dwAttrib = GetFileAttributes(SceStore.GetExpandedPath());
  167. if ( dwAttrib != -1 )
  168. {
  169. //
  170. // the file exist
  171. //
  172. BOOL bPostFilter=TRUE;
  173. DWORD dwCount = 0;
  174. m_srpKeyChain->GetKeyPropertyCount(&dwCount);
  175. if ( varKey.vt == VT_BSTR )
  176. {
  177. //
  178. // doesn't matter if this comes from QUERY, GET, or DELETE
  179. // do the same logic for QUERY and GET
  180. //
  181. if ( ACTIONTYPE_DELETE == atAction )
  182. {
  183. hr = DeleteInstance(&SceStore, varPodID.bstrVal, varPodSection.bstrVal, varKey.bstrVal );
  184. }
  185. else {
  186. if ( ACTIONTYPE_QUERY == atAction && dwCount == 2 ) {
  187. bPostFilter = FALSE;
  188. }
  189. hr = ConstructInstance(pHandler, &SceStore,
  190. varStorePath.bstrVal,
  191. (varPodID.vt == VT_BSTR) ? varPodID.bstrVal : NULL,
  192. (varPodSection.vt == VT_BSTR) ? varPodSection.bstrVal : NULL,
  193. (varKey.vt == VT_BSTR) ? varKey.bstrVal : NULL,
  194. bPostFilter );
  195. }
  196. } else if ( ACTIONTYPE_QUERY == atAction )
  197. {
  198. //
  199. // this is only valid for QUERY type
  200. //
  201. if ( dwCount == 1 ) {
  202. bPostFilter = FALSE;
  203. }
  204. hr = ConstructQueryInstances(pHandler, &SceStore,
  205. varStorePath.bstrVal,
  206. (varPodID.vt == VT_BSTR) ? varPodID.bstrVal : NULL,
  207. (varPodSection.vt == VT_BSTR) ? varPodSection.bstrVal : NULL,
  208. bPostFilter
  209. );
  210. }
  211. } else {
  212. hr = WBEM_E_NOT_FOUND;
  213. }
  214. }
  215. }
  216. return hr;
  217. }
  218. /*
  219. Routine Description:
  220. Name:
  221. CPodData::PutInst
  222. Functionality:
  223. Put an instance as instructed by WMI. Since this class implements Sce_PodData,
  224. which is persistence oriented, this will cause the Sce_PodData object's property
  225. information to be saved in our store.
  226. Virtual:
  227. Yes.
  228. Arguments:
  229. pInst - COM interface pointer to the WMI class (Sce_PodData) object.
  230. pHandler - COM interface pointer for notifying WMI of any events.
  231. pCtx - COM interface pointer. This interface is just something we pass around.
  232. WMI may mandate it (not now) in the future. But we never construct
  233. such an interface and so, we just pass around for various WMI API's
  234. Return Value:
  235. Success: it must return success code (use SUCCEEDED to test). It is
  236. not guaranteed to return WBEM_NO_ERROR.
  237. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  238. the instance.
  239. Notes:
  240. Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  241. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  242. to test for the result of retrieving a property.
  243. */
  244. HRESULT
  245. CPodData::PutInst (
  246. IN IWbemClassObject * pInst,
  247. IN IWbemObjectSink * pHandler,
  248. IN IWbemContext * pCtx
  249. )
  250. {
  251. //
  252. // this property manager will help us gain access to the properties of the WMI object
  253. //
  254. CScePropertyMgr ScePropMgr;
  255. //
  256. // This property manager is for this object (pInst) only!
  257. // Will always succeed
  258. //
  259. ScePropMgr.Attach(pInst);
  260. //
  261. // The store is used to persist the information. Since
  262. // we have a whole bunch of goto's, we are forced to define
  263. // the store here.
  264. //
  265. CSceStore SceStore;
  266. //
  267. // we manage the memory of this variable. need to free it
  268. //
  269. LPWSTR pszSectionName = NULL;
  270. // the memory for these bstrs are automatically managed by the CComBSTR class
  271. CComBSTR bstrPodID;
  272. CComBSTR bstrPodSuffix;
  273. CComBSTR bstrKey;
  274. CComBSTR bstrValue;
  275. //
  276. // we consider each property of the Sce_PodData non-optional.
  277. // For the entire duration of this save action, if missing property
  278. // will thus cause us to quit
  279. //
  280. HRESULT hr = ScePropMgr.GetProperty(pPodID, &bstrPodID);
  281. if (FAILED(hr) || hr == WBEM_S_RESET_TO_DEFAULT)
  282. {
  283. goto CleanUp;
  284. }
  285. hr = ScePropMgr.GetProperty(pPodSection, &bstrPodSuffix);
  286. if (FAILED(hr) || hr == WBEM_S_RESET_TO_DEFAULT)
  287. {
  288. goto CleanUp;
  289. }
  290. hr = ValidatePodID(bstrPodID);
  291. if (FAILED(hr))
  292. {
  293. goto CleanUp;
  294. }
  295. hr = ScePropMgr.GetProperty(pKey, &bstrKey);
  296. if (FAILED(hr) || hr == WBEM_S_RESET_TO_DEFAULT)
  297. {
  298. goto CleanUp;
  299. }
  300. hr = ScePropMgr.GetProperty(pValue, &bstrValue);
  301. if (FAILED(hr) || hr == WBEM_S_RESET_TO_DEFAULT)
  302. {
  303. goto CleanUp;
  304. }
  305. //
  306. // now build the section name
  307. //
  308. pszSectionName = new WCHAR[wcslen(bstrPodID) + wcslen(bstrPodSuffix) + 2];
  309. if ( NULL == pszSectionName )
  310. {
  311. hr = WBEM_E_OUT_OF_MEMORY;
  312. goto CleanUp;
  313. }
  314. //
  315. // this won't overrun the buffer. See the size allocated above
  316. //
  317. wcscpy(pszSectionName, bstrPodID);
  318. wcscat(pszSectionName, L"_");
  319. wcscat(pszSectionName, bstrPodSuffix);
  320. //
  321. // Attach the WMI object instance to the store and let the store know that
  322. // it's store is given by the pStorePath property of the instance.
  323. //
  324. hr = SceStore.SetPersistProperties(pInst, pStorePath);
  325. if (SUCCEEDED(hr))
  326. {
  327. hr = SceStore.SavePropertyToStore(pszSectionName, bstrKey, bstrValue);
  328. }
  329. CleanUp:
  330. //
  331. // We consider the object invalid if there is any missing property.
  332. //
  333. if (hr == WBEM_S_RESET_TO_DEFAULT)
  334. {
  335. hr = WBEM_E_INVALID_OBJECT;
  336. }
  337. delete [] pszSectionName;
  338. return hr;
  339. }
  340. /*
  341. Routine Description:
  342. Name:
  343. CPodData::ConstructInstance
  344. Functionality:
  345. This is private function to create an instance of Sce_PodData.
  346. Virtual:
  347. No.
  348. Arguments:
  349. pHandler - COM interface pointer for notifying WMI of any events.
  350. pSceStore - Pointer to our store. It must have been appropriately set up.
  351. wszLogStorePath - store path, a key property of Sce_PodData class.
  352. wszPodID - a corresponding key property of Sce_PodData class.
  353. wszSection - another corresponding property of the Sce_PodData class.
  354. wszKey - another corresponding property of the Sce_PodData class.
  355. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  356. Return Value:
  357. Success: it must return success code (use SUCCEEDED to test). It is
  358. not guaranteed to return WBEM_NO_ERROR.
  359. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  360. Notes:
  361. */
  362. HRESULT
  363. CPodData::ConstructInstance (
  364. IN IWbemObjectSink * pHandler,
  365. IN CSceStore * pSceStore,
  366. IN LPCWSTR wszLogStorePath,
  367. IN LPCWSTR wszPodID,
  368. IN LPCWSTR wszSection,
  369. IN LPCWSTR wszKey,
  370. IN BOOL bPostFilter
  371. )
  372. {
  373. HRESULT hr=WBEM_S_NO_ERROR;
  374. SCESTATUS rc;
  375. hr = ValidatePodID(wszPodID);
  376. if ( FAILED(hr) )
  377. {
  378. return hr;
  379. }
  380. //
  381. // we need to construct a more complicated section name based on the wszPodID and wszSection.
  382. //
  383. PWSTR wszSectionName = new WCHAR[wcslen(wszPodID) + wcslen(wszSection) + 2];
  384. if ( !wszSectionName )
  385. {
  386. return WBEM_E_OUT_OF_MEMORY;
  387. }
  388. //
  389. // this won't overrun the buffer. See the size allocated above
  390. //
  391. wcscpy(wszSectionName, wszPodID);
  392. wcscat(wszSectionName, L"_");
  393. wcscat(wszSectionName, wszSection);
  394. //
  395. // this will hold the information read by Sce
  396. //
  397. PSCESVC_CONFIGURATION_INFO pPodInfo=NULL;
  398. //
  399. // wszValue's memory is very strangely obtained. Be aware.
  400. // (1) When the information is from INF file, the wszValue points
  401. // to a memory already managed by pPodInfo. Hence, its release
  402. // is done by the release of pPodInfo.
  403. // (2) When the information is from a database, then we need to
  404. // release the memory pointed to by wszValue.
  405. //
  406. PWSTR wszValue=NULL;
  407. DWORD dwValueLen=0;
  408. if ( pSceStore->GetStoreType() == SCE_INF_FORMAT )
  409. {
  410. //
  411. // ask SCE to read the information
  412. //
  413. rc = SceSvcGetInformationTemplate(pSceStore->GetExpandedPath(),
  414. wszSectionName,
  415. wszKey,
  416. &pPodInfo
  417. );
  418. //
  419. // SCE returned errors needs to be translated to HRESULT.
  420. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  421. //
  422. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  423. if (rc == SCESTATUS_SUCCESS && pPodInfo && pPodInfo->Lines ) {
  424. wszValue = pPodInfo->Lines[0].Value;
  425. dwValueLen = pPodInfo->Lines[0].ValueLen;
  426. }
  427. }
  428. else
  429. {
  430. //
  431. // get information from the database
  432. //
  433. PVOID hProfile=NULL;
  434. rc = SceOpenProfile(pSceStore->GetExpandedPath(), SCE_JET_FORMAT, &hProfile);
  435. if ( SCESTATUS_SUCCESS == rc ) {
  436. rc = SceGetDatabaseSetting(
  437. hProfile,
  438. SCE_ENGINE_SMP,
  439. (PWSTR)wszSectionName,
  440. (PWSTR)wszKey,
  441. &wszValue,
  442. &dwValueLen
  443. );
  444. SceCloseProfile(&hProfile);
  445. }
  446. //
  447. // SCE returned errors needs to be translated to HRESULT.
  448. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  449. //
  450. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  451. }
  452. if ( SUCCEEDED(hr) )
  453. {
  454. CComBSTR bstrLogOut;
  455. hr = MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut);
  456. if ( FAILED(hr) )
  457. {
  458. goto CleanUp;
  459. }
  460. hr = PutPodDataInstance(pHandler,
  461. bstrLogOut,
  462. wszPodID,
  463. wszSection,
  464. wszKey,
  465. wszValue,
  466. bPostFilter
  467. );
  468. }
  469. CleanUp:
  470. //
  471. // only Sce knows how to free a PSCESVC_CONFIGURATION_INFO
  472. //
  473. if ( pPodInfo )
  474. {
  475. SceSvcFree(pPodInfo);
  476. }
  477. delete [] wszSectionName;
  478. if ( pSceStore->GetStoreType() != SCE_INF_FORMAT && wszValue )
  479. {
  480. ::LocalFree(wszValue);
  481. }
  482. return hr;
  483. }
  484. /*
  485. Routine Description:
  486. Name:
  487. CPodData::DeleteInstance
  488. Functionality:
  489. remove an instance of Sce_PodData from the specified store.
  490. Virtual:
  491. No.
  492. Arguments:
  493. pSceStore - Pointer to our store. It must have been appropriately set up.
  494. wszPodID - a corresponding key property of Sce_PodData class.
  495. wszSection - another corresponding property of the Sce_PodData class.
  496. wszKey - another corresponding property of the Sce_PodData class.
  497. Return Value:
  498. Success: it must return success code (use SUCCEEDED to test). It is
  499. not guaranteed to return WBEM_NO_ERROR.
  500. Failure: Various errors may occurs. Any such error should indicate the operation is not carried out
  501. Notes:
  502. */
  503. HRESULT
  504. CPodData::DeleteInstance (
  505. IN CSceStore * pSceStore,
  506. IN LPCWSTR wszPodID,
  507. IN LPCWSTR wszSection,
  508. IN LPCWSTR wszKey
  509. )
  510. {
  511. HRESULT hr = WBEM_S_NO_ERROR;
  512. hr = ValidatePodID(wszPodID);
  513. if ( FAILED(hr) )
  514. {
  515. return hr;
  516. }
  517. //
  518. // Our store needs a section name. But for Sce_PodData, the store section name
  519. // is composed by the supplied section name and the PodID.
  520. // Don't forget to free the memory!
  521. //
  522. PWSTR wszSectionName = new WCHAR[wcslen(wszPodID) + wcslen(wszSection) + 2];
  523. if ( !wszSectionName )
  524. {
  525. return WBEM_E_OUT_OF_MEMORY;
  526. }
  527. //
  528. // this won't overrun the buffer. See the size allocated above
  529. // Real composition happens here: the store's section name is wszPodID_wszSection
  530. //
  531. wcscpy(wszSectionName, wszPodID);
  532. wcscat(wszSectionName, L"_");
  533. wcscat(wszSectionName, wszSection);
  534. hr = pSceStore->DeletePropertyFromStore(wszSectionName, wszKey);
  535. delete [] wszSectionName;
  536. return hr;
  537. }
  538. /*
  539. Routine Description:
  540. Name:
  541. CPodData::ConstructQueryInstances
  542. Functionality:
  543. Querying instances of Sce_PodData whose key properties meet the specified parameters.
  544. Virtual:
  545. No.
  546. Arguments:
  547. pHandler - COM interface pointer used to notify WMI when instances are created.
  548. pSceStore - Pointer to our store. It must have been appropriately set up.
  549. wszLogStorePath - Log's store path.
  550. wszPodID - may be NULL.
  551. wszSection - may be NULL.
  552. bPostFilter -
  553. Return Value:
  554. Success: it must return success code (use SUCCEEDED to test). It is
  555. not guaranteed to return WBEM_NO_ERROR.
  556. Failure: Various errors may occurs. Any such error should indicate the operation is not carried out
  557. Notes:
  558. */
  559. HRESULT
  560. CPodData::ConstructQueryInstances (
  561. IWbemObjectSink * pHandler,
  562. CSceStore * pSceStore,
  563. LPCWSTR wszLogStorePath,
  564. LPCWSTR wszPodID,
  565. LPCWSTR wszSection,
  566. BOOL bPostFilter
  567. )
  568. {
  569. //
  570. // make sure that we have a valid store
  571. //
  572. if ( pSceStore == NULL ||
  573. pSceStore->GetStoreType() < SCE_INF_FORMAT ||
  574. pSceStore->GetStoreType() > SCE_JET_ANALYSIS_REQUIRED )
  575. {
  576. return WBEM_E_INVALID_PARAMETER;
  577. }
  578. //
  579. // we can't do anything if we don't have pszPodID or wszSection
  580. //
  581. if (wszPodID == NULL || wszSection == NULL)
  582. {
  583. return WBEM_E_NOT_SUPPORTED;
  584. }
  585. HRESULT hr=WBEM_S_NO_ERROR;
  586. SCESTATUS rc;
  587. PSCESVC_CONFIGURATION_INFO pPodInfo=NULL;
  588. LPWSTR wszSectionName = NULL;
  589. PVOID hProfile=NULL;
  590. CComBSTR bstrLogOut;
  591. LPWSTR pszNewValue=NULL;
  592. try {
  593. hr = ValidatePodID(wszPodID);
  594. if ( FAILED(hr) )
  595. {
  596. return hr;
  597. }
  598. //
  599. // build section name for the POD
  600. //
  601. wszSectionName = new WCHAR[wcslen(wszPodID) + wcslen(wszSection) + 2];
  602. if ( !wszSectionName )
  603. {
  604. return WBEM_E_OUT_OF_MEMORY;
  605. }
  606. //
  607. // this won't overrun the buffer. See the size allocated above
  608. //
  609. wcscpy(wszSectionName, wszPodID);
  610. wcscat(wszSectionName, L"_");
  611. wcscat(wszSectionName, wszSection);
  612. DWORD i;
  613. hr = MakeSingleBackSlashPath(wszLogStorePath, L'\\', &bstrLogOut);
  614. if ( FAILED(hr) )
  615. {
  616. goto CleanUp;
  617. }
  618. if ( pSceStore->GetStoreType() == SCE_INF_FORMAT ) {
  619. //
  620. // INF template, query info
  621. //
  622. rc = SceSvcGetInformationTemplate(pSceStore->GetExpandedPath(),
  623. wszSectionName,
  624. NULL,
  625. &pPodInfo
  626. );
  627. //
  628. // SCE returned errors needs to be translated to HRESULT.
  629. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  630. //
  631. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  632. if ( SUCCEEDED(hr) )
  633. {
  634. if ( !pPodInfo || pPodInfo->Count == 0 || pPodInfo->Lines == NULL )
  635. {
  636. hr = WBEM_E_NOT_FOUND;
  637. }
  638. }
  639. if ( SUCCEEDED(hr) ) {
  640. for ( i=0; SUCCEEDED(hr) && i<pPodInfo->Count; i++ ) {
  641. //
  642. // create instance for each one
  643. //
  644. // since this PSCESVC_CONFIGURATION_INFO is from INF template, pPodInfo->Lines[i].Value
  645. // is guaranteed to be 0 terminated. See comments of next block about using pPodInfo->Lines[i].Value.
  646. //
  647. hr = PutPodDataInstance(pHandler,
  648. bstrLogOut,
  649. wszPodID,
  650. wszSection,
  651. pPodInfo->Lines[i].Key,
  652. pPodInfo->Lines[i].Value,
  653. bPostFilter
  654. );
  655. }
  656. }
  657. } else {
  658. //
  659. // get information from the database
  660. //
  661. rc = SceOpenProfile(pSceStore->GetExpandedPath(), SCE_JET_FORMAT, &hProfile);
  662. if ( SCESTATUS_SUCCESS == rc ) {
  663. SCEP_HANDLE scepHandle;
  664. scepHandle.hProfile = hProfile;
  665. scepHandle.SectionName = wszSectionName;
  666. SCE_ENUMERATION_CONTEXT EnumHandle=0;
  667. DWORD CountReturned;
  668. do {
  669. //
  670. // enumerate the info
  671. //
  672. CountReturned = 0;
  673. rc = SceSvcQueryInfo((SCE_HANDLE)&scepHandle,
  674. SceSvcConfigurationInfo,
  675. NULL,
  676. FALSE,
  677. (PVOID *)&pPodInfo,
  678. &EnumHandle
  679. );
  680. //
  681. // SCE returned errors needs to be translated to HRESULT.
  682. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  683. //
  684. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  685. if ( SUCCEEDED(hr) ) {
  686. if ( !pPodInfo || pPodInfo->Count == 0 || pPodInfo->Lines == NULL )
  687. {
  688. hr = WBEM_E_NOT_FOUND;
  689. }
  690. }
  691. if ( SUCCEEDED(hr) ) {
  692. //
  693. // got something
  694. //
  695. CountReturned = pPodInfo->Count;
  696. for ( i=0; SUCCEEDED(hr) && i<pPodInfo->Count; i++ ) {
  697. //
  698. // create instance for each one
  699. //
  700. // pPodInfo->Lines[i].Value may not be 0 terminated
  701. // pPodInfo->Lines[i].ValueLen is the BYTE size of the buffer pPodInfo->Lines[i].Value
  702. //
  703. LPWSTR pNewVal = new WCHAR[pPodInfo->Lines[i].ValueLen/2 + 1];
  704. if (pNewVal != NULL)
  705. {
  706. memcpy(pNewVal, pPodInfo->Lines[i].Value, pPodInfo->Lines[i].ValueLen);
  707. pNewVal[pPodInfo->Lines[i].ValueLen/2] = L'\0';
  708. hr = PutPodDataInstance(pHandler,
  709. bstrLogOut,
  710. wszPodID,
  711. wszSection,
  712. pPodInfo->Lines[i].Key,
  713. pNewVal,
  714. bPostFilter
  715. );
  716. delete [] pNewVal;
  717. }
  718. else
  719. {
  720. hr = WBEM_E_OUT_OF_MEMORY;
  721. }
  722. }
  723. }
  724. if ( pPodInfo ) {
  725. SceSvcFree(pPodInfo);
  726. pPodInfo = NULL;
  727. }
  728. } while ( SUCCEEDED(hr) && CountReturned >= SCESVC_ENUMERATION_MAX );
  729. SceCloseProfile(&hProfile);
  730. } else {
  731. //
  732. // SCE returned errors needs to be translated to HRESULT.
  733. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR
  734. //
  735. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  736. }
  737. }
  738. }
  739. catch(...)
  740. {
  741. }
  742. CleanUp:
  743. if (hProfile)
  744. {
  745. SceCloseProfile(&hProfile);
  746. }
  747. if ( pPodInfo )
  748. {
  749. SceSvcFree(pPodInfo);
  750. }
  751. delete [] wszSectionName;
  752. return hr;
  753. }
  754. /*
  755. Routine Description:
  756. Name:
  757. CPodData::ValidatePodID
  758. Functionality:
  759. validate the PodID with registered Pods.
  760. Virtual:
  761. No.
  762. Arguments:
  763. wszPodID - string representing the Pod ID to be verified.
  764. Return Value:
  765. Success: it must return success code (use SUCCEEDED to test). It is
  766. not guaranteed to return WBEM_NO_ERROR.
  767. Failure: Various errors may occurs:
  768. (1) WBEM_E_NOT_FOUND if we successfully carry out the validation task and confirmed
  769. that we don't recognize the pod ID.
  770. (2) Other errors means that we can't carry out the validation at all. This doesn't mean
  771. that the Pod ID is invalid. It's just that the means to verify is not available.
  772. Notes:
  773. */
  774. HRESULT
  775. CPodData::ValidatePodID (
  776. LPCWSTR wszPodID
  777. )
  778. {
  779. //
  780. // no namespace means no access to WMI
  781. //
  782. if ( m_srpNamespace == NULL )
  783. {
  784. return WBEM_E_CRITICAL_ERROR;
  785. }
  786. if ( wszPodID == NULL )
  787. {
  788. return WBEM_E_INVALID_PARAMETER;
  789. }
  790. //
  791. // we will create a "select" query and ask WMI to return the pods
  792. //
  793. DWORD Len = wcslen(wszPodID);
  794. //
  795. // pQuery has an open quote that needs to be matched (and closed)
  796. //
  797. LPCWSTR pQuery = L"SELECT * FROM Sce_Pod WHERE PodID=\"";
  798. //
  799. // we need two extra WCHAR: one for the encloding quote, and other for the 0 terminator
  800. //
  801. LPWSTR pszQuery= new WCHAR[Len + wcslen(pQuery) + 2];
  802. if ( pszQuery == NULL )
  803. {
  804. return WBEM_E_OUT_OF_MEMORY;
  805. }
  806. //
  807. // no danger of overrun the buffer. See the size allocated above
  808. // Compose the query by appending the pod ID and the ending quote
  809. //
  810. wcscpy(pszQuery, pQuery);
  811. wcscat(pszQuery, wszPodID);
  812. wcscat(pszQuery, L"\"");
  813. //
  814. // Ask WMI to return all Pods. ExecQuery returns a enumerator.
  815. //
  816. CComPtr<IEnumWbemClassObject> srpEnum;
  817. HRESULT hr = m_srpNamespace->ExecQuery(L"WQL",
  818. pszQuery,
  819. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  820. NULL,
  821. &srpEnum);
  822. if (SUCCEEDED(hr))
  823. {
  824. //
  825. // should only get one instance because we are given its key (PodID)
  826. //
  827. CComPtr<IWbemClassObject> srpObj;
  828. ULONG n = 0;
  829. //
  830. // srpEnum->Next will return WBEM_NO_ERROR together with the WMI object
  831. // and a count (n) > 0. We only ask for 1 instance.
  832. //
  833. hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &n);
  834. if ( hr == WBEM_S_FALSE )
  835. {
  836. hr = WBEM_E_NOT_FOUND; // not find any
  837. }
  838. if (SUCCEEDED(hr))
  839. {
  840. if (n > 0)
  841. {
  842. //
  843. // find the instance
  844. //
  845. }
  846. else
  847. {
  848. hr = WBEM_E_NOT_FOUND;
  849. }
  850. }
  851. }
  852. delete [] pszQuery;
  853. return hr;
  854. }
  855. /*
  856. Routine Description:
  857. Name:
  858. CPodData::PutPodDataInstance
  859. Functionality:
  860. With all the properties of a Sce_PodData, this function just creates a new
  861. instance and populate the properties and then hand it back to WMI.
  862. Virtual:
  863. No.
  864. Arguments:
  865. pHandler - COM interface pointer for notifying WMI of any events.
  866. wszStoreName - store path, a key property of Sce_PodData class.
  867. wszPodID - a corresponding key property of Sce_PodData class.
  868. wszSection - another corresponding property of the Sce_PodData class.
  869. wszKey - another corresponding property of the Sce_PodData class.
  870. wszValue - The payload of the Sce_PodData class, where the information really is.
  871. bPostFilter - Controls how WMI will be informed with pHandler->SetStatus.
  872. Return Value:
  873. Success: it must return success code (use SUCCEEDED to test). It is
  874. not guaranteed to return WBEM_NO_ERROR.
  875. Failure: Various errors may occurs. Any error indicates the failure to create the instance.
  876. Notes:
  877. */
  878. HRESULT
  879. CPodData::PutPodDataInstance (
  880. IN IWbemObjectSink * pHandler,
  881. IN LPCWSTR wszStoreName,
  882. IN LPCWSTR wszPodID,
  883. IN LPCWSTR wszSection,
  884. IN LPCWSTR wszKey,
  885. IN LPCWSTR wszValue,
  886. IN BOOL bPostFilter
  887. )
  888. {
  889. HRESULT hr = WBEM_S_NO_ERROR;
  890. //
  891. // need a blank instance that can be used to fill in properties
  892. //
  893. CComPtr<IWbemClassObject> srpObj;
  894. if (SUCCEEDED(hr = SpawnAnInstance(&srpObj)))
  895. {
  896. CScePropertyMgr ScePropMgr;
  897. ScePropMgr.Attach(srpObj);
  898. //
  899. // the property fillup is repeatitive and boring. here we use two arrays
  900. // (pszProperties is the property names, and pszValues the the values of
  901. // the corresponding properties)
  902. //
  903. LPCWSTR pszProperties[] = {pStorePath, pPodID, pPodSection, pKey, pValue};
  904. LPCWSTR pszValues[] = {wszStoreName, wszPodID, wszSection, wszKey, wszValue};
  905. //
  906. // SCEPROV_SIZEOF_ARRAY is a macro that returns the array's size
  907. //
  908. for (int i = 0; i < SCEPROV_SIZEOF_ARRAY(pszProperties); i++)
  909. {
  910. if (FAILED(hr = ScePropMgr.PutProperty(pszProperties[i], pszValues[i])))
  911. {
  912. return hr;
  913. }
  914. }
  915. //
  916. // do the necessary gestures to WMI.
  917. // the use of WBEM_STATUS_REQUIREMENTS in SetStatus is not documented by WMI
  918. // at this point. Consult WMI team for detail if you suspect problems with
  919. // the use of WBEM_STATUS_REQUIREMENTS
  920. //
  921. hr = pHandler->SetStatus(WBEM_STATUS_REQUIREMENTS, (bPostFilter ? S_OK : S_FALSE), NULL, NULL);
  922. //
  923. // give the new instance to WMI
  924. //
  925. if (SUCCEEDED(hr))
  926. {
  927. hr = pHandler->Indicate(1, &srpObj);
  928. }
  929. }
  930. return hr;
  931. }