windows-nt/Source/XPSP1/NT/base/wmi/wbemlib/useful.cpp

871 lines
14 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//***************************************************************************
//
// Useful.CPP
//
// Module: CDM Provider
//
// Purpose: Useful classes
//
// Copyright (c) 2000 Microsoft Corporation
//
//***************************************************************************
#include <objbase.h>
#include <wbemprov.h>
#include "debug.h"
#include "useful.h"
#include "wbemmisc.h"
void FreeTheBSTRArray(
BSTR *Array,
ULONG Size
)
/*+++
Routine Description:
This routine will free the contents of an array of BSTR and then
the array itself
Arguments:
Array is the array to be freed
Size is the number of elements in the array
Return Value:
HRESULT
---*/
{
ULONG i;
if (Array != NULL)
{
for (i = 0; i < Size; i++)
{
if (Array[i] != NULL)
{
SysFreeString(Array[i]);
}
}
WmipFree(Array);
}
}
CBstrArray::CBstrArray()
{
Array = NULL;
ListSize = 0xffffffff;
}
CBstrArray::~CBstrArray()
{
ULONG i;
if (Array != NULL)
{
for (i = 0; i < ListSize; i++)
{
if (Array[i] != NULL)
{
SysFreeString(Array[i]);
}
}
WmipFree(Array);
}
ListSize = 0xffffffff;
}
HRESULT CBstrArray::Initialize(
ULONG ListCount
)
{
HRESULT hr = WBEM_S_NO_ERROR;
ULONG AllocSize;
if (ListCount != 0)
{
AllocSize = ListCount * sizeof(BSTR *);
Array = (BSTR *)WmipAlloc(AllocSize);
if (Array != NULL)
{
memset(Array, 0, AllocSize);
ListSize = ListCount;
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
ListSize = ListCount;
}
return(hr);
}
BOOLEAN CBstrArray::IsInitialized(
)
{
return( (Array != NULL) || (ListSize == 0) );
}
BSTR CBstrArray::Get(
ULONG Index
)
{
WmipAssert(Index < ListSize);
WmipAssert(IsInitialized());
return(Array[Index]);
}
void CBstrArray::Set(
ULONG Index,
BSTR s
)
{
WmipAssert(Index < ListSize);
WmipAssert(IsInitialized());
Array[Index] = s;
}
ULONG CBstrArray::GetListSize(
)
{
WmipAssert(IsInitialized());
return(ListSize);
}
CWbemObjectList::CWbemObjectList()
{
//
// Constructor, init internal values
//
List = NULL;
RelPaths = NULL;
ListSize = 0xffffffff;
}
CWbemObjectList::~CWbemObjectList()
{
ULONG i;
//
// Destructor, free memory held by this class
//
if (List != NULL)
{
for (i = 0; i < ListSize; i++)
{
if (List[i] != NULL)
{
List[i]->Release();
}
}
WmipFree(List);
}
List = NULL;
if (RelPaths != NULL)
{
FreeTheBSTRArray(RelPaths, ListSize);
RelPaths = NULL;
}
ListSize = 0xffffffff;
}
HRESULT CWbemObjectList::Initialize(
ULONG NumberPointers
)
{
HRESULT hr;
ULONG AllocSize;
//
// Initialize class by allocating internal list array
//
WmipAssert(List == NULL);
if (NumberPointers != 0)
{
AllocSize = NumberPointers * sizeof(IWbemClassObject *);
List = (IWbemClassObject **)WmipAlloc(AllocSize);
if (List != NULL)
{
memset(List, 0, AllocSize);
AllocSize = NumberPointers * sizeof(BSTR);
RelPaths = (BSTR *)WmipAlloc(AllocSize);
if (RelPaths != NULL)
{
memset(RelPaths, 0, AllocSize);
ListSize = NumberPointers;
hr = WBEM_S_NO_ERROR;
} else {
WmipDebugPrint(("CDMProv: Could not alloc memory for CWbemObjectList RelPaths\n"));
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
WmipDebugPrint(("CDMProv: Could not alloc memory for CWbemObjectList\n"));
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
ListSize = NumberPointers;
hr = WBEM_S_NO_ERROR;
}
return(hr);
}
ULONG CWbemObjectList::GetListSize(
void
)
{
//
// Accessor for list size
//
WmipAssert(IsInitialized());
return(ListSize);
}
IWbemClassObject *CWbemObjectList::Get(
ULONG Index
)
{ IWbemClassObject *Pointer;
WmipAssert(Index < ListSize);
WmipAssert(IsInitialized());
Pointer = List[Index];
return(Pointer);
}
HRESULT CWbemObjectList::Set(
IN ULONG Index,
IN IWbemClassObject *Pointer
)
{
HRESULT hr;
VARIANT v;
WmipAssert(Pointer != NULL);
WmipAssert(Index < ListSize);
WmipAssert(IsInitialized());
hr = WmiGetProperty(Pointer,
L"__RelPath",
CIM_REFERENCE,
&v);
if (hr == WBEM_S_NO_ERROR)
{
RelPaths[Index] = v.bstrVal;
List[Index] = Pointer;
}
return(hr);
}
BSTR /* NOFREE */ CWbemObjectList::GetRelPath(
IN ULONG Index
)
{
WmipAssert(Index < ListSize);
WmipAssert(IsInitialized());
return(RelPaths[Index]);
}
BOOLEAN CWbemObjectList::IsInitialized(
)
{
return((ListSize == 0) ||
((List != NULL) && (RelPaths != NULL)));
}
CValueMapping::CValueMapping(
)
{
VariantInit(&Values);
ValueMap = NULL;
}
CValueMapping::~CValueMapping(
)
{
if (ValueMap != NULL)
{
WmipFree(ValueMap);
}
VariantClear(&Values);
}
HRESULT CValueMapping::EstablishByName(
IWbemServices *pServices,
PWCHAR ClassName,
PWCHAR PropertyName
)
{
HRESULT hr;
PWCHAR Names[2];
VARTYPE Types[2];
VARIANT v[2];
VARTYPE IsValueMapArray, IsValuesArray;
Names[0] = L"ValueMap";
Types[0] = VT_BSTR;
Names[1] = L"Values";
Types[1] = VT_BSTR;
hr = WmiGetQualifierListByName(pServices,
ClassName,
PropertyName,
2,
Names,
Types,
v);
if (hr == WBEM_S_NO_ERROR)
{
IsValueMapArray = v[0].vt & VT_ARRAY;
IsValuesArray = v[1].vt & VT_ARRAY;
if (IsValueMapArray == IsValuesArray)
{
if (IsValueMapArray)
{
//
// Qualifiers specified as arrays so we can just
// set them up
//
hr = EstablishByArrays(&v[1],
&v[0]);
} else {
//
// Qualifiers specified as scalars
//
hr = EstablishByScalars(v[1].bstrVal,
v[0].bstrVal);
}
} else {
//
// Both must be an array or a scalar
//
hr = WBEM_E_FAILED;
}
VariantClear(&v[0]);
VariantClear(&v[1]);
}
return(hr);
}
HRESULT CValueMapping::EstablishByScalars(
BSTR vValues,
BSTR vValueMap
)
{
HRESULT hr;
PULONG Number;
LONG Index;
SAFEARRAYBOUND Bound;
//
// First, establish the ValueMap values
//
ValueMap = (PULONG64)WmipAlloc(sizeof(ULONG64));
if (ValueMap != NULL)
{
*ValueMap = _wtoi(vValueMap);
ValueMapElements = 1;
//
// Now build a safearray to store the Values element
//
ValuesLBound = 0;
Bound.lLbound = ValuesLBound;
Bound.cElements = 1;
Values.parray = SafeArrayCreate(VT_BSTR,
1,
&Bound);
if (Values.parray != NULL)
{
Values.vt = VT_BSTR | VT_ARRAY;
Index = 0;
hr = SafeArrayPutElement(Values.parray,
&Index,
vValues);
if (hr != WBEM_S_NO_ERROR)
{
VariantClear(&Values);
}
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT CValueMapping::EstablishByArrays(
VARIANT *vValues,
VARIANT *vValueMap
)
{
HRESULT hr;
BSTR s;
LONG ValueMapLBound, ValueMapUBound;
LONG ValuesUBound, ValuesElements;
LONG Index;
LONG i;
//
// Get the array sizes and ensure that they match
//
hr = WmiGetArraySize(vValueMap->parray,
&ValueMapLBound,
&ValueMapUBound,
&ValueMapElements);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiGetArraySize(vValues->parray,
&ValuesLBound,
&ValuesUBound,
&ValuesElements);
if (hr == WBEM_S_NO_ERROR)
{
if ((ValuesLBound == ValueMapLBound) &&
(ValuesUBound == ValueMapUBound) &&
(ValuesElements == ValueMapElements))
{
//
// The ValueMap is balance with the values so parse the
// valuemaps from strings to ulongs
//
ValueMap = (PULONG64)WmipAlloc(ValueMapElements * sizeof(ULONG64));
if (ValueMap != NULL)
{
for (i = 0; i < ValueMapElements; i++)
{
Index = i + ValueMapLBound;
hr = SafeArrayGetElement(vValueMap->parray,
&Index,
&s);
if (hr == WBEM_S_NO_ERROR)
{
ValueMap[i] = _wtoi(s);
SysFreeString(s);
}
}
//
// And assign Values to our class
//
Values = *vValues;
VariantInit(vValues);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
}
return(hr);
}
HRESULT CValueMapping::MapToString(
IN ULONG64 Number,
OUT BSTR *String
)
{
LONG i;
WCHAR ss[MAX_PATH];
LONG Index;
HRESULT hr;
//
// Loop over all values and try to find a match
//
for (i = 0, hr = WBEM_E_FAILED;
(i < ValueMapElements) && (hr != WBEM_S_NO_ERROR);
i++)
{
if (Number == ValueMap[i])
{
//
// We found something to map the value to
//
Index = i + ValuesLBound;
hr = SafeArrayGetElement(Values.parray,
&Index,
String);
}
}
if (hr != WBEM_S_NO_ERROR)
{
//
// There was no match so we just leave the result as a number
//
wsprintfW(ss, L"%d", Number);
*String = SysAllocString(ss);
if (*String == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
return(hr);
}
HRESULT CValueMapping::MapToNumber(
IN BSTR String,
OUT PULONG64 Number
)
{
LONG i;
BSTR s;
LONG Index;
HRESULT hr, hr2;
for (i = 0, hr = WBEM_E_FAILED;
(i < ValueMapElements) && (hr != WBEM_S_NO_ERROR);
i++)
{
Index = i + ValuesLBound;
hr2 = SafeArrayGetElement(Values.parray,
&Index,
&s);
if (hr2 == WBEM_S_NO_ERROR)
{
if (_wcsicmp(s, String) == 0)
{
*Number = ValueMap[i];
hr = WBEM_S_NO_ERROR;
}
SysFreeString(s);
}
}
//
// There was no match so we don't really have anything to map to
//
return(hr);
}
HRESULT CValueMapping::MapVariantToNumber(
VARIANT *v,
CIMTYPE NewType
)
{
HRESULT hr;
VARTYPE BaseType, IsArray;
ULONG64 Number;
VARTYPE NewVarType;
WCHAR ss[MAX_PATH];
BaseType = v->vt & ~VT_ARRAY;
IsArray = v->vt & VT_ARRAY;
WmipAssert(BaseType == VT_BSTR);
if (IsArray == VT_ARRAY)
{
//
// The variant is an array so we need to map each element in an
// array
//
SAFEARRAYBOUND Bounds;
SAFEARRAY *Array;
ULONG Value;
LONG UBound, LBound, Elements, Index;
BSTR s;
LONG i;
hr = WmiGetArraySize(v->parray,
&LBound,
&UBound,
&Elements);
if (hr == WBEM_S_NO_ERROR)
{
if ((NewType == (CIM_SINT64 | CIM_FLAG_ARRAY)) ||
(NewType == (CIM_UINT64 | CIM_FLAG_ARRAY)))
{
//
// If we are mapping to a 64bit number we need to make
// it into a string so setup as an safearray of strings
//
NewVarType = VT_BSTR | VT_ARRAY;
} else {
NewVarType = (VARTYPE)NewType;
}
Bounds.lLbound = LBound;
Bounds.cElements = Elements;
Array = SafeArrayCreate(NewVarType,
1,
&Bounds);
if (Array != NULL)
{
for (i = 0;
(i < Elements) && (hr == WBEM_S_NO_ERROR);
i++)
{
Index = i + LBound;
hr = SafeArrayGetElement(v->parray,
&Index,
&s);
if (hr == WBEM_S_NO_ERROR)
{
hr = MapToNumber(s,
&Number);
SysFreeString(s);
if (hr == WBEM_S_NO_ERROR)
{
if (NewVarType == (VT_BSTR | VT_ARRAY))
{
//
// Mapping to a 64bit number so convert
// to string first
//
wsprintfW(ss, L"%d", Number);
s = SysAllocString(ss);
if (s != NULL)
{
hr = SafeArrayPutElement(Array,
&Index,
s);
SysFreeString(s);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
hr = SafeArrayPutElement(Array,
&Index,
&Number);
}
}
}
}
if (hr == WBEM_S_NO_ERROR)
{
VariantClear(v);
v->vt = NewType | VT_ARRAY;
v->parray = Array;
} else {
SafeArrayDestroy(Array);
}
}
}
} else {
//
// The variant is a scalar so we just need to map one thing
//
hr = MapToNumber(v->bstrVal,
&Number);
if (hr == WBEM_S_NO_ERROR)
{
VariantClear(v);
WmiSetNumberInVariant(v,
NewType,
Number);
}
}
return(hr);
}
HRESULT CValueMapping::MapVariantToString(
VARIANT *v,
CIMTYPE OldType
)
{
VARTYPE BaseType, IsArray;
ULONG64 Number;
BSTR s;
HRESULT hr;
LONG i;
BaseType = v->vt & ~VT_ARRAY;
IsArray = v->vt & VT_ARRAY;
if (IsArray == VT_ARRAY)
{
//
// The variant is an array so we need to map each element in an
// array
//
SAFEARRAYBOUND Bounds;
SAFEARRAY *Array;
ULONG Value;
LONG UBound, LBound, Elements, Index;
hr = WmiGetArraySize(v->parray,
&LBound,
&UBound,
&Elements);
if (hr == WBEM_S_NO_ERROR)
{
Bounds.lLbound = LBound;
Bounds.cElements = Elements;
Array = SafeArrayCreate(VT_BSTR,
1,
&Bounds);
if (Array != NULL)
{
for (i = 0;
(i < Elements) && (hr == WBEM_S_NO_ERROR);
i++)
{
Index = i + LBound;
if (BaseType == VT_BSTR)
{
//
// If base type is a string then we assume that
// we've got a 64bit number which is encoded as
// a string. So we need to fish out the string
// and convert it to a ULONG64
//
WmipAssert((OldType == (CIM_SINT64 | CIM_FLAG_ARRAY)) ||
(OldType == (CIM_UINT64 | CIM_FLAG_ARRAY)));
hr = SafeArrayGetElement(v->parray,
&Index,
&s);
if (hr == WBEM_S_NO_ERROR)
{
Number = _wtoi(s);
SysFreeString(s);
}
} else {
//
// Otherwise the number is acutally encoded as
// a number so fish out the number
//
Number = 0;
hr = SafeArrayGetElement(v->parray,
&Index,
&Number);
}
if (hr == WBEM_S_NO_ERROR)
{
hr = MapToString(Number,
&s);
if (hr == WBEM_S_NO_ERROR)
{
hr = SafeArrayPutElement(Array,
&Index,
s);
SysFreeString(s);
}
}
}
if (hr == WBEM_S_NO_ERROR)
{
VariantClear(v);
v->vt = VT_BSTR | VT_ARRAY;
v->parray = Array;
} else {
SafeArrayDestroy(Array);
}
}
}
} else {
//
// The variant is a scalar so we just need to map one thing
//
WmiGetNumberFromVariant(v,
OldType,
&Number);
hr = MapToString(Number,
&s);
if (hr == WBEM_S_NO_ERROR)
{
VariantClear(v);
v->vt = VT_BSTR;
v->bstrVal = s;
}
}
return(hr);
}
#ifndef HEAP_DEBUG
PVOID WmipAlloc(
IN ULONG Size
)
/*+++
Routine Description:
Internal memory allocator
Arguments:
Size is the number of bytes to allocate
Return Value:
pointer to alloced memory or NULL
---*/
{
return(LocalAlloc(LPTR, Size));
}
void WmipFree(
IN PVOID Ptr
)
/*+++
Routine Description:
Internal memory deallocator
Arguments:
Pointer to freed memory
Return Value:
void
---*/
{
WmipAssert(Ptr != NULL);
LocalFree(Ptr);
}
#endif