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.
 
 
 
 
 
 

1554 lines
31 KiB

//***************************************************************************
//
// TestInfo.CPP
//
// Module: CDM Provider
//
// Purpose: Defines the CClassPro class. An object of this class is
// created by the class factory for each connection.
//
// Copyright (c) 2000 Microsoft Corporation
//
//***************************************************************************
#include <objbase.h>
#ifndef _MT
#define _MT
#endif
#include <wbemidl.h>
#include "debug.h"
#include "useful.h"
#include "wbemmisc.h"
#include "testinfo.h"
#include "cimmap.h"
#include "text.h"
IWbemServices *pCimServices;
IWbemServices *pWdmServices;
HRESULT TestInfoInitialize(
void
)
/*+++
Routine Description:
This routine will establishes a connection to the root\wmi and
root\cimv2 namespaces in global memory
Arguments:
Return Value:
HRESULT
---*/
{
HRESULT hr;
WmipAssert(pCimServices == NULL);
WmipAssert(pWdmServices == NULL);
hr = WmiConnectToWbem(L"root\\cimv2",
&pCimServices);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiConnectToWbem(L"root\\wmi",
&pWdmServices);
if (hr != WBEM_S_NO_ERROR)
{
pCimServices->Release();
pCimServices = NULL;
}
}
return(hr);
}
void TestInfoDeinitialize(
void
)
/*+++
Routine Description:
This routine will disestablish a connection to the root\wmi and
root\cimv2 namespaces in global memory
Arguments:
Return Value:
---*/
{
WmipAssert(pCimServices != NULL);
WmipAssert(pWdmServices != NULL);
pCimServices->Release();
pCimServices = NULL;
pWdmServices->Release();
pWdmServices = NULL;
}
CWdmClass::CWdmClass()
/*+++
Routine Description:
Constructor for CWdmClass class
Arguments:
Return Value:
---*/
{
Next = NULL;
Prev = NULL;
WdmShadowClassName = NULL;
WdmMappingClassName = NULL;
WdmMappingProperty = NULL;
CimClassName = NULL;
CimMappingClassName = NULL;
CimMappingProperty = NULL;
PnPDeviceIds = NULL;
FriendlyName = NULL;
DeviceDesc = NULL;
CimMapRelPaths = NULL;
WdmRelPaths = NULL;
CimInstances = NULL;
RelPathCount = (int)-1;
DerivationType = UnknownDerivation;
//
// Start out with the class marked as not having instances
// availabel
//
MappingInProgress = 1;
}
CWdmClass::~CWdmClass()
/*+++
Routine Description:
Destructor for CWdmClass class
Arguments:
Return Value:
---*/
{
int i;
if (WdmShadowClassName != NULL)
{
SysFreeString(WdmShadowClassName);
}
if (WdmMappingClassName != NULL)
{
SysFreeString(WdmMappingClassName);
}
if (WdmMappingProperty != NULL)
{
SysFreeString(WdmMappingProperty);
}
if (CimMappingClassName != NULL)
{
SysFreeString(CimMappingClassName);
}
if (CimClassName != NULL)
{
SysFreeString(CimClassName);
}
if (CimMappingProperty != NULL)
{
SysFreeString(CimMappingProperty);
}
if (WdmMappingProperty != NULL)
{
SysFreeString(WdmMappingProperty);
}
if (CimMapRelPaths != NULL)
{
delete CimMapRelPaths;
}
if (WdmRelPaths != NULL)
{
delete WdmRelPaths;
}
if (CimInstances != NULL)
{
delete CimInstances;
}
if (PnPDeviceIds != NULL)
{
delete PnPDeviceIds;
}
if (FriendlyName != NULL)
{
delete FriendlyName;
}
if (DeviceDesc != NULL)
{
delete DeviceDesc;
}
}
IWbemServices *CWdmClass::GetWdmServices(
void
)
/*+++
Routine Description:
Accessor for the WDM namespace IWbemServices
Arguments:
Return Value:
IWbemServices
---*/
{
WmipAssert(pWdmServices != NULL);
return(pWdmServices);
}
IWbemServices *CWdmClass::GetCimServices(
void
)
/*+++
Routine Description:
Accessor for the CIM namespace IWbemServices
Arguments:
Return Value:
IWbemServices
---*/
{
WmipAssert(pCimServices != NULL);
return(pCimServices);
}
HRESULT CWdmClass::DiscoverPropertyTypes(
IWbemContext *pCtx,
IWbemClassObject *pCimClassObject
)
{
HRESULT hr, hrDontCare;
VARIANT v;
BSTR PropertyName;
ULONG Count;
IWbemQualifierSet *pQualifierList;
WmipAssert(pCimClassObject != NULL);
if (DerivationType == ConcreteDerivation)
{
//
// For a concrete derivation, get all of the key properties
// from the superclass so we can populate them too
//
hr = pCimClassObject->BeginEnumeration(WBEM_FLAG_KEYS_ONLY);
if (hr == WBEM_S_NO_ERROR)
{
//
// TODO: Make CBstrArray allocation dynamic
//
PropertyList.Initialize(10);
Count = 0;
do
{
hr = pCimClassObject->Next(0,
&PropertyName,
NULL,
NULL,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
PropertyList.Set(Count++, PropertyName);
} else if (hr == WBEM_S_NO_MORE_DATA) {
//
// This signifies the end of the enumerations
//
hr = WBEM_S_NO_ERROR;
break;
}
} while (hr == WBEM_S_NO_ERROR);
pCimClassObject->EndEnumeration();
}
} else if (DerivationType == NonConcreteDerivation) {
//
// TODO: Figure out how we want to create the list of
// superclass properties to fill
//
PropertyList.Initialize(1);
hr = WBEM_S_NO_ERROR;
}
return(hr);
}
HRESULT CWdmClass::InitializeSelf(
IWbemContext *pCtx,
PWCHAR CimClass
)
{
HRESULT hr;
VARIANT v, vSuper;
IWbemClassObject *pClass;
IWbemQualifierSet *pQualifiers;
PWCHAR Names[6];
VARTYPE Types[6];
VARIANT Values[6];
WmipAssert(CimClass != NULL);
WmipAssert(CimMappingClassName == NULL);
WmipAssert(WdmShadowClassName == NULL);
WmipAssert(CimClassName == NULL);
//
// We assume that this method will always be the first one called
// by the class provider
//
EnterCritSection();
if ((pCimServices == NULL) &&
(pWdmServices == NULL))
{
hr = TestInfoInitialize();
if (hr != WBEM_S_NO_ERROR)
{
LeaveCritSection();
WmipDebugPrint(("WMIMAP: TestInfoInitialize -> %x\n", hr));
return(hr);
}
}
LeaveCritSection();
CimClassName = SysAllocString(CimClass);
if (CimClassName != NULL)
{
//
// Get the WdmShadowClass class qualifier to discover the name of
// the Wdm class that is represented by this cim class
//
hr = GetCimServices()->GetObject(CimClassName,
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
pCtx,
&pClass,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
//
// See if this is a derived class or not
//
VariantInit(&vSuper);
hr = WmiGetProperty(pClass,
SUPERCLASS,
CIM_STRING,
&vSuper);
if (hr == WBEM_S_NO_ERROR)
{
hr = pClass->GetQualifierSet(&pQualifiers);
if (hr == WBEM_S_NO_ERROR)
{
Names[0] = WDM_SHADOW_CLASS;
Types[0] = VT_BSTR;
Names[1] = WDM_MAPPING_CLASS;
Types[1] = VT_BSTR;
Names[2] = WDM_MAPPING_PROPERTY;
Types[2] = VT_BSTR;
Names[3] = CIM_MAPPING_CLASS;
Types[3] = VT_BSTR;
Names[4] = CIM_MAPPING_PROPERTY;
Types[4] = VT_BSTR;
Names[5] = DERIVED_CLASS_TYPE;
Types[5] = VT_BSTR;
hr = GetListOfQualifiers(pQualifiers,
6,
Names,
Types,
Values,
FALSE);
if (hr == WBEM_S_NO_ERROR)
{
//
// First determine if this is a concrete or non
// concrete derivation
//
if (Values[5].vt == VT_BSTR)
{
if (_wcsicmp(Values[5].bstrVal, CONCRETE) == 0)
{
DerivationType = ConcreteDerivation;
} else if (_wcsicmp(Values[5].bstrVal, NONCONCRETE) == 0)
{
DerivationType = NonConcreteDerivation;
}
}
if (DerivationType == UnknownDerivation)
{
//
// Must specify derivation type
//
hr = WBEM_E_AMBIGUOUS_OPERATION;
WmipDebugPrint(("WMIMAP: class %ws must specify derivation type\n",
CimClass));
} else {
if (Values[3].vt == VT_BSTR)
{
//
// Use CimMappingClass as specified
//
CimMappingClassName = Values[3].bstrVal;
VariantInit(&Values[3]);
} else {
//
// CimMappingClass not specified, use
// superclass as mapping class
//
CimMappingClassName = vSuper.bstrVal;
VariantInit(&vSuper);
}
if (Values[0].vt == VT_BSTR)
{
//
// WdmShadowClass is required
//
WdmShadowClassName = Values[0].bstrVal;
VariantInit(&Values[0]);
if (Values[1].vt == VT_BSTR)
{
//
// WdmMappingClass can specify that
// the mapping class is different
// from the shadow class
//
WdmMappingClassName = Values[1].bstrVal;
VariantInit(&Values[1]);
}
if (Values[2].vt == VT_BSTR)
{
WdmMappingProperty = Values[2].bstrVal;
VariantInit(&Values[2]);
}
if (Values[4].vt == VT_BSTR)
{
CimMappingProperty = Values[4].bstrVal;
VariantInit(&Values[4]);
if (WdmMappingProperty == NULL)
{
//
// If CimMappingProperty
// specified then
// WdmMappingProperty is
// required
//
hr = WBEM_E_INVALID_CLASS;
}
} else {
if (WdmMappingProperty != NULL)
{
//
// If CimMappingProperty is not
// specified then
// WdmMappingProperty should
// not be specified
//
hr = WBEM_E_INVALID_CLASS;
}
}
if (hr == WBEM_S_NO_ERROR)
{
//
// Look at all properties to discover which ones
// need to be handled
//
hr = DiscoverPropertyTypes(pCtx,
pClass);
}
} else {
//
// WDMShadowClass qualifier is required
//
hr = WBEM_E_INVALID_CLASS;
}
}
VariantClear(&Values[0]);
VariantClear(&Values[1]);
VariantClear(&Values[2]);
VariantClear(&Values[3]);
VariantClear(&Values[4]);
VariantClear(&Values[5]);
}
pQualifiers->Release();
}
VariantClear(&vSuper);
} else {
//
// No superclass implies no derivation
//
DerivationType = NoDerivation;
hr = WBEM_S_NO_ERROR;
}
pClass->Release();
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT CWdmClass::RemapToCimClass(
IWbemContext *pCtx
)
/*+++
Routine Description:
This routine will setup this class and initialize everything so
that the provider can interact with the CDM and WDM classes
Arguments:
CdmClass is the name of the CDM class
Return Value:
HRESULT
---*/
{
CBstrArray WdmInstanceNames;
CBstrArray *WdmPaths;
CBstrArray *CimPaths;
CBstrArray *CimMapPaths;
IWbemClassObject *CimInstance;
HRESULT hr;
int i;
WmipAssert(CimMappingClassName != NULL);
WmipAssert(WdmShadowClassName != NULL);
//
// Increment this to indicate that mapping is in progress and thus
// there are no instances available. Consider changing this to some
// kind of synchronization mechanism
//
IncrementMappingInProgress();
//
// Free rel path bstr arrays
//
if (CimMapRelPaths != NULL)
{
delete CimMapRelPaths;
}
if (CimInstances != NULL)
{
delete CimInstances;
}
if (WdmRelPaths != NULL)
{
delete WdmRelPaths;
}
//
// allocate new rel paths
//
CimMapRelPaths = new CBstrArray;
WdmRelPaths = new CBstrArray;
CimInstances = new CWbemObjectList;
PnPDeviceIds = new CBstrArray;
FriendlyName = new CBstrArray;
DeviceDesc = new CBstrArray;
if ((CimMapRelPaths != NULL) &&
(CimInstances != NULL) &&
(PnPDeviceIds != NULL) &&
(FriendlyName != NULL) &&
(DeviceDesc != NULL) &&
(WdmRelPaths != NULL))
{
if ((WdmMappingProperty == NULL) &&
(CimMappingProperty == NULL))
{
//
// Use worker function to determine which
// Wdm relpaths map to which CIM_LogicalDevice relpaths
// via the PnP ids
//
hr = MapWdmClassToCimClassViaPnpId(pCtx,
pWdmServices,
pCimServices,
WdmShadowClassName,
CimMappingClassName,
PnPDeviceIds,
FriendlyName,
DeviceDesc,
&WdmInstanceNames,
WdmRelPaths,
CimMapRelPaths,
&RelPathCount);
} else {
//
// Use worker function to map WDM relpaths to CIM relpaths
// using a common property in both classes
//
hr = MapWdmClassToCimClassViaProperty(pCtx,
pWdmServices,
pCimServices,
WdmShadowClassName,
WdmMappingClassName ?
WdmMappingClassName :
WdmShadowClassName,
WdmMappingProperty,
CimMappingClassName,
CimMappingProperty,
&WdmInstanceNames,
WdmRelPaths,
CimMapRelPaths,
&RelPathCount);
}
if (hr == WBEM_S_NO_ERROR)
{
//
// Collect the relpaths for our cim instances that we are
// providing. Best way to do this is to create our instances
//
CimInstances->Initialize(RelPathCount);
for (i = 0; i < RelPathCount; i++)
{
WmipDebugPrint(("WMIMAP: %ws maps to %ws\n",
WdmRelPaths->Get(i),
CimMapRelPaths->Get(i)));
hr = CreateCimInstance(pCtx,
i,
&CimInstance);
if (hr == WBEM_S_NO_ERROR)
{
hr = CimInstances->Set(i,
CimInstance);
if (hr != WBEM_S_NO_ERROR)
{
break;
}
} else {
break;
}
}
}
}
if (hr != WBEM_S_NO_ERROR)
{
delete CimMapRelPaths;
CimMapRelPaths = NULL;
delete WdmRelPaths;
WdmRelPaths = NULL;
delete CimInstances;
CimInstances = NULL;
}
DecrementMappingInProgress();
return(hr);
}
HRESULT CWdmClass::WdmPropertyToCimProperty(
IN IWbemClassObject *pCdmClassInstance,
IN IWbemClassObject *pWdmClassInstance,
IN BSTR PropertyName,
IN OUT VARIANT *PropertyValue,
IN CIMTYPE CdmCimType,
IN CIMTYPE WdmCimType
)
/*+++
Routine Description:
This routine will convert a property in a Wdm class into the form
required for the property in the Cdm class.
Arguments:
pCdmClassInstance is the instnace of the Cdm class that will get
the property value
pWdmClassInstance is the instance of the Wdm class that has the
property value
PropertyName is the name of the property in the Wdm and Cdm classes
PropertyValue on entry has the value of the property in the Wdm
instance and on return has the value to set in the Cdm instance
CdmCimType is the property type for the property in the Cdm
instance
WdmCimType is the property type for the property in the Wdm
instance
Return Value:
HRESULT
---*/
{
HRESULT hr;
CIMTYPE BaseWdmCimType, BaseCdmCimType;
CIMTYPE WdmCimArray, CdmCimArray;
WmipAssert(pCdmClassInstance != NULL);
WmipAssert(pWdmClassInstance != NULL);
WmipAssert(PropertyName != NULL);
WmipAssert(PropertyValue != NULL);
WmipAssert(IsThisInitialized());
//
// Rules for converting Wdm Classes into Cdm Classes
// Wdm Class Type Cdm Class Type Conversion Done
// enumeration string Build string from enum
//
BaseWdmCimType = WdmCimType & ~CIM_FLAG_ARRAY;
BaseCdmCimType = CdmCimType & ~CIM_FLAG_ARRAY;
WdmCimArray = WdmCimType & CIM_FLAG_ARRAY;
CdmCimArray = CdmCimType & CIM_FLAG_ARRAY;
if (((BaseWdmCimType == CIM_UINT32) ||
(BaseWdmCimType == CIM_UINT16) ||
(BaseWdmCimType == CIM_UINT8)) &&
(BaseCdmCimType == CIM_STRING) &&
(WdmCimArray == CdmCimArray) &&
(PropertyValue->vt != VT_NULL))
{
CValueMapping ValueMapping;
hr = ValueMapping.EstablishByName(GetWdmServices(),
WdmShadowClassName,
PropertyName);
if (hr == WBEM_S_NO_ERROR)
{
hr = ValueMapping.MapVariantToString(PropertyValue,
WdmCimType);
}
} else {
//
// No conversion needs to occur
//
hr = WBEM_S_NO_ERROR;
}
return(hr);
}
HRESULT CWdmClass::CimPropertyToWdmProperty(
IN IWbemClassObject *pWdmClassInstance,
IN IWbemClassObject *pCdmClassInstance,
IN BSTR PropertyName,
IN OUT VARIANT *PropertyValue,
IN CIMTYPE WdmCimType,
IN CIMTYPE CdmCimType
)
/*+++
Routine Description:
This routine will convert a property in a Cdm class into the form
required for the property in the Wdm class.
Arguments:
pWdmClassInstance is the instance of the Wdm class that has the
property value
pCdmClassInstance is the instnace of the Cdm class that will get
the property value
PropertyName is the name of the property in the Wdm and Cdm classes
PropertyValue on entry has the value of the property in the Wdm
instance and on return has the value to set in the Cdm instance
WdmCimType is the property type for the property in the Wdm
instance
CdmCimType is the property type for the property in the Cdm
instance
Return Value:
HRESULT
---*/
{
HRESULT hr;
CIMTYPE BaseWdmCimType, BaseCdmCimType;
CIMTYPE WdmCimArray, CdmCimArray;
WmipAssert(pCdmClassInstance != NULL);
WmipAssert(pWdmClassInstance != NULL);
WmipAssert(PropertyName != NULL);
WmipAssert(PropertyValue != NULL);
WmipAssert(IsThisInitialized());
//
// Rules for converting Wdm Classes into Cdm Classes
// Wdm Class Type Cdm Class Type Conversion Done
// enumeration string Map string to enum value
//
//
BaseWdmCimType = WdmCimType & ~CIM_FLAG_ARRAY;
BaseCdmCimType = CdmCimType & ~CIM_FLAG_ARRAY;
WdmCimArray = WdmCimType & CIM_FLAG_ARRAY;
CdmCimArray = CdmCimType & CIM_FLAG_ARRAY;
if (((BaseWdmCimType == CIM_UINT32) ||
(BaseWdmCimType == CIM_UINT16) ||
(BaseWdmCimType == CIM_UINT8)) &&
(BaseCdmCimType == CIM_STRING) &&
(WdmCimArray == CdmCimArray) &&
(PropertyValue->vt != VT_NULL))
{
CValueMapping ValueMapping;
hr = ValueMapping.EstablishByName(GetWdmServices(),
WdmShadowClassName,
PropertyName);
if (hr == WBEM_S_NO_ERROR)
{
hr = ValueMapping.MapVariantToNumber(PropertyValue,
(VARTYPE)BaseWdmCimType);
}
} else {
//
// No conversion needs to occur
//
hr = WBEM_S_NO_ERROR;
}
return(hr);
}
HRESULT CWdmClass::CopyBetweenCimAndWdmClasses(
IN IWbemClassObject *pDestinationInstance,
IN IWbemClassObject *pSourceInstance,
IN BOOLEAN WdmToCdm
)
/*+++
Routine Description:
This routine will do the work to copy and convert all properties in
an instance of a Wdm or Cdm class to an instance of a Cdm or Wdm
class.
Note that properties from one instance are only copied to
properties of another instance when the property names are
identical. No assumption is ever made on the name of the
properties. The only info used to determine how to convert a
property is based upon the source and destination cim type.
Arguments:
pDestinationInstance is the class instance that the properties will
be copied into
pSourceInstance is the class instance that the properties will be
copied from
WdmToCdm is TRUE if copying from Wdm to Cdm, else FALSE
Return Value:
HRESULT
---*/
{
HRESULT hr;
VARIANT PropertyValue;
BSTR PropertyName;
CIMTYPE SourceCimType, DestCimType;
HRESULT hrDontCare;
WmipAssert(pDestinationInstance != NULL);
WmipAssert(pSourceInstance != NULL);
WmipAssert(IsThisInitialized());
//
// Now we need to move over all of the properties from the source
// class into the destination class. Note that some properties need
// some special effort such as OtherCharacteristics which needs
// to be converted from an enumeration value (in wdm) to a
// string (in CDM).
//
// Our strategy is to enumerate all of the proeprties in the
// source class and then look for a property with the same name
// and type in the destination class. If so we just copy over the
// value. If the data type is different we need to do some
// conversion.
//
hr = pSourceInstance->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
if (hr == WBEM_S_NO_ERROR)
{
do
{
//
// Get a property from the source class
//
hr = pSourceInstance->Next(0,
&PropertyName,
&PropertyValue,
&SourceCimType,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
//
// Try to get a property with the same name from the
// dest class. If the identically named property does
// not exist in the destination class then it is ignored
//
hrDontCare = pDestinationInstance->Get(PropertyName,
0,
NULL,
&DestCimType,
NULL);
if (hrDontCare == WBEM_S_NO_ERROR)
{
if (WdmToCdm)
{
hr = WdmPropertyToCimProperty(pDestinationInstance,
pSourceInstance,
PropertyName,
&PropertyValue,
DestCimType,
SourceCimType);
} else {
hr = CimPropertyToWdmProperty(pDestinationInstance,
pSourceInstance,
PropertyName,
&PropertyValue,
DestCimType,
SourceCimType);
}
if (hr == WBEM_S_NO_ERROR)
{
//
// Try to place the transformed property into the
// destination class.
//
hr = pDestinationInstance->Put(PropertyName,
0,
&PropertyValue,
0);
}
}
SysFreeString(PropertyName);
VariantClear(&PropertyValue);
} else if (hr == WBEM_S_NO_MORE_DATA) {
//
// This signifies the end of the enumerations
//
hr = WBEM_S_NO_ERROR;
break;
}
} while (hr == WBEM_S_NO_ERROR);
pSourceInstance->EndEnumeration();
}
return(hr);
}
HRESULT CWdmClass::FillInCimInstance(
IN IWbemContext *pCtx,
IN int RelPathIndex,
IN OUT IWbemClassObject *pCimInstance,
IN IWbemClassObject *pWdmInstance
)
{
IWbemClassObject *pSuperInstance;
ULONG Count;
ULONG i;
BSTR Property;
VARIANT v;
HRESULT hr, hrDontCare;
CIMTYPE CimType;
BSTR s;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(pCimInstance != NULL);
WmipAssert(pWdmInstance != NULL);
switch (DerivationType)
{
case ConcreteDerivation:
{
//
// We derived from a concrete class, so we need to duplicate
// the key properties
//
hr = GetCimServices()->GetObject(CimMapRelPaths->Get(RelPathIndex),
0,
pCtx,
&pSuperInstance,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
Count = PropertyList.GetListSize();
for (i = 0; (i < Count) && (hr == WBEM_S_NO_ERROR); i++)
{
Property = PropertyList.Get(i);
WmipDebugPrint(("WMIMAP: Concrete Property %ws\n", Property));
if (Property != NULL)
{
hr = pSuperInstance->Get(Property,
0,
&v,
&CimType,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
hr = pCimInstance->Put(Property,
0,
&v,
CimType);
VariantClear(&v);
}
}
}
pSuperInstance->Release();
}
break;
}
case NonConcreteDerivation:
{
//
// We derived from a non concrete class, so we need to fill
// in any properties from the super class that we feel we
// should. The list includes
// Description (from FriendlyName device property)
// Caption (from DeviceDesc device property)
// Name (From DeviceDesc device property)
// Status (always OK)
// PNPDeviceID
//
if (PnPDeviceIds != NULL)
{
s = PnPDeviceIds->Get(RelPathIndex);
v.vt = VT_BSTR;
v.bstrVal = s;
hrDontCare = pCimInstance->Put(PNP_DEVICE_ID,
0,
&v,
0);
}
if (FriendlyName != NULL)
{
s = FriendlyName->Get(RelPathIndex);
if (s != NULL)
{
v.vt = VT_BSTR;
v.bstrVal = s;
hrDontCare = pCimInstance->Put(DESCRIPTION,
0,
&v,
0);
}
}
if (DeviceDesc != NULL)
{
s = DeviceDesc->Get(RelPathIndex);
if (s != NULL)
{
v.vt = VT_BSTR;
v.bstrVal = s;
hrDontCare = pCimInstance->Put(NAME,
0,
&v,
0);
hrDontCare = pCimInstance->Put(CAPTION,
0,
&v,
0);
}
}
s = SysAllocString(OK);
if (s != NULL)
{
v.vt = VT_BSTR;
v.bstrVal = s;
hrDontCare = pCimInstance->Put(STATUS,
0,
&v,
0);
SysFreeString(s);
}
break;
}
case NoDerivation:
{
//
// Nothing to do
//
hr = WBEM_S_NO_ERROR;
break;
}
default:
{
WmipAssert(FALSE);
hr = WBEM_S_NO_ERROR;
break;
}
}
return(hr);
}
HRESULT CWdmClass::CreateCimInstance(
IN IWbemContext *pCtx,
IN int RelPathIndex,
OUT IWbemClassObject **pCimInstance
)
/*+++
Routine Description:
This routine will create a CIM instance corresponding to the WDM
instance for the relpath index. No data is cached as the WDM class
is always queried to create the instance.
Arguments:
pCtx is the WBEM context
RelPathIndex is the index into the class corresponding to the
instance
*pCimInstance returns with a CIM class instance
Return Value:
HRESULT
---*/
{
IWbemClassObject *pWdmInstance;
HRESULT hr;
WmipAssert(pCimInstance != NULL);
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
//
// Create a template Cim instance to be filled with WDM properties
//
hr = CreateInst(pCtx,
GetCimServices(),
CimClassName,
pCimInstance);
if (hr == WBEM_S_NO_ERROR)
{
hr = GetWdmInstanceByIndex(pCtx,
RelPathIndex,
&pWdmInstance);
if (hr == WBEM_S_NO_ERROR)
{
hr = CopyBetweenCimAndWdmClasses(*pCimInstance,
pWdmInstance,
TRUE);
if (hr == WBEM_S_NO_ERROR)
{
//
// Fill in additional CIM properties in the case of
// classes derived from concrete and non concrete classes
//
hr = FillInCimInstance(pCtx,
RelPathIndex,
*pCimInstance,
pWdmInstance);
}
pWdmInstance->Release();
}
if (hr != WBEM_S_NO_ERROR)
{
(*pCimInstance)->Release();
*pCimInstance = NULL;
}
}
return(hr);
}
HRESULT CWdmClass::GetIndexByCimRelPath(
BSTR CimObjectPath,
int *RelPathIndex
)
/*+++
Routine Description:
This routine will return the RelPathIndex for a specific Cim
Relpath
Arguments:
CimRelPath is the Cim relpath
*RelPathIndex returns with the relpath index
Return Value:
HRESULT
---*/
{
int i;
WmipAssert(CimObjectPath != NULL);
WmipAssert(CimInstances->IsInitialized());
WmipAssert(WdmRelPaths->IsInitialized());
WmipAssert(IsThisInitialized());
for (i = 0; i < RelPathCount; i++)
{
if (_wcsicmp(CimObjectPath, GetCimRelPath(i)) == 0)
{
*RelPathIndex = i;
return(WBEM_S_NO_ERROR);
}
}
return(WBEM_E_NOT_FOUND);
}
HRESULT CWdmClass::GetWdmInstanceByIndex(
IN IWbemContext *pCtx,
IN int RelPathIndex,
OUT IWbemClassObject **ppWdmInstance
)
/*+++
Routine Description:
This routine will return a IWbemClassObject pointer associated
with the RelPath index
Arguments:
RelPathIndex
*ppWdmClassObject returns with an instance for the relpaht
Return Value:
HRESULT
---*/
{
HRESULT hr;
WmipAssert(ppWdmInstance != NULL);
WmipAssert(IsThisInitialized());
//
// Run in the caller's context so that if he is not able to access
// the WDM classes, he can't
//
hr = CoImpersonateClient();
if (hr == WBEM_S_NO_ERROR)
{
*ppWdmInstance = NULL;
hr = GetWdmServices()->GetObject(WdmRelPaths->Get(RelPathIndex),
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
pCtx,
ppWdmInstance,
NULL);
CoRevertToSelf();
}
return(hr);
}
BOOLEAN CWdmClass::IsThisInitialized(
void
)
/*+++
Routine Description:
This routine determines if this class has been initialized to
access CDM and WDM classes
Arguments:
Return Value:
TRUE if initialiezed else FALSE
---*/
{
return( (CimClassName != NULL) );
}
IWbemClassObject *CWdmClass::GetCimInstance(
int RelPathIndex
)
{
WmipAssert(CimInstances->IsInitialized());
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
return(CimInstances->Get(RelPathIndex));
}
BSTR /* NOFREE */ CWdmClass::GetCimRelPath(
int RelPathIndex
)
/*+++
Routine Description:
This routine will return the Cim relpath for a RelPathIndex
Arguments:
RelPathIndex
Return Value:
Cim RelPath. This should not be freed
---*/
{
WmipAssert(CimInstances->IsInitialized());
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
return(CimInstances->GetRelPath(RelPathIndex));
}
BSTR /* NOFREE */ CWdmClass::GetWdmRelPath(
int RelPathIndex
)
/*+++
Routine Description:
This routine will return the Wdm relpath for a RelPathIndex
Arguments:
RelPathIndex
Return Value:
Cim RelPath. This should not be freed
---*/
{
WmipAssert(WdmRelPaths->IsInitialized());
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
return(WdmRelPaths->Get(RelPathIndex));
}
//
// Linked list management routines
//
CWdmClass *CWdmClass::GetNext(
)
{
return(Next);
}
CWdmClass *CWdmClass::GetPrev(
)
{
return(Prev);
}
void CWdmClass::InsertSelf(
CWdmClass **Head
)
{
WmipAssert(Next == NULL);
WmipAssert(Prev == NULL);
if (*Head != NULL)
{
Next = (*Head);
(*Head)->Prev = this;
}
*Head = this;
}
BOOLEAN CWdmClass::ClaimCimClassName(
PWCHAR ClassName
)
{
//
// If this class has the same CIM class name as the one we are
// looking for then we have a match
//
if (_wcsicmp(ClassName, CimClassName) == 0)
{
return(TRUE);
}
return(FALSE);
}
HRESULT CWdmClass::PutInstance(
IWbemContext *pCtx,
int RelPathIndex,
IWbemClassObject *pCimInstance
)
{
HRESULT hr;
IWbemClassObject *pWdmInstance;
WmipAssert(pCimInstance != NULL);
WmipAssert(RelPathIndex < RelPathCount);
//
// First thing is to obtain the WDM instance that corresponds to
// the cim instance
//
hr = GetWdmServices()->GetObject(WdmRelPaths->Get(RelPathIndex),
0,
pCtx,
&pWdmInstance,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
//
// Now copy properties from the CIM class into the WDM class
//
hr = CopyBetweenCimAndWdmClasses(pWdmInstance,
pCimInstance,
FALSE);
if (hr == WBEM_S_NO_ERROR)
{
//
// Finally put the WDM instance to reflect the changed
// properties down into the driver
//
hr = GetWdmServices()->PutInstance(pWdmInstance,
WBEM_FLAG_UPDATE_ONLY,
pCtx,
NULL);
}
}
return(hr);
}