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.

532 lines
13 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation
  4. //
  5. // NVALUE.CPP
  6. //
  7. // alanbos 15-Aug-96 Created.
  8. //
  9. // Defines the implementation of ISWbemNamedValue
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. //***************************************************************************
  14. //
  15. // CSWbemNamedValue::CSWbemNamedValue
  16. //
  17. // DESCRIPTION:
  18. //
  19. // Constructor.
  20. //
  21. //***************************************************************************
  22. CSWbemNamedValue::CSWbemNamedValue(
  23. CSWbemServices *pService,
  24. CSWbemNamedValueSet *pCSWbemNamedValueSet,
  25. BSTR name,
  26. bool bMutable
  27. )
  28. : m_bMutable (bMutable),
  29. m_cRef (1),
  30. m_pCSWbemNamedValueSet (pCSWbemNamedValueSet),
  31. m_pSWbemServices (pService)
  32. {
  33. m_Dispatch.SetObj (this, IID_ISWbemNamedValue,
  34. CLSID_SWbemNamedValue, L"SWbemNamedValue");
  35. if (m_pCSWbemNamedValueSet)
  36. m_pCSWbemNamedValueSet->AddRef ();
  37. if (m_pSWbemServices)
  38. m_pSWbemServices->AddRef ();
  39. m_name = SysAllocString (name);
  40. InterlockedIncrement(&g_cObj);
  41. }
  42. //***************************************************************************
  43. //
  44. // CSWbemNamedValue::~CSWbemNamedValue
  45. //
  46. // DESCRIPTION:
  47. //
  48. // Destructor.
  49. //
  50. //***************************************************************************
  51. CSWbemNamedValue::~CSWbemNamedValue(void)
  52. {
  53. InterlockedDecrement(&g_cObj);
  54. if (m_pCSWbemNamedValueSet)
  55. {
  56. m_pCSWbemNamedValueSet->Release ();
  57. m_pCSWbemNamedValueSet = NULL;
  58. }
  59. if (m_pSWbemServices)
  60. {
  61. m_pSWbemServices->Release ();
  62. m_pSWbemServices = NULL;
  63. }
  64. SysFreeString (m_name);
  65. }
  66. //***************************************************************************
  67. // HRESULT CSWbemNamedValue::QueryInterface
  68. // long CSWbemNamedValue::AddRef
  69. // long CSWbemNamedValue::Release
  70. //
  71. // DESCRIPTION:
  72. //
  73. // Standard Com IUNKNOWN functions.
  74. //
  75. //***************************************************************************
  76. STDMETHODIMP CSWbemNamedValue::QueryInterface (
  77. IN REFIID riid,
  78. OUT LPVOID *ppv
  79. )
  80. {
  81. *ppv=NULL;
  82. if (IID_IUnknown==riid)
  83. *ppv = reinterpret_cast<IUnknown*>(this);
  84. else if (IID_ISWbemNamedValue==riid)
  85. *ppv = (ISWbemNamedValue *)this;
  86. else if (IID_IDispatch==riid)
  87. *ppv = (IDispatch *)this;
  88. else if (IID_ISupportErrorInfo==riid)
  89. *ppv = (ISupportErrorInfo *)this;
  90. else if (IID_IProvideClassInfo==riid)
  91. *ppv = (IProvideClassInfo *)this;
  92. if (NULL!=*ppv)
  93. {
  94. ((LPUNKNOWN)*ppv)->AddRef();
  95. return NOERROR;
  96. }
  97. return ResultFromScode(E_NOINTERFACE);
  98. }
  99. STDMETHODIMP_(ULONG) CSWbemNamedValue::AddRef(void)
  100. {
  101. InterlockedIncrement(&m_cRef);
  102. return m_cRef;
  103. }
  104. STDMETHODIMP_(ULONG) CSWbemNamedValue::Release(void)
  105. {
  106. InterlockedDecrement(&m_cRef);
  107. if (0L!=m_cRef)
  108. return m_cRef;
  109. delete this;
  110. return 0;
  111. }
  112. //***************************************************************************
  113. // HRESULT CSWbemNamedValue::InterfaceSupportsErrorInfo
  114. //
  115. // DESCRIPTION:
  116. //
  117. // Standard Com ISupportErrorInfo functions.
  118. //
  119. //***************************************************************************
  120. STDMETHODIMP CSWbemNamedValue::InterfaceSupportsErrorInfo (IN REFIID riid)
  121. {
  122. return (IID_ISWbemNamedValue == riid) ? S_OK : S_FALSE;
  123. }
  124. //***************************************************************************
  125. //
  126. // SCODE CSWbemNamedValue::get_Value
  127. //
  128. // DESCRIPTION:
  129. //
  130. // Retrieve the value
  131. //
  132. // PARAMETERS:
  133. //
  134. // pValue holds the value on return
  135. //
  136. // RETURN VALUES:
  137. //
  138. // WBEM_S_NO_ERROR success
  139. // WBEM_E_INVALID_PARAMETER bad input parameters
  140. // WBEM_E_FAILED otherwise
  141. //
  142. //***************************************************************************
  143. HRESULT CSWbemNamedValue::get_Value (
  144. VARIANT *pValue
  145. )
  146. {
  147. HRESULT hr = WBEM_E_FAILED;
  148. ResetLastErrors ();
  149. if (NULL == pValue)
  150. hr = WBEM_E_INVALID_PARAMETER;
  151. else
  152. {
  153. VariantClear (pValue);
  154. IWbemContext *pIWbemContext = m_pCSWbemNamedValueSet->GetIWbemContext ();
  155. if (pIWbemContext)
  156. {
  157. hr = pIWbemContext->GetValue (m_name, 0, pValue);
  158. pIWbemContext->Release ();
  159. }
  160. }
  161. if (FAILED(hr))
  162. m_Dispatch.RaiseException (hr);
  163. return hr;
  164. }
  165. //***************************************************************************
  166. //
  167. // SCODE CSWbemNamedValue::put_Value
  168. //
  169. // DESCRIPTION:
  170. //
  171. // Set the value
  172. //
  173. // PARAMETERS:
  174. //
  175. // pVal the new value
  176. //
  177. // RETURN VALUES:
  178. //
  179. // WBEM_S_NO_ERROR success
  180. // WBEM_E_INVALID_PARAMETER bad input parameters
  181. // WBEM_E_FAILED otherwise
  182. //
  183. //***************************************************************************
  184. HRESULT CSWbemNamedValue::put_Value (
  185. VARIANT *pVal
  186. )
  187. {
  188. HRESULT hr = WBEM_E_FAILED;
  189. ResetLastErrors ();
  190. if (NULL == pVal)
  191. hr = WBEM_E_INVALID_PARAMETER;
  192. else if (!m_bMutable)
  193. hr = WBEM_E_READ_ONLY;
  194. else
  195. {
  196. CComPtr<IWbemContext> pIWbemContext;
  197. //Can't assign directly because the raw pointer gets AddRef'd twice and we leak,
  198. //So we use Attach() instead to prevent the smart pointer from AddRef'ing.
  199. pIWbemContext.Attach(m_pCSWbemNamedValueSet->GetIWbemContext ());
  200. if (pIWbemContext)
  201. {
  202. CWbemPathCracker *pPathCracker = m_pCSWbemNamedValueSet->GetWbemPathCracker ();
  203. CIMTYPE newCimType = CIM_ILLEGAL;
  204. if (VT_BYREF & V_VT(pVal))
  205. {
  206. // We must dereference all byref's
  207. VARIANT var;
  208. VariantInit (&var);
  209. if (VT_ARRAY & V_VT(pVal))
  210. {
  211. var.vt = V_VT(pVal) & ~VT_BYREF;
  212. hr = SafeArrayCopy (*(pVal->pparray), &(var.parray));
  213. }
  214. else
  215. hr = VariantChangeType(&var, pVal, 0, V_VT(pVal) & ~VT_BYREF);
  216. if (SUCCEEDED(hr))
  217. {
  218. // Here the oldCimType is a "serving suggestion" - if
  219. // we need a different cimtype to match the new value
  220. // so be it, even if it's CIM_ILLEGAL
  221. newCimType = MapVariantTypeToCimType (&var, CIM_ILLEGAL);
  222. bool ok = true;
  223. // If we have a keylist, must ensure we can set it in the
  224. // keylist first
  225. if (pPathCracker)
  226. {
  227. if (pPathCracker->SetKey (m_name, (WbemCimtypeEnum) newCimType, var))
  228. ok = false;
  229. }
  230. if (ok)
  231. {
  232. // Finally set it in the context itself
  233. hr = pIWbemContext->SetValue (m_name, 0, &var);
  234. }
  235. else
  236. hr = WBEM_E_FAILED;
  237. }
  238. VariantClear (&var);
  239. }
  240. else if ((VT_ERROR == V_VT(pVal)) && (DISP_E_PARAMNOTFOUND == pVal->scode))
  241. {
  242. // Treat as NULL assignment
  243. pVal->vt = VT_NULL;
  244. // NULL assigments not valid for keylists
  245. if (pPathCracker)
  246. hr = WBEM_E_FAILED;
  247. else
  248. {
  249. hr = pIWbemContext->SetValue (m_name, 0, pVal);
  250. }
  251. }
  252. else
  253. {
  254. // Here the oldCimType is a "serving suggestion" - if
  255. // we need a different cimtype to match the new value
  256. // so be it, even if it's CIM_ILLEGAL
  257. newCimType = MapVariantTypeToCimType (pVal, CIM_ILLEGAL);
  258. bool ok = true;
  259. // If we have a keylist, must ensure we can set it in the
  260. // keylist first
  261. if (pPathCracker)
  262. {
  263. if (pPathCracker->SetKey (m_name, (WbemCimtypeEnum) newCimType, *pVal))
  264. ok = false;
  265. }
  266. if (ok)
  267. {
  268. // Finally set it in the context itself
  269. hr = pIWbemContext->SetValue (m_name, 0, pVal);
  270. }
  271. else
  272. hr = WBEM_E_FAILED;
  273. }
  274. if (pPathCracker)
  275. pPathCracker->Release ();
  276. }
  277. }
  278. if (FAILED(hr))
  279. m_Dispatch.RaiseException (hr);
  280. return hr;
  281. }
  282. //***************************************************************************
  283. //
  284. // SCODE CSWbemNamedValue::get_Name
  285. //
  286. // DESCRIPTION:
  287. //
  288. // Retrieve the value name
  289. //
  290. // PARAMETERS:
  291. //
  292. // pName holds the name on return
  293. //
  294. // RETURN VALUES:
  295. //
  296. // WBEM_S_NO_ERROR success
  297. // WBEM_E_INVALID_PARAMETER bad input parameters
  298. // WBEM_E_FAILED otherwise
  299. //
  300. //***************************************************************************
  301. HRESULT CSWbemNamedValue::get_Name (
  302. BSTR *pName
  303. )
  304. {
  305. HRESULT hr = WBEM_S_NO_ERROR;
  306. ResetLastErrors ();
  307. if (NULL == pName)
  308. hr = WBEM_E_INVALID_PARAMETER;
  309. else
  310. *pName = SysAllocString (m_name);
  311. if (FAILED(hr))
  312. m_Dispatch.RaiseException (hr);
  313. return hr;
  314. }
  315. //***************************************************************************
  316. //
  317. // SCODE CSWbemNamedValue::CNamedValueDispatchHelp::HandleError
  318. //
  319. // DESCRIPTION:
  320. //
  321. // Provide bespoke handling of error conditions in the bolierplate
  322. // Dispatch implementation.
  323. //
  324. // PARAMETERS:
  325. //
  326. // dispidMember, wFlags,
  327. // pdispparams, pvarResult,
  328. // puArgErr, All passed directly from IDispatch::Invoke
  329. // hr The return code from the bolierplate invoke
  330. //
  331. // RETURN VALUES:
  332. // The new return code (to be ultimately returned from Invoke)
  333. //
  334. // WBEM_S_NO_ERROR success
  335. // WBEM_E_INVALID_PARAMETER bad input parameters
  336. // WBEM_E_FAILED otherwise
  337. //
  338. //***************************************************************************
  339. HRESULT CSWbemNamedValue::CNamedValueDispatchHelp::HandleError (
  340. DISPID dispidMember,
  341. unsigned short wFlags,
  342. DISPPARAMS FAR* pdispparams,
  343. VARIANT FAR* pvarResult,
  344. UINT FAR* puArgErr,
  345. HRESULT hr
  346. )
  347. {
  348. /*
  349. * We are looking for calls on the default member (the Value property) which
  350. * supplied an argument. Since the Value property is of type VARIANT, this may
  351. * be legal but undetectable by the standard Dispatch mechanism, because in the
  352. * the case that the named value happens to be an array type, it is meaningful to
  353. * pass an index (the interpretation is that the index specifies an offset in
  354. * the VT_ARRAY|VT_VARIANT structure that represents the named value).
  355. */
  356. if ((DISPID_VALUE == dispidMember) && (DISP_E_NOTACOLLECTION == hr) && (pdispparams->cArgs > 0))
  357. {
  358. // Looks promising - get the object to try and resolve this
  359. ISWbemNamedValue *pNamedValue = NULL;
  360. // This tells us where to expect the array index to appear in the argument list
  361. UINT indexArg = (DISPATCH_PROPERTYGET & wFlags) ? 0 : 1;
  362. if (SUCCEEDED (m_pObj->QueryInterface (IID_ISWbemNamedValue, (PPVOID) &pNamedValue)))
  363. {
  364. // Extract the current named value
  365. VARIANT vNVal;
  366. VariantInit (&vNVal);
  367. if (SUCCEEDED(pNamedValue->get_Value (&vNVal)) && V_ISARRAY(&vNVal))
  368. {
  369. VARIANT indexVar;
  370. VariantInit (&indexVar);
  371. // Attempt to coerce the index argument into a value suitable for an array index
  372. if (S_OK == VariantChangeType (&indexVar, &pdispparams->rgvarg[indexArg], 0, VT_I4))
  373. {
  374. long lArrayPropInx = V_I4(&indexVar);
  375. // Is this a Get? There should be one argument (the array index)
  376. if (DISPATCH_PROPERTYGET & wFlags)
  377. {
  378. if (1 == pdispparams->cArgs)
  379. {
  380. // We should have a VT_ARRAY|VT_VARIANT value at this point; extract the
  381. // VARIANT
  382. VariantInit (pvarResult);
  383. hr = SafeArrayGetElement (vNVal.parray, &lArrayPropInx, pvarResult);
  384. }
  385. else
  386. hr = DISP_E_BADPARAMCOUNT;
  387. }
  388. else if (DISPATCH_PROPERTYPUT & wFlags)
  389. {
  390. if (2 == pdispparams->cArgs)
  391. {
  392. /*
  393. * Try to interpret this as an array member set operation. For
  394. * this the first argument passed is the new value, and the second
  395. * is the array index.
  396. */
  397. VARIANT vNewVal;
  398. VariantInit(&vNewVal);
  399. if (SUCCEEDED(VariantCopy(&vNewVal, &pdispparams->rgvarg[0])))
  400. {
  401. // Check the index is not out of bounds and, if it is, grow
  402. // the array accordingly
  403. CheckArrayBounds (vNVal.parray, lArrayPropInx);
  404. // How do we decide on the type - try to access an array
  405. // member and use that type
  406. VARTYPE expectedVarType = VT_ILLEGAL;
  407. VARIANT dummyVar;
  408. VariantInit (&dummyVar);
  409. long lBound;
  410. SafeArrayGetLBound (vNVal.parray, 1, &lBound);
  411. if (SUCCEEDED (SafeArrayGetElement (vNVal.parray, &lBound, &dummyVar)))
  412. expectedVarType = V_VT(&dummyVar);
  413. VariantClear (&dummyVar);
  414. if (S_OK == VariantChangeType (&vNewVal, &vNewVal, 0, expectedVarType))
  415. {
  416. // Set the value into the relevant index of the named value array
  417. if (S_OK == (hr =
  418. SafeArrayPutElement (vNVal.parray, &lArrayPropInx, &vNewVal)))
  419. {
  420. // Set the entire property value
  421. if (SUCCEEDED (pNamedValue->put_Value (&vNVal)))
  422. hr = S_OK;
  423. else
  424. {
  425. hr = DISP_E_TYPEMISMATCH;
  426. if (puArgErr)
  427. *puArgErr = 0;
  428. }
  429. }
  430. }
  431. else
  432. {
  433. hr = DISP_E_TYPEMISMATCH;
  434. if (puArgErr)
  435. *puArgErr = 0;
  436. }
  437. VariantClear (&vNewVal);
  438. }
  439. }
  440. else
  441. hr = DISP_E_BADPARAMCOUNT;
  442. }
  443. }
  444. else
  445. {
  446. hr = DISP_E_TYPEMISMATCH;
  447. if (puArgErr)
  448. *puArgErr = indexArg;
  449. }
  450. VariantClear (&indexVar);
  451. }
  452. VariantClear (&vNVal);
  453. }
  454. pNamedValue->Release ();
  455. }
  456. return hr;
  457. }