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.

1554 lines
33 KiB

  1. //***************************************************************************
  2. //
  3. // TestInfo.CPP
  4. //
  5. // Module: CDM Provider
  6. //
  7. // Purpose: Defines the CClassPro class. An object of this class is
  8. // created by the class factory for each connection.
  9. //
  10. // Copyright (c) 2000 Microsoft Corporation
  11. //
  12. //***************************************************************************
  13. #include <objbase.h>
  14. #ifndef _MT
  15. #define _MT
  16. #endif
  17. #include <wbemidl.h>
  18. #include "debug.h"
  19. #include "useful.h"
  20. #include "wbemmisc.h"
  21. #include "testinfo.h"
  22. #include "cimmap.h"
  23. #include "text.h"
  24. IWbemServices *pCimServices;
  25. IWbemServices *pWdmServices;
  26. HRESULT TestInfoInitialize(
  27. void
  28. )
  29. /*+++
  30. Routine Description:
  31. This routine will establishes a connection to the root\wmi and
  32. root\cimv2 namespaces in global memory
  33. Arguments:
  34. Return Value:
  35. HRESULT
  36. ---*/
  37. {
  38. HRESULT hr;
  39. WmipAssert(pCimServices == NULL);
  40. WmipAssert(pWdmServices == NULL);
  41. hr = WmiConnectToWbem(L"root\\cimv2",
  42. &pCimServices);
  43. if (hr == WBEM_S_NO_ERROR)
  44. {
  45. hr = WmiConnectToWbem(L"root\\wmi",
  46. &pWdmServices);
  47. if (hr != WBEM_S_NO_ERROR)
  48. {
  49. pCimServices->Release();
  50. pCimServices = NULL;
  51. }
  52. }
  53. return(hr);
  54. }
  55. void TestInfoDeinitialize(
  56. void
  57. )
  58. /*+++
  59. Routine Description:
  60. This routine will disestablish a connection to the root\wmi and
  61. root\cimv2 namespaces in global memory
  62. Arguments:
  63. Return Value:
  64. ---*/
  65. {
  66. WmipAssert(pCimServices != NULL);
  67. WmipAssert(pWdmServices != NULL);
  68. pCimServices->Release();
  69. pCimServices = NULL;
  70. pWdmServices->Release();
  71. pWdmServices = NULL;
  72. }
  73. CWdmClass::CWdmClass()
  74. /*+++
  75. Routine Description:
  76. Constructor for CWdmClass class
  77. Arguments:
  78. Return Value:
  79. ---*/
  80. {
  81. Next = NULL;
  82. Prev = NULL;
  83. WdmShadowClassName = NULL;
  84. WdmMappingClassName = NULL;
  85. WdmMappingProperty = NULL;
  86. CimClassName = NULL;
  87. CimMappingClassName = NULL;
  88. CimMappingProperty = NULL;
  89. PnPDeviceIds = NULL;
  90. FriendlyName = NULL;
  91. DeviceDesc = NULL;
  92. CimMapRelPaths = NULL;
  93. WdmRelPaths = NULL;
  94. CimInstances = NULL;
  95. RelPathCount = (int)-1;
  96. DerivationType = UnknownDerivation;
  97. //
  98. // Start out with the class marked as not having instances
  99. // availabel
  100. //
  101. MappingInProgress = 1;
  102. }
  103. CWdmClass::~CWdmClass()
  104. /*+++
  105. Routine Description:
  106. Destructor for CWdmClass class
  107. Arguments:
  108. Return Value:
  109. ---*/
  110. {
  111. int i;
  112. if (WdmShadowClassName != NULL)
  113. {
  114. SysFreeString(WdmShadowClassName);
  115. }
  116. if (WdmMappingClassName != NULL)
  117. {
  118. SysFreeString(WdmMappingClassName);
  119. }
  120. if (WdmMappingProperty != NULL)
  121. {
  122. SysFreeString(WdmMappingProperty);
  123. }
  124. if (CimMappingClassName != NULL)
  125. {
  126. SysFreeString(CimMappingClassName);
  127. }
  128. if (CimClassName != NULL)
  129. {
  130. SysFreeString(CimClassName);
  131. }
  132. if (CimMappingProperty != NULL)
  133. {
  134. SysFreeString(CimMappingProperty);
  135. }
  136. if (WdmMappingProperty != NULL)
  137. {
  138. SysFreeString(WdmMappingProperty);
  139. }
  140. if (CimMapRelPaths != NULL)
  141. {
  142. delete CimMapRelPaths;
  143. }
  144. if (WdmRelPaths != NULL)
  145. {
  146. delete WdmRelPaths;
  147. }
  148. if (CimInstances != NULL)
  149. {
  150. delete CimInstances;
  151. }
  152. if (PnPDeviceIds != NULL)
  153. {
  154. delete PnPDeviceIds;
  155. }
  156. if (FriendlyName != NULL)
  157. {
  158. delete FriendlyName;
  159. }
  160. if (DeviceDesc != NULL)
  161. {
  162. delete DeviceDesc;
  163. }
  164. }
  165. IWbemServices *CWdmClass::GetWdmServices(
  166. void
  167. )
  168. /*+++
  169. Routine Description:
  170. Accessor for the WDM namespace IWbemServices
  171. Arguments:
  172. Return Value:
  173. IWbemServices
  174. ---*/
  175. {
  176. WmipAssert(pWdmServices != NULL);
  177. return(pWdmServices);
  178. }
  179. IWbemServices *CWdmClass::GetCimServices(
  180. void
  181. )
  182. /*+++
  183. Routine Description:
  184. Accessor for the CIM namespace IWbemServices
  185. Arguments:
  186. Return Value:
  187. IWbemServices
  188. ---*/
  189. {
  190. WmipAssert(pCimServices != NULL);
  191. return(pCimServices);
  192. }
  193. HRESULT CWdmClass::DiscoverPropertyTypes(
  194. IWbemContext *pCtx,
  195. IWbemClassObject *pCimClassObject
  196. )
  197. {
  198. HRESULT hr, hrDontCare;
  199. VARIANT v;
  200. BSTR PropertyName;
  201. ULONG Count;
  202. IWbemQualifierSet *pQualifierList;
  203. WmipAssert(pCimClassObject != NULL);
  204. if (DerivationType == ConcreteDerivation)
  205. {
  206. //
  207. // For a concrete derivation, get all of the key properties
  208. // from the superclass so we can populate them too
  209. //
  210. hr = pCimClassObject->BeginEnumeration(WBEM_FLAG_KEYS_ONLY);
  211. if (hr == WBEM_S_NO_ERROR)
  212. {
  213. //
  214. // TODO: Make CBstrArray allocation dynamic
  215. //
  216. PropertyList.Initialize(10);
  217. Count = 0;
  218. do
  219. {
  220. hr = pCimClassObject->Next(0,
  221. &PropertyName,
  222. NULL,
  223. NULL,
  224. NULL);
  225. if (hr == WBEM_S_NO_ERROR)
  226. {
  227. PropertyList.Set(Count++, PropertyName);
  228. } else if (hr == WBEM_S_NO_MORE_DATA) {
  229. //
  230. // This signifies the end of the enumerations
  231. //
  232. hr = WBEM_S_NO_ERROR;
  233. break;
  234. }
  235. } while (hr == WBEM_S_NO_ERROR);
  236. pCimClassObject->EndEnumeration();
  237. }
  238. } else if (DerivationType == NonConcreteDerivation) {
  239. //
  240. // TODO: Figure out how we want to create the list of
  241. // superclass properties to fill
  242. //
  243. PropertyList.Initialize(1);
  244. hr = WBEM_S_NO_ERROR;
  245. }
  246. return(hr);
  247. }
  248. HRESULT CWdmClass::InitializeSelf(
  249. IWbemContext *pCtx,
  250. PWCHAR CimClass
  251. )
  252. {
  253. HRESULT hr;
  254. VARIANT v, vSuper;
  255. IWbemClassObject *pClass;
  256. IWbemQualifierSet *pQualifiers;
  257. PWCHAR Names[6];
  258. VARTYPE Types[6];
  259. VARIANT Values[6];
  260. WmipAssert(CimClass != NULL);
  261. WmipAssert(CimMappingClassName == NULL);
  262. WmipAssert(WdmShadowClassName == NULL);
  263. WmipAssert(CimClassName == NULL);
  264. //
  265. // We assume that this method will always be the first one called
  266. // by the class provider
  267. //
  268. EnterCritSection();
  269. if ((pCimServices == NULL) &&
  270. (pWdmServices == NULL))
  271. {
  272. hr = TestInfoInitialize();
  273. if (hr != WBEM_S_NO_ERROR)
  274. {
  275. LeaveCritSection();
  276. WmipDebugPrint(("WMIMAP: TestInfoInitialize -> %x\n", hr));
  277. return(hr);
  278. }
  279. }
  280. LeaveCritSection();
  281. CimClassName = SysAllocString(CimClass);
  282. if (CimClassName != NULL)
  283. {
  284. //
  285. // Get the WdmShadowClass class qualifier to discover the name of
  286. // the Wdm class that is represented by this cim class
  287. //
  288. hr = GetCimServices()->GetObject(CimClassName,
  289. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  290. pCtx,
  291. &pClass,
  292. NULL);
  293. if (hr == WBEM_S_NO_ERROR)
  294. {
  295. //
  296. // See if this is a derived class or not
  297. //
  298. VariantInit(&vSuper);
  299. hr = WmiGetProperty(pClass,
  300. SUPERCLASS,
  301. CIM_STRING,
  302. &vSuper);
  303. if (hr == WBEM_S_NO_ERROR)
  304. {
  305. hr = pClass->GetQualifierSet(&pQualifiers);
  306. if (hr == WBEM_S_NO_ERROR)
  307. {
  308. Names[0] = WDM_SHADOW_CLASS;
  309. Types[0] = VT_BSTR;
  310. Names[1] = WDM_MAPPING_CLASS;
  311. Types[1] = VT_BSTR;
  312. Names[2] = WDM_MAPPING_PROPERTY;
  313. Types[2] = VT_BSTR;
  314. Names[3] = CIM_MAPPING_CLASS;
  315. Types[3] = VT_BSTR;
  316. Names[4] = CIM_MAPPING_PROPERTY;
  317. Types[4] = VT_BSTR;
  318. Names[5] = DERIVED_CLASS_TYPE;
  319. Types[5] = VT_BSTR;
  320. hr = GetListOfQualifiers(pQualifiers,
  321. 6,
  322. Names,
  323. Types,
  324. Values,
  325. FALSE);
  326. if (hr == WBEM_S_NO_ERROR)
  327. {
  328. //
  329. // First determine if this is a concrete or non
  330. // concrete derivation
  331. //
  332. if (Values[5].vt == VT_BSTR)
  333. {
  334. if (_wcsicmp(Values[5].bstrVal, CONCRETE) == 0)
  335. {
  336. DerivationType = ConcreteDerivation;
  337. } else if (_wcsicmp(Values[5].bstrVal, NONCONCRETE) == 0)
  338. {
  339. DerivationType = NonConcreteDerivation;
  340. }
  341. }
  342. if (DerivationType == UnknownDerivation)
  343. {
  344. //
  345. // Must specify derivation type
  346. //
  347. hr = WBEM_E_AMBIGUOUS_OPERATION;
  348. WmipDebugPrint(("WMIMAP: class %ws must specify derivation type\n",
  349. CimClass));
  350. } else {
  351. if (Values[3].vt == VT_BSTR)
  352. {
  353. //
  354. // Use CimMappingClass as specified
  355. //
  356. CimMappingClassName = Values[3].bstrVal;
  357. VariantInit(&Values[3]);
  358. } else {
  359. //
  360. // CimMappingClass not specified, use
  361. // superclass as mapping class
  362. //
  363. CimMappingClassName = vSuper.bstrVal;
  364. VariantInit(&vSuper);
  365. }
  366. if (Values[0].vt == VT_BSTR)
  367. {
  368. //
  369. // WdmShadowClass is required
  370. //
  371. WdmShadowClassName = Values[0].bstrVal;
  372. VariantInit(&Values[0]);
  373. if (Values[1].vt == VT_BSTR)
  374. {
  375. //
  376. // WdmMappingClass can specify that
  377. // the mapping class is different
  378. // from the shadow class
  379. //
  380. WdmMappingClassName = Values[1].bstrVal;
  381. VariantInit(&Values[1]);
  382. }
  383. if (Values[2].vt == VT_BSTR)
  384. {
  385. WdmMappingProperty = Values[2].bstrVal;
  386. VariantInit(&Values[2]);
  387. }
  388. if (Values[4].vt == VT_BSTR)
  389. {
  390. CimMappingProperty = Values[4].bstrVal;
  391. VariantInit(&Values[4]);
  392. if (WdmMappingProperty == NULL)
  393. {
  394. //
  395. // If CimMappingProperty
  396. // specified then
  397. // WdmMappingProperty is
  398. // required
  399. //
  400. hr = WBEM_E_INVALID_CLASS;
  401. }
  402. } else {
  403. if (WdmMappingProperty != NULL)
  404. {
  405. //
  406. // If CimMappingProperty is not
  407. // specified then
  408. // WdmMappingProperty should
  409. // not be specified
  410. //
  411. hr = WBEM_E_INVALID_CLASS;
  412. }
  413. }
  414. if (hr == WBEM_S_NO_ERROR)
  415. {
  416. //
  417. // Look at all properties to discover which ones
  418. // need to be handled
  419. //
  420. hr = DiscoverPropertyTypes(pCtx,
  421. pClass);
  422. }
  423. } else {
  424. //
  425. // WDMShadowClass qualifier is required
  426. //
  427. hr = WBEM_E_INVALID_CLASS;
  428. }
  429. }
  430. VariantClear(&Values[0]);
  431. VariantClear(&Values[1]);
  432. VariantClear(&Values[2]);
  433. VariantClear(&Values[3]);
  434. VariantClear(&Values[4]);
  435. VariantClear(&Values[5]);
  436. }
  437. pQualifiers->Release();
  438. }
  439. VariantClear(&vSuper);
  440. } else {
  441. //
  442. // No superclass implies no derivation
  443. //
  444. DerivationType = NoDerivation;
  445. hr = WBEM_S_NO_ERROR;
  446. }
  447. pClass->Release();
  448. }
  449. } else {
  450. hr = WBEM_E_OUT_OF_MEMORY;
  451. }
  452. return(hr);
  453. }
  454. HRESULT CWdmClass::RemapToCimClass(
  455. IWbemContext *pCtx
  456. )
  457. /*+++
  458. Routine Description:
  459. This routine will setup this class and initialize everything so
  460. that the provider can interact with the CDM and WDM classes
  461. Arguments:
  462. CdmClass is the name of the CDM class
  463. Return Value:
  464. HRESULT
  465. ---*/
  466. {
  467. CBstrArray WdmInstanceNames;
  468. CBstrArray *WdmPaths;
  469. CBstrArray *CimPaths;
  470. CBstrArray *CimMapPaths;
  471. IWbemClassObject *CimInstance;
  472. HRESULT hr;
  473. int i;
  474. WmipAssert(CimMappingClassName != NULL);
  475. WmipAssert(WdmShadowClassName != NULL);
  476. //
  477. // Increment this to indicate that mapping is in progress and thus
  478. // there are no instances available. Consider changing this to some
  479. // kind of synchronization mechanism
  480. //
  481. IncrementMappingInProgress();
  482. //
  483. // Free rel path bstr arrays
  484. //
  485. if (CimMapRelPaths != NULL)
  486. {
  487. delete CimMapRelPaths;
  488. }
  489. if (CimInstances != NULL)
  490. {
  491. delete CimInstances;
  492. }
  493. if (WdmRelPaths != NULL)
  494. {
  495. delete WdmRelPaths;
  496. }
  497. //
  498. // allocate new rel paths
  499. //
  500. CimMapRelPaths = new CBstrArray;
  501. WdmRelPaths = new CBstrArray;
  502. CimInstances = new CWbemObjectList;
  503. PnPDeviceIds = new CBstrArray;
  504. FriendlyName = new CBstrArray;
  505. DeviceDesc = new CBstrArray;
  506. if ((CimMapRelPaths != NULL) &&
  507. (CimInstances != NULL) &&
  508. (PnPDeviceIds != NULL) &&
  509. (FriendlyName != NULL) &&
  510. (DeviceDesc != NULL) &&
  511. (WdmRelPaths != NULL))
  512. {
  513. if ((WdmMappingProperty == NULL) &&
  514. (CimMappingProperty == NULL))
  515. {
  516. //
  517. // Use worker function to determine which
  518. // Wdm relpaths map to which CIM_LogicalDevice relpaths
  519. // via the PnP ids
  520. //
  521. hr = MapWdmClassToCimClassViaPnpId(pCtx,
  522. pWdmServices,
  523. pCimServices,
  524. WdmShadowClassName,
  525. CimMappingClassName,
  526. PnPDeviceIds,
  527. FriendlyName,
  528. DeviceDesc,
  529. &WdmInstanceNames,
  530. WdmRelPaths,
  531. CimMapRelPaths,
  532. &RelPathCount);
  533. } else {
  534. //
  535. // Use worker function to map WDM relpaths to CIM relpaths
  536. // using a common property in both classes
  537. //
  538. hr = MapWdmClassToCimClassViaProperty(pCtx,
  539. pWdmServices,
  540. pCimServices,
  541. WdmShadowClassName,
  542. WdmMappingClassName ?
  543. WdmMappingClassName :
  544. WdmShadowClassName,
  545. WdmMappingProperty,
  546. CimMappingClassName,
  547. CimMappingProperty,
  548. &WdmInstanceNames,
  549. WdmRelPaths,
  550. CimMapRelPaths,
  551. &RelPathCount);
  552. }
  553. if (hr == WBEM_S_NO_ERROR)
  554. {
  555. //
  556. // Collect the relpaths for our cim instances that we are
  557. // providing. Best way to do this is to create our instances
  558. //
  559. CimInstances->Initialize(RelPathCount);
  560. for (i = 0; i < RelPathCount; i++)
  561. {
  562. WmipDebugPrint(("WMIMAP: %ws maps to %ws\n",
  563. WdmRelPaths->Get(i),
  564. CimMapRelPaths->Get(i)));
  565. hr = CreateCimInstance(pCtx,
  566. i,
  567. &CimInstance);
  568. if (hr == WBEM_S_NO_ERROR)
  569. {
  570. hr = CimInstances->Set(i,
  571. CimInstance);
  572. if (hr != WBEM_S_NO_ERROR)
  573. {
  574. break;
  575. }
  576. } else {
  577. break;
  578. }
  579. }
  580. }
  581. }
  582. if (hr != WBEM_S_NO_ERROR)
  583. {
  584. delete CimMapRelPaths;
  585. CimMapRelPaths = NULL;
  586. delete WdmRelPaths;
  587. WdmRelPaths = NULL;
  588. delete CimInstances;
  589. CimInstances = NULL;
  590. }
  591. DecrementMappingInProgress();
  592. return(hr);
  593. }
  594. HRESULT CWdmClass::WdmPropertyToCimProperty(
  595. IN IWbemClassObject *pCdmClassInstance,
  596. IN IWbemClassObject *pWdmClassInstance,
  597. IN BSTR PropertyName,
  598. IN OUT VARIANT *PropertyValue,
  599. IN CIMTYPE CdmCimType,
  600. IN CIMTYPE WdmCimType
  601. )
  602. /*+++
  603. Routine Description:
  604. This routine will convert a property in a Wdm class into the form
  605. required for the property in the Cdm class.
  606. Arguments:
  607. pCdmClassInstance is the instnace of the Cdm class that will get
  608. the property value
  609. pWdmClassInstance is the instance of the Wdm class that has the
  610. property value
  611. PropertyName is the name of the property in the Wdm and Cdm classes
  612. PropertyValue on entry has the value of the property in the Wdm
  613. instance and on return has the value to set in the Cdm instance
  614. CdmCimType is the property type for the property in the Cdm
  615. instance
  616. WdmCimType is the property type for the property in the Wdm
  617. instance
  618. Return Value:
  619. HRESULT
  620. ---*/
  621. {
  622. HRESULT hr;
  623. CIMTYPE BaseWdmCimType, BaseCdmCimType;
  624. CIMTYPE WdmCimArray, CdmCimArray;
  625. WmipAssert(pCdmClassInstance != NULL);
  626. WmipAssert(pWdmClassInstance != NULL);
  627. WmipAssert(PropertyName != NULL);
  628. WmipAssert(PropertyValue != NULL);
  629. WmipAssert(IsThisInitialized());
  630. //
  631. // Rules for converting Wdm Classes into Cdm Classes
  632. // Wdm Class Type Cdm Class Type Conversion Done
  633. // enumeration string Build string from enum
  634. //
  635. BaseWdmCimType = WdmCimType & ~CIM_FLAG_ARRAY;
  636. BaseCdmCimType = CdmCimType & ~CIM_FLAG_ARRAY;
  637. WdmCimArray = WdmCimType & CIM_FLAG_ARRAY;
  638. CdmCimArray = CdmCimType & CIM_FLAG_ARRAY;
  639. if (((BaseWdmCimType == CIM_UINT32) ||
  640. (BaseWdmCimType == CIM_UINT16) ||
  641. (BaseWdmCimType == CIM_UINT8)) &&
  642. (BaseCdmCimType == CIM_STRING) &&
  643. (WdmCimArray == CdmCimArray) &&
  644. (PropertyValue->vt != VT_NULL))
  645. {
  646. CValueMapping ValueMapping;
  647. hr = ValueMapping.EstablishByName(GetWdmServices(),
  648. WdmShadowClassName,
  649. PropertyName);
  650. if (hr == WBEM_S_NO_ERROR)
  651. {
  652. hr = ValueMapping.MapVariantToString(PropertyValue,
  653. WdmCimType);
  654. }
  655. } else {
  656. //
  657. // No conversion needs to occur
  658. //
  659. hr = WBEM_S_NO_ERROR;
  660. }
  661. return(hr);
  662. }
  663. HRESULT CWdmClass::CimPropertyToWdmProperty(
  664. IN IWbemClassObject *pWdmClassInstance,
  665. IN IWbemClassObject *pCdmClassInstance,
  666. IN BSTR PropertyName,
  667. IN OUT VARIANT *PropertyValue,
  668. IN CIMTYPE WdmCimType,
  669. IN CIMTYPE CdmCimType
  670. )
  671. /*+++
  672. Routine Description:
  673. This routine will convert a property in a Cdm class into the form
  674. required for the property in the Wdm class.
  675. Arguments:
  676. pWdmClassInstance is the instance of the Wdm class that has the
  677. property value
  678. pCdmClassInstance is the instnace of the Cdm class that will get
  679. the property value
  680. PropertyName is the name of the property in the Wdm and Cdm classes
  681. PropertyValue on entry has the value of the property in the Wdm
  682. instance and on return has the value to set in the Cdm instance
  683. WdmCimType is the property type for the property in the Wdm
  684. instance
  685. CdmCimType is the property type for the property in the Cdm
  686. instance
  687. Return Value:
  688. HRESULT
  689. ---*/
  690. {
  691. HRESULT hr;
  692. CIMTYPE BaseWdmCimType, BaseCdmCimType;
  693. CIMTYPE WdmCimArray, CdmCimArray;
  694. WmipAssert(pCdmClassInstance != NULL);
  695. WmipAssert(pWdmClassInstance != NULL);
  696. WmipAssert(PropertyName != NULL);
  697. WmipAssert(PropertyValue != NULL);
  698. WmipAssert(IsThisInitialized());
  699. //
  700. // Rules for converting Wdm Classes into Cdm Classes
  701. // Wdm Class Type Cdm Class Type Conversion Done
  702. // enumeration string Map string to enum value
  703. //
  704. //
  705. BaseWdmCimType = WdmCimType & ~CIM_FLAG_ARRAY;
  706. BaseCdmCimType = CdmCimType & ~CIM_FLAG_ARRAY;
  707. WdmCimArray = WdmCimType & CIM_FLAG_ARRAY;
  708. CdmCimArray = CdmCimType & CIM_FLAG_ARRAY;
  709. if (((BaseWdmCimType == CIM_UINT32) ||
  710. (BaseWdmCimType == CIM_UINT16) ||
  711. (BaseWdmCimType == CIM_UINT8)) &&
  712. (BaseCdmCimType == CIM_STRING) &&
  713. (WdmCimArray == CdmCimArray) &&
  714. (PropertyValue->vt != VT_NULL))
  715. {
  716. CValueMapping ValueMapping;
  717. hr = ValueMapping.EstablishByName(GetWdmServices(),
  718. WdmShadowClassName,
  719. PropertyName);
  720. if (hr == WBEM_S_NO_ERROR)
  721. {
  722. hr = ValueMapping.MapVariantToNumber(PropertyValue,
  723. (VARTYPE)BaseWdmCimType);
  724. }
  725. } else {
  726. //
  727. // No conversion needs to occur
  728. //
  729. hr = WBEM_S_NO_ERROR;
  730. }
  731. return(hr);
  732. }
  733. HRESULT CWdmClass::CopyBetweenCimAndWdmClasses(
  734. IN IWbemClassObject *pDestinationInstance,
  735. IN IWbemClassObject *pSourceInstance,
  736. IN BOOLEAN WdmToCdm
  737. )
  738. /*+++
  739. Routine Description:
  740. This routine will do the work to copy and convert all properties in
  741. an instance of a Wdm or Cdm class to an instance of a Cdm or Wdm
  742. class.
  743. Note that properties from one instance are only copied to
  744. properties of another instance when the property names are
  745. identical. No assumption is ever made on the name of the
  746. properties. The only info used to determine how to convert a
  747. property is based upon the source and destination cim type.
  748. Arguments:
  749. pDestinationInstance is the class instance that the properties will
  750. be copied into
  751. pSourceInstance is the class instance that the properties will be
  752. copied from
  753. WdmToCdm is TRUE if copying from Wdm to Cdm, else FALSE
  754. Return Value:
  755. HRESULT
  756. ---*/
  757. {
  758. HRESULT hr;
  759. VARIANT PropertyValue;
  760. BSTR PropertyName;
  761. CIMTYPE SourceCimType, DestCimType;
  762. HRESULT hrDontCare;
  763. WmipAssert(pDestinationInstance != NULL);
  764. WmipAssert(pSourceInstance != NULL);
  765. WmipAssert(IsThisInitialized());
  766. //
  767. // Now we need to move over all of the properties from the source
  768. // class into the destination class. Note that some properties need
  769. // some special effort such as OtherCharacteristics which needs
  770. // to be converted from an enumeration value (in wdm) to a
  771. // string (in CDM).
  772. //
  773. // Our strategy is to enumerate all of the proeprties in the
  774. // source class and then look for a property with the same name
  775. // and type in the destination class. If so we just copy over the
  776. // value. If the data type is different we need to do some
  777. // conversion.
  778. //
  779. hr = pSourceInstance->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  780. if (hr == WBEM_S_NO_ERROR)
  781. {
  782. do
  783. {
  784. //
  785. // Get a property from the source class
  786. //
  787. hr = pSourceInstance->Next(0,
  788. &PropertyName,
  789. &PropertyValue,
  790. &SourceCimType,
  791. NULL);
  792. if (hr == WBEM_S_NO_ERROR)
  793. {
  794. //
  795. // Try to get a property with the same name from the
  796. // dest class. If the identically named property does
  797. // not exist in the destination class then it is ignored
  798. //
  799. hrDontCare = pDestinationInstance->Get(PropertyName,
  800. 0,
  801. NULL,
  802. &DestCimType,
  803. NULL);
  804. if (hrDontCare == WBEM_S_NO_ERROR)
  805. {
  806. if (WdmToCdm)
  807. {
  808. hr = WdmPropertyToCimProperty(pDestinationInstance,
  809. pSourceInstance,
  810. PropertyName,
  811. &PropertyValue,
  812. DestCimType,
  813. SourceCimType);
  814. } else {
  815. hr = CimPropertyToWdmProperty(pDestinationInstance,
  816. pSourceInstance,
  817. PropertyName,
  818. &PropertyValue,
  819. DestCimType,
  820. SourceCimType);
  821. }
  822. if (hr == WBEM_S_NO_ERROR)
  823. {
  824. //
  825. // Try to place the transformed property into the
  826. // destination class.
  827. //
  828. hr = pDestinationInstance->Put(PropertyName,
  829. 0,
  830. &PropertyValue,
  831. 0);
  832. }
  833. }
  834. SysFreeString(PropertyName);
  835. VariantClear(&PropertyValue);
  836. } else if (hr == WBEM_S_NO_MORE_DATA) {
  837. //
  838. // This signifies the end of the enumerations
  839. //
  840. hr = WBEM_S_NO_ERROR;
  841. break;
  842. }
  843. } while (hr == WBEM_S_NO_ERROR);
  844. pSourceInstance->EndEnumeration();
  845. }
  846. return(hr);
  847. }
  848. HRESULT CWdmClass::FillInCimInstance(
  849. IN IWbemContext *pCtx,
  850. IN int RelPathIndex,
  851. IN OUT IWbemClassObject *pCimInstance,
  852. IN IWbemClassObject *pWdmInstance
  853. )
  854. {
  855. IWbemClassObject *pSuperInstance;
  856. ULONG Count;
  857. ULONG i;
  858. BSTR Property;
  859. VARIANT v;
  860. HRESULT hr, hrDontCare;
  861. CIMTYPE CimType;
  862. BSTR s;
  863. WmipAssert(RelPathIndex < RelPathCount);
  864. WmipAssert(pCimInstance != NULL);
  865. WmipAssert(pWdmInstance != NULL);
  866. switch (DerivationType)
  867. {
  868. case ConcreteDerivation:
  869. {
  870. //
  871. // We derived from a concrete class, so we need to duplicate
  872. // the key properties
  873. //
  874. hr = GetCimServices()->GetObject(CimMapRelPaths->Get(RelPathIndex),
  875. 0,
  876. pCtx,
  877. &pSuperInstance,
  878. NULL);
  879. if (hr == WBEM_S_NO_ERROR)
  880. {
  881. Count = PropertyList.GetListSize();
  882. for (i = 0; (i < Count) && (hr == WBEM_S_NO_ERROR); i++)
  883. {
  884. Property = PropertyList.Get(i);
  885. WmipDebugPrint(("WMIMAP: Concrete Property %ws\n", Property));
  886. if (Property != NULL)
  887. {
  888. hr = pSuperInstance->Get(Property,
  889. 0,
  890. &v,
  891. &CimType,
  892. NULL);
  893. if (hr == WBEM_S_NO_ERROR)
  894. {
  895. hr = pCimInstance->Put(Property,
  896. 0,
  897. &v,
  898. CimType);
  899. VariantClear(&v);
  900. }
  901. }
  902. }
  903. pSuperInstance->Release();
  904. }
  905. break;
  906. }
  907. case NonConcreteDerivation:
  908. {
  909. //
  910. // We derived from a non concrete class, so we need to fill
  911. // in any properties from the super class that we feel we
  912. // should. The list includes
  913. // Description (from FriendlyName device property)
  914. // Caption (from DeviceDesc device property)
  915. // Name (From DeviceDesc device property)
  916. // Status (always OK)
  917. // PNPDeviceID
  918. //
  919. if (PnPDeviceIds != NULL)
  920. {
  921. s = PnPDeviceIds->Get(RelPathIndex);
  922. v.vt = VT_BSTR;
  923. v.bstrVal = s;
  924. hrDontCare = pCimInstance->Put(PNP_DEVICE_ID,
  925. 0,
  926. &v,
  927. 0);
  928. }
  929. if (FriendlyName != NULL)
  930. {
  931. s = FriendlyName->Get(RelPathIndex);
  932. if (s != NULL)
  933. {
  934. v.vt = VT_BSTR;
  935. v.bstrVal = s;
  936. hrDontCare = pCimInstance->Put(DESCRIPTION,
  937. 0,
  938. &v,
  939. 0);
  940. }
  941. }
  942. if (DeviceDesc != NULL)
  943. {
  944. s = DeviceDesc->Get(RelPathIndex);
  945. if (s != NULL)
  946. {
  947. v.vt = VT_BSTR;
  948. v.bstrVal = s;
  949. hrDontCare = pCimInstance->Put(NAME,
  950. 0,
  951. &v,
  952. 0);
  953. hrDontCare = pCimInstance->Put(CAPTION,
  954. 0,
  955. &v,
  956. 0);
  957. }
  958. }
  959. s = SysAllocString(OK);
  960. if (s != NULL)
  961. {
  962. v.vt = VT_BSTR;
  963. v.bstrVal = s;
  964. hrDontCare = pCimInstance->Put(STATUS,
  965. 0,
  966. &v,
  967. 0);
  968. SysFreeString(s);
  969. }
  970. break;
  971. }
  972. case NoDerivation:
  973. {
  974. //
  975. // Nothing to do
  976. //
  977. hr = WBEM_S_NO_ERROR;
  978. break;
  979. }
  980. default:
  981. {
  982. WmipAssert(FALSE);
  983. hr = WBEM_S_NO_ERROR;
  984. break;
  985. }
  986. }
  987. return(hr);
  988. }
  989. HRESULT CWdmClass::CreateCimInstance(
  990. IN IWbemContext *pCtx,
  991. IN int RelPathIndex,
  992. OUT IWbemClassObject **pCimInstance
  993. )
  994. /*+++
  995. Routine Description:
  996. This routine will create a CIM instance corresponding to the WDM
  997. instance for the relpath index. No data is cached as the WDM class
  998. is always queried to create the instance.
  999. Arguments:
  1000. pCtx is the WBEM context
  1001. RelPathIndex is the index into the class corresponding to the
  1002. instance
  1003. *pCimInstance returns with a CIM class instance
  1004. Return Value:
  1005. HRESULT
  1006. ---*/
  1007. {
  1008. IWbemClassObject *pWdmInstance;
  1009. HRESULT hr;
  1010. WmipAssert(pCimInstance != NULL);
  1011. WmipAssert(RelPathIndex < RelPathCount);
  1012. WmipAssert(IsThisInitialized());
  1013. //
  1014. // Create a template Cim instance to be filled with WDM properties
  1015. //
  1016. hr = CreateInst(pCtx,
  1017. GetCimServices(),
  1018. CimClassName,
  1019. pCimInstance);
  1020. if (hr == WBEM_S_NO_ERROR)
  1021. {
  1022. hr = GetWdmInstanceByIndex(pCtx,
  1023. RelPathIndex,
  1024. &pWdmInstance);
  1025. if (hr == WBEM_S_NO_ERROR)
  1026. {
  1027. hr = CopyBetweenCimAndWdmClasses(*pCimInstance,
  1028. pWdmInstance,
  1029. TRUE);
  1030. if (hr == WBEM_S_NO_ERROR)
  1031. {
  1032. //
  1033. // Fill in additional CIM properties in the case of
  1034. // classes derived from concrete and non concrete classes
  1035. //
  1036. hr = FillInCimInstance(pCtx,
  1037. RelPathIndex,
  1038. *pCimInstance,
  1039. pWdmInstance);
  1040. }
  1041. pWdmInstance->Release();
  1042. }
  1043. if (hr != WBEM_S_NO_ERROR)
  1044. {
  1045. (*pCimInstance)->Release();
  1046. *pCimInstance = NULL;
  1047. }
  1048. }
  1049. return(hr);
  1050. }
  1051. HRESULT CWdmClass::GetIndexByCimRelPath(
  1052. BSTR CimObjectPath,
  1053. int *RelPathIndex
  1054. )
  1055. /*+++
  1056. Routine Description:
  1057. This routine will return the RelPathIndex for a specific Cim
  1058. Relpath
  1059. Arguments:
  1060. CimRelPath is the Cim relpath
  1061. *RelPathIndex returns with the relpath index
  1062. Return Value:
  1063. HRESULT
  1064. ---*/
  1065. {
  1066. int i;
  1067. WmipAssert(CimObjectPath != NULL);
  1068. WmipAssert(CimInstances->IsInitialized());
  1069. WmipAssert(WdmRelPaths->IsInitialized());
  1070. WmipAssert(IsThisInitialized());
  1071. for (i = 0; i < RelPathCount; i++)
  1072. {
  1073. if (_wcsicmp(CimObjectPath, GetCimRelPath(i)) == 0)
  1074. {
  1075. *RelPathIndex = i;
  1076. return(WBEM_S_NO_ERROR);
  1077. }
  1078. }
  1079. return(WBEM_E_NOT_FOUND);
  1080. }
  1081. HRESULT CWdmClass::GetWdmInstanceByIndex(
  1082. IN IWbemContext *pCtx,
  1083. IN int RelPathIndex,
  1084. OUT IWbemClassObject **ppWdmInstance
  1085. )
  1086. /*+++
  1087. Routine Description:
  1088. This routine will return a IWbemClassObject pointer associated
  1089. with the RelPath index
  1090. Arguments:
  1091. RelPathIndex
  1092. *ppWdmClassObject returns with an instance for the relpaht
  1093. Return Value:
  1094. HRESULT
  1095. ---*/
  1096. {
  1097. HRESULT hr;
  1098. WmipAssert(ppWdmInstance != NULL);
  1099. WmipAssert(IsThisInitialized());
  1100. //
  1101. // Run in the caller's context so that if he is not able to access
  1102. // the WDM classes, he can't
  1103. //
  1104. hr = CoImpersonateClient();
  1105. if (hr == WBEM_S_NO_ERROR)
  1106. {
  1107. *ppWdmInstance = NULL;
  1108. hr = GetWdmServices()->GetObject(WdmRelPaths->Get(RelPathIndex),
  1109. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  1110. pCtx,
  1111. ppWdmInstance,
  1112. NULL);
  1113. CoRevertToSelf();
  1114. }
  1115. return(hr);
  1116. }
  1117. BOOLEAN CWdmClass::IsThisInitialized(
  1118. void
  1119. )
  1120. /*+++
  1121. Routine Description:
  1122. This routine determines if this class has been initialized to
  1123. access CDM and WDM classes
  1124. Arguments:
  1125. Return Value:
  1126. TRUE if initialiezed else FALSE
  1127. ---*/
  1128. {
  1129. return( (CimClassName != NULL) );
  1130. }
  1131. IWbemClassObject *CWdmClass::GetCimInstance(
  1132. int RelPathIndex
  1133. )
  1134. {
  1135. WmipAssert(CimInstances->IsInitialized());
  1136. WmipAssert(RelPathIndex < RelPathCount);
  1137. WmipAssert(IsThisInitialized());
  1138. return(CimInstances->Get(RelPathIndex));
  1139. }
  1140. BSTR /* NOFREE */ CWdmClass::GetCimRelPath(
  1141. int RelPathIndex
  1142. )
  1143. /*+++
  1144. Routine Description:
  1145. This routine will return the Cim relpath for a RelPathIndex
  1146. Arguments:
  1147. RelPathIndex
  1148. Return Value:
  1149. Cim RelPath. This should not be freed
  1150. ---*/
  1151. {
  1152. WmipAssert(CimInstances->IsInitialized());
  1153. WmipAssert(RelPathIndex < RelPathCount);
  1154. WmipAssert(IsThisInitialized());
  1155. return(CimInstances->GetRelPath(RelPathIndex));
  1156. }
  1157. BSTR /* NOFREE */ CWdmClass::GetWdmRelPath(
  1158. int RelPathIndex
  1159. )
  1160. /*+++
  1161. Routine Description:
  1162. This routine will return the Wdm relpath for a RelPathIndex
  1163. Arguments:
  1164. RelPathIndex
  1165. Return Value:
  1166. Cim RelPath. This should not be freed
  1167. ---*/
  1168. {
  1169. WmipAssert(WdmRelPaths->IsInitialized());
  1170. WmipAssert(RelPathIndex < RelPathCount);
  1171. WmipAssert(IsThisInitialized());
  1172. return(WdmRelPaths->Get(RelPathIndex));
  1173. }
  1174. //
  1175. // Linked list management routines
  1176. //
  1177. CWdmClass *CWdmClass::GetNext(
  1178. )
  1179. {
  1180. return(Next);
  1181. }
  1182. CWdmClass *CWdmClass::GetPrev(
  1183. )
  1184. {
  1185. return(Prev);
  1186. }
  1187. void CWdmClass::InsertSelf(
  1188. CWdmClass **Head
  1189. )
  1190. {
  1191. WmipAssert(Next == NULL);
  1192. WmipAssert(Prev == NULL);
  1193. if (*Head != NULL)
  1194. {
  1195. Next = (*Head);
  1196. (*Head)->Prev = this;
  1197. }
  1198. *Head = this;
  1199. }
  1200. BOOLEAN CWdmClass::ClaimCimClassName(
  1201. PWCHAR ClassName
  1202. )
  1203. {
  1204. //
  1205. // If this class has the same CIM class name as the one we are
  1206. // looking for then we have a match
  1207. //
  1208. if (_wcsicmp(ClassName, CimClassName) == 0)
  1209. {
  1210. return(TRUE);
  1211. }
  1212. return(FALSE);
  1213. }
  1214. HRESULT CWdmClass::PutInstance(
  1215. IWbemContext *pCtx,
  1216. int RelPathIndex,
  1217. IWbemClassObject *pCimInstance
  1218. )
  1219. {
  1220. HRESULT hr;
  1221. IWbemClassObject *pWdmInstance;
  1222. WmipAssert(pCimInstance != NULL);
  1223. WmipAssert(RelPathIndex < RelPathCount);
  1224. //
  1225. // First thing is to obtain the WDM instance that corresponds to
  1226. // the cim instance
  1227. //
  1228. hr = GetWdmServices()->GetObject(WdmRelPaths->Get(RelPathIndex),
  1229. 0,
  1230. pCtx,
  1231. &pWdmInstance,
  1232. NULL);
  1233. if (hr == WBEM_S_NO_ERROR)
  1234. {
  1235. //
  1236. // Now copy properties from the CIM class into the WDM class
  1237. //
  1238. hr = CopyBetweenCimAndWdmClasses(pWdmInstance,
  1239. pCimInstance,
  1240. FALSE);
  1241. if (hr == WBEM_S_NO_ERROR)
  1242. {
  1243. //
  1244. // Finally put the WDM instance to reflect the changed
  1245. // properties down into the driver
  1246. //
  1247. hr = GetWdmServices()->PutInstance(pWdmInstance,
  1248. WBEM_FLAG_UPDATE_ONLY,
  1249. pCtx,
  1250. NULL);
  1251. }
  1252. }
  1253. return(hr);
  1254. }