//*************************************************************************** // // 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 #include "sample.h" #include #include #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); }