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.

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