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.

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