|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2000
//
// File: wbemmisc.cpp
//
// Abstract: Misc routines useful for interfacing with WBEM
//
//--------------------------------------------------------------------------
#include <objbase.h>
#include <windows.h>
#include <wbemidl.h>
#include <wbemtime.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include "debug.h"
#include "wbemmisc.h"
HRESULT GetMethodInParamInstance( IN IWbemServices *pServices, IN PWCHAR ClassName, IN BSTR MethodName, OUT IWbemClassObject **ppInParamInstance ) /*+++
Routine Description:
This routine will return an instance object for a methods in parameter. WBEM requires that we go through this dance to get an instance object. Arguments:
pServices
ClassName is the class containing the method
MethodName is the name of the method
*ppInParamInstance returns the instance object to fill with in parameters
Return Value:
HRESULT
---*/ { HRESULT hr; IWbemClassObject *pClass; IWbemClassObject *pInParamClass;
WmipAssert(pServices != NULL); WmipAssert(ClassName != NULL); WmipAssert(MethodName != NULL); WmipAssert(ppInParamInstance != NULL); hr = pServices->GetObject(ClassName, 0, NULL, &pClass, NULL); if (hr == WBEM_S_NO_ERROR) { hr = pClass->GetMethod(MethodName, 0, &pInParamClass, NULL); if (hr == WBEM_S_NO_ERROR) { hr = pInParamClass->SpawnInstance(0, ppInParamInstance); pInParamClass->Release(); } pClass->Release(); } return(hr); }
HRESULT WmiGetQualifier( IN IWbemQualifierSet *pIWbemQualifierSet, IN PWCHAR QualifierName, IN VARTYPE Type, OUT /* FREE */ VARIANT *Value ) /*+++
Routine Description:
This routine will return the value for a specific qualifier Arguments:
pIWbemQualifierSet is the qualifier set object QualifierName is the name of the qualifier Type is the type of qualifier expected *Value returns with the value of the qualifier. Caller must call VariantClear
Return Value:
HRESULT
---*/ { BSTR s; HRESULT hr;
WmipAssert(pIWbemQualifierSet != NULL); WmipAssert(QualifierName != NULL); WmipAssert(Value != NULL); s = SysAllocString(QualifierName); if (s != NULL) { hr = pIWbemQualifierSet->Get(s, 0, Value, NULL); if ((Value->vt & ~CIM_FLAG_ARRAY) != Type) { hr = WBEM_E_FAILED; VariantClear(Value); } SysFreeString(s); } else { hr = WBEM_E_OUT_OF_MEMORY; } return(hr); }
HRESULT WmiGetQualifierListByName( IN IWbemServices *pServices, IN PWCHAR ClassName, IN PWCHAR PropertyName, IN ULONG QualifierCount, IN PWCHAR *QualifierNames, IN VARTYPE *Types, OUT VARIANT /* FREE */ *Values ) /*+++
Routine Description:
This routine will return the values for a list of qualifiers. If all qualifiers cannot be returned then none are. Arguments:
pServices is the IWbemServices pointer
ClassName is the name of the class with qualifiers
PropertyName is the name of the property with qualfiers. If NULL then class qualifiers are returned
QualifierCount is the count of qualifers to get
QualifierNames is an array contaiing names of qualifiers to get
Types is an array of expected value types for the qualifiers
Values is an array of variants that return with the qualifer values
Return Value:
HRESULT
---*/ { HRESULT hr; IWbemClassObject *pClass; IWbemQualifierSet *pQualifiers; ULONG i, j;
WmipAssert(pServices != NULL); WmipAssert(ClassName != NULL); WmipAssert(QualifierNames != NULL); WmipAssert(Types != NULL); WmipAssert(Values != NULL); //
// Create the class so we can look at the properties
//
hr = pServices->GetObject(ClassName, WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, &pClass, NULL);
if (hr == WBEM_S_NO_ERROR) { if (PropertyName == NULL) { hr = pClass->GetQualifierSet(&pQualifiers); } else { hr = pClass->GetPropertyQualifierSet(PropertyName, &pQualifiers); } if (hr == WBEM_S_NO_ERROR) { for (i = 0; (i < QualifierCount) && (hr == WBEM_S_NO_ERROR); i++) { hr = WmiGetQualifier(pQualifiers, QualifierNames[i], Types[i], &Values[i]); }
if (hr != WBEM_S_NO_ERROR) { for (j = 0; j < i; j++) { VariantClear(&Values[j]); } } pQualifiers->Release(); } pClass->Release(); } return(hr); }
HRESULT WmiGetProperty( IN IWbemClassObject *pIWbemClassObject, IN PWCHAR PropertyName, IN CIMTYPE ExpectedCimType, OUT VARIANT /* FREE */ *Value ) /*+++
Routine Description:
This routine will return the value for a specific property Arguments:
pIWbemQualifierSet is the qualifier set object PropertyName is the name of the property Type is the type of property expected *Value returns with the value of the property
Return Value:
HRESULT
---*/ { HRESULT hr; CIMTYPE CimType;
WmipAssert(pIWbemClassObject != NULL); WmipAssert(PropertyName != NULL); WmipAssert(Value != NULL); hr = pIWbemClassObject->Get(PropertyName, 0, Value, &CimType, NULL);
//
// Treat a NULL value for a property as an error
//
if (Value->vt == VT_NULL) { hr = WBEM_E_ILLEGAL_NULL; WmipDebugPrint(("CDMPROV: Property %ws is NULL\n", PropertyName)); } //
// Treat CIM_REFERENCE and CIM_STRING as interchangable
//
if ((ExpectedCimType == CIM_REFERENCE) && (CimType == CIM_STRING)) { ExpectedCimType = CIM_STRING; } if ((ExpectedCimType == CIM_STRING) && (CimType == CIM_REFERENCE)) { ExpectedCimType = CIM_REFERENCE; } if ((hr == WBEM_S_NO_ERROR) && (ExpectedCimType != CimType)) { WmipDebugPrint(("CDMPROV: Property %ws was expected as %d but was got as %d\n", PropertyName, ExpectedCimType, CimType)); WmipAssert(FALSE); hr = WBEM_E_FAILED; VariantClear(Value); }
return(hr); }
HRESULT WmiGetPropertyList( IN IWbemClassObject *pIWbemClassObject, IN ULONG PropertyCount, IN PWCHAR *PropertyNames, IN CIMTYPE *ExpectedCimType, OUT VARIANT /* FREE */ *Value ) /*+++
Routine Description:
This routine will return the value for a specific property Arguments:
pIWbemQualifierSet is the qualifier set object PropertyNames is the name of the property Type is the type of property expected *Value returns with the value of the property
Return Value:
HRESULT
---*/ { ULONG i,j; HRESULT hr;
WmipAssert(pIWbemClassObject != NULL); WmipAssert(PropertyNames != NULL); WmipAssert(ExpectedCimType != NULL); WmipAssert(Value != NULL);
for (i = 0, hr = WBEM_S_NO_ERROR; (i < PropertyCount) && (hr == WBEM_S_NO_ERROR); i++) { hr = WmiGetProperty(pIWbemClassObject, PropertyNames[i], ExpectedCimType[i], &Value[i]); }
if (hr != WBEM_S_NO_ERROR) { for (j = 0; j < i; j++) { VariantClear(&Value[i]); } } return(hr); }
HRESULT WmiGetPropertyByName( IN IWbemServices *pServices, IN PWCHAR ClassName, IN PWCHAR PropertyName, IN CIMTYPE ExpectedCimType, OUT VARIANT /* FREE */ *Value ) /*+++
Routine Description:
This routine will return the value for a specific property within a class Arguments:
pServices is the IWbemServices for the namespace containing your class ClassName is the name of the class whose property you are interested in PropertyName is the name of the property Type is the type of property expected *Value returns with the value of the property
Return Value:
HRESULT
---*/ { HRESULT hr; IWbemClassObject *pClass;
WmipAssert(pServices != NULL); WmipAssert(ClassName != NULL); WmipAssert(PropertyName != NULL); WmipAssert(Value != NULL); //
// Create the class so we can look at the properties
//
hr = pServices->GetObject(ClassName, 0, NULL, &pClass, NULL);
if (hr == WBEM_S_NO_ERROR) { hr = WmiGetProperty(pClass, PropertyName, ExpectedCimType, Value);
pClass->Release(); } return(hr); }
HRESULT WmiSetProperty( IN IWbemClassObject *pIWbemClassObject, IN PWCHAR PropertyName, IN VARIANT *Value ) /*+++
Routine Description:
This routine will set the value of a property to something Arguments:
pIWbemClassObject is the object whose property is being set
PropertyName is the name of the property being set
Value is the value that the property is being set to
Return Value:
HRESULT
---*/ { HRESULT hr; WmipAssert(pIWbemClassObject != NULL); WmipAssert(PropertyName != NULL); WmipAssert(Value != NULL);
hr = pIWbemClassObject->Put(PropertyName, 0, Value, 0);
if (hr == WBEM_E_TYPE_MISMATCH) { WmipDebugPrint(("CDMPROV: Put %ws has wrong type %d\n", PropertyName, Value->vt)); WmipAssert(FALSE); } return(hr); }
HRESULT WmiSetPropertyList( IN IWbemClassObject *pIWbemClassObject, IN ULONG PropertyCount, IN PWCHAR *PropertyNames, IN VARIANT *Values ) /*+++
Routine Description:
This routine will set the values of multiple properties to something Arguments:
pIWbemClassObject is the object whose property is being set
PropertyCount is the number of properties to set
PropertyNames is the names of the property being set
Values is the value that the property is being set to
Return Value:
HRESULT
---*/ { ULONG i; HRESULT hr = WBEM_S_NO_ERROR;
WmipAssert(pIWbemClassObject != NULL); WmipAssert(PropertyNames != NULL); WmipAssert(Values != NULL);
for (i = 0; (i < PropertyCount) && (hr == WBEM_S_NO_ERROR); i++) { hr = WmiSetProperty(pIWbemClassObject, PropertyNames[i], &Values[i]); } return(hr); }
// @@BEGIN_DDKSPLIT
#ifndef HEAP_DEBUG
// @@END_DDKSPLIT
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); } // @@BEGIN_DDKSPLIT
#endif
// @@END_DDKSPLIT
PWCHAR AddSlashesToStringW( OUT PWCHAR SlashedNamespace, IN PWCHAR Namespace ) /*+++
Routine Description:
This routine will convert ever \ in the string into \\. It needs to do this since WBEM will collapse \\ into \ sometimes. Arguments:
SlashedNamespace returns with string double slashed
Namespace is the input string
Return Value:
pointer to SlashedNamespace
---*/ { PWCHAR Return = SlashedNamespace;
WmipAssert(SlashedNamespace != NULL); WmipAssert(Namespace != NULL); //
// MOF likes the namespace paths to be C-style, that is to have a
// '\\' instad of a '\'. So whereever we see a '\', we insert a
// second one
//
while (*Namespace != 0) { if (*Namespace == L'\\') { *SlashedNamespace++ = L'\\'; } *SlashedNamespace++ = *Namespace++; } *SlashedNamespace = 0; return(Return); }
PWCHAR AddSlashesToStringExW( OUT PWCHAR SlashedNamespace, IN PWCHAR Namespace ) /*+++
Routine Description:
This routine will convert ever \ in the string into \\ and " into \". It needs to do this since WBEM will collapse \\ into \ sometimes. Arguments:
SlashedNamespace returns with string double slashed
Namespace is the input string
Return Value:
pointer to SlashedNamespace
---*/ { PWCHAR Return = SlashedNamespace; WmipAssert(SlashedNamespace != NULL); WmipAssert(Namespace != NULL); //
// MOF likes the namespace paths to be C-style, that is to have a
// '\\' instad of a '\'. So whereever we see a '\', we insert a
// second one. We also need to add a \ before any ".
//
while (*Namespace != 0) { if ((*Namespace == L'\\') || (*Namespace == L'"')) { *SlashedNamespace++ = L'\\'; } *SlashedNamespace++ = *Namespace++; } *SlashedNamespace = 0; return(Return); }
HRESULT WmiConnectToWbem( IN PWCHAR Namespace, OUT IWbemServices **ppIWbemServices ) /*+++
Routine Description:
This routine will establishes a connection to a WBEM namespace on the local machine.
Arguments:
Namespace is the namespace to which to connect
*ppIWbemServices returns with a IWbemServices * for the namespace
Return Value:
HRESULT
---*/ { IWbemLocator *pIWbemLocator; DWORD hr; BSTR s;
WmipAssert(Namespace != NULL); WmipAssert(ppIWbemServices != NULL); hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pIWbemLocator); if (hr == S_OK) { s = SysAllocString(Namespace); if (s != NULL) { *ppIWbemServices = NULL; hr = pIWbemLocator->ConnectServer(s, NULL, // Userid
NULL, // PW
NULL, // Locale
0, // flags
NULL, // Authority
NULL, // Context
ppIWbemServices ); SysFreeString(s); } else { *ppIWbemServices = NULL; hr = WBEM_E_OUT_OF_MEMORY; } pIWbemLocator->Release(); } return(hr); }
HRESULT CreateInst( IN IWbemServices * pNamespace, OUT /* FREE */ IWbemClassObject ** pNewInst, IN WCHAR * pwcClassName, IN IWbemContext *pCtx ) /*+++
Routine Description:
This routine will create a new instance for the specified class
Arguments:
pNamespace is the IWbemServices * to the namespace in which the class lives
*pNewinst returns with the new instance of the class
pwcClassName has the name of the class whose instance is created
pCtx is the context to use in creating the instance
Return Value:
HRESULT
---*/ { HRESULT hr; IWbemClassObject * pClass; hr = pNamespace->GetObject(pwcClassName, 0, pCtx, &pClass, NULL); if (hr != S_OK) { return WBEM_E_FAILED; } hr = pClass->SpawnInstance(0, pNewInst); pClass->Release();
WmipDebugPrint(("CDMProv:: Created %ws as %p\n", pwcClassName, *pNewInst));
return(hr); }
/* FREE */ BSTR GetCurrentDateTime( void ) { SYSTEMTIME SystemTime; WBEMTime WbemTime;
GetSystemTime(&SystemTime); WbemTime = SystemTime; return(WbemTime.GetBSTR()); }
HRESULT WmiGetArraySize( IN SAFEARRAY *Array, OUT LONG *LBound, OUT LONG *UBound, OUT LONG *NumberElements ) /*+++
Routine Description:
This routine will information about the size and bounds of a single dimensional safe array. Arguments:
Array is the safe array *LBound returns with the lower bound of the array
*UBound returns with the upper bound of the array *NumberElements returns with the number of elements in the array
Return Value:
TRUE if successful else FALSE
---*/ { HRESULT hr;
WmipAssert(Array != NULL); WmipAssert(LBound != NULL); WmipAssert(UBound != NULL); WmipAssert(NumberElements != NULL); //
// Only single dim arrays are supported
//
WmipAssert(SafeArrayGetDim(Array) == 1); hr = SafeArrayGetLBound(Array, 1, LBound); if (hr == WBEM_S_NO_ERROR) { hr = SafeArrayGetUBound(Array, 1, UBound); *NumberElements = (*UBound - *LBound) + 1; } return(hr); }
BOOLEAN IsUlongAndStringEqual( IN ULONG Number, IN PWCHAR String ) /*+++
Routine Description:
This routine will convert the passed string to an integer and compare it to the passed integer value Arguments:
Number
String
Return Value:
TRUE if equal else FALSE
---*/ { ULONG SNumber;
SNumber = _wtoi(String); return ( (Number == SNumber) ? TRUE : FALSE ); }
HRESULT LookupValueMap( IN IWbemServices *pServices, IN PWCHAR ClassName, IN PWCHAR PropertyName, IN ULONG Value, OUT /* FREE */ BSTR *MappedValue ) /*+++
Routine Description:
This routine will lookup the string value corresponding to an integer valuemap Arguments:
pServices is the pointer to the namespace in which the class is locaed
ClassName is the name of the class
PropertyName is the name of the property
Value is the value of the property and is used to look up the string that corresponsds to it
*MappedValue returns a string that contains the string which the value maps to Return Value:
HRESULT
---*/ { PWCHAR Names[2]; VARIANT QualifierValues[2]; VARTYPE Types[2]; HRESULT hr; BSTR s; LONG ValuesLBound, ValuesUBound, ValuesElements; LONG ValueMapLBound, ValueMapUBound, ValueMapElements; LONG i, Index;
WmipAssert(pServices != NULL); WmipAssert(ClassName != NULL); WmipAssert(PropertyName != NULL); WmipAssert(MappedValue != NULL); //
// Get the Values and ValueMap qualifiers so we can do the mapping
//
Names[0] = L"Values"; Types[0] = VT_BSTR; Names[1] = L"ValueMap"; Types[1] = VT_BSTR; hr = WmiGetQualifierListByName(pServices, ClassName, PropertyName, 2, Names, Types, QualifierValues); if (hr == WBEM_S_NO_ERROR) { //
// Now do a sanity check to make sure the values and valuemaps
// have the same number of elements
//
if (QualifierValues[0].vt == QualifierValues[1].vt) { //
// Values and ValueMap both agree that they are both
// scalars or both arrays and are both strings
//
if (QualifierValues[0].vt & VT_ARRAY) { //
// We have an array of thing to check for mapping.
// First lets make sure that the arrays have identical
// dimensions
//
hr = WmiGetArraySize(QualifierValues[0].parray, &ValuesLBound, &ValuesUBound, &ValuesElements);
if (hr == WBEM_S_NO_ERROR) { hr = WmiGetArraySize(QualifierValues[1].parray, &ValueMapLBound, &ValueMapUBound, &ValueMapElements);
if (hr == WBEM_S_NO_ERROR) { if ((ValuesLBound == ValueMapLBound) && (ValuesUBound == ValueMapUBound) && (ValuesElements == ValueMapElements)) { for (i = 0; i < ValueMapElements; i++) { Index = i + ValueMapLBound; hr = SafeArrayGetElement(QualifierValues[1].parray, &Index, &s); if (hr == WBEM_S_NO_ERROR) { if (IsUlongAndStringEqual(Value, s)) { hr = SafeArrayGetElement(QualifierValues[0].parray, &Index, MappedValue); //
// Make sure loop will
// terminate
i = ValueMapElements; } SysFreeString(s); } } } else { hr = WBEM_E_NOT_FOUND; } } } } else { //
// We have scalars so this should make a fairly simple
// mapping
//
if (IsUlongAndStringEqual(Value, QualifierValues[1].bstrVal)) { *MappedValue = SysAllocString(QualifierValues[0].bstrVal); if (*MappedValue == NULL) { hr = WBEM_E_OUT_OF_MEMORY; } } else { hr = WBEM_E_NOT_FOUND; } } } else { hr = WBEM_E_NOT_FOUND; } VariantClear(&QualifierValues[0]); VariantClear(&QualifierValues[1]); } return(hr); }
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); } }
|