Source code of Windows XP (NT5)
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.

791 lines
18 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation
  4. //
  5. // PROPERTY.CPP
  6. //
  7. // alanbos 15-Aug-96 Created.
  8. //
  9. // Defines the implementation of ISWbemProperty
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. //***************************************************************************
  14. //
  15. // CSWbemProperty::CSWbemProperty
  16. //
  17. // DESCRIPTION:
  18. //
  19. // Constructor.
  20. //
  21. //***************************************************************************
  22. CSWbemProperty::CSWbemProperty(
  23. CSWbemServices *pService,
  24. ISWbemInternalObject *pSWbemObject,
  25. BSTR name)
  26. {
  27. m_Dispatch.SetObj (this, IID_ISWbemProperty,
  28. CLSID_SWbemProperty, L"SWbemProperty");
  29. m_cRef=1;
  30. m_pSWbemObject = pSWbemObject;
  31. m_pSWbemObject->AddRef ();
  32. m_pSWbemObject->GetIWbemClassObject (&m_pIWbemClassObject);
  33. m_pSite = new CWbemObjectSite (m_pSWbemObject);
  34. m_pSWbemServices = pService;
  35. if (m_pSWbemServices)
  36. m_pSWbemServices->AddRef ();
  37. m_name = SysAllocString (name);
  38. InterlockedIncrement(&g_cObj);
  39. }
  40. //***************************************************************************
  41. //
  42. // CSWbemProperty::~CSWbemProperty
  43. //
  44. // DESCRIPTION:
  45. //
  46. // Destructor.
  47. //
  48. //***************************************************************************
  49. CSWbemProperty::~CSWbemProperty(void)
  50. {
  51. InterlockedDecrement(&g_cObj);
  52. if (m_pSWbemObject)
  53. m_pSWbemObject->Release ();
  54. if (m_pIWbemClassObject)
  55. m_pIWbemClassObject->Release ();
  56. if (m_pSWbemServices)
  57. m_pSWbemServices->Release ();
  58. if (m_pSite)
  59. m_pSite->Release ();
  60. SysFreeString (m_name);
  61. }
  62. //***************************************************************************
  63. // HRESULT CSWbemProperty::QueryInterface
  64. // long CSWbemProperty::AddRef
  65. // long CSWbemProperty::Release
  66. //
  67. // DESCRIPTION:
  68. //
  69. // Standard Com IUNKNOWN functions.
  70. //
  71. //***************************************************************************
  72. STDMETHODIMP CSWbemProperty::QueryInterface (
  73. IN REFIID riid,
  74. OUT LPVOID *ppv
  75. )
  76. {
  77. *ppv=NULL;
  78. if (IID_IUnknown==riid)
  79. *ppv = reinterpret_cast<IUnknown*>(this);
  80. else if (IID_ISWbemProperty==riid)
  81. *ppv = (ISWbemProperty *)this;
  82. else if (IID_IDispatch==riid)
  83. *ppv = (IDispatch *)this;
  84. else if (IID_ISupportErrorInfo==riid)
  85. *ppv = (ISupportErrorInfo *)this;
  86. else if (IID_IProvideClassInfo==riid)
  87. *ppv = (IProvideClassInfo *)this;
  88. if (NULL!=*ppv)
  89. {
  90. ((LPUNKNOWN)*ppv)->AddRef();
  91. return NOERROR;
  92. }
  93. return ResultFromScode(E_NOINTERFACE);
  94. }
  95. STDMETHODIMP_(ULONG) CSWbemProperty::AddRef(void)
  96. {
  97. InterlockedIncrement(&m_cRef);
  98. return m_cRef;
  99. }
  100. STDMETHODIMP_(ULONG) CSWbemProperty::Release(void)
  101. {
  102. InterlockedDecrement(&m_cRef);
  103. if (0L!=m_cRef)
  104. return m_cRef;
  105. delete this;
  106. return 0;
  107. }
  108. //***************************************************************************
  109. // HRESULT CSWbemProperty::InterfaceSupportsErrorInfo
  110. //
  111. // DESCRIPTION:
  112. //
  113. // Standard Com ISupportErrorInfo functions.
  114. //
  115. //***************************************************************************
  116. STDMETHODIMP CSWbemProperty::InterfaceSupportsErrorInfo (IN REFIID riid)
  117. {
  118. return (IID_ISWbemProperty == riid) ? S_OK : S_FALSE;
  119. }
  120. //***************************************************************************
  121. //
  122. // SCODE CSWbemProperty::get_Value
  123. //
  124. // DESCRIPTION:
  125. //
  126. // Retrieve the property value
  127. //
  128. // PARAMETERS:
  129. //
  130. // pValue holds the value on return
  131. //
  132. // RETURN VALUES:
  133. //
  134. // WBEM_S_NO_ERROR success
  135. // WBEM_E_INVALID_PARAMETER bad input parameters
  136. // WBEM_E_FAILED otherwise
  137. //
  138. //***************************************************************************
  139. HRESULT CSWbemProperty::get_Value (
  140. VARIANT *pValue
  141. )
  142. {
  143. HRESULT hr = WBEM_E_FAILED;
  144. ResetLastErrors ();
  145. if (NULL == pValue)
  146. hr = WBEM_E_INVALID_PARAMETER;
  147. else
  148. {
  149. VariantClear (pValue);
  150. if (m_pIWbemClassObject)
  151. {
  152. VARIANT var;
  153. VariantInit (&var);
  154. if (WBEM_S_NO_ERROR == (hr = m_pIWbemClassObject->Get
  155. (m_name, 0, &var, NULL, NULL)))
  156. {
  157. MapFromCIMOMObject(m_pSWbemServices, &var,
  158. m_pSWbemObject, m_name);
  159. if(var.vt & VT_ARRAY)
  160. {
  161. hr = ConvertArrayRev(pValue, &var);
  162. }
  163. else
  164. {
  165. hr = VariantCopy (pValue, &var);
  166. }
  167. VariantClear(&var);
  168. }
  169. }
  170. }
  171. if (FAILED(hr))
  172. m_Dispatch.RaiseException (hr);
  173. return hr;
  174. }
  175. //***************************************************************************
  176. //
  177. // SCODE CSWbemProperty::put_Value
  178. //
  179. // DESCRIPTION:
  180. //
  181. // Set the property value
  182. //
  183. // PARAMETERS:
  184. //
  185. // pVal the new value
  186. //
  187. // RETURN VALUES:
  188. //
  189. // WBEM_S_NO_ERROR success
  190. // WBEM_E_INVALID_PARAMETER bad input parameters
  191. // WBEM_E_FAILED otherwise
  192. //
  193. //***************************************************************************
  194. HRESULT CSWbemProperty::put_Value (
  195. VARIANT *pVal
  196. )
  197. {
  198. HRESULT hr = WBEM_E_FAILED;
  199. ResetLastErrors ();
  200. /*
  201. * We can only _change_ the value, not the type. When dealing with
  202. * CIMOM interfaces 2 golden rules must be obeyed.
  203. * (1) For instance-level Put's, you can specify the CIMTYPE (provided
  204. * you get it right), but can also specify 0.
  205. * (2) For class-level Put's, always specify the CIMTYPE
  206. */
  207. if (m_pIWbemClassObject)
  208. {
  209. CIMTYPE cimType = CIM_EMPTY;
  210. if (SUCCEEDED(hr = m_pIWbemClassObject->Get (m_name, 0, NULL, &cimType, NULL)))
  211. {
  212. VARIANT vWMI;
  213. VariantInit (&vWMI);
  214. if (SUCCEEDED(WmiVariantChangeType(vWMI, pVal, cimType)))
  215. hr = m_pIWbemClassObject->Put (m_name, 0, &vWMI, cimType);
  216. VariantClear (&vWMI);
  217. }
  218. }
  219. if (FAILED(hr))
  220. m_Dispatch.RaiseException (hr);
  221. else
  222. {
  223. // Did we save an embedded object value? If so make sure the
  224. // site is correctly set to this property.
  225. SetSite (pVal, m_pSWbemObject, m_name);
  226. // Propagate the change to the owning site
  227. if (m_pSite)
  228. m_pSite->Update ();
  229. }
  230. return hr;
  231. }
  232. //***************************************************************************
  233. //
  234. // SCODE CSWbemProperty::get_Name
  235. //
  236. // DESCRIPTION:
  237. //
  238. // Retrieve the property name
  239. //
  240. // PARAMETERS:
  241. //
  242. // pName holds the name on return
  243. //
  244. // RETURN VALUES:
  245. //
  246. // WBEM_S_NO_ERROR success
  247. // WBEM_E_INVALID_PARAMETER bad input parameters
  248. // WBEM_E_FAILED otherwise
  249. //
  250. //***************************************************************************
  251. HRESULT CSWbemProperty::get_Name (
  252. BSTR *pName
  253. )
  254. {
  255. HRESULT hr = WBEM_S_NO_ERROR;
  256. ResetLastErrors ();
  257. if (NULL == pName)
  258. hr = WBEM_E_INVALID_PARAMETER;
  259. else
  260. *pName = SysAllocString (m_name);
  261. if (FAILED(hr))
  262. m_Dispatch.RaiseException (hr);
  263. return hr;
  264. }
  265. //***************************************************************************
  266. //
  267. // SCODE CSWbemProperty::get_CIMType
  268. //
  269. // DESCRIPTION:
  270. //
  271. // Retrieve the property base CIM type (i.e. without the array type)
  272. //
  273. // PARAMETERS:
  274. //
  275. // pType holds the type on return
  276. //
  277. // RETURN VALUES:
  278. //
  279. // WBEM_S_NO_ERROR success
  280. // WBEM_E_INVALID_PARAMETER bad input parameters
  281. // WBEM_E_FAILED otherwise
  282. //
  283. //***************************************************************************
  284. HRESULT CSWbemProperty::get_CIMType (
  285. WbemCimtypeEnum *pType
  286. )
  287. {
  288. HRESULT hr = WBEM_E_FAILED;
  289. ResetLastErrors ();
  290. if (NULL == pType)
  291. return WBEM_E_INVALID_PARAMETER;
  292. if (m_pIWbemClassObject)
  293. {
  294. CIMTYPE cimType;
  295. hr = m_pIWbemClassObject->Get (m_name, 0, NULL, &cimType, NULL);
  296. *pType = (WbemCimtypeEnum)(cimType & ~CIM_FLAG_ARRAY);
  297. }
  298. if (FAILED(hr))
  299. m_Dispatch.RaiseException (hr);
  300. return hr;
  301. }
  302. //***************************************************************************
  303. //
  304. // SCODE CSWbemProperty::get_IsArray
  305. //
  306. // DESCRIPTION:
  307. //
  308. // Retrieve whether the property is an array type
  309. //
  310. // PARAMETERS:
  311. //
  312. // pIsArray holds the value on return
  313. //
  314. // RETURN VALUES:
  315. //
  316. // WBEM_S_NO_ERROR success
  317. // WBEM_E_INVALID_PARAMETER bad input parameters
  318. // WBEM_E_FAILED otherwise
  319. //
  320. //***************************************************************************
  321. HRESULT CSWbemProperty::get_IsArray (
  322. VARIANT_BOOL *pIsArray
  323. )
  324. {
  325. HRESULT hr = WBEM_E_FAILED;
  326. ResetLastErrors ();
  327. if (NULL == pIsArray)
  328. return WBEM_E_INVALID_PARAMETER;
  329. *pIsArray = FALSE;
  330. if (m_pIWbemClassObject)
  331. {
  332. CIMTYPE cimType = CIM_EMPTY;
  333. hr = m_pIWbemClassObject->Get (m_name, 0, NULL, &cimType, NULL);
  334. *pIsArray = (0 != (cimType & CIM_FLAG_ARRAY))
  335. ? VARIANT_TRUE : VARIANT_FALSE;
  336. }
  337. if (FAILED(hr))
  338. m_Dispatch.RaiseException (hr);
  339. return hr;
  340. }
  341. //***************************************************************************
  342. //
  343. // SCODE CSWbemProperty::get_IsLocal
  344. //
  345. // DESCRIPTION:
  346. //
  347. // Retrieve the property flavor
  348. //
  349. // PARAMETERS:
  350. //
  351. // pFlavor holds the flavor on return
  352. //
  353. // RETURN VALUES:
  354. //
  355. // WBEM_S_NO_ERROR success
  356. // WBEM_E_INVALID_PARAMETER bad input parameters
  357. // WBEM_E_FAILED otherwise
  358. //
  359. //***************************************************************************
  360. HRESULT CSWbemProperty::get_IsLocal (
  361. VARIANT_BOOL *pValue
  362. )
  363. {
  364. HRESULT hr = WBEM_E_FAILED;
  365. ResetLastErrors ();
  366. if (NULL == pValue)
  367. hr = WBEM_E_INVALID_PARAMETER;
  368. else
  369. {
  370. long flavor = 0;
  371. if (m_pIWbemClassObject)
  372. {
  373. if (WBEM_S_NO_ERROR == (hr = m_pIWbemClassObject->Get (m_name, 0, NULL, NULL, &flavor)))
  374. *pValue = (WBEM_FLAVOR_ORIGIN_LOCAL == (flavor & WBEM_FLAVOR_MASK_ORIGIN)) ?
  375. VARIANT_TRUE : VARIANT_FALSE;
  376. }
  377. }
  378. if (FAILED(hr))
  379. m_Dispatch.RaiseException (hr);
  380. return hr;
  381. }
  382. //***************************************************************************
  383. //
  384. // SCODE CSWbemProperty::get_Origin
  385. //
  386. // DESCRIPTION:
  387. //
  388. // Retrieve the property origin
  389. //
  390. // PARAMETERS:
  391. //
  392. // pOrigin holds the origin class on return
  393. //
  394. // RETURN VALUES:
  395. //
  396. // WBEM_S_NO_ERROR success
  397. // WBEM_E_INVALID_PARAMETER bad input parameters
  398. // WBEM_E_FAILED otherwise
  399. //
  400. //***************************************************************************
  401. HRESULT CSWbemProperty::get_Origin (
  402. BSTR *pOrigin
  403. )
  404. {
  405. HRESULT hr = WBEM_S_NO_ERROR;
  406. ResetLastErrors ();
  407. if (NULL == pOrigin)
  408. hr = WBEM_E_INVALID_PARAMETER;
  409. else
  410. {
  411. if (m_pIWbemClassObject)
  412. m_pIWbemClassObject->GetPropertyOrigin (m_name, pOrigin);
  413. if (NULL == *pOrigin)
  414. *pOrigin = SysAllocString (OLESTR(""));
  415. }
  416. if (FAILED(hr))
  417. m_Dispatch.RaiseException (hr);
  418. return hr;
  419. }
  420. //***************************************************************************
  421. //
  422. // SCODE CSWbemProperty::get_Qualifiers_
  423. //
  424. // DESCRIPTION:
  425. //
  426. // Retrieve the property qualifier set
  427. //
  428. // PARAMETERS:
  429. //
  430. // ppQualSet addresses the qualifier set on return
  431. //
  432. // RETURN VALUES:
  433. //
  434. // WBEM_S_NO_ERROR success
  435. // WBEM_E_INVALID_PARAMETER bad input parameters
  436. // WBEM_E_FAILED otherwise
  437. //
  438. //***************************************************************************
  439. HRESULT CSWbemProperty::get_Qualifiers_ (
  440. ISWbemQualifierSet **ppQualSet
  441. )
  442. {
  443. HRESULT hr = WBEM_E_FAILED;
  444. ResetLastErrors ();
  445. if (NULL == ppQualSet)
  446. hr = WBEM_E_INVALID_PARAMETER;
  447. else
  448. {
  449. *ppQualSet = NULL;
  450. if (m_pIWbemClassObject)
  451. {
  452. IWbemQualifierSet *pQualSet = NULL;
  453. if (WBEM_S_NO_ERROR == (hr = m_pIWbemClassObject->GetPropertyQualifierSet
  454. (m_name, &pQualSet)))
  455. {
  456. if (!(*ppQualSet = new CSWbemQualifierSet (pQualSet, m_pSWbemObject)))
  457. hr = WBEM_E_OUT_OF_MEMORY;
  458. pQualSet->Release ();
  459. }
  460. }
  461. }
  462. if (FAILED(hr))
  463. m_Dispatch.RaiseException (hr);
  464. return hr;
  465. }
  466. //***************************************************************************
  467. //
  468. // SCODE CSWbemProperty::UpdateEmbedded
  469. //
  470. // DESCRIPTION:
  471. //
  472. // Given a variant representing an embedded value, set the value
  473. // and update the parent object.
  474. //
  475. // PARAMETERS:
  476. //
  477. // var embedded value (VT_UNKNOWN)
  478. //
  479. // RETURN VALUES:
  480. //
  481. // WBEM_S_NO_ERROR success
  482. // WBEM_E_INVALID_PARAMETER bad input parameters
  483. // WBEM_E_FAILED otherwise
  484. //
  485. //***************************************************************************
  486. void CSWbemProperty::UpdateEmbedded (VARIANT &vNewVal, long index)
  487. {
  488. if (m_pIWbemClassObject)
  489. {
  490. CIMTYPE cimType = CIM_EMPTY;
  491. if (-1 == index)
  492. {
  493. m_pIWbemClassObject->Get (m_name, 0, NULL, &cimType, NULL);
  494. m_pIWbemClassObject->Put (m_name, 0, &vNewVal, cimType);
  495. }
  496. else
  497. {
  498. VARIANT vPropVal;
  499. VariantInit(&vPropVal);
  500. if (SUCCEEDED (m_pIWbemClassObject->Get (m_name, 0, &vPropVal, &cimType, NULL))
  501. && ((VT_UNKNOWN|VT_ARRAY) == V_VT(&vPropVal)))
  502. {
  503. // Set the value into the relevant index of the property value array
  504. if (S_OK == SafeArrayPutElement (vPropVal.parray, &index, V_UNKNOWN(&vNewVal)))
  505. {
  506. // Set the entire property value
  507. m_pIWbemClassObject->Put (m_name, 0, &vPropVal, cimType);
  508. }
  509. }
  510. VariantClear (&vPropVal);
  511. }
  512. }
  513. }
  514. void CSWbemProperty::UpdateSite ()
  515. {
  516. // Update the parent site if it exists
  517. if (m_pSite)
  518. m_pSite->Update ();
  519. }
  520. //***************************************************************************
  521. //
  522. // SCODE CSWbemProperty::CPropertyDispatchHelp::HandleError
  523. //
  524. // DESCRIPTION:
  525. //
  526. // Provide bespoke handling of error conditions in the bolierplate
  527. // Dispatch implementation.
  528. //
  529. // PARAMETERS:
  530. //
  531. // dispidMember, wFlags,
  532. // pdispparams, pvarResult,
  533. // puArgErr, All passed directly from IDispatch::Invoke
  534. // hr The return code from the bolierplate invoke
  535. //
  536. // RETURN VALUES:
  537. // The new return code (to be ultimately returned from Invoke)
  538. //
  539. // WBEM_S_NO_ERROR success
  540. // WBEM_E_INVALID_PARAMETER bad input parameters
  541. // WBEM_E_FAILED otherwise
  542. //
  543. //***************************************************************************
  544. HRESULT CSWbemProperty::CPropertyDispatchHelp::HandleError (
  545. DISPID dispidMember,
  546. unsigned short wFlags,
  547. DISPPARAMS FAR* pdispparams,
  548. VARIANT FAR* pvarResult,
  549. UINT FAR* puArgErr,
  550. HRESULT hr
  551. )
  552. {
  553. if ((DISPID_VALUE == dispidMember) && (DISP_E_NOTACOLLECTION == hr) && (pdispparams->cArgs > 0))
  554. {
  555. /*
  556. * We are looking for calls on the default member (the Value property) which
  557. * supplied an argument. Since the Value property is of type VARIANT, this may
  558. * be legal but undetectable by the standard Dispatch mechanism, because in the
  559. * the case that the property happens to be an array type, it is meaningful to
  560. * pass an index (the interpretation is that the index specifies an offset in
  561. * the VT_ARRAY|VT_VARIANT structure that represents the property value).
  562. */
  563. WbemCimtypeEnum cimtype;
  564. VARIANT_BOOL isArray = FALSE;
  565. ISWbemProperty *pProperty = NULL;
  566. // This tells use where to expect the array index to appear in the argument list
  567. UINT indexArg = (DISPATCH_PROPERTYGET & wFlags) ? 0 : 1;
  568. if (SUCCEEDED (m_pObj->QueryInterface (IID_ISWbemProperty, (PPVOID) &pProperty)))
  569. {
  570. if (SUCCEEDED(pProperty->get_CIMType (&cimtype)) &&
  571. SUCCEEDED(pProperty->get_IsArray (&isArray)) && (isArray))
  572. {
  573. // Extract the current property value
  574. VARIANT vPropVal;
  575. VariantInit(&vPropVal);
  576. if (SUCCEEDED (pProperty->get_Value (&vPropVal)) && V_ISARRAY(&vPropVal))
  577. {
  578. VARIANT indexVar;
  579. VariantInit (&indexVar);
  580. // Attempt to coerce the index argument into a value suitable for an array index
  581. if (S_OK == VariantChangeType (&indexVar, &pdispparams->rgvarg[indexArg], 0, VT_I4))
  582. {
  583. long lArrayPropInx = V_I4(&indexVar);
  584. // Is this a Get? There should be one argument (the array index)
  585. if (DISPATCH_PROPERTYGET & wFlags)
  586. {
  587. if (1 == pdispparams->cArgs)
  588. {
  589. // We should have a VT_ARRAY|VT_VARIANT value at this point; extract the
  590. // VARIANT element we require
  591. VariantInit (pvarResult);
  592. hr = SafeArrayGetElement (vPropVal.parray, &lArrayPropInx, pvarResult);
  593. }
  594. else
  595. hr = DISP_E_BADPARAMCOUNT;
  596. }
  597. else if (DISPATCH_PROPERTYPUT & wFlags)
  598. {
  599. if (2 == pdispparams->cArgs)
  600. {
  601. /*
  602. * Try to interpret this as an array member set operation. For
  603. * this the first argument passed is the new value, and the second
  604. * is the array index.
  605. */
  606. VARIANT vNewVal;
  607. VariantInit(&vNewVal);
  608. if (SUCCEEDED(VariantCopy(&vNewVal, &pdispparams->rgvarg[0])))
  609. {
  610. // Coerce the value if necessary (unless it's embedded)
  611. if ((wbemCimtypeObject == cimtype) ||
  612. (S_OK == VariantChangeType (&vNewVal, &vNewVal, 0, CimTypeToVtType (cimtype))))
  613. {
  614. // Check the index is not out of bounds and, if it is, grow
  615. // the array accordingly
  616. CheckArrayBounds (vPropVal.parray, lArrayPropInx);
  617. // Set the value into the relevant index of the property value array
  618. if (S_OK == (hr =
  619. SafeArrayPutElement (vPropVal.parray, &lArrayPropInx, &vNewVal)))
  620. {
  621. // Set the entire property value
  622. if (SUCCEEDED (pProperty->put_Value (&vPropVal)))
  623. {
  624. hr = S_OK;
  625. // Upcast is OK here because m_pObj is really a (CSWbemProperty*)
  626. CSWbemProperty *pSProperty = (CSWbemProperty *)m_pObj;
  627. // Did we save an embedded object value? If so make sure the
  628. // site is correctly set to this property.
  629. SetSite (&pdispparams->rgvarg[0],
  630. pSProperty->m_pSWbemObject, pSProperty->m_name,
  631. lArrayPropInx);
  632. // Propagate the change to the owning site
  633. pSProperty->UpdateSite ();
  634. }
  635. else
  636. {
  637. hr = DISP_E_TYPEMISMATCH;
  638. if (puArgErr)
  639. *puArgErr = 0;
  640. }
  641. }
  642. }
  643. else
  644. {
  645. hr = DISP_E_TYPEMISMATCH;
  646. if (puArgErr)
  647. *puArgErr = 0;
  648. }
  649. VariantClear (&vNewVal);
  650. }
  651. }
  652. else
  653. hr = DISP_E_BADPARAMCOUNT;
  654. }
  655. }
  656. else
  657. {
  658. hr = DISP_E_TYPEMISMATCH;
  659. if (puArgErr)
  660. *puArgErr = indexArg;
  661. }
  662. VariantClear (&indexVar);
  663. }
  664. VariantClear (&vPropVal);
  665. }
  666. pProperty->Release ();
  667. }
  668. }
  669. return hr;
  670. }