Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1603 lines
49 KiB

//***************************************************************************
//
// CLASSPRO.CPP
//
// Module: CDM Provider
//
// Purpose: Defines the CClassPro class. An object of this class is
// created by the class factory for each connection.
//
// Copyright (c) 2000 Microsoft Corporation
//
//***************************************************************************
#include <objbase.h>
#include "sample.h"
#include <process.h>
#include <unknwn.h>
#include "wbemmisc.h"
#include "debug.h"
// @@BEGIN_DDKSPLIT
// TODO: pass down all pCtx so that all calls into wbem use it
// @@END_DDKSPLIT
//
// This is the global list of all of the CDM classes and their
// corresponsing WDM classes that are managed by the provider.
//
// It is maintained as a global since WinMgmt is aggressive in
// releasing the CClassProv, but we really want to maintain the result
// objects and do not want to be unloaded unless all result objects are
// cleared.
//
CTestServices *WdmTestHead;
void CleanupAllTests(
)
{
CTestServices *WdmTest;
CTestServices *WdmTestNext;
//
// Loop over all classes that were supported by the provider and
// clean them up
//
WdmTest = WdmTestHead;
while (WdmTest != NULL)
{
WdmTestNext = WdmTest->GetNext();
delete WdmTest;
}
}
//***************************************************************************
//
// CClassPro::CClassPro
// CClassPro::~CClassPro
//
//***************************************************************************
CClassPro::CClassPro(
BSTR ObjectPath,
BSTR User,
BSTR Password,
IWbemContext * pCtx
)
{
m_pCdmServices = NULL;
m_cRef=0;
InterlockedIncrement(&g_cObj);
return;
}
CClassPro::~CClassPro(void)
{
if(m_pCdmServices)
{
m_pCdmServices->Release();
}
InterlockedDecrement(&g_cObj);
return;
}
//***************************************************************************
//
// CClassPro::QueryInterface
// CClassPro::AddRef
// CClassPro::Release
//
// Purpose: IUnknown members for CClassPro object.
//***************************************************************************
STDMETHODIMP CClassPro::QueryInterface(REFIID riid, PPVOID ppv)
{
HRESULT hr;
*ppv=NULL;
// Since we have dual inheritance, it is necessary to cast the return type
if(riid== IID_IWbemServices)
{
*ppv=(IWbemServices*)this;
}
if(IID_IUnknown==riid || riid== IID_IWbemProviderInit)
{
*ppv=(IWbemProviderInit*)this;
}
if (NULL!=*ppv)
{
AddRef();
hr = NOERROR;
}
else {
hr = E_NOINTERFACE;
}
return(hr);
}
STDMETHODIMP_(ULONG) CClassPro::AddRef(void)
{
return(++m_cRef);
}
STDMETHODIMP_(ULONG) CClassPro::Release(void)
{
ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
if (0L == nNewCount)
{
delete this;
}
return(nNewCount);
}
/***********************************************************************
* *
* CClassPro::Initialize *
* *
* Purpose: This is the implementation of IWbemProviderInit. The method *
* is need to initialize with CIMOM. *
* *
***********************************************************************/
STDMETHODIMP CClassPro::Initialize(LPWSTR pszUser, LONG lFlags,
LPWSTR pszNamespace, LPWSTR pszLocale,
IWbemServices *pNamespace,
IWbemContext *pCtx,
IWbemProviderInitSink *pInitSink)
{
if (pNamespace)
{
pNamespace->AddRef();
}
m_pCdmServices = pNamespace;
//
// Let CIMOM know you are initialized
//
pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
return(WBEM_S_NO_ERROR);
}
//***************************************************************************
//
// CClassPro::CreateClassEnumAsync
//
// Purpose: Asynchronously enumerates the classes this provider supports.
// Note that this sample only supports one.
//
//***************************************************************************
SCODE CClassPro::CreateClassEnumAsync(
const BSTR Superclass, long lFlags,
IWbemContext *pCtx,
IWbemObjectSink *pHandler
)
{
return(WBEM_E_NOT_SUPPORTED);
}
//***************************************************************************
//
// CClassPro::CreateInstanceEnumAsync
//
// Purpose: Asynchronously enumerates the instances.
//
//***************************************************************************
SCODE CClassPro::CreateInstanceEnumAsync(
const BSTR ClassName,
long lFlags,
IWbemContext *pCtx,
IWbemObjectSink FAR* pHandler
)
{
HRESULT hr, hr2;
ULONG i, Count;
IWbemClassObject *pCdmTest;
CTestServices *WdmTest;
WmipDebugPrint(("CDMPROV: Enumerate instances of class %ws\n",
ClassName));
//
// Do a check of arguments and make sure we have pointer to Namespace
//
if (pHandler == NULL || m_pCdmServices == NULL)
{
return WBEM_E_INVALID_PARAMETER;
}
//
// Plan for success
//
hr = WBEM_S_NO_ERROR;
//
// Obtain a test services object that represents this class
//
hr = LookupTestServices(ClassName,
&WdmTest);
if (hr == WBEM_S_NO_ERROR)
{
if (_wcsicmp(ClassName, WdmTest->GetCdmTestClassName()) == 0)
{
hr = CreateTestInst(WdmTest, &pCdmTest, pCtx);
if (hr == WBEM_S_NO_ERROR)
{
//
// Send the object to the caller
//
hr = pHandler->Indicate(1,&pCdmTest);
pCdmTest->Release();
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultClassName()) == 0) {
//
// Loop over all instances of the test and report all results
// that we have previously recorded
//
IWbemClassObject **pCdmResultsList;
ULONG ResultCount, j;
Count = WdmTest->GetInstanceCount();
for (i = 0; (i < Count) && SUCCEEDED(hr); i++)
{
hr2 = WdmTest->GetResultsList(i,
&ResultCount,
&pCdmResultsList);
if ((hr2 == WBEM_S_NO_ERROR) && (pCdmResultsList != NULL))
{
//
// Send the object to the caller
//
hr = pHandler->Indicate(ResultCount, pCdmResultsList);
for (j = 0; j < ResultCount; j++)
{
//
// Release ref taken when results list was
// built
//
pCdmResultsList[j]->Release();
}
WmipFree(pCdmResultsList);
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmSettingClassName()) == 0) {
//
// Return a setting instances for all tests
//
ULONG j, ListCount;
IWbemClassObject *pCdmSetting;
Count = WdmTest->GetInstanceCount();
for (i = 0; (i < Count) && SUCCEEDED(hr); i++)
{
ListCount = WdmTest->GetCdmSettingCount(i);
for (j = 0; (j < ListCount) && SUCCEEDED(hr); j++)
{
pCdmSetting = WdmTest->GetCdmSettingObject(i, j);
if (pCdmSetting != NULL)
{
hr = pHandler->Indicate(1, &pCdmSetting);
// NO release required since object is cached
}
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultForMSEClassName()) == 0) {
IWbemClassObject **pCdmResultsList;
ULONG ResultCount, j;
IWbemClassObject *pCdmResultForMSE;
Count = WdmTest->GetInstanceCount();
for (i = 0; (i < Count) && SUCCEEDED(hr); i++)
{
hr2 = WdmTest->GetResultsList(i,
&ResultCount,
&pCdmResultsList);
if ((hr2 == WBEM_S_NO_ERROR) && (pCdmResultsList != NULL))
{
for (j = 0; (j < ResultCount); j++)
{
if (SUCCEEDED(hr))
{
//
// for each instance of this test we create a ResultForMSE
// association instance and then set the properties within
// it to the appropriate values and relpaths
hr2 = CreateResultForMSEInst(WdmTest,
&pCdmResultForMSE,
i,
pCdmResultsList[j],
pCtx);
if (hr2 == WBEM_S_NO_ERROR)
{
//
// Send the object to the caller
//
hr = pHandler->Indicate(1, &pCdmResultForMSE);
pCdmResultForMSE->Release();
}
}
pCdmResultsList[j]->Release();
}
WmipFree(pCdmResultsList);
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultForTestClassName()) == 0) {
IWbemClassObject **pCdmResultsList;
ULONG ResultCount,j;
IWbemClassObject *pCdmResultForTest;
Count = WdmTest->GetInstanceCount();
for (i = 0; (i < Count) && SUCCEEDED(hr); i++)
{
hr2 = WdmTest->GetResultsList(i,
&ResultCount,
&pCdmResultsList);
if ((hr2 == WBEM_S_NO_ERROR) && (pCdmResultsList != NULL))
{
for (j = 0; (j < ResultCount); j++)
{
if (SUCCEEDED(hr))
{
//
// DiagnosticResult is a reference to the CIM_Diagnostic result class
//
hr2 = CreateResultForTestInst(WdmTest,
&pCdmResultForTest,
pCdmResultsList[j],
pCtx);
if (hr2 == WBEM_S_NO_ERROR)
{
//
// Send the object to the caller
//
hr = pHandler->Indicate(1,&pCdmResultForTest);
pCdmResultForTest->Release();
}
}
pCdmResultsList[j]->Release();
}
WmipFree(pCdmResultsList);
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmTestForMSEClassName()) == 0) {
//
// Here we create the associations between tests and MSE
//
IWbemClassObject *pCdmTestForMSE;
Count = WdmTest->GetInstanceCount();
for (i = 0; i < Count; i++)
{
//
// for each instance of this test we create a TestForMSE
// association instance and then set the properties within
// it to the appropriate values and relpaths
hr2 = CreateTestForMSEInst(WdmTest,
&pCdmTestForMSE,
i,
pCtx);
if (hr2 == WBEM_S_NO_ERROR)
{
//
// Send the object to the caller
//
hr = pHandler->Indicate(1, &pCdmTestForMSE);
pCdmTestForMSE->Release();
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmSettingForTestClassName()) == 0) {
//
// Return all settings instances for this test
//
ULONG j, ListCount;
IWbemClassObject *pCdmSettingForTest;
Count = WdmTest->GetInstanceCount();
for (i = 0; (i < Count) && SUCCEEDED(hr); i++)
{
ListCount = WdmTest->GetCdmSettingCount(i);
for (j = 0; (j < ListCount) && SUCCEEDED(hr); j++)
{
hr2 = CreateSettingForTestInst(WdmTest,
&pCdmSettingForTest,
i,
j,
pCtx);
if (hr2 == WBEM_S_NO_ERROR)
{
pHandler->Indicate(1, &pCdmSettingForTest);
pCdmSettingForTest->Release();
}
}
}
#if 0 // Not supported
} else if (_wcsicmp(ClassName, WdmTest->GetCdmTestForSoftwareClassName()) == 0) {
//
// We do not support this
//
} else if (_wcsicmp(ClassName, WdmTest->GetCdmTestInPackageClassName()) == 0) {
//
// We do not support packages
//
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultInPackageClassName()) == 0) {
//
// We do not support packages
//
#endif
} else {
//
// Is this the right thing to do if we do not know what the
// class name is
//
hr = WBEM_S_NO_ERROR;
}
}
//
// TODO: Create extended error object with more info about the
// error that occured. The object is created by
// CreateInst("__ExtendedStatus")
//
pHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(hr);
}
//***************************************************************************
//
// CClassPro::GetObjectByPathAsync
//
// Purpose: Returns either an instance or a class.
//
//***************************************************************************
SCODE CClassPro::GetObjectAsync(
const BSTR ObjectPath,
long lFlags,
IWbemContext *pCtx,
IWbemObjectSink FAR* pHandler
)
{
HRESULT hr;
IWbemClassObject FAR* pObj;
// Do a check of arguments and make sure we have pointer to Namespace
if(ObjectPath == NULL || pHandler == NULL || m_pCdmServices == NULL)
{
return WBEM_E_INVALID_PARAMETER;
}
hr = GetByPath(ObjectPath,&pObj, pCtx);
if (hr == WBEM_S_NO_ERROR)
{
WmipDebugPrint(("CDMProv: Found instance %p for relpath %ws\n",
pObj, ObjectPath));
hr = pHandler->Indicate(1,&pObj);
pObj->Release();
} else {
WmipDebugPrint(("CDMProv: Did not find instance for relpath %ws\n",
ObjectPath));
hr = WBEM_E_NOT_FOUND;
}
// Set Status
pHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(hr);
}
//***************************************************************************
//
// CClassPro::GetByPath
//
// Purpose: Creates an instance given a particular Path value.
//
// All objects returned are assumed to be AddRefed
//
//***************************************************************************
HRESULT CClassPro::GetByPath(
BSTR ObjectPath,
IWbemClassObject **ppObj,
IWbemContext *pCtx
)
{
HRESULT hr = WBEM_S_NO_ERROR;
WCHAR ClassName[MAX_PATH+1];
WCHAR *p;
int iNumQuotes = 0;
int i, Count;
CTestServices *WdmTest;
BSTR s;
//
// This is where we are queried for a class based upon its relpath.
// We need to parse the relpath to get the class name and then look
// at the relpath to determine which instance of the class we are
// interested in and then build up the instance and return it
//
//
// Relpaths created at init
//
// Sample_Filter_DiagTest.Name="Sample_Filter_DiagTest"
// Sample_Filter_DiagTestForMSE.Antecedent="Win32_USBController.DeviceID=\"PCI\\\\VEN_8086&DEV_7112&SUBSYS_00000000&REV_01\\\\2&EBB567F&0&3A\"",Dependent="Sample_Filter_DiagTest.Name=\"Sample_Filter_DiagTest\""
//
//
// Relpaths created at method execute
//
// Sample_Filter_DiagResult.DiagnosticCreationClassName="MSSample_DiagnosticTest.InstanceName=\"PCI\\\\VEN_8086&DEV_7112&SUBSYS_00000000&REV_01\\\\2&ebb567f&0&3A_0\"",DiagnosticName="Sample_Filter_DiagTest",ExecutionID="0"
// Sample_Filter_DiagResultForMSE.Result="Sample_Filter_DiagResult.DiagnosticCreationClassName=\"MSSample_DiagnosticTest.InstanceName=\\\"PCI\\\\\\\\VEN_8086&DEV_7112&SUBSYS_00000000&REV_01\\\\\\\\2&ebb567f&0&3A_0\\\"\",DiagnosticName=\"Sample_Filter_DiagTest\",ExecutionID=\"0\"",SystemElement="Win32_USBController.DeviceID=\"PCI\\\\VEN_8086&DEV_7112&SUBSYS_00000000&REV_01\\\\2&EBB567F&0&3A\""
// Sample_Filter_DiagResultForTest.DiagnosticResult="Sample_Filter_DiagResult.DiagnosticCreationClassName=\"MSSample_DiagnosticTest.InstanceName=\\\"PCI\\\\\\\\VEN_8086&DEV_7112&SUBSYS_00000000&REV_01\\\\\\\\2&ebb567f&0&3A_0\\\"\",DiagnosticName=\"Sample_Filter_DiagTest\",ExecutionID=\"0\"",DiagnosticTest="Sample_Filter_DiagTest.Name=\"Sample_Filter_DiagTest\""
//
// Obtain the class name by copying up to the .
//
for (p = ObjectPath, i = 0;
(*p != 0) && (*p != L'.') && (i < MAX_PATH);
p++, i++)
{
ClassName[i] = *p;
}
if (*p != L'.')
{
//
// If we did end our loop with a . then we failed to parse
// properly
//
WmipDebugPrint(("CDMPROV: Unable to parse relpath %ws at %ws, i = %d\n",
ObjectPath, p, i));
}
ClassName[i] = 0;
WmipDebugPrint(("CDMPROV: Class %ws looking for relpath %ws\n",
ClassName, ObjectPath));
//
// Obtain a test services object that represents this class
//
hr = LookupTestServices(ClassName,
&WdmTest);
if (hr == WBEM_S_NO_ERROR)
{
//
// Assume that we will not find the object instance
//
hr = WBEM_E_NOT_FOUND;
if (_wcsicmp(ClassName, WdmTest->GetCdmTestClassName()) == 0)
{
//
// This is a CdmTest class object instance
//
#ifdef VERBOSE_DEBUG
WmipDebugPrint(("CDMPROV: Compareing \n%ws\n\nwith\n%ws\n\n",
ObjectPath, WdmTest->GetCdmTestRelPath()));
#endif
if (_wcsicmp(ObjectPath, WdmTest->GetCdmTestRelPath()) == 0)
{
hr = CreateTestInst(WdmTest, ppObj, pCtx);
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultClassName()) == 0) {
//
// This is a CdmResult class object instance
//
IWbemClassObject *pCdmResult;
Count = WdmTest->GetInstanceCount();
for (i = 0; i < Count; i++)
{
hr = WdmTest->GetCdmResultByResultRelPath(i,
ObjectPath,
&pCdmResult);
if (hr == WBEM_S_NO_ERROR)
{
*ppObj = pCdmResult;
break;
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmSettingClassName()) == 0) {
//
// This is a CDM settings class instnace
//
ULONG j, ListCount;
IWbemClassObject *pCdmSetting;
Count = WdmTest->GetInstanceCount();
for (i = 0; i < Count; i++)
{
ListCount = WdmTest->GetCdmSettingCount(i);
for (j = 0; j < ListCount; j++)
{
s = WdmTest->GetCdmSettingRelPath(i, j);
#ifdef VERBOSE_DEBUG
WmipDebugPrint(("CDMPROV: Compareing \n%ws\n\nwith\n%ws\n\n",
ObjectPath, s));
#endif
if (_wcsicmp(ObjectPath,
s) == 0)
{
pCdmSetting = WdmTest->GetCdmSettingObject(i, j);
pCdmSetting->AddRef();
*ppObj = pCdmSetting;
hr = WBEM_S_NO_ERROR;
break;
}
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultForMSEClassName()) == 0) {
//
// This is a CDM result for MSE class instance
//
IWbemClassObject *pCdmResult;
Count = WdmTest->GetInstanceCount();
for (i = 0; i < Count; i++)
{
hr = WdmTest->GetCdmResultByResultForMSERelPath(i,
ObjectPath,
&pCdmResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = CreateResultForMSEInst(WdmTest,
ppObj,
i,
pCdmResult,
pCtx);
pCdmResult->Release();
break;
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultForTestClassName()) == 0) {
IWbemClassObject *pCdmResult;
Count = WdmTest->GetInstanceCount();
for (i = 0; i < Count; i++)
{
hr = WdmTest->GetCdmResultByResultForTestRelPath(i,
ObjectPath,
&pCdmResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = CreateResultForTestInst(WdmTest,
ppObj,
pCdmResult,
pCtx);
pCdmResult->Release();
break;
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmTestForMSEClassName()) == 0) {
//
// TestForMSE class object
//
Count = WdmTest->GetInstanceCount();
for (i = 0; i < Count; i++)
{
#ifdef VERBOSE_DEBUG
WmipDebugPrint(("CDMPROV: Compareing \n%ws\n\nwith\n%ws\n\n",
ObjectPath, WdmTest->GetCdmTestForMSERelPath(i)));
#endif
if (_wcsicmp(ObjectPath,
WdmTest->GetCdmTestForMSERelPath(i)) == 0)
{
hr = CreateTestForMSEInst(WdmTest,
ppObj,
i,
pCtx);
break;
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmSettingForTestClassName()) == 0) {
//
// This is a CDM settings for test class instnace
//
ULONG j, ListCount;
Count = WdmTest->GetInstanceCount();
for (i = 0; i < Count; i++)
{
ListCount = WdmTest->GetCdmSettingCount(i);
for (j = 0; j < ListCount; j++)
{
s = WdmTest->GetCdmSettingForTestRelPath(i, j);
#ifdef VERBOSE_DEBUG
WmipDebugPrint(("CDMPROV: Compareing \n%ws\n\nwith\n%ws\n\n",
ObjectPath, s));
#endif
if (_wcsicmp(ObjectPath,
s) == 0)
{
hr = CreateSettingForTestInst(WdmTest,
ppObj,
i,
j,
pCtx);
break;
}
}
}
} else if (_wcsicmp(ClassName, WdmTest->GetCdmTestForSoftwareClassName()) == 0) {
//
// We do not support this
//
} else if (_wcsicmp(ClassName, WdmTest->GetCdmTestInPackageClassName()) == 0) {
//
// We do not support packages
//
} else if (_wcsicmp(ClassName, WdmTest->GetCdmResultInPackageClassName()) == 0) {
//
// We do not support packages
//
}
}
return(hr);
}
/************************************************************************
* *
*CMethodPro::ExecMethodAsync *
* *
*Purpose: This is the Async function implementation. *
* The only method supported in this sample is named Echo. It *
* takes an input string, copies it to the output and returns the*
* length. *
* *
* *
************************************************************************/
STDMETHODIMP CClassPro::ExecMethodAsync(
const BSTR ObjectPath,
const BSTR MethodName,
long lFlags,
IWbemContext* pCtx,
IWbemClassObject* pInParams,
IWbemObjectSink* pResultSink
)
{
HRESULT hr, hrDontCare;
IWbemClassObject * pMethodClass = NULL;
IWbemClassObject * pOutClass = NULL;
IWbemClassObject* pOutParams = NULL;
WCHAR ClassName[MAX_PATH];
WCHAR *p;
VARIANT v, vRetVal;
int RelPathIndex;
CTestServices *WdmTest;
BSTR ExecutionID;
VariantInit(&v);
VariantInit(&vRetVal);
//
// Extract this class name from the object path
//
wcscpy(ClassName, ObjectPath);
p = ClassName;
while ((*p != 0) && (*p != L'.'))
{
p++;
}
*p = 0;
WmipDebugPrint(("CDMPROV: Exec method %ws for instanec %ws\n",
MethodName, ObjectPath));
//
// Obtain a test services object that represents this class
//
hr = LookupTestServices(ClassName,
&WdmTest);
if (hr != WBEM_S_NO_ERROR)
{
pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(WBEM_S_NO_ERROR);
}
//
// Get the input parameter SystemElement which is the Cim Relative
// Path
//
hr = WmiGetProperty(pInParams,
L"SystemElement",
CIM_REFERENCE,
&v);
if (hr != WBEM_S_NO_ERROR)
{
pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(WBEM_S_NO_ERROR);
}
//
// Find the relpath index that matches the Cim Path
//
hr = WdmTest->GetRelPathIndex(v.bstrVal,
&RelPathIndex);
VariantClear(&v);
if (hr != WBEM_S_NO_ERROR)
{
pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(WBEM_S_NO_ERROR);
}
//
// Get our class object for the method so we can set the output
// parameters
//
hr = m_pCdmServices->GetObject(ClassName, 0, pCtx, &pMethodClass, NULL);
if (hr != S_OK)
{
pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(WBEM_S_NO_ERROR);
}
//
// These methods returns values, and so create an instance of the
// output argument class.
hr = pMethodClass->GetMethod(MethodName, 0, NULL, &pOutClass);
if (hr != S_OK)
{
pMethodClass->Release();
pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(WBEM_S_NO_ERROR);
}
hr = pOutClass->SpawnInstance(0, &pOutParams);
pOutClass->Release();
pMethodClass->Release();
if (hr != WBEM_S_NO_ERROR)
{
pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
return(WBEM_S_NO_ERROR);
}
//
// See what method we are being called on and deal with it
//
if (_wcsicmp(MethodName, L"RunTest") == 0)
{
//
// Run test
//
// uint16 RunTest([IN] CIM_ManagedSystemElement ref SystemElement,
// [IN] DiagnosticSetting ref Setting,
// [OUT] CIM_DiagnosticResult ref Result);
//
IWbemClassObject *pCdmSettings;
IWbemClassObject *pCdmResult;
ULONG Result;
VARIANT vSettingRelPath;
VARIANT vResult;
//
// Get the settings for the test by first getting the
// relpath for them and then getting the actual object
//
hr = WmiGetProperty(pInParams,
L"Setting",
CIM_REFERENCE,
&vSettingRelPath);
if (hr == WBEM_S_NO_ERROR)
{
if (vSettingRelPath.vt != VT_NULL)
{
hr = m_pCdmServices->GetObject(vSettingRelPath.bstrVal,
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
&pCdmSettings,
NULL);
} else {
pCdmSettings = NULL;
}
VariantClear(&vSettingRelPath);
if (hr == WBEM_S_NO_ERROR)
{
//
// Create an empty instance of the results
// class which will get filled in when the test
// is run
//
hr = CreateInst(m_pCdmServices,
&pCdmResult,
WdmTest->GetCdmResultClassName(),
NULL);
if (hr == WBEM_S_NO_ERROR)
{
//
// Setup the test starting time
//
v.vt = VT_BSTR;
v.bstrVal = GetCurrentDateTime();
hr = WmiSetProperty(pCdmResult,
L"TestStartTime",
&v);
VariantClear(&v);
if (hr == WBEM_S_NO_ERROR)
{
//
// Go and get the Wdm test run and the
// results copied back into our cdm class
//
hr = WdmTest->ExecuteWdmTest(pCdmSettings,
pCdmResult,
RelPathIndex,
&Result,
&ExecutionID);
if (hr == WBEM_S_NO_ERROR)
{
//
// Fill in any additional properties
// for the result object
//
hr = WdmTest->FillInCdmResult(pCdmResult,
pCdmSettings,
RelPathIndex,
ExecutionID);
if (hr == WBEM_S_NO_ERROR)
{
//
// return result as an output pointer
//
hr = WmiGetProperty(pCdmResult,
L"__RelPath",
CIM_STRING,
&vResult);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiSetProperty(pOutParams,
L"Result",
&vResult);
if (hr == WBEM_S_NO_ERROR)
{
// @@BEGIN_DDKSPLIT
// We'll do this when we support reboot diags and
// keeping results after reboot
#if 0
//
// Persist the result
// object into the schema
// for later access
//
hr = WdmTest->PersistResultInSchema(pCdmResult,
ExecutionID,
RelPathIndex);
#endif
// @@END_DDKSPLIT
if (hr == WBEM_S_NO_ERROR)
{
//
// Include the relpath
// to the result
// object to our
// internal list
hr = WdmTest->AddResultToList(pCdmResult,
ExecutionID,
RelPathIndex
);
if (hr == WBEM_S_NO_ERROR)
{
//
// Setup a return value of success
//
vRetVal.vt = VT_I4;
vRetVal.lVal = Result;
}
}
}
VariantClear(&vResult);
}
}
SysFreeString(ExecutionID);
}
}
pCdmResult->Release();
}
if (pCdmSettings != NULL)
{
pCdmSettings->Release();
}
}
}
} else if (_wcsicmp(MethodName, L"ClearResults") == 0) {
//
// Clear the results for the test
//
// uint32 ClearResults([IN] CIM_ManagedSystemElement ref SystemElement,
// [OUT] String ResultsNotCleared[]);
//
VARIANT vResultsNotCleared;
//
// Clear all results for this test
//
WdmTest->ClearResultsList(RelPathIndex);
//
// Setup the output parameter
//
VariantInit(&vResultsNotCleared);
vResultsNotCleared.vt = VT_BSTR;
vResultsNotCleared.bstrVal = NULL;
WmiSetProperty(pOutParams,
L"ResultsNotCleared",
&vResultsNotCleared);
VariantClear(&vResultsNotCleared);
//
// Setup a return value of success
//
vRetVal.vt = VT_I4;
vRetVal.ulVal = 0;
} else if (_wcsicmp(MethodName, L"DiscontinueTest") == 0) {
//
// Discontinue a test in progress.
//
// uint32 DiscontinueTest([IN] CIM_ManagedSystemElement ref SystemElement,
// [IN] CIM_DiagnosticResult ref Result,
// [OUT] Boolean TestingStopped);
//
BOOLEAN TestingStopped;
ULONG Result;
VARIANT vTestingStopped;
hr = WdmTest->StopWdmTest(RelPathIndex,
&Result,
&TestingStopped);
//
// Setup the output parameter
//
if (hr == WBEM_S_NO_ERROR)
{
VariantInit(&vTestingStopped);
vTestingStopped.vt = VT_BOOL;
vTestingStopped.boolVal = TestingStopped ? VARIANT_TRUE :
VARIANT_FALSE;
WmiSetProperty(pOutParams,
L"TestingStopped",
&vTestingStopped);
VariantClear(&vTestingStopped);
//
// Setup a return value of result
//
vRetVal.vt = VT_I4;
vRetVal.ulVal = Result;
}
} else {
hr = WBEM_E_INVALID_PARAMETER;
}
if (hr == WBEM_S_NO_ERROR)
{
//
// Establish the return value for the method call
//
WmiSetProperty(pOutParams,
L"ReturnValue",
&vRetVal);
VariantClear(&vRetVal);
// Send the output object back to the client via the sink. Then
// release the pointers and free the strings.
hr = pResultSink->Indicate(1, &pOutParams);
}
pOutParams->Release();
pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL,NULL);
return(hr);
}
SCODE CClassPro::PutClassAsync(
/* [in] */ IWbemClassObject __RPC_FAR *pObject,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{
return(WBEM_E_NOT_SUPPORTED);
}
SCODE CClassPro::DeleteClassAsync(
/* [in] */ const BSTR Class,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{
return(WBEM_E_NOT_SUPPORTED);
}
SCODE CClassPro::PutInstanceAsync(
/* [in] */ IWbemClassObject __RPC_FAR *pInst,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{
return(WBEM_E_NOT_SUPPORTED);
}
SCODE CClassPro::DeleteInstanceAsync(
/* [in] */ const BSTR ObjectPath,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{
return(WBEM_E_NOT_SUPPORTED);
}
CTestServices *CClassPro::FindExistingTestServices(
PWCHAR CdmClassName
)
{
CTestServices *WdmTest;
//
// This routine assumes any sync mechanism has been done outside of
// this routine
//
WdmTest = WdmTestHead;
while (WdmTest != NULL)
{
if (WdmTest->ClaimCdmClassName(CdmClassName))
{
//
// We found an existing test services for this class
//
return(WdmTest);
}
WdmTest = WdmTest->GetNext();
}
return(NULL);
}
HRESULT CClassPro::LookupTestServices(
const BSTR CdmClassName,
CTestServices **TestServices
)
{
HRESULT hr;
CTestServices *WdmTest, *OtherWdmTest;
WmipAssert(CdmClassName != NULL);
WmipAssert(TestServices != NULL);
//
// Look up the class name and find the Wdm Test Services
// class that represents it.
//
EnterCdmCritSection();
WdmTest = FindExistingTestServices(CdmClassName);
LeaveCdmCritSection();
if (WdmTest != NULL)
{
*TestServices = WdmTest;
return(WBEM_S_NO_ERROR);
}
//
// If the WDM test services has not yet been initialized for this
// CDM diagnostic classes then go ahead and do so
//
WdmTest = new CTestServices();
hr = WdmTest->InitializeCdmClasses(CdmClassName);
if (hr == WBEM_S_NO_ERROR)
{
//
// Now check to see if another thread created and inserted the
// test services for the class while we were trying to
// initialize it. Since we want only one test services we throw
// ours away and use the other
//
EnterCdmCritSection();
OtherWdmTest = FindExistingTestServices(CdmClassName);
if (OtherWdmTest == NULL)
{
//
// Horray, we win do insert our own test into list
//
WdmTest->InsertSelf(&WdmTestHead);
LeaveCdmCritSection();
} else {
//
// We lost, so use existing test services
//
WmipDebugPrint(("CDMPROV: WdmTest %p lost insertion race to %p\n",
WdmTest, OtherWdmTest));
LeaveCdmCritSection();
delete WdmTest;
WdmTest = OtherWdmTest;
}
*TestServices = WdmTest;
WmipDebugPrint(("CDMPROV: Inited WdmTest %p for %ws\n",
WdmTest, CdmClassName));
} else {
WmipDebugPrint(("CDMPROV: Inited failed %x for %p for %ws\n",
hr, WdmTest, CdmClassName));
delete WdmTest;
}
return(hr);
}
HRESULT CClassPro::CreateTestInst(
CTestServices *WdmTest,
IWbemClassObject **pCdmTest,
IWbemContext *pCtx
)
{
HRESULT hr;
VARIANT v;
//
// We create 1 instance of the CIM_DiagnosticTest class
// regardless of the number of devices that support this class.
// Note that for the CDM proeprties of the test we arbitrarily
// pick the first device and get its WDM properties.
//
hr = CreateInst(m_pCdmServices,
pCdmTest,
WdmTest->GetCdmTestClassName(),
pCtx);
if (hr == WBEM_S_NO_ERROR)
{
//
// Get WDM properties from WDM
//
hr = WdmTest->QueryWdmTest(*pCdmTest,
0);
if (hr == WBEM_S_NO_ERROR)
{
//
// Set UM provider properties here. These are Name
//
VariantInit(&v);
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(WdmTest->GetCdmTestClassName());
hr = (*pCdmTest)->Put(L"Name", 0, &v, 0);
if (hr != WBEM_S_NO_ERROR)
{
(*pCdmTest)->Release();
}
VariantClear(&v);
} else {
(*pCdmTest)->Release();
}
}
return(hr);
}
HRESULT CClassPro::CreateResultForMSEInst(
CTestServices *WdmTest,
IWbemClassObject **pCdmResultForMSE,
int RelPathIndex,
IWbemClassObject *pCdmResult,
IWbemContext *pCtx
)
{
HRESULT hr;
PWCHAR PropertyNames[2];
VARIANT PropertyValues[2];
hr = CreateInst(m_pCdmServices,
pCdmResultForMSE,
WdmTest->GetCdmResultForMSEClassName(),
pCtx);
if (hr == WBEM_S_NO_ERROR)
{
//
// Result is a reference to the CIM_Diagnostic result class
//
hr = WmiGetProperty(pCdmResult,
L"__RelPath",
CIM_REFERENCE,
&PropertyValues[0]);
PropertyNames[0] = L"Result";
if (hr == WBEM_S_NO_ERROR)
{
//
// SystemElement is a reference to the CIM class (MSE)
//
PropertyNames[1] = L"SystemElement";
PropertyValues[1].vt = VT_BSTR;
PropertyValues[1].bstrVal = WdmTest->GetCimRelPath(RelPathIndex);
hr = WmiSetPropertyList(*pCdmResultForMSE,
2,
PropertyNames,
PropertyValues);
if (hr != WBEM_S_NO_ERROR)
{
(*pCdmResultForMSE)->Release();
}
VariantClear(&PropertyValues[0]);
} else {
(*pCdmResultForMSE)->Release();
}
} else {
hr = WBEM_E_NOT_FOUND;
(*pCdmResultForMSE)->Release();
}
return(hr);
}
HRESULT CClassPro::CreateResultForTestInst(
CTestServices *WdmTest,
IWbemClassObject **pCdmResultForTest,
IWbemClassObject *pCdmResult,
IWbemContext *pCtx
)
{
PWCHAR PropertyNames[2];
VARIANT PropertyValues[2];
HRESULT hr;
//
// Set the DiagnosticTest property which is the relpath to
// this test
//
PropertyNames[0] = L"DiagnosticTest";
PropertyValues[0].vt = VT_BSTR;
PropertyValues[0].bstrVal = WdmTest->GetCdmTestRelPath();
hr = WmiGetProperty(pCdmResult,
L"__RelPath",
CIM_REFERENCE,
&PropertyValues[1]);
PropertyNames[1] = L"DiagnosticResult";
if (hr == WBEM_S_NO_ERROR)
{
//
// for each instance of this test we create a ResultForTest
// association instance and then set the properties within
// it to the appropriate values and relpaths
hr = CreateInst(m_pCdmServices,
pCdmResultForTest,
WdmTest->GetCdmResultForTestClassName(),
pCtx);
if (hr == WBEM_S_NO_ERROR)
{
hr = WmiSetPropertyList((*pCdmResultForTest),
2,
PropertyNames,
PropertyValues);
if (hr != WBEM_S_NO_ERROR)
{
(*pCdmResultForTest)->Release();
}
}
VariantClear(&PropertyValues[1]);
}
return(hr);
}
HRESULT CClassPro::CreateTestForMSEInst(
CTestServices *WdmTest,
IWbemClassObject **pCdmTestForMSE,
int RelPathIndex,
IWbemContext *pCtx
)
{
HRESULT hr;
PWCHAR PropertyNames[8];
VARIANT PropertyValues[8];
hr = CreateInst(m_pCdmServices,
pCdmTestForMSE,
WdmTest->GetCdmTestForMSEClassName(),
pCtx);
if (hr == WBEM_S_NO_ERROR)
{
//
// Set the antecedent property which is the relpath to
// the DiagTest
//
PropertyNames[0] = L"Antecedent";
PropertyValues[0].vt = VT_BSTR;
PropertyValues[0].bstrVal = WdmTest->GetCdmTestRelPath();
//
// Set the dependent property which is the relpath to
// this MSE
//
PropertyNames[1] = L"Dependent";
PropertyValues[1].vt = VT_BSTR;
PropertyValues[1].bstrVal = WdmTest->GetCimRelPath(RelPathIndex);
//
// Set the estimated time of performing which is
// obtained from querying the test itself
//
PropertyNames[2] = L"EstimatedTimeOfPerforming";
PropertyValues[2].vt = VT_I4;
PropertyValues[2].lVal = WdmTest->GetTestEstimatedTime(RelPathIndex);
//
// Set IsExclusiveForMSE which is obtained from
// querying the test itself
//
PropertyNames[3] = L"IsExclusiveForMSE";
PropertyValues[3].vt = VT_BOOL;
PropertyValues[3].boolVal = WdmTest->GetTestIsExclusiveForMSE(RelPathIndex) ?
VARIANT_TRUE :
VARIANT_FALSE;
//
// Not sure what this is for
//
PropertyNames[4] = L"MessageLine";
PropertyValues[4].vt = VT_BSTR;
PropertyValues[4].bstrVal = NULL;
//
// Not sure what this is for
//
PropertyNames[5] = L"ReturnMessage";
PropertyValues[5].vt = VT_BSTR;
PropertyValues[5].bstrVal = NULL;
//
// Not sure what this is for
//
PropertyNames[6] = L"Prompt";
PropertyValues[6].vt = VT_I4;
PropertyValues[6].lVal = 0;
//
// Not sure what this is for
//
PropertyNames[7] = L"RequestedLanguage";
PropertyValues[7].vt = VT_I4;
PropertyValues[7].lVal = 0;
hr = WmiSetPropertyList(*pCdmTestForMSE,
8,
PropertyNames,
PropertyValues);
if (hr != WBEM_S_NO_ERROR)
{
(*pCdmTestForMSE)->Release();
}
}
return(hr);
}
HRESULT CClassPro::CreateSettingForTestInst(
CTestServices *WdmTest,
IWbemClassObject **pCdmSettingForTest,
int RelPathIndex,
ULONG SettingIndex,
IWbemContext *pCtx
)
{
HRESULT hr;
PWCHAR PropertyNames[2];
VARIANT PropertyValues[2];
hr = CreateInst(m_pCdmServices,
pCdmSettingForTest,
WdmTest->GetCdmSettingForTestClassName(),
pCtx);
if (hr == WBEM_S_NO_ERROR)
{
//
// Set the e;lement property which is the relpath to
// the Diagn
//
PropertyNames[0] = L"Element";
PropertyValues[0].vt = VT_BSTR;
PropertyValues[0].bstrVal = WdmTest->GetCdmTestRelPath();
//
// Set the setting property which is the relpath to
// this setting
//
PropertyNames[1] = L"Setting";
PropertyValues[1].vt = VT_BSTR;
PropertyValues[1].bstrVal = WdmTest->GetCdmSettingRelPath(RelPathIndex,
SettingIndex);
hr = WmiSetPropertyList(*pCdmSettingForTest,
2,
PropertyNames,
PropertyValues);
if (hr != WBEM_S_NO_ERROR)
{
(*pCdmSettingForTest)->Release();
}
}
return(hr);
}