windows-nt/Source/XPSP1/NT/base/wmi/cdmprov/testinfo.cpp
2020-09-26 16:20:57 +08:00

3898 lines
80 KiB
C++

//***************************************************************************
//
// 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
//
//***************************************************************************
// @@BEGIN_DDKSPLIT
//
// What is left to do:
//
// Finish reboot diagnostics - This involves persisting the pending
// result in the schema and then trying to query for the actual
// results later
//
// Keep more than 1 historical result instance. This involves
// persisting the historical results in the schema and picking them
// up from there
// @@END_DDKSPLIT
#include <objbase.h>
#ifndef _MT
#define _MT
#endif
#include <wbemidl.h>
#include "debug.h"
#include "testinfo.h"
#include "wbemmisc.h"
#include "cimmap.h"
#include "reload.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;
}
CTestServices::CTestServices()
/*+++
Routine Description:
Constructor for CTestServices class
Arguments:
Return Value:
---*/
{
WdmTestClassName = NULL;
WdmSettingClassName = NULL;
WdmSettingListClassName = NULL;
WdmResultClassName = NULL;
WdmOfflineResultClassName = NULL;
CdmTestClassName = NULL;
CdmTestRelPath = NULL;
CdmResultClassName = NULL;
CdmSettingClassName = NULL;
CdmTestForMSEClassName = NULL;
CdmTestForMSERelPath = NULL;
CdmSettingForTestClassName = NULL;
CdmSettingForTestRelPath = NULL;
CdmResultForMSEClassName = NULL;
CdmResultForTestClassName = NULL;
CdmTestForSoftwareClassName = NULL;
CdmTestForSoftwareRelPath = NULL;
CdmTestInPackageClassName = NULL;
CdmTestInPackageRelPath = NULL;
CdmResultInPackageClassName = NULL;
CdmResultInPackageRelPath = NULL;
CimClassMappingClassName = NULL;
CimRelPaths = NULL;
WdmRelPaths = NULL;
PnPDeviceIdsX = NULL;
WdmInstanceNames = NULL;
CdmSettingsList = NULL;
CdmResultsList = NULL;
Next = NULL;
Prev = NULL;
}
CTestServices::~CTestServices()
/*+++
Routine Description:
Destructor for CTestServices class
Arguments:
Return Value:
---*/
{
int i;
if (WdmTestClassName != NULL)
{
SysFreeString(WdmTestClassName);
}
if (WdmSettingClassName != NULL)
{
SysFreeString(WdmSettingClassName);
}
if (WdmResultClassName != NULL)
{
SysFreeString(WdmResultClassName);
}
if (WdmOfflineResultClassName != NULL)
{
SysFreeString(WdmOfflineResultClassName);
}
if (WdmSettingListClassName != NULL)
{
SysFreeString(WdmSettingListClassName);
}
if (CdmTestClassName != NULL)
{
SysFreeString(CdmTestClassName);
}
if (CdmTestRelPath != NULL)
{
SysFreeString(CdmTestRelPath);
}
if (CdmResultClassName != NULL)
{
SysFreeString(CdmResultClassName);
}
if (CdmSettingClassName != NULL)
{
SysFreeString(CdmSettingClassName);
}
if (CdmTestForMSEClassName != NULL)
{
SysFreeString(CdmTestForMSEClassName);
}
FreeTheBSTRArray(CdmTestForMSERelPath, RelPathCount);
if (CdmSettingForTestClassName != NULL)
{
SysFreeString(CdmSettingForTestClassName);
}
if (CdmSettingForTestRelPath != NULL)
{
for (i = 0; i < RelPathCount; i++)
{
delete CdmSettingForTestRelPath[i];
}
WmipFree(CdmSettingForTestRelPath);
}
if (CdmResultForMSEClassName != NULL)
{
SysFreeString(CdmResultForMSEClassName);
}
if (CdmResultForTestClassName != NULL)
{
SysFreeString(CdmResultForTestClassName);
}
if (CdmTestForSoftwareClassName != NULL)
{
SysFreeString(CdmTestForSoftwareClassName);
}
if (CdmTestForSoftwareRelPath != NULL)
{
SysFreeString(CdmTestForSoftwareRelPath);
}
if (CdmTestInPackageClassName != NULL)
{
SysFreeString(CdmTestInPackageClassName);
}
if (CdmTestInPackageRelPath != NULL)
{
SysFreeString(CdmTestInPackageRelPath);
}
if (CdmResultInPackageClassName != NULL)
{
SysFreeString(CdmResultInPackageClassName);
}
if (CdmResultInPackageRelPath != NULL)
{
SysFreeString(CdmResultInPackageRelPath);
}
if (CimClassMappingClassName != NULL)
{
SysFreeString(CimClassMappingClassName);
}
FreeTheBSTRArray(CimRelPaths, RelPathCount);
FreeTheBSTRArray(WdmRelPaths, RelPathCount);
FreeTheBSTRArray(WdmInstanceNames, RelPathCount);
FreeTheBSTRArray(PnPDeviceIdsX, RelPathCount);
if (CdmSettingsList != NULL)
{
for (i = 0; i < RelPathCount; i++)
{
delete CdmSettingsList[i];
}
WmipFree(CdmSettingsList);
}
if (CdmResultsList != NULL)
{
for (i = 0; i < RelPathCount; i++)
{
delete &CdmResultsList[i];
}
}
}
BOOLEAN ClassIsCdmBaseClass(
BSTR ClassName,
BOOLEAN *IsTestClass
)
/*+++
Routine Description:
This routine determines if the class name is a CDM base class name
Arguments:
ClassName is the name of the class
*IsTestClass returns TRUE if the class name is CIM_DiagnosticTest
Return Value:
TRUE if class is a CDM base class else FALSE
---*/
{
WmipAssert(ClassName != NULL);
WmipAssert(IsTestClass != NULL);
if (_wcsicmp(ClassName, L"CIM_DiagnosticTest") == 0)
{
*IsTestClass = TRUE;
return(TRUE);
}
if ((_wcsicmp(ClassName, L"CIM_DiagnosticResult") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticSetting") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticResultForMSE") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticResultForTest") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticTestForMSE") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticTestSoftware") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticTestInPackage") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticResultInPackage") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticResultForMSE") == 0) ||
(_wcsicmp(ClassName, L"CIM_DiagnosticSettingForTest") == 0))
{
*IsTestClass = FALSE;
return(TRUE);
}
return(FALSE);
}
HRESULT CTestServices::GetCdmClassNamesFromOne(
PWCHAR CdmClass
)
/*+++
Routine Description:
This routine obtains the names of all of the CDM classes from the
name of a single CDM class
Arguments:
CdmClass is the name of the CDM class
Return Value:
HRESULT
---*/
{
IWbemServices * pCdmServices = GetCdmServices();
VARIANT v, vClass, vSuper;
HRESULT hr, hrDontCare;
BOOLEAN IsTestClass;
BSTR SuperClass;
BSTR CdmTestClass;
//
// First thing is that we need to do is figure out what kind of
// class we have been handed. If it is a CIM_DiagnosticTest derived
// class then we can proceed to obtain all of the other class names
// via qualifiers. If not then we have to link back from the class
// we have to the CIM_DiagnosticTest derived class via the
// CdmDiagTest qualifier.
//
//
// Get a class object for Cdm class passed and then check the
// __SUPERCLASS property to see which CDM class it is derived from.
//
SuperClass = SysAllocString(CdmClass);
if (SuperClass == NULL)
{
return(WBEM_E_OUT_OF_MEMORY);
}
v.vt = VT_BSTR;
v.bstrVal = SuperClass;
do
{
hr = WmiGetPropertyByName(pCdmServices,
v.bstrVal,
L"__SuperClass",
CIM_STRING,
&vSuper);
if (hr == WBEM_S_NO_ERROR)
{
#ifdef VERBOSE_DEBUG
WmipDebugPrint(("CDMPROV: Class %ws has superclass of %ws\n",
SuperClass, vSuper.bstrVal));
#endif
if (_wcsicmp(v.bstrVal, vSuper.bstrVal) == 0)
{
//
// When the superclass is the same as the base
// class then we are at the top of the class tree
// and so this class must not be in the CDM
// heirarchy. In this case the cdm provider cannot
// support it.
//
hr = WBEM_E_NOT_FOUND;
VariantClear(&vSuper);
} else if (ClassIsCdmBaseClass(vSuper.bstrVal, &IsTestClass)) {
//
// We have found a CDM base class
//
if (! IsTestClass)
{
//
// The CDM base class was not the test class so
// lookup the CdmDiagTest qualifier to find it
//
PWCHAR Name = L"CdmDiagTest";
VARTYPE VarType = VT_BSTR;
hr = WmiGetQualifierListByName(pCdmServices,
CdmClass,
NULL,
1,
&Name,
&VarType,
&vClass);
if (hr == WBEM_S_NO_ERROR)
{
CdmTestClass = vClass.bstrVal;
#ifdef VERBOSE_DEBUG
WmipDebugPrint(("CDMPROV: Class %ws has a CdmDiagTestClass %ws\n",
CdmClass, CdmTestClass));
#endif
}
} else {
CdmTestClass = SysAllocString(CdmClass);
if (CdmTestClass == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
#ifdef VERBOSE_DEBUG
WmipDebugPrint(("CDMPROV: Class %ws is already CdmDiagTestClass\n",
CdmClass));
#endif
}
VariantClear(&vSuper);
} else {
//
// This is a more basic class, but is not the CDM base
// class, so we need to continue up the derivation
// chain
//
}
}
VariantClear(&v);
v = vSuper;
} while ((CdmTestClass == NULL) && (hr == WBEM_S_NO_ERROR));
if (hr == WBEM_S_NO_ERROR)
{
PWCHAR Names[11];
VARTYPE VarType[11];
VARIANT Values[11];
//
// Now that we know the CDM Diagnostic test class name we can
// go and discover the rest of the CDM class names via
// the appropriate qualifiers on the Cdm Test class.
//
Names[0] = L"CimClassMapping";
VarType[0] = VT_BSTR;
VariantInit(&Values[0]);
Names[1] = L"CdmDiagResult";
VarType[1] = VT_BSTR;
VariantInit(&Values[1]);
Names[2] = L"CdmDiagSetting";
VarType[2] = VT_BSTR;
VariantInit(&Values[2]);
Names[3] = L"CdmDiagTestForMSE";
VarType[3] = VT_BSTR;
VariantInit(&Values[3]);
Names[4] = L"CdmDiagResultForMSE";
VarType[4] = VT_BSTR;
VariantInit(&Values[4]);
Names[5] = L"CdmDiagResultForTest";
VarType[5] = VT_BSTR;
VariantInit(&Values[5]);
Names[6] = L"CdmDiagTestSoftware";
VarType[6] = VT_BSTR;
VariantInit(&Values[6]);
Names[7] = L"CdmDiagTestInPackage";
VarType[7] = VT_BSTR;
VariantInit(&Values[7]);
Names[8] = L"CdmDiagResultInPackage";
VarType[8] = VT_BSTR;
VariantInit(&Values[8]);
Names[9] = L"CdmDiagSettingForTest";
VarType[9] = VT_BSTR;
VariantInit(&Values[9]);
Names[10] = L"WdmDiagTest";
VarType[10] = VT_BSTR;
VariantInit(&Values[10]);
hr = WmiGetQualifierListByName(pCdmServices,
CdmTestClass,
NULL,
11,
Names,
VarType,
Values);
if (hr == WBEM_S_NO_ERROR)
{
//
// Remember the class names
//
CimClassMappingClassName = Values[0].bstrVal;
CdmResultClassName = Values[1].bstrVal;
CdmSettingClassName = Values[2].bstrVal;
CdmTestForMSEClassName = Values[3].bstrVal;
CdmResultForMSEClassName = Values[4].bstrVal;
CdmResultForTestClassName = Values[5].bstrVal;
CdmTestForSoftwareClassName = Values[6].bstrVal;
CdmTestInPackageClassName = Values[7].bstrVal;
CdmResultInPackageClassName = Values[8].bstrVal;
CdmSettingForTestClassName = Values[9].bstrVal;
WdmTestClassName = Values[10].bstrVal;
//
// Now that we have got all of the Cdm class names we need
// to get the WdmDiagResult, WdmDiagSetting and
// WdmDiagSettingList classes
//
Names[0] = L"WdmDiagResult";
VariantInit(&Values[0]);
hr = WmiGetQualifierListByName(pCdmServices,
CdmResultClassName,
NULL,
1,
Names,
VarType,
Values);
if (hr == WBEM_S_NO_ERROR)
{
WdmResultClassName = Values[0].bstrVal;
//
// See if this is an offline diagnostic class
//
Names[0] = L"WdmDiagOfflineResult";
VariantInit(&Values[0]);
hrDontCare = WmiGetQualifierListByName(pCdmServices,
CdmResultClassName,
NULL,
1,
Names,
VarType,
Values);
if (hrDontCare == WBEM_S_NO_ERROR)
{
WdmOfflineResultClassName = Values[0].bstrVal;
}
Names[0] = L"WdmDiagSetting";
VariantInit(&Values[0]);
hr = WmiGetQualifierListByName(pCdmServices,
CdmSettingClassName,
NULL,
1,
Names,
VarType,
Values);
if (hr == WBEM_S_NO_ERROR)
{
WdmSettingClassName = Values[0].bstrVal;
Names[0] = L"WdmDiagSettingList";
VariantInit(&Values[0]);
hr = WmiGetQualifierListByName(pCdmServices,
CdmSettingClassName,
NULL,
1,
Names,
VarType,
Values);
if (hr == WBEM_S_NO_ERROR)
{
//
// Whew, we got all of our class names
// successfully. Setup the CdmTestClassName which
// denotes that we are all setup properly
//
WdmSettingListClassName = Values[0].bstrVal;
CdmTestClassName = CdmTestClass;
}
}
}
}
}
return(hr);
}
HRESULT CTestServices::BuildResultRelPaths(
IN int RelPathIndex,
IN BSTR ExecutionId,
OUT BSTR *ResultRelPath,
OUT BSTR *ResultForMSERelPath,
OUT BSTR *ResultForTestRelPath
)
/*+++
Routine Description:
This routine will create the string names for the CDM Result
relative paths for a specific index. These are for the classes
CIM_DiagnosticResult
CIM_DiagnosticResultForMSE
CIM_DiagnosticResultForTest
Arguments:
RelPathIndex is the index into the list of result objects
ExecutionId is the unique id used for the execution
ResultRelPath returns with the result relpath
ResultForMSERelPath returns with the ResultForMSE association
relpath
ResultForTestRelPath returns with the ResultForTest association
relpath
Return Value:
HRESULT
---*/
{
PWCHAR RelPath;
HRESULT hr;
ULONG AllocSize;
WCHAR s1[2*MAX_PATH];
WCHAR s2[2*MAX_PATH];
RelPath = (PWCHAR)WmipAlloc(4096);
if (RelPath != NULL)
{
//
// Create the relpaths for the result classes and associations
//
wsprintfW(RelPath, L"%ws.DiagnosticCreationClassName=\"%ws\",DiagnosticName=\"%ws\",ExecutionID=\"%ws\"",
CdmResultClassName,
AddSlashesToStringExW(s1, WdmRelPaths[RelPathIndex]),
CdmTestClassName,
ExecutionId);
*ResultRelPath = SysAllocString(RelPath);
if (*ResultRelPath != NULL)
{
wsprintfW(RelPath, L"%ws.Result=\"%ws\",SystemElement=\"%ws\"",
CdmResultForMSEClassName,
AddSlashesToStringExW(s1, *ResultRelPath),
AddSlashesToStringExW(s2, CimRelPaths[RelPathIndex]));
*ResultForMSERelPath = SysAllocString(RelPath);
wsprintfW(RelPath, L"%ws.DiagnosticResult=\"%ws\",DiagnosticTest=\"%ws\"",
CdmResultForTestClassName,
AddSlashesToStringExW(s1, *ResultRelPath),
AddSlashesToStringExW(s2, CdmTestRelPath));
*ResultForTestRelPath = SysAllocString(RelPath);
if ((*ResultForMSERelPath == NULL) ||
(*ResultForTestRelPath == NULL))
{
SysFreeString(*ResultRelPath);
if (*ResultForMSERelPath != NULL)
{
SysFreeString(*ResultForMSERelPath);
}
if (*ResultForTestRelPath != NULL)
{
SysFreeString(*ResultForTestRelPath);
}
hr = WBEM_E_OUT_OF_MEMORY;
} else {
hr = WBEM_S_NO_ERROR;
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
WmipFree(RelPath);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT CTestServices::BuildTestRelPaths(
void
)
/*+++
Routine Description:
This routine will create the string names for the CDM Test
relative paths for all index
These are for the following classes:
CIM_DiagnosticTest,
CIM_DiagnosticTestForMSE
Arguments:
Return Value:
HRESULT
---*/
{
PWCHAR RelPath;
int i;
HRESULT hr;
WCHAR s1[MAX_PATH];
WCHAR s2[MAX_PATH];
ULONG AllocSize;
RelPath = (PWCHAR)WmipAlloc(4096);
if (RelPath != NULL)
{
wsprintfW(RelPath, L"%ws.Name=\"%ws\"",
CdmTestClassName, CdmTestClassName);
CdmTestRelPath = SysAllocString(RelPath);
if (CdmTestRelPath != NULL)
{
AllocSize = RelPathCount * sizeof(BSTR);
CdmTestForMSERelPath = (PWCHAR *)WmipAlloc(AllocSize);
if (CdmTestForMSERelPath != NULL)
{
memset(CdmTestForMSERelPath, 0, AllocSize);
hr = WBEM_S_NO_ERROR;
for (i = 0; (i < RelPathCount) && (hr == WBEM_S_NO_ERROR); i++)
{
wsprintfW(RelPath, L"%ws.Antecedent=\"%ws\",Dependent=\"%ws\"",
CdmTestForMSEClassName,
AddSlashesToStringExW(s1, CimRelPaths[i]),
AddSlashesToStringExW(s2, CdmTestRelPath));
CdmTestForMSERelPath[i] = SysAllocString(RelPath);
if (CdmTestForMSERelPath[i] == NULL)
{
SysFreeString(CdmTestRelPath);
CdmTestRelPath = NULL;
FreeTheBSTRArray(CdmTestForMSERelPath, RelPathCount);
CdmTestForMSERelPath = NULL;
hr = WBEM_E_OUT_OF_MEMORY;
}
}
} else {
SysFreeString(CdmTestRelPath);
CdmTestRelPath = NULL;
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
WmipFree(RelPath);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT CTestServices::BuildSettingForTestRelPath(
OUT BSTR *RelPath,
IN IWbemClassObject *pCdmSettingInstance
)
{
WCHAR *Buffer;
VARIANT v;
WCHAR s[MAX_PATH];
HRESULT hr;
WmipAssert(RelPath != NULL);
WmipAssert(pCdmSettingInstance != NULL);
WmipAssert(IsThisInitialized());
Buffer = (WCHAR *)WmipAlloc(4096);
if (Buffer != NULL)
{
hr = WmiGetProperty(pCdmSettingInstance,
L"__RELPATH",
CIM_REFERENCE,
&v);
if (hr == WBEM_S_NO_ERROR)
{
wsprintfW(Buffer, L"%ws.Element=\"%ws.Name=\\\"%ws\\\"\",Setting=\"%ws\"",
CdmSettingForTestClassName,
CdmTestClassName,
CdmTestClassName,
AddSlashesToStringExW(s, v.bstrVal));
VariantClear(&v);
*RelPath = SysAllocString(Buffer);
if (*RelPath != NULL)
{
hr = WBEM_S_NO_ERROR;
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
}
WmipFree(Buffer);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT CTestServices::ParseSettingList(
VARIANT *SettingList,
CWbemObjectList *CdmSettings,
CBstrArray *CdmSettingForTestRelPath,
int RelPathIndex
)
/*+++
Routine Description:
This routine will obtain all of the settings for a particular test
and store them into a settings list object
Arguments:
SettingList points at a variant continaing an array of embedded
WDM setting objects
CdmSettings points at a WbemObjectList class
CdmSettingForTestRelPath has the relpaths for the cdm settings for
test classes
RelPathIndex is the relpath index associated with the settings
Return Value:
HRESULT
---*/
{
HRESULT hr;
IWbemClassObject *pWdmSettingInstance;
IWbemClassObject *pCdmSettingInstance;
LONG Index, UBound, LBound, NumberElements;
LONG i;
IUnknown *punk;
BSTR s;
WCHAR SettingId[MAX_PATH];
VARIANT v;
WmipAssert(SettingList != NULL);
WmipAssert(CdmSettingForTestRelPath != NULL);
WmipAssert(SettingList->vt == (CIM_OBJECT | CIM_FLAG_ARRAY));
WmipAssert(CdmSettings != NULL);
hr = WmiGetArraySize(SettingList->parray,
&LBound,
&UBound,
&NumberElements);
if (hr == WBEM_S_NO_ERROR)
{
hr = CdmSettingForTestRelPath->Initialize(NumberElements);
if (hr == WBEM_S_NO_ERROR)
{
hr = CdmSettings->Initialize(NumberElements);
for (i = 0, Index = LBound;
(i < NumberElements) && (hr == WBEM_S_NO_ERROR);
i++, Index++)
{
hr = SafeArrayGetElement(SettingList->parray,
&Index,
&punk);
if (hr == WBEM_S_NO_ERROR)
{
hr = punk->QueryInterface(IID_IWbemClassObject,
(PVOID *)&pWdmSettingInstance);
if (hr == WBEM_S_NO_ERROR)
{
hr = CreateInst(GetCdmServices(),
&pCdmSettingInstance,
CdmSettingClassName,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
hr = CopyBetweenCdmAndWdmClasses(pCdmSettingInstance,
pWdmSettingInstance,
TRUE);
if (hr == WBEM_S_NO_ERROR)
{
//
// Set CdmSetting.SettingId to a unique
// setting id
//
wsprintfW(SettingId, L"%ws_%d_%d",
CdmTestClassName,
RelPathIndex,
i);
s = SysAllocString(SettingId);
if (s != NULL)
{
VariantInit(&v);
v.vt = VT_BSTR;
v.bstrVal = s;
hr = WmiSetProperty(pCdmSettingInstance,
L"SettingId",
&v);
VariantClear(&v);
if (hr == WBEM_S_NO_ERROR)
{
hr = BuildSettingForTestRelPath(&s,
pCdmSettingInstance);
if (hr == WBEM_S_NO_ERROR)
{
CdmSettingForTestRelPath->Set(i,
s);
CdmSettings->Set(i,
pCdmSettingInstance,
TRUE);
}
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
}
if (hr != WBEM_S_NO_ERROR)
{
pCdmSettingInstance->Release();
}
}
pWdmSettingInstance->Release();
}
punk->Release();
}
}
}
}
return(hr);
}
HRESULT CTestServices::GetCdmTestSettings(
void
)
/*+++
Routine Description:
This routine will obtain all of the CDM settings available for all
instnaces of the test
Arguments:
Return Value:
HRESULT
---*/
{
WCHAR Query[MAX_PATH * 2];
WCHAR s[MAX_PATH];
ULONG AllocSize;
BSTR sWQL, sQuery;
IEnumWbemClassObject *pWdmEnumInstances;
IWbemClassObject *pWdmInstance;
int i;
ULONG Count;
HRESULT hr;
VARIANT SettingList;
//
// We need to get all of the settings exposed by the WDM class and
// then convert them to Cdm classes.
//
sWQL = SysAllocString(L"WQL");
if (sWQL != NULL)
{
AllocSize = RelPathCount * sizeof(CWbemObjectList *);
CdmSettingsList = (CWbemObjectList **)WmipAlloc(AllocSize);
if (CdmSettingsList != NULL)
{
memset(CdmSettingsList, 0, AllocSize);
AllocSize = RelPathCount * sizeof(CBstrArray *);
CdmSettingForTestRelPath = (CBstrArray **)WmipAlloc(AllocSize);
if (CdmSettingForTestRelPath != NULL)
{
memset(CdmSettingForTestRelPath, 0, AllocSize);
hr = WBEM_S_NO_ERROR;
for (i = 0; (i < RelPathCount) && (hr == WBEM_S_NO_ERROR); i++)
{
CdmSettingsList[i] = new CWbemObjectList();
CdmSettingForTestRelPath[i] = new CBstrArray;
wsprintfW(Query, L"select * from %ws where InstanceName = \"%ws\"",
WdmSettingListClassName,
AddSlashesToStringW(s, WdmInstanceNames[i]));
sQuery = SysAllocString(Query);
if (sQuery != NULL)
{
hr = pWdmServices->ExecQuery(sWQL,
sQuery,
WBEM_FLAG_FORWARD_ONLY |
WBEM_FLAG_ENSURE_LOCATABLE,
NULL,
&pWdmEnumInstances);
if (hr == WBEM_S_NO_ERROR)
{
hr = pWdmEnumInstances->Next(WBEM_INFINITE,
1,
&pWdmInstance,
&Count);
if ((hr == WBEM_S_NO_ERROR) &&
(Count == 1))
{
hr = WmiGetProperty(pWdmInstance,
L"SettingList",
CIM_FLAG_ARRAY | CIM_OBJECT,
&SettingList);
if (hr == WBEM_S_NO_ERROR)
{
if (SettingList.vt & VT_ARRAY)
{
hr = ParseSettingList(&SettingList,
CdmSettingsList[i],
CdmSettingForTestRelPath[i],
i);
} else {
hr = WBEM_E_FAILED;
}
VariantClear(&SettingList);
}
pWdmInstance->Release();
}
pWdmEnumInstances->Release();
} else {
//
// There must not be any predefined settings
//
hr = CdmSettingsList[i]->Initialize(0);
}
SysFreeString(sQuery);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
SysFreeString(sWQL);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT CTestServices::InitializeCdmClasses(
PWCHAR CdmClass
)
/*+++
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
---*/
{
HRESULT hr, hrDontCare;
ULONG AllocSize;
int i;
WmipAssert(CdmClass != NULL);
WmipAssert(! IsThisInitialized());
//
// We assume that this method will always be the first one called
// by the class provider
//
if ((pCimServices == NULL) &&
(pWdmServices == NULL))
{
hr = TestInfoInitialize();
if (hr != WBEM_S_NO_ERROR)
{
return(hr);
}
}
//
// We are given a random CDM class name - it could be a test,
// setting, association, etc so we need to go from that class name
// and obtain all of the class names related to this diagnostic
//
hr = GetCdmClassNamesFromOne(CdmClass);
if (hr == WBEM_S_NO_ERROR)
{
//
// Use worker function to determine which
// Wdm relpaths map to which Cdm relpaths
//
hr = MapWdmClassToCimClass(pWdmServices,
pCimServices,
WdmTestClassName,
CimClassMappingClassName,
&PnPDeviceIdsX,
&WdmInstanceNames,
&WdmRelPaths,
&CimRelPaths,
&RelPathCount);
if (hr == WBEM_S_NO_ERROR)
{
//
// Obtain all of the possible settings for this test
//
hr = GetCdmTestSettings();
if (hr == WBEM_S_NO_ERROR)
{
//
// Initialize the results object lists
//
CdmResultsList = new CResultList[RelPathCount];
//
// Build the test class instance relpaths
//
hr = BuildTestRelPaths();
// @@BEGIN_DDKSPLIT
#ifdef REBOOT_DIAGNOSTICS
if (hr == WBEM_S_NO_ERROR)
{
hrDontCare = GatherRebootResults();
}
#else
//
// Reboot diagnostics are not yet supported
//
#endif
// @@END_DDKSPLIT
}
}
}
return(hr);
}
IWbemServices *CTestServices::GetWdmServices(
void
)
/*+++
Routine Description:
Accessor for the WDM namespace IWbemServices
Arguments:
Return Value:
IWbemServices
---*/
{
WmipAssert(pWdmServices != NULL);
return(pWdmServices);
}
IWbemServices *CTestServices::GetCdmServices(
void
)
/*+++
Routine Description:
Accessor for the CIM namespace IWbemServices
Arguments:
Return Value:
IWbemServices
---*/
{
WmipAssert(pCimServices != NULL);
return(pCimServices);
}
HRESULT CTestServices::WdmPropertyToCdmProperty(
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;
BSTR Mapped;
VARIANT vClassName;
CIMTYPE BaseWdmCimType, BaseCdmCimType;
CIMTYPE WdmCimArray, CdmCimArray;
LONG i;
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))
{
hr = WmiGetProperty(pWdmClassInstance,
L"__Class",
CIM_STRING,
&vClassName);
if (hr == WBEM_S_NO_ERROR)
{
if (WdmCimArray)
{
SAFEARRAYBOUND Bounds;
SAFEARRAY *Array;
ULONG Value;
LONG UBound, LBound, Elements, Index;
//
// We have an array of enumeration types to convert into an
// array of corresponding strings
//
hr = WmiGetArraySize(PropertyValue->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;
hr = SafeArrayGetElement(PropertyValue->parray,
&Index,
&Value);
if (hr == WBEM_S_NO_ERROR)
{
hr = LookupValueMap(GetWdmServices(),
vClassName.bstrVal,
PropertyName,
Value,
&Mapped);
if (hr == WBEM_S_NO_ERROR)
{
hr = SafeArrayPutElement(Array,
&Index,
Mapped);
}
}
}
if (hr == WBEM_S_NO_ERROR)
{
VariantClear(PropertyValue);
PropertyValue->vt = VT_BSTR | VT_ARRAY;
PropertyValue->parray = Array;
} else {
SafeArrayDestroy(Array);
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
}
} else {
//
// We need to convert a scalar enumeration type into the
// corresponding string. First we need to get the Wdm class
// object and from that get the Values and ValueMap qualifiers
// to determine the string we need to place into the cim class
//
hr = LookupValueMap(GetWdmServices(),
vClassName.bstrVal,
PropertyName,
PropertyValue->uiVal,
&Mapped);
if (hr == WBEM_S_NO_ERROR)
{
VariantClear(PropertyValue);
PropertyValue->vt = VT_BSTR;
PropertyValue->bstrVal = Mapped;
}
}
VariantClear(&vClassName);
}
} else {
//
// No conversion needs to occur
//
hr = WBEM_S_NO_ERROR;
}
return(hr);
}
HRESULT CTestServices::CdmPropertyToWdmProperty(
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
---*/
{
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
//
//
// There are no conversion requirements when converting from Cdm to
// Wdm instances
//
return(WBEM_S_NO_ERROR);
}
HRESULT CTestServices::CopyBetweenCdmAndWdmClasses(
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 = WdmPropertyToCdmProperty(pDestinationInstance,
pSourceInstance,
PropertyName,
&PropertyValue,
DestCimType,
SourceCimType);
} else {
hr = CdmPropertyToWdmProperty(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 CTestServices::QueryWdmTest(
OUT IWbemClassObject *pCdmTest,
IN int RelPathIndex
)
/*+++
Routine Description:
This routine will query the Wdm test class instance and copy the results
into the Cdm Test class instance
Arguments:
pCdmTest points at the Cdm Test class instance
RelPathIndex
Return Value:
HRESULT
---*/
{
IWbemClassObject *pWdmTest;
HRESULT hr;
WmipAssert(pCdmTest != NULL);
WmipAssert(IsThisInitialized());
hr = ConnectToWdmClass(RelPathIndex,
&pWdmTest);
if (hr == WBEM_S_NO_ERROR)
{
hr = CopyBetweenCdmAndWdmClasses(pCdmTest,
pWdmTest,
TRUE);
pWdmTest->Release();
}
return(hr);
}
#define OBJECTCOLONSIZE (((sizeof(L"object:")/sizeof(WCHAR)))-1)
HRESULT CTestServices::FillTestInParams(
OUT IWbemClassObject *pInParamInstance,
IN IWbemClassObject *pCdmSettings,
IN BSTR ExecutionID
)
{
HRESULT hr;
IWbemServices *pWdmServices;
VARIANT v;
VARIANT PropertyValues[2];
PWCHAR PropertyNames[2];
PWCHAR ClassName;
IWbemClassObject *pRunTestIn;
IWbemClassObject *pWdmSettingsInstance;
IWbemQualifierSet *pQualSet;
WmipAssert(pInParamInstance != NULL);
pWdmServices = GetWdmServices();
pRunTestIn = NULL;
//
// Get the name of the embedded class for the RunTestIn input
// parameter. This should be an embedded class that contains all of
// the input parameters. We get this from the __CIMTYPE qualifier
// on the RunTestIn property.
//
// We need to do this since the wmiprov can't
// handle anything with an embedded object as an input parameter to
// a method
//
hr = pInParamInstance->GetPropertyQualifierSet(L"RunTestIn",
&pQualSet);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiGetQualifier(pQualSet,
L"CIMTYPE",
VT_BSTR,
&v);
if (hr == WBEM_S_NO_ERROR)
{
if (_wcsnicmp(v.bstrVal, L"object:", OBJECTCOLONSIZE) == 0)
{
ClassName = v.bstrVal + OBJECTCOLONSIZE;
hr = CreateInst(pWdmServices,
&pRunTestIn,
ClassName,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
hr = CreateInst(pWdmServices,
&pWdmSettingsInstance,
WdmSettingClassName,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
if (pCdmSettings != NULL)
{
hr = CopyBetweenCdmAndWdmClasses(pWdmSettingsInstance,
pCdmSettings,
FALSE);
}
if (hr == WBEM_S_NO_ERROR)
{
PWCHAR PropertyNames[2];
VARIANT PropertyValues[2];
PropertyNames[0] = L"DiagSettings";
PropertyValues[0].vt = VT_UNKNOWN;
PropertyValues[0].punkVal = pWdmSettingsInstance;
PropertyNames[1] = L"ExecutionID";
PropertyValues[1].vt = VT_BSTR;
PropertyValues[1].bstrVal = ExecutionID;
hr = WmiSetPropertyList(pRunTestIn,
2,
PropertyNames,
PropertyValues);
if (hr == WBEM_S_NO_ERROR)
{
PropertyValues[0].vt = VT_UNKNOWN;
PropertyValues[0].punkVal = pRunTestIn;
hr = WmiSetProperty(pInParamInstance,
L"RunTestIn",
&PropertyValues[0]);
}
}
//
// We can release here since we know that wbem
// took a ref count when we set the property
//
pWdmSettingsInstance->Release();
}
}
}
VariantClear(&v);
}
pQualSet->Release();
}
if ((hr != WBEM_S_NO_ERROR) && (pRunTestIn != NULL))
{
pRunTestIn->Release();
}
return(hr);
}
HRESULT CTestServices::GetTestOutParams(
IN IWbemClassObject *OutParams,
OUT IWbemClassObject *pCdmResult,
OUT ULONG *Result
)
{
HRESULT hr;
VARIANT v;
IWbemClassObject *pRunTestOut;
IWbemClassObject *pWdmResult;
WmipAssert(OutParams != NULL);
WmipAssert(pCdmResult != NULL);
WmipAssert(Result != NULL);
hr = WmiGetProperty(OutParams,
L"RunTestOut",
CIM_OBJECT,
&v);
if (hr == WBEM_S_NO_ERROR)
{
hr = v.punkVal->QueryInterface(IID_IWbemClassObject,
(PVOID *)&pRunTestOut);
VariantClear(&v);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiGetProperty(pRunTestOut,
L"Result",
CIM_UINT32,
&v);
if (hr == WBEM_S_NO_ERROR)
{
*Result = v.ulVal;
VariantClear(&v);
hr = WmiGetProperty(pRunTestOut,
L"DiagResult",
CIM_OBJECT,
&v);
if (hr == WBEM_S_NO_ERROR)
{
if (v.vt != VT_NULL)
{
hr = v.punkVal->QueryInterface(IID_IWbemClassObject,
(PVOID *)&pWdmResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = CopyBetweenCdmAndWdmClasses(pCdmResult,
pWdmResult,
TRUE);
pWdmResult->Release();
}
} else {
hr = WBEM_E_FAILED;
}
VariantClear(&v);
}
}
pRunTestOut->Release();
}
}
return(hr);
}
LONG GlobalExecutionID;
BSTR CTestServices::GetExecutionID(
void
)
{
BSTR s;
WCHAR x[MAX_PATH];
//
// We make up a unique execution ID for this test by using the
// current date and time plus a unique counter. The execution id
// must be unique.
//
s = GetCurrentDateTime();
if (s != NULL)
{
wsprintfW(x, L"%ws*%08x", s, InterlockedIncrement(&GlobalExecutionID));
SysFreeString(s);
s = SysAllocString(x);
}
return(s);
}
HRESULT CTestServices::ExecuteWdmTest(
IN IWbemClassObject *pCdmSettings,
OUT IWbemClassObject *pCdmResult,
IN int RelPathIndex,
OUT ULONG *Result,
OUT BSTR *ExecutionID
)
/*+++
Routine Description:
This routine will execute a test on the Wdm class instance and copy
the results back to the Cdm results instance, along with creating
all result instance relpaths
Arguments:
pCdmSettings is a CDM settings instance that is used to create the
wdm settings instance that is used to run the test. This may be
NULL if default test settings are assumed
pCdmResult is a CDM result instance that returns with the results
form the test
RelPathIndex
*Result returns with the return value result from the test
*ExecutionId returns with the unique execution id for the test
Return Value:
HRESULT
---*/
{
HRESULT hr;
IWbemClassObject *pOutParams;
IWbemClassObject *pInParamInstance;
BSTR s;
WmipAssert(pCdmResult != NULL);
WmipAssert(Result != NULL);
WmipAssert(ExecutionID != 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)
{
return(hr);
}
*ExecutionID = GetExecutionID();
if (*ExecutionID != NULL)
{
s = SysAllocString(L"RunTest");
if (s != NULL)
{
hr = GetMethodInParamInstance(GetWdmServices(),
WdmTestClassName,
s,
&pInParamInstance);
if (hr == WBEM_S_NO_ERROR)
{
hr = FillTestInParams(pInParamInstance,
pCdmSettings,
*ExecutionID);
if (hr == WBEM_S_NO_ERROR)
{
hr = pWdmServices->ExecMethod(WdmRelPaths[RelPathIndex],
s,
0,
NULL,
pInParamInstance,
&pOutParams,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
hr = GetTestOutParams(pOutParams,
pCdmResult,
Result);
if (hr == WBEM_S_NO_ERROR)
{
//
// if the test requires the device being
// taken offline then do that now
//
hr = OfflineDeviceForTest(pCdmResult,
*ExecutionID,
RelPathIndex);
}
pOutParams->Release();
}
}
pInParamInstance->Release();
}
SysFreeString(s);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
CoRevertToSelf();
return(hr);
}
HRESULT CTestServices::StopWdmTest(
IN int RelPathIndex,
OUT ULONG *Result,
OUT BOOLEAN *TestingStopped
)
/*+++
Routine Description:
This routine will attempt to stop an executing WDM test
Arguments:
RelPathIndex
*Result returns with the result value
*TestingStopped returns TRUE if testing was stopped successfully
Return Value:
HRESULT
---*/
{
HRESULT hr;
IWbemClassObject *OutParams;
BSTR s;
IWbemServices *pWdmServices;
VARIANT Value;
WmipAssert(Result != NULL);
WmipAssert(TestingStopped != 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)
{
return(hr);
}
pWdmServices = GetWdmServices();
s = SysAllocString(L"DiscontinueTest");
if (s != NULL)
{
hr = pWdmServices->ExecMethod(WdmRelPaths[RelPathIndex],
s,
0,
NULL,
NULL,
&OutParams,
NULL);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiGetProperty(OutParams,
L"Result",
CIM_UINT32,
&Value);
if (hr == WBEM_S_NO_ERROR)
{
*Result = Value.ulVal;
VariantClear(&Value);
hr = WmiGetProperty(OutParams,
L"TestingStopped",
CIM_BOOLEAN,
&Value);
if (hr == WBEM_S_NO_ERROR)
{
*TestingStopped = (Value.boolVal != 0) ? TRUE : FALSE;
VariantClear(&Value);
}
}
OutParams->Release();
}
SysFreeString(s);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
CoRevertToSelf();
return(hr);
}
HRESULT CTestServices::GetRelPathIndex(
BSTR CimRelPath,
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(CimRelPath != NULL);
WmipAssert(CimRelPaths != NULL);
WmipAssert(WdmRelPaths != NULL);
WmipAssert(IsThisInitialized());
for (i = 0; i < RelPathCount; i++)
{
if (_wcsicmp(CimRelPath, CimRelPaths[i]) == 0)
{
*RelPathIndex = i;
return(WBEM_S_NO_ERROR);
}
}
return(WBEM_E_NOT_FOUND);
}
HRESULT CTestServices::ConnectToWdmClass(
IN int RelPathIndex,
OUT IWbemClassObject **ppWdmClassObject
)
/*+++
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(ppWdmClassObject != 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)
{
*ppWdmClassObject = NULL;
hr = GetWdmServices()->GetObject(WdmRelPaths[RelPathIndex],
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
ppWdmClassObject,
NULL);
CoRevertToSelf();
}
return(hr);
}
HRESULT CTestServices::FillInCdmResult(
OUT IWbemClassObject *pCdmResult,
IN IWbemClassObject *pCdmSettings,
IN int RelPathIndex,
IN BSTR ExecutionID
)
/*+++
Routine Description:
This routine will fill in the various properties needed in a CDM
result instance
Arguments:
pCdmResult has its properties set
pCdmSettings has the settings used to execute the test. This can be
NULL
RelPathIndex
ExecutionID has a unique id used to execute the test
Return Value:
HRESULT
---*/
{
HRESULT hr, hrDontCare;
WCHAR s[MAX_PATH];
PWCHAR PropertyNames[12];
VARIANT PropertyValues[12];
ULONG PropertyCount;
BSTR ss;
WmipAssert(pCdmResult != NULL);
WmipAssert(IsThisInitialized());
PropertyNames[0] = L"DiagnosticCreationClassName";
PropertyValues[0].vt = VT_BSTR;
PropertyValues[0].bstrVal = WdmRelPaths[RelPathIndex];
PropertyNames[1] = L"DiagnosticName";
PropertyValues[1].vt = VT_BSTR;
PropertyValues[1].bstrVal = CdmTestClassName;
PropertyNames[2] = L"ExecutionID";
PropertyValues[2].vt = VT_BSTR;
PropertyValues[2].bstrVal = ExecutionID;
PropertyNames[3] = L"TimeStamp";
PropertyValues[3].vt = VT_BSTR;
PropertyValues[3].bstrVal = GetCurrentDateTime();
PropertyNames[4] = L"TestCompletionTime";
PropertyValues[4].vt = VT_BSTR;
PropertyValues[4].bstrVal = GetCurrentDateTime();
PropertyNames[5] = L"IsPackage";
PropertyValues[5].vt = VT_BOOL;
PropertyValues[5].boolVal = VARIANT_FALSE;
//
// These properties are copied from pCdmSettings
//
if (pCdmSettings != NULL)
{
PropertyNames[6] = L"TestWarningLevel";
hrDontCare = WmiGetProperty(pCdmSettings,
L"TestWarningLevel",
CIM_UINT16,
&PropertyValues[6]);
PropertyNames[7] = L"ReportSoftErrors";
hrDontCare = WmiGetProperty(pCdmSettings,
L"ReportSoftErrors",
CIM_BOOLEAN,
&PropertyValues[7]);
PropertyNames[8] = L"ReportStatusMessages";
hrDontCare = WmiGetProperty(pCdmSettings,
L"ReportStatusMessages",
CIM_BOOLEAN,
&PropertyValues[8]);
PropertyNames[9] = L"HaltOnError";
hrDontCare = WmiGetProperty(pCdmSettings,
L"HaltOnError",
CIM_BOOLEAN,
&PropertyValues[9]);
PropertyNames[10] = L"QuickMode";
hrDontCare = WmiGetProperty(pCdmSettings,
L"QuickMode",
CIM_BOOLEAN,
&PropertyValues[10]);
PropertyNames[11] = L"PercentOfTestCoverage";
hrDontCare = WmiGetProperty(pCdmSettings,
L"PercentOfTestCoverage",
CIM_UINT8,
&PropertyValues[11]);
PropertyCount = 12;
} else {
PropertyCount = 6;
}
hr = WmiSetPropertyList(pCdmResult,
PropertyCount,
PropertyNames,
PropertyValues);
VariantClear(&PropertyValues[3]);
VariantClear(&PropertyValues[4]);
return(hr);
}
HRESULT CTestServices::QueryOfflineResult(
OUT IWbemClassObject *pCdmResult,
IN BSTR ExecutionID,
IN int RelPathIndex
)
{
WCHAR Query[MAX_PATH * 2];
WCHAR s[MAX_PATH];
BSTR sWQL, sQuery;
IEnumWbemClassObject *pWdmEnumInstances;
IWbemClassObject *pWdmResult, *pWdmInstance;
ULONG Count;
HRESULT hr;
VARIANT vResult;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
WmipAssert(WdmOfflineResultClassName != NULL);
//
// 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)
{
return(hr);
}
sWQL = SysAllocString(L"WQL");
if (sWQL != NULL)
{
wsprintfW(Query, L"select * from %ws where InstanceName = \"%ws\"",
WdmOfflineResultClassName,
AddSlashesToStringW(s, WdmInstanceNames[RelPathIndex]));
sQuery = SysAllocString(Query);
if (sQuery != NULL)
{
hr = GetWdmServices()->ExecQuery(sWQL,
sQuery,
WBEM_FLAG_FORWARD_ONLY |
WBEM_FLAG_ENSURE_LOCATABLE,
NULL,
&pWdmEnumInstances);
SysFreeString(sQuery);
if (hr == WBEM_S_NO_ERROR)
{
hr = pWdmEnumInstances->Next(WBEM_INFINITE,
1,
&pWdmInstance,
&Count);
if ((hr == WBEM_S_NO_ERROR) &&
(Count == 1))
{
//
// Check that the result has the correct execution
// ID
//
hr = WmiGetProperty(pWdmInstance,
L"ExecutionID",
CIM_STRING,
&vResult);
if (hr == WBEM_S_NO_ERROR)
{
if (_wcsicmp(ExecutionID, vResult.bstrVal) != 0)
{
hr = WBEM_E_FAILED;
WmipDebugPrint(("CdmProv: Expected execution ID %ws, but got %ws\n",
ExecutionID, vResult.bstrVal));
}
VariantClear(&vResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiGetProperty(pWdmInstance,
L"TestResult",
CIM_OBJECT,
&vResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = (vResult.punkVal)->QueryInterface(IID_IWbemClassObject,
(PVOID *)&pWdmResult);
VariantClear(&vResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = CopyBetweenCdmAndWdmClasses(pCdmResult,
pWdmResult,
TRUE);
pWdmResult->Release();
}
}
}
}
pWdmInstance->Release();
}
pWdmEnumInstances->Release();
}
}
SysFreeString(sWQL);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
CoRevertToSelf();
return(hr);
}
//@@BEGIN_DDKSPLIT
HRESULT CTestServices::GatherRebootResults(
void
)
/*+++
Routine Description:
This routine will check the schema to see if there were any tests
that were pending reboot for this DiagnosticTest and if so gather
the results of them.
When a test is pending reboot, it gets stored as an instance of the
static class CDMPROV_Result. The instance contains the Test class
name, the result class name, the PnPId of the device stack and the
result object. What we do is get all of the saved results for this
DiagTest and then see if they apply to any of the PnP Device Ids
for the WdmTest. If so then we call the device to retrieve the
results and build the result objects.
Arguments:
Return Value:
HRESULT
---*/
{
#ifdef REBOOT_DIAGNOSTICS
HRESULT hr, hrDontCare;
WCHAR Query[2*MAX_PATH];
BSTR sQuery, sWQL;
IEnumWbemClassObject *pEnumInstances;
IWbemClassObject *pInstance;
IWbemClassObject *pCdmResult;
int i;
ULONG Count;
VARIANT vResult, vPnPId, vExecutionID;
BSTR ExecutionId;
hr = WBEM_S_NO_ERROR;
sWQL = SysAllocString(L"WQL");
if (sWQL != NULL)
{
wsprintfW(Query, L"select * from CdmProv_Result where CdmTestClass = \"%ws\"\n",
CdmTestClassName);
sQuery = SysAllocString(Query);
if (sQuery != NULL)
{
hrDontCare = GetCdmServices()->ExecQuery(sWQL,
sQuery,
WBEM_FLAG_FORWARD_ONLY |
WBEM_FLAG_ENSURE_LOCATABLE,
NULL,
&pEnumInstances);
SysFreeString(sQuery);
if (hrDontCare == WBEM_S_NO_ERROR)
{
hr = pEnumInstances->Next(WBEM_INFINITE,
1,
&pInstance,
&Count);
if ((hr == WBEM_S_NO_ERROR) &&
(Count == 1))
{
hr = WmiGetProperty(pInstance,
L"PnPId",
CIM_STRING,
&vPnPId);
if (hr == WBEM_S_NO_ERROR)
{
for (i = 0; i < RelPathCount; i++)
{
if (_wcsicmp(vPnPId.bstrVal, PnPDeviceIdsX[i]) == 0)
{
//
// We found an instance for this class
// and PnPId. get out the stored
// result, assign it a new execution
// id, and then retrieve the active
// result from the driver
//
PWCHAR PropertyNames[2];
VARIANT Values[2];
CIMTYPE CimTypes[2];
PropertyNames[0] = L"CdmResult";
CimTypes[0] = CIM_OBJECT;
PropertyNames[1] = L"ResultTag";
CimTypes[1] = CIM_STRING;
hr = WmiGetPropertyList(pInstance,
PropertyNames,
CimTypes,
Values);
if (hr == WBEM_S_NO_ERROR)
{
hr = (Values[0].punkVal)->QueryInterface(IID_IWbemClassObject,
(PVOID *)&pCdmResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiGetProperty(pCdmResult,
L"ExecutionID",
CIM_STRING,
&vExecutionId);
WmipAssert(vExecutionId.vt != VT_NULL);
if (hr == WBEM_S_NO_ERROR)
{
hr = QueryOfflineResult(pCdmResult,
Values[1].bstrVal,
i);
if (hr == WBEM_S_NO_ERROR)
{
hr = SetResultObject(pCdmResult,
i,
vExecutionId.bstrVal);
if (hr == WBEM_S_NO_ERROR)
{
hr = FillInCdmResult(pCdmResult,
NULL,
i,
ExecutionId);
if (hr != WBEM_S_NO_ERROR)
{
hrDontCare = SetResultObject(NULL,
i,
0);
}
}
}
}
}
VariantClear(&Values[0]);
VariantClear(&Values[1]);
}
}
}
VariantClear(&vPnPId);
}
}
pEnumInstances->Release();
}
}
SysFreeString(sWQL);
}
return(hr);
#else
return(WBEM_S_NO_ERROR);
#endif
}
HRESULT CTestServices::PersistResultInSchema(
IN IWbemClassObject *pCdmResult,
IN BSTR ExecutionID,
IN int RelPathIndex
)
/*+++
Routine Description:
This routine will persist a diagnostic result into the schema
Arguments:
Return Value:
HRESULT
---*/
{
HRESULT hr;
IWbemClassObject *pPendingTest;
IUnknown *punk;
WCHAR *PropertyNames[5];
VARIANT PropertyValues[5];
WmipAssert(pCdmResult != NULL);
WmipAssert(IsThisInitialized());
hr = CreateInst(GetCdmServices(),
&pPendingTest,
L"CDMProv_Result",
NULL);
if (hr == WBEM_S_NO_ERROR)
{
hr = pCdmResult->QueryInterface(IID_IUnknown,
(PVOID *)&punk);
if (hr == WBEM_S_NO_ERROR)
{
PropertyNames[0] = L"PnPId";
PropertyValues[0].vt = VT_BSTR;
PropertyValues[0].bstrVal = PnPDeviceIdsX[RelPathIndex];
PropertyNames[1] = L"CdmTestClass";
PropertyValues[1].vt = VT_BSTR;
PropertyValues[1].bstrVal = CdmTestClassName;
PropertyNames[2] = L"CdmResultClass";
PropertyValues[2].vt = VT_BSTR;
PropertyValues[2].bstrVal = CdmResultClassName;
PropertyNames[3] = L"CdmResult";
PropertyValues[3].vt = VT_UNKNOWN;
PropertyValues[3].punkVal = punk;
PropertyNames[4] = L"ExecutionID";
PropertyValues[4].vt = VT_BSTR;
PropertyValues[4].bstrVal = ExecutionID;
hr = WmiSetPropertyList(pPendingTest,
5,
PropertyNames,
PropertyValues);
if (hr == WBEM_S_NO_ERROR)
{
hr = GetCdmServices()->PutInstance(pPendingTest,
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL);
}
punk->Release();
}
pPendingTest->Release();
}
return(hr);
}
//@@END_DDKSPLIT
HRESULT CTestServices::OfflineDeviceForTest(
IWbemClassObject *pCdmResult,
BSTR ExecutionID,
int RelPathIndex
)
{
HRESULT hr = WBEM_S_NO_ERROR;
ULONG Status;
VARIANT v;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
//
// First determine if the test is one where it expects to be taken
// offline and that the result from the RunTest method indicates
// that an offline execution is pending
//
if (WdmOfflineResultClassName != NULL)
{
//
// The device expects to be taken offline since it had a
// WdmOfflineResultClass qualifier on the CIM_DiagnosticResult
// class. Now see if the OtherStateDescription property in the
// CIM_DiagnosticResult is set to "Offline Pending Execution"
//
hr = WmiGetProperty(pCdmResult,
L"OtherStateDescription",
CIM_STRING,
&v);
if (hr == WBEM_S_NO_ERROR)
{
if (_wcsicmp(v.bstrVal, L"Offline Pending Execution") == 0)
{
//
// Ok, the test is waiting for the device to be taken
// offline. Lets do this now and then when the device
// comes back, pickup the results from the
// OfflineResultClass
//
// @@BEGIN_DDKSPLIT
//#define FORCE_REBOOT_REQUIRED
#ifdef FORCE_REBOOT_REQUIRED
Status = ERROR_INVALID_PARAMETER;
#else
// @@END_DDKSPLIT
//
// Make sure to use the clients security context to try
// to bring the device offline.
//
hr = CoImpersonateClient();
if (hr == WBEM_S_NO_ERROR)
{
Status = RestartDevice(PnPDeviceIdsX[RelPathIndex]);
CoRevertToSelf();
}
// @@BEGIN_DDKSPLIT
#endif
// @@END_DDKSPLIT
if (Status == ERROR_SUCCESS)
{
hr = QueryOfflineResult(pCdmResult,
ExecutionID,
RelPathIndex);
} else {
//
// For some reason we were not able to bring the
// device offline. Most likely this is because the
// device is critical to the system and cannot be
// taken offline right now - for example a disk
// that is in the paging path.
//
// @@BEGIN_DDKSPLIT
#if REBOOT_DIAGNOSTICS
// What we'll need to do is to remember that
// this test is pending and so the next time the
// system is rebooted we can check for the results
// of this test and report them.
//
hr = PersistResultInSchema(pCdmResult,
RelPathIndex);
#else
//
// Reboot diagnostics are not currently supported.
//
// @@END_DDKSPLIT
hr = WBEM_E_FAILED;
// @@BEGIN_DDKSPLIT
#endif
// @@END_DDKSPLIT
}
}
VariantClear(&v);
} else {
//
// Since the OtherStateDescription was not set then we
// assume that the tests isn't setup to go offline and has
// already been completed
//
hr = WBEM_S_NO_ERROR;
}
}
return(hr);
}
BOOLEAN CTestServices::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( (CdmTestClassName != NULL) );
}
HRESULT CTestServices::AddResultToList(
IN IWbemClassObject *ResultInstance,
IN BSTR ExecutionID,
IN int RelPathIndex
)
/*+++
Routine Description:
This routine will add a result object and the related association
relpaths to the list of result objects for the test
Arguments:
ResultInstance is an instance of CIM_DiagnosticResults
RelPathIndex
ExecutionID
Return Value:
Never fails
---*/
{
HRESULT hr;
BSTR ResultRelPath;
BSTR ResultForMSERelPath;
BSTR ResultForTestRelPath;
WmipAssert(ResultInstance != NULL);
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
//
// If there is a new result object then establish the various
// result relpaths for it
//
hr = BuildResultRelPaths(RelPathIndex,
ExecutionID,
&ResultRelPath,
&ResultForMSERelPath,
&ResultForTestRelPath);
if (hr == WBEM_S_NO_ERROR)
{
hr = CdmResultsList[RelPathIndex].Add(ResultInstance,
ResultRelPath,
ResultForMSERelPath,
ResultForTestRelPath);
}
return(hr);
}
HRESULT CTestServices::GetResultsList(
IN int RelPathIndex,
OUT ULONG *ResultsCount,
OUT IWbemClassObject ***Results
)
{
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
return(CdmResultsList[RelPathIndex].GetResultsList(ResultsCount,
Results));
}
void CTestServices::ClearResultsList(
int RelPathIndex
)
{
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
CdmResultsList[RelPathIndex].Clear();
}
BSTR /* NOFREE */ CTestServices::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(CimRelPaths != NULL);
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
return(CimRelPaths[RelPathIndex]);
}
BSTR /* NOFREE */ CTestServices::GetCdmTestRelPath(
void
)
/*+++
Routine Description:
This routine will return the Cdm Test class relpath
Arguments:
Return Value:
Cdm Test Class RelPath. This should not be freed
---*/
{
WmipAssert(IsThisInitialized());
return(CdmTestRelPath);
}
BSTR /* NOFREE */ CTestServices::GetCdmTestClassName(
void
)
/*+++
Routine Description:
This routine will return the Cdm Test class name
Arguments:
Return Value:
Cdm Test Class Name. This should not be freed
---*/
{
WmipAssert(IsThisInitialized());
return(CdmTestClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmResultClassName(
void
)
/*+++
Routine Description:
This routine will return the Cdm Result class name
Arguments:
Return Value:
Cdm Result Class Name. This should not be freed
---*/
{
WmipAssert(IsThisInitialized());
return(CdmResultClassName);
}
HRESULT CTestServices::GetCdmResultByResultRelPath(
IN int RelPathIndex,
IN PWCHAR ObjectPath,
OUT IWbemClassObject **ppCdmResult
)
/*+++
Routine Description:
This routine will return the Cdm Result object for a specific RelPath
Arguments:
RelPathIndex
Return Value:
Cdm Result RelPath or NULL of there is no ressult object for the
relpath. This should not be freed
---*/
{
HRESULT hr;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
hr = CdmResultsList[RelPathIndex].GetResultByResultRelPath(ObjectPath,
ppCdmResult);
return(hr);
}
HRESULT CTestServices::GetCdmResultByResultForMSERelPath(
IN int RelPathIndex,
IN PWCHAR ObjectPath,
OUT IWbemClassObject **ppCdmResult
)
/*+++
Routine Description:
This routine will return the Cdm Result object for a specific RelPath
Arguments:
RelPathIndex
Return Value:
Cdm Result RelPath or NULL of there is no ressult object for the
relpath. This should not be freed
---*/
{
HRESULT hr;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
hr = CdmResultsList[RelPathIndex].GetResultByResultForMSERelPath(ObjectPath,
ppCdmResult);
return(hr);
}
HRESULT CTestServices::GetCdmResultByResultForTestRelPath(
IN int RelPathIndex,
IN PWCHAR ObjectPath,
OUT IWbemClassObject **ppCdmResult
)
/*+++
Routine Description:
This routine will return the Cdm Result object for a specific RelPath
Arguments:
RelPathIndex
Return Value:
Cdm Result RelPath or NULL of there is no ressult object for the
relpath. This should not be freed
---*/
{
HRESULT hr;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
hr = CdmResultsList[RelPathIndex].GetResultByResultForTestRelPath(ObjectPath,
ppCdmResult);
return(hr);
}
BSTR /* NOFREE */ CTestServices::GetCdmSettingClassName(
void
)
/*+++
Routine Description:
This routine will return the Cdm settings class name
Arguments:
Return Value:
Cdm Settings class name. This should not be freed
---*/
{
WmipAssert(IsThisInitialized());
return(CdmSettingClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmSettingRelPath(
int RelPathIndex,
ULONG SettingIndex
)
/*+++
Routine Description:
This routine will return the Cdm settings relpath by relpath index
and index with the settings for that relpath.
Arguments:
RelPathIndex
SettingIndex
Return Value:
Cdm Settings relpath. This should not be freed
---*/
{
CWbemObjectList *CdmSettings;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(CdmSettingsList != NULL);
WmipAssert(IsThisInitialized());
CdmSettings = CdmSettingsList[RelPathIndex];
return(CdmSettings->GetRelPath(SettingIndex));
}
IWbemClassObject *CTestServices::GetCdmSettingObject(
int RelPathIndex,
ULONG SettingIndex
)
{
CWbemObjectList *CdmSettings;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(CdmSettingsList != NULL);
WmipAssert(IsThisInitialized());
CdmSettings = CdmSettingsList[RelPathIndex];
return(CdmSettings->Get(SettingIndex));
}
ULONG CTestServices::GetCdmSettingCount(
int RelPathIndex
)
{
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(CdmSettingsList != NULL);
WmipAssert(IsThisInitialized());
return(CdmSettingsList[RelPathIndex]->GetListSize());
}
BSTR /* NOFREE */ CTestServices::GetCdmTestForMSEClassName(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmTestForMSEClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmTestForMSERelPath(
int RelPathIndex
)
{
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
return(CdmTestForMSERelPath[RelPathIndex]);
}
BSTR /* NOFREE */ CTestServices::GetCdmSettingForTestClassName(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmSettingForTestClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmSettingForTestRelPath(
int RelPathIndex,
ULONG SettingIndex
)
{
CBstrArray *BstrArray;
BSTR s;
WmipAssert(RelPathIndex < RelPathCount);
WmipAssert(IsThisInitialized());
if (CdmSettingForTestRelPath != NULL)
{
BstrArray = CdmSettingForTestRelPath[RelPathIndex];
s = BstrArray->Get(SettingIndex);
} else {
s = NULL;
}
return(s);
}
BSTR /* NOFREE */ CTestServices::GetCdmResultForMSEClassName(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmResultForMSEClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmResultForTestClassName(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmResultForTestClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmTestForSoftwareClassName(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmTestForSoftwareClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmTestForSoftwareRelPath(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmTestForSoftwareRelPath);
}
BSTR /* NOFREE */ CTestServices::GetCdmTestInPackageClassName(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmTestInPackageClassName);
}
BSTR /* NOFREE */CTestServices::GetCdmTestInPackageRelPath(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmTestInPackageRelPath);
}
BSTR /* NOFREE */ CTestServices::GetCdmResultInPackageClassName(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmResultInPackageClassName);
}
BSTR /* NOFREE */ CTestServices::GetCdmResultInPackageRelPath(
void
)
{
WmipAssert(IsThisInitialized());
return(CdmResultInPackageRelPath);
}
CWbemObjectList::CWbemObjectList()
{
//
// Constructor, init internal values
//
List = NULL;
RelPaths = NULL;
ListSize = 0xffffffff;
}
CWbemObjectList::~CWbemObjectList()
{
//
// Destructor, free memory held by this class
//
if (List != NULL)
{
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,
IN BOOLEAN KeepRelPath
)
{
HRESULT hr;
VARIANT v;
WmipAssert(Index < ListSize);
WmipAssert(IsInitialized());
if (Pointer != NULL)
{
hr = WmiGetProperty(Pointer,
L"__RelPath",
CIM_REFERENCE,
&v);
if (hr == WBEM_S_NO_ERROR)
{
RelPaths[Index] = v.bstrVal;
List[Index] = Pointer;
} else {
if (! KeepRelPath)
{
RelPaths[Index] = NULL;
List[Index] = Pointer;
}
}
} else {
if (RelPaths[Index] != NULL)
{
SysFreeString(RelPaths[Index]);
RelPaths[Index] = NULL;
hr = WBEM_S_NO_ERROR;
}
List[Index] = NULL;
}
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)));
}
//
// Linked list management routines
//
CTestServices *CTestServices::GetNext(
)
{
return(Next);
}
CTestServices *CTestServices::GetPrev(
)
{
return(Prev);
}
void CTestServices::InsertSelf(
CTestServices **Head
)
{
WmipAssert(Next == NULL);
WmipAssert(Prev == NULL);
if (*Head != NULL)
{
Next = (*Head);
(*Head)->Prev = this;
}
*Head = this;
}
BOOLEAN CTestServices::ClaimCdmClassName(
PWCHAR CdmClassName
)
{
if (_wcsicmp(CdmClassName, CdmTestClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmResultClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmSettingClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmTestForMSEClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmSettingForTestClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmResultForMSEClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmResultForTestClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmTestForSoftwareClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmTestInPackageClassName) == 0)
{
return(TRUE);
}
if (_wcsicmp(CdmClassName, CdmResultInPackageClassName) == 0)
{
return(TRUE);
}
return(FALSE);
}
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);
}
CResultList::CResultList()
{
ListSize = 0;
ListEntries = 0;
List = NULL;
}
CResultList::~CResultList()
{
ULONG i;
Clear();
if (List != NULL)
{
WmipFree(List);
}
}
void CResultList::Clear(
void
)
{
ULONG i;
PRESULTENTRY Entry;
if (List != NULL)
{
for (i = 0; i < ListEntries; i++)
{
Entry = &List[i];
if (Entry->ResultInstance != NULL)
{
Entry->ResultInstance->Release();
Entry->ResultInstance = NULL;
}
if (Entry->ResultRelPath != NULL)
{
SysFreeString(Entry->ResultRelPath);
Entry->ResultRelPath = NULL;
}
if (Entry->ResultForMSERelPath != NULL)
{
SysFreeString(Entry->ResultForMSERelPath);
Entry->ResultForMSERelPath = NULL;
}
if (Entry->ResultForTestRelPath != NULL)
{
SysFreeString(Entry->ResultForTestRelPath);
Entry->ResultForTestRelPath = NULL;
}
}
}
ListEntries = 0;
}
//
// The result list will grow itself this many entries at a time
//
#define RESULTLISTGROWSIZE 4
HRESULT CResultList::Add(
IWbemClassObject *CdmResultInstance,
BSTR CdmResultRelPath,
BSTR CdmResultForMSERelPath,
BSTR CdmResultForTestRelPath
)
{
ULONG AllocSize;
PRESULTENTRY NewList, Entry;
ULONG CurrentSize;
EnterCdmCritSection();
if (List == NULL)
{
//
// We are starting with an empty list
//
AllocSize = RESULTLISTGROWSIZE * sizeof(RESULTENTRY);
List = (PRESULTENTRY)WmipAlloc(AllocSize);
if (List == NULL)
{
LeaveCdmCritSection();
return(WBEM_E_OUT_OF_MEMORY);
}
memset(List, 0, AllocSize);
ListSize = RESULTLISTGROWSIZE;
ListEntries = 0;
} else if (ListEntries == ListSize) {
//
// The list needs to grow, so we allocate more memory and copy
// over the current list
//
CurrentSize = ListSize * sizeof(RESULTENTRY);
AllocSize = CurrentSize + (RESULTLISTGROWSIZE * sizeof(RESULTENTRY));
NewList = (PRESULTENTRY)WmipAlloc(AllocSize);
if (NewList == NULL)
{
LeaveCdmCritSection();
return(WBEM_E_OUT_OF_MEMORY);
}
memset(NewList, 0, AllocSize);
memcpy(NewList, List, CurrentSize);
WmipFree(List);
List = NewList;
ListSize += RESULTLISTGROWSIZE;
}
//
// We have room to add a new entry to the list
//
Entry = &List[ListEntries++];
Entry->ResultInstance = CdmResultInstance;
Entry->ResultInstance->AddRef();
Entry->ResultRelPath = CdmResultRelPath;
Entry->ResultForMSERelPath = CdmResultForMSERelPath;
Entry->ResultForTestRelPath = CdmResultForTestRelPath;
LeaveCdmCritSection();
return(WBEM_S_NO_ERROR);
}
HRESULT CResultList::GetResultsList(
OUT ULONG *Count,
OUT IWbemClassObject ***Objects
)
{
IWbemClassObject **Things;
HRESULT hr;
ULONG i;
EnterCdmCritSection();
*Count = ListEntries;
if (ListEntries != 0)
{
Things = (IWbemClassObject **)WmipAlloc( ListEntries *
sizeof(IWbemClassObject *));
if (Things != NULL)
{
*Objects = Things;
for (i = 0; i < ListEntries; i++)
{
Things[i] = List[i].ResultInstance;
Things[i]->AddRef();
}
hr = WBEM_S_NO_ERROR;
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
} else {
*Objects = NULL;
hr = WBEM_S_NO_ERROR;
}
LeaveCdmCritSection();
return(hr);
}
HRESULT CResultList::GetResultByResultRelPath(
PWCHAR ObjectPath,
IWbemClassObject **ppResult
)
{
HRESULT hr;
ULONG i;
hr = WBEM_E_NOT_FOUND;
EnterCdmCritSection();
for (i = 0; i < ListEntries; i++)
{
if (_wcsicmp(ObjectPath, List[i].ResultRelPath) == 0)
{
*ppResult = List[i].ResultInstance;
(*ppResult)->AddRef();
hr = WBEM_S_NO_ERROR;
break;
}
}
LeaveCdmCritSection();
return(hr);
}
HRESULT CResultList::GetResultByResultForMSERelPath(
PWCHAR ObjectPath,
IWbemClassObject **ppResult
)
{
HRESULT hr;
ULONG i;
hr = WBEM_E_NOT_FOUND;
EnterCdmCritSection();
for (i = 0; i < ListEntries; i++)
{
if (_wcsicmp(ObjectPath, List[i].ResultForMSERelPath) == 0)
{
*ppResult = List[i].ResultInstance;
(*ppResult)->AddRef();
hr = WBEM_S_NO_ERROR;
break;
}
}
LeaveCdmCritSection();
return(hr);
}
HRESULT CResultList::GetResultByResultForTestRelPath(
PWCHAR ObjectPath,
IWbemClassObject **ppResult
)
{
HRESULT hr;
ULONG i;
hr = WBEM_E_NOT_FOUND;
EnterCdmCritSection();
for (i = 0; i < ListEntries; i++)
{
if (_wcsicmp(ObjectPath, List[i].ResultForTestRelPath) == 0)
{
*ppResult = List[i].ResultInstance;
(*ppResult)->AddRef();
hr = WBEM_S_NO_ERROR;
break;
}
}
LeaveCdmCritSection();
return(hr);
}