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.

1254 lines
32 KiB

  1. /*++
  2. Copyright (C) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. IMPDYN.CPP
  5. Abstract:
  6. Defines the virtual base class for the Dynamic Provider
  7. objects. The base class is overriden for each specific
  8. provider which provides the details of how an actual
  9. property "Put" or "Get" is done.
  10. History:
  11. a-davj 27-Sep-95 Created.
  12. --*/
  13. #include "precomp.h"
  14. #include <wbemidl.h>
  15. //#define _MT
  16. #include <process.h>
  17. #include "impdyn.h"
  18. #include "CVariant.h"
  19. #include <genlex.h>
  20. #include <objpath.h>
  21. #include <genutils.h>
  22. #include <cominit.h>
  23. //***************************************************************************
  24. //
  25. // CImpDyn::CImpDyn
  26. //
  27. // DESCRIPTION:
  28. //
  29. // Constructor.
  30. //
  31. // PARAMETERS:
  32. //
  33. // ObjectPath Full path to the namespace
  34. // User User name
  35. // Password Password
  36. //
  37. //***************************************************************************
  38. CImpDyn::CImpDyn() : m_pGateway(NULL), m_cRef(0)
  39. {
  40. wcCLSID[0] = 0; // Set to correct value in derived class constructors
  41. }
  42. HRESULT STDMETHODCALLTYPE CImpDyn::Initialize(LPWSTR wszUser, long lFlags,
  43. LPWSTR wszNamespace, LPWSTR wszLocale,
  44. IWbemServices* pNamespace, IWbemContext* pContext,
  45. IWbemProviderInitSink* pSink)
  46. {
  47. m_pGateway = pNamespace;
  48. m_pGateway->AddRef();
  49. pSink->SetStatus(WBEM_S_NO_ERROR, 0);
  50. return WBEM_S_NO_ERROR;
  51. }
  52. //***************************************************************************
  53. //
  54. // CImpDyn::~CImpDyn
  55. //
  56. // DESCRIPTION:
  57. //
  58. // Destructor.
  59. //
  60. //***************************************************************************
  61. CImpDyn::~CImpDyn(void)
  62. {
  63. if(m_pGateway)
  64. m_pGateway->Release();
  65. return;
  66. }
  67. //***************************************************************************
  68. //
  69. // SCODE CImpDyn::CreateInstanceEnum
  70. //
  71. // DESCRIPTION:
  72. //
  73. // Creates an enumerator object that can be used to enumerate
  74. // the instances of this class.
  75. //
  76. // PARAMETERS:
  77. //
  78. // Class Path specifying the class to be enumerated
  79. // lFlags flags to control the enumeration
  80. // phEnum returned pointer to enumerator
  81. // ppErrorObject returned pointer to error object
  82. //
  83. // RETURN VALUE:
  84. //
  85. // S_OK if all is well
  86. // WBEM_E_OUT_OF_MEMORY if not enough memory
  87. // various error codes from IWbemServices::GetObject
  88. //
  89. //***************************************************************************
  90. SCODE CImpDyn::CreateInstanceEnum(
  91. IN const BSTR Class,
  92. IN long lFlags,
  93. IWbemContext *pCtx,
  94. OUT IN IEnumWbemClassObject FAR* FAR* phEnum)
  95. {
  96. CEnumInst * pEnumObj;
  97. SCODE sc;
  98. WCHAR * pwcClassContext = NULL;
  99. IWbemClassObject * pClassInt = NULL;
  100. CEnumInfo * pInfo = NULL;
  101. // Get the class
  102. sc = m_pGateway->GetObject(Class,0, pCtx, &pClassInt,NULL);
  103. if(sc != S_OK)
  104. return sc;
  105. // Get the class context string
  106. sc = GetAttString(pClassInt, NULL, L"classcontext", &pwcClassContext);
  107. pClassInt->Release();
  108. if(sc != S_OK)
  109. return sc;
  110. // Get the info needed for enumeration. This is overrided by any
  111. // provider that supports dynamic instances.
  112. CProvObj ProvObj(pwcClassContext,MAIN_DELIM, NeedsEscapes());
  113. sc = MakeEnum(pClassInt,ProvObj,&pInfo);
  114. delete pwcClassContext;
  115. if(sc != S_OK)
  116. return sc;
  117. pEnumObj=new CEnumInst(pInfo,lFlags,Class,m_pGateway,this, pCtx);
  118. if(pEnumObj == NULL)
  119. {
  120. delete pInfo;
  121. return WBEM_E_OUT_OF_MEMORY;
  122. }
  123. // Once the enumerator object is created, it owns the info object and
  124. // will free it appropriatly
  125. sc = pEnumObj->QueryInterface(IID_IEnumWbemClassObject,(void **) phEnum);
  126. if(FAILED(sc))
  127. delete pEnumObj;
  128. return sc;
  129. }
  130. //***************************************************************************
  131. //
  132. // CreateInstanceEnumAsyncThread
  133. //
  134. // DESCRIPTION:
  135. //
  136. // Routine for which does the work and sends the
  137. // subsequent notify for the Instance provider's CreateInstanceEnumAsync
  138. // routine.
  139. //
  140. // PARAMETERS:
  141. //
  142. // pIEnum Our enumerator
  143. // pSink Core's sink
  144. // pGateway IWbemServices pointer to the core
  145. // pCtx context to be used.
  146. //
  147. //***************************************************************************
  148. void CreateInstanceEnumAsyncThread( IEnumWbemClassObject FAR* pIEnum,
  149. IWbemObjectSink FAR* pSink, IWbemServices FAR * pGateway, IWbemContext *pCtx)
  150. {
  151. IWbemClassObject * pNewInst = NULL;
  152. SCODE sc = S_OK;
  153. // enumerate and send each object to the notify interface
  154. while (sc == S_OK)
  155. {
  156. ULONG uRet;
  157. sc = pIEnum->Next(-1, 1,&pNewInst,&uRet);
  158. if(sc == S_OK)
  159. {
  160. pSink->Indicate(1,&pNewInst);
  161. pNewInst->Release();
  162. }
  163. }
  164. pSink->SetStatus(0,0,NULL, NULL);
  165. }
  166. //***************************************************************************
  167. //
  168. // SCODE CInstPro::CreateInstanceEnumAsync
  169. //
  170. // DESCRIPTION:
  171. //
  172. // Asynchronously enumeratres the instances of this class.
  173. //
  174. // PARAMETERS:
  175. //
  176. // RefStr Path which defines the object class
  177. // lFlags enumeration flags
  178. // pSink Pointer to the notify object
  179. // plAsyncRequestHandle pointer to the enumeration cancel handle (future use)
  180. //
  181. // RETURN VALUE:
  182. //
  183. // S_OK All is well
  184. // WBEM_E_INVALID_PARAMETER Bad argument
  185. // WBEM_E_OUT_OF_MEMORY Lacked resources to create a thread
  186. // otherwise, error from CreateInstanceEnum
  187. //
  188. //***************************************************************************
  189. SCODE CImpDyn::CreateInstanceEnumAsync(
  190. IN const BSTR RefStr,
  191. IN long lFlags,
  192. IWbemContext __RPC_FAR *pCtx,
  193. OUT IWbemObjectSink FAR* pSink)
  194. {
  195. SCODE sc = S_OK;
  196. IEnumWbemClassObject * pIEnum = NULL;
  197. if(pSink == NULL || RefStr == NULL)
  198. return WBEM_E_INVALID_PARAMETER;
  199. if(IsNT() && IsDcomEnabled())
  200. sc = WbemCoImpersonateClient();
  201. if(sc == S_OK)
  202. sc = CreateInstanceEnum(RefStr,lFlags, pCtx, &pIEnum);
  203. if(sc != S_OK)
  204. {
  205. pSink->SetStatus(0, sc, NULL, NULL);
  206. return S_OK;
  207. }
  208. CreateInstanceEnumAsyncThread(pIEnum, pSink, m_pGateway, pCtx);
  209. pIEnum->Release();
  210. return S_OK;
  211. }
  212. //***************************************************************************
  213. //
  214. // SCODE CImpDyn::CreateClassEnumAsync
  215. //
  216. // DESCRIPTION:
  217. //
  218. // Asynchronously enumeratres the classes that this provider supplies. This is
  219. // acutally just a ruse to get the core to load the dll.
  220. //
  221. // PARAMETERS:
  222. //
  223. // SuperClass Parent to be enumerated.
  224. // lFlags enumeration flags
  225. // pResponseHandler Pointer to the notify object
  226. // plAsyncRequestHandle pointer to the enumeration cancel handle (future use)
  227. //
  228. // RETURN VALUE:
  229. //
  230. // S_OK All is well
  231. //
  232. //***************************************************************************
  233. IWbemServices * gGateway;
  234. SCODE CImpDyn::CreateClassEnumAsync(BSTR Superclass, long lFlags,IWbemContext *pCtx, IWbemObjectSink FAR* pResponseHandler)
  235. {
  236. return E_NOTIMPL;
  237. }
  238. //***************************************************************************
  239. //
  240. // SCODE CImpDyn::GetObject
  241. //
  242. // DESCRIPTION:
  243. //
  244. // Creates an instance given a particular path value.
  245. //
  246. // PARAMETERS:
  247. //
  248. // ObjectPath Object path
  249. // lFlags flags
  250. // pObj Set to point to the created object
  251. // ppErrorObject Optional error object pointer
  252. //
  253. // RETURN VALUE:
  254. //
  255. // S_OK All is well
  256. // WBEM_E_NOT_FOUND bad path
  257. // otherwise the return code from CreateInst
  258. //
  259. //***************************************************************************
  260. SCODE CImpDyn::GetObject(
  261. IN BSTR ObjectPath,
  262. IN long lFlags,
  263. IWbemContext *pCtx,
  264. OUT IWbemClassObject FAR* FAR* pObj,
  265. IWbemCallResult **ppCallResult)
  266. {
  267. SCODE sc = S_OK;
  268. // Parse the object path.
  269. // ======================
  270. ParsedObjectPath * pOutput = 0;
  271. CObjectPathParser p;
  272. int nStatus = p.Parse(ObjectPath, &pOutput);
  273. if(nStatus != 0)
  274. return ReturnAndSetObj(WBEM_E_NOT_FOUND, ppCallResult);
  275. WCHAR wcKeyValue[BUFF_SIZE];
  276. sc = WBEM_E_NOT_FOUND;
  277. if(pOutput->m_dwNumKeys > 0 || pOutput->m_bSingletonObj)
  278. {
  279. if(pOutput->m_bSingletonObj)
  280. wcscpy(wcKeyValue,L"@");
  281. else
  282. {
  283. KeyRef *pTmp = pOutput->m_paKeys[0];
  284. switch (V_VT(&pTmp->m_vValue))
  285. {
  286. case VT_I4:
  287. swprintf(wcKeyValue, L"%d", V_I4(&pTmp->m_vValue));
  288. break;
  289. case VT_BSTR:
  290. wcsncpy(wcKeyValue, V_BSTR(&pTmp->m_vValue), BUFF_SIZE-1);
  291. break;
  292. default:
  293. wcscpy(wcKeyValue, L"<unknown>");;
  294. }
  295. }
  296. sc = CreateInst(m_pGateway,pOutput->m_pClass,wcKeyValue,pObj, NULL, NULL, pCtx);
  297. }
  298. // Create the instance.
  299. p.Free(pOutput);
  300. return ReturnAndSetObj(sc, ppCallResult);
  301. }
  302. //***************************************************************************
  303. //
  304. // GetObjectAsyncThread
  305. //
  306. // DESCRIPTION:
  307. //
  308. // Routine for the thread which does the work and sends the
  309. // subsequent notify to the Instance provider's GetObjectAsync
  310. // routine.
  311. //
  312. // PARAMETERS:
  313. //
  314. // pTemp pointer to the argument structure
  315. //
  316. //***************************************************************************
  317. void GetObjectAsyncThread(WCHAR * pObjPath, long lFlags, IWbemObjectSink FAR* pSink,
  318. CImpDyn * pThis, IWbemContext *pCtx)
  319. {
  320. IWbemClassObject FAR* pNewInst = NULL;
  321. SCODE sc = pThis->GetObject(pObjPath, lFlags, pCtx, &pNewInst, NULL);
  322. if(sc == WBEM_NO_ERROR)
  323. {
  324. pSink->Indicate(1,&pNewInst);
  325. pNewInst->Release();
  326. }
  327. pSink->SetStatus(0, sc, NULL, NULL);
  328. }
  329. //***************************************************************************
  330. //
  331. // SCODE CInstPro::GetObjectAsync
  332. //
  333. // DESCRIPTION:
  334. //
  335. // Asynchronously gets an instance of this class.
  336. //
  337. // PARAMETERS:
  338. //
  339. // RefStr Path which defines the object class
  340. // lFlags enumeration flags
  341. // pSink Pointer to the notify object
  342. // plAsyncRequestHandle pointer to the enumeration cancel handle (future use)
  343. //
  344. // RETURN VALUE:
  345. //
  346. // S_OK All is well
  347. // WBEM_E_INVALID_PARAMETER Bad argument
  348. // WBEM_E_OUT_OF_MEMORY Lacked resources to create a thread
  349. //
  350. //***************************************************************************
  351. SCODE CImpDyn::GetObjectAsync(
  352. IN BSTR ObjPath,
  353. IN long lFlags,
  354. IWbemContext __RPC_FAR *pCtx,
  355. IN IWbemObjectSink FAR* pSink)
  356. {
  357. if(pSink == NULL || ObjPath == NULL)
  358. return WBEM_E_INVALID_PARAMETER;
  359. if(IsNT() && IsDcomEnabled())
  360. {
  361. SCODE sc = WbemCoImpersonateClient();
  362. if(sc != S_OK)
  363. {
  364. pSink->SetStatus(0, sc, NULL, NULL);
  365. return S_OK;
  366. }
  367. }
  368. GetObjectAsyncThread(ObjPath, lFlags, pSink, this, pCtx);
  369. return S_OK;
  370. }
  371. //***************************************************************************
  372. //
  373. // SCODE CImpDyn::StartBatch
  374. //
  375. // DESCRIPTION:
  376. //
  377. // Called at the start of a batch of gets or puts. Overriden by
  378. // derived classes which need to do something.
  379. //
  380. // PARAMETERS:
  381. //
  382. // lFlags flags
  383. // pClassInt Points to an instance object
  384. // pObj Misc object pointer
  385. // bGet TRUE if we will be getting data.
  386. //
  387. // RETURN VALUE:
  388. //
  389. // S_OK
  390. //***************************************************************************
  391. SCODE CImpDyn::StartBatch(
  392. IN long lFlags,
  393. IN IWbemClassObject FAR * pClassInt,
  394. IN CObject **pObj,
  395. IN BOOL bGet)
  396. {
  397. *pObj = NULL;
  398. return S_OK;
  399. }
  400. //***************************************************************************
  401. //
  402. // CImpDyn::EndBatch
  403. //
  404. // DESCRIPTION:
  405. //
  406. // Called at the end of a batch of gets or puts. Overriden by
  407. // derived classes which need to do something.
  408. //
  409. // lFlags flags
  410. // pClassInt Points to an instance object
  411. // pObj Misc object pointer
  412. // bGet TRUE if we will be getting data.
  413. //
  414. // RETURN VALUE:
  415. //
  416. // S_OK
  417. //***************************************************************************
  418. void CImpDyn::EndBatch(
  419. IN long lFlags,
  420. IN IWbemClassObject FAR * pClassInt,
  421. IN CObject *pObj,
  422. IN BOOL bGet)
  423. {
  424. if(pObj)
  425. delete pObj;
  426. }
  427. //***************************************************************************
  428. // HRESULT CImpDyn::QueryInterface
  429. // long CImpDyn::AddRef
  430. // long CImpDyn::Release
  431. //
  432. // DESCRIPTION:
  433. //
  434. // Standard Com IUNKNOWN functions.
  435. //
  436. //***************************************************************************
  437. STDMETHODIMP CImpDyn::QueryInterface(
  438. IN REFIID riid,
  439. OUT PPVOID ppv)
  440. {
  441. *ppv=NULL;
  442. // The only calls for IUnknown are either in a nonaggregated
  443. // case or when created in an aggregation, so in either case
  444. // always return our IUnknown for IID_IUnknown.
  445. if (IID_IUnknown==riid || IID_IWbemServices == riid)
  446. *ppv=(IWbemServices*)this;
  447. else if (IID_IWbemProviderInit==riid)
  448. *ppv=(IWbemProviderInit*)this;
  449. if (NULL!=*ppv)
  450. {
  451. ((LPUNKNOWN)*ppv)->AddRef();
  452. return NOERROR;
  453. }
  454. return ResultFromScode(E_NOINTERFACE);
  455. }
  456. STDMETHODIMP_(ULONG) CImpDyn::AddRef(void)
  457. {
  458. return InterlockedIncrement(&m_cRef);
  459. }
  460. STDMETHODIMP_(ULONG) CImpDyn::Release(void)
  461. {
  462. long lRet = InterlockedDecrement(&m_cRef);
  463. if (0L!=lRet)
  464. return lRet;
  465. /*
  466. * Tell the housing that an object is going away so it can
  467. * shut down if appropriate.
  468. */
  469. delete this; // do before decrementing module obj count.
  470. InterlockedDecrement(&lObj);
  471. return 0;
  472. }
  473. //***************************************************************************
  474. //
  475. // CImpDyn::EnumPropDoFunc
  476. //
  477. // DESCRIPTION:
  478. //
  479. // This gets an objects attributes and then loops through the propeties
  480. // calling UpdateProperty or RefreshProperty to put or get the data.
  481. //
  482. // PARAMETERS:
  483. //
  484. // lFlags flags
  485. // pClassInt Object being refreshed or updated
  486. // FuncType Indicates if refresh or update
  487. // pwcKey Optional Key value of the object
  488. // pCache Option cache
  489. //
  490. // RETURN VALUE:
  491. //
  492. // S_OK all is well
  493. // otherwise an WBEMSVC type error.
  494. //
  495. //***************************************************************************
  496. SCODE CImpDyn::EnumPropDoFunc(
  497. IN long lFlags,
  498. OUT IN IWbemClassObject FAR* pInstance,
  499. IN FUNCTYPE FuncType,
  500. IN WCHAR * pwcKey,
  501. OUT IN CIndexCache * pCache,
  502. IN IWbemClassObject * pClass)
  503. {
  504. SCODE sc;
  505. BSTR PropName;
  506. WCHAR * pwcClassContext = NULL;
  507. WCHAR * pwcKeyValue = NULL;
  508. WCHAR * pwcTemp = NULL;
  509. BOOL bClsidSetForClass = FALSE;
  510. CProvObj * pProvObj = NULL;
  511. BSTR bstrKeyName = NULL;
  512. BOOL bGotOurClass = FALSE;
  513. int iWorked = 0;
  514. int iCurr = 0;
  515. CVariant vProp;
  516. BOOL bTesterDetails = FALSE;
  517. bool bAccessDenied = false;
  518. // Make sure we have a class object. In some cases, such as enumeration, it
  519. // is passed. In others, it must be obtained
  520. if(pClass == NULL)
  521. {
  522. VARIANT var;
  523. VariantInit(&var);
  524. sc = pInstance->Get(L"__Class",0,&var,NULL,NULL);
  525. if(sc != S_OK)
  526. return sc;
  527. if(m_pGateway == NULL)
  528. return WBEM_E_FAILED;
  529. sc = m_pGateway->GetObject(var.bstrVal,0, NULL, &pClass, NULL);
  530. VariantClear(&var);
  531. if(FAILED(sc))
  532. return sc;
  533. bGotOurClass = TRUE;
  534. }
  535. // Find out if expensive test data is desired
  536. {
  537. IWbemQualifierSet * pQualifier = NULL;
  538. CVariant var;
  539. sc = pClass->GetQualifierSet(&pQualifier); // Get instance Qualifier
  540. if(FAILED(sc))
  541. return sc;
  542. sc = pQualifier->Get(L"TesterDetails" ,0,var.GetVarPtr(), NULL);
  543. pQualifier->Release(); // free up the interface
  544. if(sc == S_OK && var.GetType() == VT_BOOL && var.bGetBOOL())
  545. bTesterDetails = TRUE;
  546. }
  547. CObject * pPackageObj = NULL;
  548. sc = StartBatch(lFlags,pInstance,&pPackageObj,FuncType == REFRESH);
  549. if(sc != S_OK)
  550. return WBEM_E_FAILED;
  551. sc = GetAttString(pClass, NULL, L"classcontext", &pwcClassContext);
  552. if(pwcKey)
  553. {
  554. // This is a special case and means that we are being called
  555. // as part of instance enumeration. This means that the key value
  556. // is already known, and that the class is one of ours
  557. pwcKeyValue = pwcKey;
  558. bClsidSetForClass = TRUE;
  559. }
  560. else
  561. {
  562. // Get the Key property. Note that this doesnt have to work since
  563. // there might be single instance classes supported by this provider!
  564. bstrKeyName = GetKeyName(pClass);
  565. if(bstrKeyName != NULL)
  566. {
  567. sc = pInstance->Get(bstrKeyName,0,vProp.GetVarPtr(),NULL,NULL);
  568. SysFreeString(bstrKeyName);
  569. if(sc == S_OK)
  570. {
  571. VARIANT * pTemp = vProp.GetVarPtr();
  572. if(pTemp->vt == VT_BSTR && pTemp->bstrVal != 0)
  573. {
  574. pwcKeyValue = new WCHAR[wcslen(vProp.GetBstr())+1];
  575. if(pwcKeyValue == NULL)
  576. {
  577. sc = WBEM_E_OUT_OF_MEMORY;
  578. goto EnumCleanUp;
  579. }
  580. wcscpy(pwcKeyValue,vProp.GetBstr());
  581. }
  582. }
  583. vProp.Clear();
  584. }
  585. }
  586. // For each property, Get the properties Qualifiers and
  587. // call the appropriate function to do the a refreshing/updating
  588. pInstance->BeginEnumeration(0);
  589. while(WBEM_NO_ERROR == pInstance->Next(0,&PropName, vProp.GetVarPtr(), NULL, NULL))
  590. {
  591. vProp.Clear();
  592. pwcTemp = NULL;
  593. sc = GetAttString(pClass, PropName, L"propertycontext", &pwcTemp, pCache, iCurr);
  594. iCurr++;
  595. if(sc== S_OK)
  596. {
  597. LPWSTR pwcFullContext = NULL;
  598. sc = MergeStrings(&pwcFullContext,pwcClassContext,pwcKeyValue,pwcTemp);
  599. if(pwcTemp)
  600. {
  601. delete pwcTemp;
  602. pwcTemp = NULL;
  603. }
  604. if(sc == S_OK)
  605. {
  606. if(pProvObj == NULL)
  607. {
  608. pProvObj = new CProvObj(pwcFullContext,MAIN_DELIM,NeedsEscapes());
  609. if(pProvObj == NULL)
  610. {
  611. sc = WBEM_E_OUT_OF_MEMORY;
  612. break;
  613. }
  614. }
  615. else if (!pProvObj->Update(pwcFullContext))
  616. {
  617. sc = WBEM_E_FAILED;
  618. break;
  619. }
  620. sc = pProvObj->dwGetStatus(iGetMinTokens());
  621. if(FuncType == REFRESH && sc == S_OK)
  622. {
  623. sc = RefreshProperty(lFlags,pInstance,
  624. PropName, *pProvObj, pPackageObj, NULL,bTesterDetails);
  625. if(sc == S_OK)
  626. iWorked++;
  627. else if (sc == 5)
  628. bAccessDenied = true;
  629. }
  630. else if(FuncType == UPDATE && sc == S_OK)
  631. {
  632. sc = UpdateProperty(lFlags,pInstance,
  633. PropName, *pProvObj, pPackageObj, NULL);
  634. if(sc == S_OK)
  635. iWorked++;
  636. else if (sc == 5)
  637. bAccessDenied = true;
  638. }
  639. if(pwcFullContext)
  640. delete pwcFullContext;
  641. }
  642. }
  643. else
  644. sc = S_OK; // ignore props without propertyContext
  645. SysFreeString(PropName);
  646. }
  647. EnumCleanUp:
  648. if(iWorked > 0)
  649. sc = S_OK;
  650. else if(bAccessDenied)
  651. sc = WBEM_E_ACCESS_DENIED;
  652. else
  653. sc = WBEM_E_INVALID_OBJECT_PATH;
  654. if(pProvObj)
  655. delete pProvObj;
  656. if(pwcTemp)
  657. delete pwcTemp;
  658. if(pwcClassContext)
  659. delete pwcClassContext;
  660. if(pwcKeyValue && pwcKey == NULL)
  661. delete pwcKeyValue;
  662. if(bGotOurClass)
  663. pClass->Release();
  664. EndBatch(lFlags,pInstance,pPackageObj,FuncType == REFRESH);
  665. return sc;
  666. }
  667. //***************************************************************************
  668. //
  669. // SCODE CImpDyn::GetAttString
  670. //
  671. // DESCRIPTION:
  672. //
  673. // Gets an Qualifier string. The string is will be pointed to by
  674. // the ppResult argument and should be freed by "delete".
  675. //
  676. // PARAMETERS:
  677. //
  678. // pClassInt Class object pointer
  679. // pPropName Property Name, could be null if going after
  680. // class attribute
  681. // pAttName Attribute name
  682. // ppResult Set to point to the retuned value.
  683. // pCache Optional cache of values
  684. // iIndex Optional index in the cache
  685. //
  686. // RETURN VALUE:
  687. //
  688. // S_OK all is well
  689. // WBEM_E_OUT_OF_MEMORY
  690. // otherwise the error is set by the class object's GetQualifierSet function
  691. // or by the qualifier sets "Get" function.
  692. //
  693. //***************************************************************************
  694. SCODE CImpDyn::GetAttString(
  695. IN IWbemClassObject FAR* pClassInt,
  696. IN LPWSTR pPropName,
  697. IN LPWSTR pAttName,
  698. OUT IN LPWSTR * ppResult,
  699. OUT IN CIndexCache * pCache,
  700. IN int iIndex)
  701. {
  702. SCODE sc;
  703. IWbemQualifierSet * pQualifier = NULL;
  704. CVariant var;
  705. if(*ppResult)
  706. delete *ppResult;
  707. *ppResult = NULL;
  708. // if there is a cache, try to get it from there
  709. if(pCache && iIndex != -1)
  710. {
  711. *ppResult = pCache->GetWString(iIndex);
  712. if(*ppResult != NULL)
  713. return S_OK;
  714. }
  715. // Get an Qualifier set interface.
  716. if(pPropName == NULL)
  717. sc = pClassInt->GetQualifierSet(&pQualifier); // Get instance Qualifier
  718. else
  719. sc = pClassInt->GetPropertyQualifierSet(pPropName,&pQualifier); // Get prop att
  720. if(FAILED(sc))
  721. return sc;
  722. // Get the string and free the Qualifier interface
  723. sc = pQualifier->Get(pAttName,0,var.GetVarPtr(), NULL);
  724. pQualifier->Release(); // free up the interface
  725. if(FAILED(sc))
  726. return sc;
  727. // make sure the type is OK
  728. if(var.GetType() != VT_BSTR)
  729. return WBEM_E_FAILED;
  730. // Allocate data for the buffer and copy the results
  731. *ppResult = new WCHAR[wcslen(var.GetBstr())+1];
  732. if(*ppResult)
  733. {
  734. wcscpy(*ppResult,var.GetBstr());
  735. sc = S_OK;
  736. }
  737. else
  738. sc = WBEM_E_OUT_OF_MEMORY;
  739. // If there is a cache, add this to it
  740. if(pCache && iIndex != -1 && *ppResult)
  741. {
  742. pCache->SetAt(*ppResult, iIndex);
  743. }
  744. return sc;
  745. }
  746. //***************************************************************************
  747. //
  748. // BSTR CImpDyn::GetKeyName
  749. //
  750. // DESCRIPTION:
  751. //
  752. // Gets the name of the property with the the key Qualifier.
  753. //
  754. // PARAMETERS:
  755. //
  756. // pClassInt Class object pointer
  757. //
  758. // RETURN VALUE:
  759. //
  760. // NULL if error,
  761. // other wise a BSTR which the caller must free
  762. //
  763. //***************************************************************************
  764. BSTR CImpDyn::GetKeyName(
  765. IN IWbemClassObject FAR* pClassInt)
  766. {
  767. IWbemQualifierSet * pQualifier = NULL;
  768. BSTR PropName = NULL;
  769. pClassInt->BeginEnumeration(WBEM_FLAG_KEYS_ONLY);
  770. // Loop through each of the properties and stop once one if found that
  771. // has a "Key" Qualifier
  772. while(WBEM_NO_ERROR == pClassInt->Next(0,&PropName,NULL, NULL, NULL))
  773. {
  774. return PropName;
  775. }
  776. return NULL;
  777. }
  778. //***************************************************************************
  779. //
  780. // SCODE CImpDyn::PutInstanceAsync
  781. //
  782. // DESCRIPTION:
  783. //
  784. // PutInstaceAsync writes instance data out.
  785. //
  786. // PARAMETERS:
  787. //
  788. // pClassInt Class Object pointer
  789. // lFlags flags.
  790. // pCtx Context object, not used anymore.
  791. // pResponseHandler Where to set the return code.
  792. //
  793. // RETURN VALUE:
  794. //
  795. // Set by EnumPropDoFunc
  796. //
  797. //***************************************************************************
  798. STDMETHODIMP CImpDyn::PutInstanceAsync(
  799. /* [in] */ IWbemClassObject __RPC_FAR *pInst,
  800. /* [in] */ long lFlags,
  801. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  802. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  803. {
  804. SCODE sc = S_OK;
  805. if(pInst == NULL || pResponseHandler == NULL)
  806. return WBEM_E_INVALID_PARAMETER;
  807. if(IsNT() && IsDcomEnabled())
  808. sc = WbemCoImpersonateClient();
  809. if(sc == S_OK)
  810. sc = EnumPropDoFunc(lFlags,pInst,UPDATE);
  811. // Set the status
  812. pResponseHandler->SetStatus(0,sc, NULL, NULL);
  813. return sc;
  814. }
  815. //***************************************************************************
  816. //
  817. // SCODE CImpDyn::ExecMethodAsync
  818. //
  819. // DESCRIPTION:
  820. //
  821. // Executes methods.
  822. //
  823. // PARAMETERS:
  824. //
  825. // pClassInt Class Object pointer
  826. // lFlags flags.
  827. // pCtx Context object, not used anymore.
  828. // pResponseHandler Where to set the return code.
  829. //
  830. // RETURN VALUE:
  831. //
  832. // Set by EnumPropDoFunc
  833. //
  834. //***************************************************************************
  835. STDMETHODIMP CImpDyn::ExecMethodAsync(
  836. /* [in] */ const BSTR ObjectPath,
  837. /* [in] */ const BSTR MethodName,
  838. /* [in] */ long lFlags,
  839. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  840. /* [in] */ IWbemClassObject __RPC_FAR *pInParams,
  841. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler
  842. )
  843. {
  844. return MethodAsync(ObjectPath, MethodName,
  845. lFlags,pCtx, pInParams, pResponseHandler);
  846. }
  847. //***************************************************************************
  848. //
  849. // SCODE CImpDyn::RefreshInstance
  850. //
  851. // DESCRIPTION:
  852. //
  853. // gets fresh values for the properties.
  854. //
  855. // PARAMETERS:
  856. //
  857. // pClassInt Class Object pointer
  858. // lFlags flags.
  859. // ppErrorObject Optional error object
  860. //
  861. // RETURN VALUE:
  862. //
  863. // Set by EnumPropDoFunc
  864. //
  865. //***************************************************************************
  866. STDMETHODIMP CImpDyn::RefreshInstance(
  867. IN long lFlags,
  868. OUT IN IWbemClassObject FAR* pClassInt)
  869. {
  870. return EnumPropDoFunc(lFlags,pClassInt,REFRESH);
  871. }
  872. //***************************************************************************
  873. //
  874. // SCODE CImpDyn::CreateInst
  875. //
  876. // DESCRIPTION:
  877. //
  878. // Creates a new instance via the gateway provider and sets
  879. // the inital values of the properties.
  880. //
  881. // PARAMETERS:
  882. //
  883. // pGateway Pointer to WBEM
  884. // pwcClass Class Name
  885. // pKey Key value
  886. // pNewInst returned pointer to created instance
  887. // pwcKeyName Name of key property
  888. // pCache Optional cache
  889. //
  890. // RETURN VALUE:
  891. //
  892. // Return: S_OK if all is well,
  893. // otherwise an error code is returned by either GetObject(most likely)
  894. // or spawn instance.
  895. //
  896. //***************************************************************************
  897. SCODE CImpDyn::CreateInst(
  898. IN IWbemServices * pGateway,
  899. IN LPWSTR pwcClass,
  900. IN LPWSTR pKey,
  901. OUT IN IWbemClassObject ** pNewInst,
  902. IN LPWSTR pwcKeyName,
  903. OUT IN CIndexCache * pCache,
  904. IWbemContext *pCtx)
  905. {
  906. SCODE sc;
  907. IWbemClassObject * pClass = NULL;
  908. // Create the new instance
  909. sc = pGateway->GetObject(pwcClass,0, pCtx, &pClass, NULL);
  910. if(FAILED(sc))
  911. return sc;
  912. sc = pClass->SpawnInstance(0, pNewInst);
  913. if(FAILED(sc))
  914. {
  915. pClass->Release();
  916. return sc;
  917. }
  918. // Set the key value. Note that CVariant isnt used because
  919. // it assumes that the input is a TCHAR.
  920. VARIANT var;
  921. var.vt = VT_BSTR;
  922. var.bstrVal = SysAllocString(pKey);
  923. if(var.bstrVal == NULL)
  924. {
  925. (*pNewInst)->Release();
  926. pClass->Release();
  927. return WBEM_E_OUT_OF_MEMORY;
  928. }
  929. BSTR bstrKeyName;
  930. if(pwcKeyName == NULL)
  931. bstrKeyName = GetKeyName(*pNewInst);
  932. else
  933. bstrKeyName = SysAllocString(pwcKeyName);
  934. if(bstrKeyName != NULL)
  935. {
  936. sc = (*pNewInst)->Put(bstrKeyName,0,&var,0);
  937. SysFreeString(bstrKeyName);
  938. }
  939. VariantClear(&var);
  940. // Use the RefreshInstance routine to set all the other properties
  941. sc = EnumPropDoFunc(0,*pNewInst,REFRESH, pKey, pCache, pClass);
  942. pClass->Release();
  943. if (FAILED(sc))
  944. (*pNewInst)->Release();
  945. // Clean up
  946. return sc;
  947. }
  948. //***************************************************************************
  949. //
  950. // SCODE CImpDyn::MergeStrings
  951. //
  952. // DESCRIPTION:
  953. //
  954. // Combines the Class Context, Key, and Property Context strings.
  955. //
  956. // PARAMETERS:
  957. //
  958. // ppOut output combined string, must be freed via delete
  959. // pClassContext class context
  960. // pKey key value
  961. // pPropContext property context
  962. //
  963. // RETURN VALUE:
  964. //
  965. // S_OK if all is well,
  966. // WBEM_E_INVALID_PARAMETER no property context string or ppOut is NULL
  967. // WBEM_E_OUT_OF_MEMORY
  968. //***************************************************************************
  969. SCODE CImpDyn::MergeStrings(
  970. OUT LPWSTR * ppOut,
  971. IN LPWSTR pClassContext,
  972. IN LPWSTR pKey,
  973. IN LPWSTR pPropContext)
  974. {
  975. // Allocate space for output
  976. int iLen = 3;
  977. if(pClassContext)
  978. iLen += wcslen(pClassContext);
  979. if(pKey)
  980. iLen += wcslen(pKey);
  981. if(pPropContext)
  982. iLen += wcslen(pPropContext);
  983. else
  984. return WBEM_E_INVALID_PARAMETER; // should always have this!
  985. if(ppOut == NULL)
  986. return WBEM_E_INVALID_PARAMETER; // should always have this!
  987. *ppOut = new WCHAR[iLen];
  988. if(*ppOut == NULL)
  989. return WBEM_E_OUT_OF_MEMORY;
  990. // simple case is that everything is in the property context. That would
  991. // be the case when the provider is being used as a simple dynamic
  992. // property provider
  993. if(pClassContext == NULL || pKey == NULL) {
  994. wcscpy(*ppOut,pPropContext);
  995. return S_OK;
  996. }
  997. // Copy the class context, then search for the delimeter
  998. wcscpy(*ppOut,pClassContext);
  999. WCHAR * pTest;
  1000. for(pTest = *ppOut; *pTest; pTest++)
  1001. if(*pTest == MAIN_DELIM)
  1002. break;
  1003. // Three cases;
  1004. if(*pTest == NULL)
  1005. wcscat(*ppOut,L"|"); // HKLM BLA VALUE add |
  1006. else if( *(pTest +1))
  1007. wcscat(*ppOut,L"\\"); // HKLM|BLA BLA VALUE add \
  1008. else; // HKLM| BLA VALUE do nothing!
  1009. wcscat(*ppOut,pKey);
  1010. if(pPropContext[0] != L'|' && pPropContext[0] != L'\\')
  1011. wcscat(*ppOut,L"|");
  1012. wcscat(*ppOut,pPropContext);
  1013. return S_OK;
  1014. }
  1015. //***************************************************************************
  1016. //
  1017. // SCODE CImpDyn::ReturnAndSetObj
  1018. //
  1019. // DESCRIPTION:
  1020. //
  1021. // Takes care of creating and setting an error object.
  1022. //
  1023. // PARAMETERS:
  1024. //
  1025. // sc value to set
  1026. // ppErrorObject point which will point to the error object.
  1027. //
  1028. // RETURN VALUE:
  1029. //
  1030. // what ever was passed in.
  1031. //***************************************************************************
  1032. SCODE CImpDyn::ReturnAndSetObj(
  1033. IN SCODE sc,
  1034. OUT IN IWbemCallResult FAR* FAR* ppCallResult)
  1035. {
  1036. // if(ppErrorObject)
  1037. // *ppErrorObject = GetNotifyObj(m_pGateway,sc);
  1038. return sc;
  1039. }
  1040. //***************************************************************************
  1041. //
  1042. // long CImpDyn::AddRef
  1043. //
  1044. // DESCRIPTION:
  1045. //
  1046. // Adds to the reference count.
  1047. //
  1048. // RETURN VALUE:
  1049. //
  1050. // current reference count.
  1051. //
  1052. //***************************************************************************
  1053. long CEnumInfo::AddRef(void)
  1054. {
  1055. return InterlockedIncrement(&m_cRef);
  1056. }
  1057. //***************************************************************************
  1058. //
  1059. // long CImpDyn::Release
  1060. //
  1061. // DESCRIPTION:
  1062. //
  1063. // Interface has been released. Object will be deleted if the
  1064. // usage count is zero.
  1065. //
  1066. // RETURN VALUE:
  1067. //
  1068. // current reference count.
  1069. //
  1070. //***************************************************************************
  1071. long CEnumInfo::Release(void)
  1072. {
  1073. long lRet = InterlockedDecrement(&m_cRef);
  1074. if (0L!=lRet)
  1075. return lRet;
  1076. delete this;
  1077. return 0;
  1078. }