1166 lines
35 KiB
C++
1166 lines
35 KiB
C++
// HistoryParser.cpp: implementation of the CHistoryParser class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "resource.h"
|
|
#include "HistoryParser.h"
|
|
#include "Filestuff.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
|
|
|
|
extern CMSInfoHistoryCategory catHistorySystemSummary;
|
|
extern CMSInfoHistoryCategory catHistoryResources;
|
|
extern CMSInfoHistoryCategory catHistoryComponents;
|
|
extern CMSInfoHistoryCategory catHistorySWEnv;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CHistoryParser::CHistoryParser(CComPtr<IXMLDOMDocument> pDoc) : m_pDoc(pDoc)
|
|
{
|
|
|
|
}
|
|
|
|
void CHistoryParser::DeleteAllInstances()
|
|
{
|
|
for(POSITION pos = this->m_listInstances.GetHeadPosition();pos;)
|
|
{
|
|
if (!pos)
|
|
{
|
|
return;
|
|
}
|
|
CInstance* pInci = (CInstance*) m_listInstances.GetNext(pos);
|
|
delete pInci;
|
|
}
|
|
m_listInstances.RemoveAll();
|
|
}
|
|
|
|
CHistoryParser::~CHistoryParser()
|
|
{
|
|
DeleteAllInstances();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
// takes a CTime, which comes from timestamp element of the Delta or Snaphot
|
|
// node of which pInstanceNode is a child; an Instance node, and a string
|
|
// containing the WMI class of the Instance
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CInstance::CInstance(CTime tmstmp, CComPtr<IXMLDOMNode> pInstanceNode,CString strClass) : m_tmstamp(tmstmp), m_strClassName(strClass)
|
|
{
|
|
CComPtr<IXMLDOMNodeList> pPropList;
|
|
HRESULT hr;
|
|
//Get node data, add each PROPERTY name and VALUE to m_mapNameValue
|
|
if (strClass.CompareNoCase(_T("Win32_PNPAllocatedResource")) == 0)
|
|
{
|
|
hr = ProcessPNPAllocatedResource(pInstanceNode);
|
|
ASSERT(SUCCEEDED(hr) && "failed to process Win32_PNPAllocatedResource");
|
|
return;
|
|
}
|
|
hr = pInstanceNode->selectNodes(CComBSTR("PROPERTY"),&pPropList);
|
|
if (FAILED(hr) || !pPropList)
|
|
{
|
|
ASSERT(0 && "could not get property list from Instance node");
|
|
return;
|
|
}
|
|
long lListLen;
|
|
hr = pPropList->get_length(&lListLen);
|
|
CComPtr<IXMLDOMNode> pVNode;
|
|
CComBSTR bstrValue;
|
|
CComVariant varName;
|
|
for(long i = 0; i < lListLen; i++)
|
|
{
|
|
hr = pPropList->nextNode(&pVNode);
|
|
if (FAILED(hr) || !pVNode)
|
|
{
|
|
return;
|
|
}
|
|
CComPtr<IXMLDOMElement> pElement;
|
|
hr = pVNode->QueryInterface(IID_IXMLDOMElement,(void**) &pElement);
|
|
if (FAILED(hr) || !pElement)
|
|
{
|
|
return;
|
|
}
|
|
hr = pElement->getAttribute(L"NAME",&varName);
|
|
ASSERT(SUCCEEDED(hr));
|
|
hr = pVNode->get_text(&bstrValue);
|
|
ASSERT(SUCCEEDED(hr));
|
|
USES_CONVERSION;
|
|
m_mapNameValue.SetAt(OLE2T(varName.bstrVal) ,OLE2T(bstrValue));
|
|
pVNode.Release();
|
|
}
|
|
pPropList.Release();
|
|
return;
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//Refresh is called for selected category when category selection or delta range changes
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CHistoryParser::Refresh(CMSInfoHistoryCategory* pHistCat,int nDeltasBack)
|
|
{
|
|
nDeltasBack++;
|
|
this->m_fChangeLines = FALSE;// v-stlowe 2/28/2001
|
|
DeleteAllInstances();
|
|
m_pHistCat = pHistCat;
|
|
CComPtr<IXMLDOMNodeList> pDeltaList;
|
|
HRESULT hr;
|
|
hr = this->GetDeltaAndSnapshotNodes(pDeltaList);
|
|
if (FAILED(hr) || !pDeltaList)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (pHistCat == &catHistoryComponents)
|
|
{
|
|
DeleteAllInstances();
|
|
|
|
hr = ProcessDeltas(pDeltaList,"Win32_DriverVXD",nDeltasBack);
|
|
ASSERT(SUCCEEDED(hr));
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
hr = ProcessDeltas(pDeltaList,"Win32_CodecFile",nDeltasBack);
|
|
ASSERT(SUCCEEDED(hr));
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
hr = ProcessDeltas(pDeltaList,"Win32_LogicalDisk",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
hr = ProcessDeltas(pDeltaList,"Win32_NetworkProtocol",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
hr = ProcessDeltas(pDeltaList,"Win32_Printer",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
hr = ProcessDeltas(pDeltaList,"Win32_PortResource",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
hr = ProcessDeltas(pDeltaList,"Win32_PnPEntity",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
else if (pHistCat == &catHistorySystemSummary)
|
|
{
|
|
DeleteAllInstances();
|
|
hr = ProcessDeltas(pDeltaList,"Win32_ComputerSystem",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
hr = ProcessDeltas(pDeltaList,"Win32_OperatingSystem",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
//hr = ProcessDeltas(pDeltaList,"Win32_Win32_LogicalMemoryConfiguration",nDeltasBack);
|
|
hr = ProcessDeltas(pDeltaList,"Win32_LogicalMemoryConfiguration",nDeltasBack); //v-stlowe 2/28/2001
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
else if(pHistCat == &catHistoryResources)
|
|
{
|
|
DeleteAllInstances();
|
|
hr = ProcessDeltas(pDeltaList,"Win32_PNPAllocatedResource",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
else if (pHistCat == &catHistorySWEnv)
|
|
{
|
|
DeleteAllInstances();
|
|
hr = ProcessDeltas(pDeltaList,"Win32_ProgramGroup",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
hr = ProcessDeltas(pDeltaList,"Win32_StartupCommand",nDeltasBack);
|
|
DeleteAllInstances();
|
|
pDeltaList->reset();
|
|
|
|
}
|
|
if (!m_fChangeLines)
|
|
{
|
|
#ifdef A_STEPHL2
|
|
::MessageBox(NULL,"!m_fChangeLines)","",MB_OK);
|
|
#endif
|
|
m_fChangeLines = TRUE;
|
|
CString strMSG;
|
|
strMSG.LoadString(IDS_DELTANOCHANGES);//this would be the place to change messaging for situation where summary has no changes
|
|
m_pHistCat->InsertLine(-1, strMSG, _T(""), _T(""), _T(""));
|
|
}
|
|
pDeltaList.Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//Gets the value appropriate to use as a description for the class
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
CString CInstance::GetInstanceDescription()
|
|
{
|
|
CString strDescName = GetDescriptionForClass(m_strClassName);
|
|
CString strInstDesc;
|
|
VERIFY(m_mapNameValue.Lookup(strDescName,strInstDesc));
|
|
return strInstDesc;
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//Gets the value that can be used to uniquely identify a specific instance of a class
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
CString CInstance::GetInstanceID()
|
|
{
|
|
CString strIDName = GetIDForClass(m_strClassName);
|
|
CString strInstID;
|
|
VERIFY(m_mapNameValue.Lookup(strIDName,strInstID));
|
|
return strInstID;
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//used to deal with antecedent\dependant relationship classes in Win32_PNPAllocatedResource classes
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CInstance::ProcessPropertyDotReferenceNodes(CComPtr<IXMLDOMNode> pInstanceNameNode,CString* pstrClassName, CString* pstrKeyName,CString* pstrKeyValue)
|
|
{
|
|
USES_CONVERSION;
|
|
HRESULT hr;
|
|
CComPtr<IXMLDOMElement> pNameElement;
|
|
hr = pInstanceNameNode->QueryInterface(IID_IXMLDOMElement,(void**) &pNameElement);
|
|
if (FAILED(hr) | !pNameElement)
|
|
{
|
|
ASSERT(0 && "could not QI pNode for Element");
|
|
return E_FAIL;
|
|
}
|
|
CComVariant varClassName;
|
|
hr = pNameElement->getAttribute(L"CLASSNAME",&varClassName);
|
|
pNameElement.Release();
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(0 && "could not get CLASSNAME element");
|
|
}
|
|
*pstrClassName = OLE2T(varClassName.bstrVal);
|
|
CComPtr<IXMLDOMNode> pKeybindingNode;
|
|
hr = pInstanceNameNode->selectSingleNode(CComBSTR("KEYBINDING"),&pKeybindingNode);
|
|
if (FAILED(hr) || !pKeybindingNode)
|
|
{
|
|
ASSERT(0 && "could not get antecedent node");
|
|
}
|
|
CComBSTR bstrKeyValue;
|
|
hr = pKeybindingNode->get_text(&bstrKeyValue);
|
|
ASSERT(SUCCEEDED(hr) && "failed to get keybinding value");
|
|
*pstrKeyValue = OLE2T(bstrKeyValue);
|
|
hr = pKeybindingNode->QueryInterface(IID_IXMLDOMElement,(void**) &pNameElement);
|
|
if (FAILED(hr) | !pNameElement)
|
|
{
|
|
ASSERT(0 && "could not QI pNode for Element");
|
|
return E_FAIL;
|
|
}
|
|
CComVariant varKeybindingName;
|
|
hr = pNameElement->getAttribute(CComBSTR("NAME"),&varKeybindingName);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(0 && "could not get NAME attribute from pNameElement");
|
|
}
|
|
|
|
*pstrKeyName = OLE2T(varKeybindingName.bstrVal);
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//used to deal with antecedent\dependant relationship classes in Win32_PNPAllocatedResource classes
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CInstance::ProcessPNPAllocatedResource(CComPtr<IXMLDOMNode> pInstanceNode)
|
|
{
|
|
|
|
HRESULT hr;
|
|
CComPtr<IXMLDOMNodeList> pPropDotRefList;
|
|
hr = pInstanceNode->selectNodes(CComBSTR("PROPERTY.REFERENCE/VALUE.REFERENCE/INSTANCEPATH/INSTANCENAME"),&pPropDotRefList);
|
|
if (FAILED(hr) || !pPropDotRefList)
|
|
{
|
|
ASSERT(0 && "PROPERTY.REFERENCE nodes not found");
|
|
return E_FAIL;
|
|
}
|
|
|
|
//get antecedent node
|
|
CComPtr<IXMLDOMNode> pInstanceNameNode;
|
|
hr = pPropDotRefList->nextNode(&pInstanceNameNode);
|
|
if (FAILED(hr) || !pInstanceNameNode)
|
|
{
|
|
ASSERT(0 && "could not get antecedent node");
|
|
}
|
|
CString strAntecedentName,strResourceName,strResourceValue;
|
|
hr = ProcessPropertyDotReferenceNodes(pInstanceNameNode,&strAntecedentName,&strResourceName,&strResourceValue);
|
|
m_mapNameValue.SetAt(_T("ANTECEDENT"),strAntecedentName);
|
|
m_mapNameValue.SetAt(strResourceName,strResourceValue);
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
CString strPNPEntity,strKeyname,strDeviceIDval;
|
|
pInstanceNameNode.Release();
|
|
hr = pPropDotRefList->nextNode(&pInstanceNameNode);
|
|
if (FAILED(hr) || !pInstanceNameNode)
|
|
{
|
|
return hr;
|
|
}
|
|
hr = ProcessPropertyDotReferenceNodes(pInstanceNameNode,&strPNPEntity,&strKeyname,&strDeviceIDval);
|
|
CComPtr<IXMLDOMDocument> pDoc;
|
|
hr = pInstanceNode->get_ownerDocument(&pDoc);
|
|
if (FAILED(hr) || !pDoc)
|
|
{
|
|
ASSERT(0 && "could not get owner doc from pInstanceNode");
|
|
return E_FAIL;
|
|
}
|
|
CString strPNPDeviceName = GetPNPNameByID(pDoc,CComBSTR(strDeviceIDval));
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
ASSERT(strPNPEntity.CompareNoCase("Win32_PnPEntity") == 0 && "unexpected value for Dependent classname");
|
|
ASSERT(strKeyname.CompareNoCase("DeviceID") == 0 && "unexpected value for Dependent Keybinding name");
|
|
//we will create an arificial attribute "ASSOCNAME", which will be used to identify this device.
|
|
m_mapNameValue.SetAt(_T("ASSOCNAME"),strAntecedentName + ":" + strDeviceIDval);
|
|
m_mapNameValue.SetAt(_T("DeviceID"),strDeviceIDval);
|
|
m_mapNameValue.SetAt(_T("DeviceName"),strPNPDeviceName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//Retrives a value used to select appropriate description value for the class
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
CString CInstance::GetDescriptionForClass(CString strClass)
|
|
{
|
|
//lookup a key which can uniquely identify an instance of a given class
|
|
//for example, DeviceID for Printers
|
|
if (strClass.CompareNoCase(_T("Win32_LogicalDisk")) == 0)
|
|
{
|
|
return "DeviceID";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_CodecFile")) == 0)
|
|
{
|
|
return "Description";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_ComputerSystem")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_OperatingSystem")) == 0)
|
|
{
|
|
return "Caption";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_LogicalMemoryConfiguration")) == 0)
|
|
{
|
|
return "TotalPhysicalMemory";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_PortResource")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_NetworkProtocol")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_Printer")) == 0)
|
|
{
|
|
return "DeviceID";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_PnPEntity")) == 0)
|
|
{
|
|
return "Description";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_StartupCommand")) == 0)
|
|
{
|
|
return "Command";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_ProgramGroup")) == 0)
|
|
{
|
|
return "GroupName";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_PNPAllocatedResource")) == 0)
|
|
{
|
|
//this is an artificial string created in CInstance::ProcessPNPAllocatedResource
|
|
return "DeviceName";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_DriverVXD")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//used to determine which mapped value to use to ID instances of the clas
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
CString CInstance::GetIDForClass(CString strClass)
|
|
{
|
|
//lookup a key which can uniquely identify an instance of a given class
|
|
//for example, DeviceID for Printers
|
|
if (strClass.CompareNoCase(_T("Win32_LogicalDisk")) == 0)
|
|
{
|
|
return "DeviceID";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_CodecFile")) == 0)
|
|
{
|
|
return "Description";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_OperatingSystem")) == 0)
|
|
{
|
|
return "Caption";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_LogicalMemoryConfiguration")) == 0)
|
|
{
|
|
return "TotalPhysicalMemory";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_ComputerSystem")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_PortResource")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_NetworkProtocol")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_Printer")) == 0)
|
|
{
|
|
return "DeviceID";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_PnPEntity")) == 0)
|
|
{
|
|
return "DeviceID";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_PNPAllocatedResource")) == 0)
|
|
{
|
|
//this is an artificial string created in CInstance::ProcessPNPAllocatedResource
|
|
return "ASSOCNAME";
|
|
}
|
|
|
|
if (strClass.CompareNoCase(_T("Win32_ProgramGroup")) == 0)
|
|
{
|
|
return "GroupName";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_StartupCommand")) == 0)
|
|
{
|
|
return "Command";
|
|
}
|
|
if (strClass.CompareNoCase(_T("Win32_DriverVXD")) == 0)
|
|
{
|
|
return "Name";
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//used when rolling back through history list, to find previous instance of a given class
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
CInstance* CHistoryParser::FindPreviousInstance(CInstance* pNewInstance)
|
|
{
|
|
//for each existing instance pOld
|
|
for(POSITION pos = m_listInstances.GetHeadPosition( );;)
|
|
{
|
|
if (!pos)
|
|
{
|
|
return NULL;
|
|
}
|
|
CInstance* pOld = (CInstance*) m_listInstances.GetNext(pos);
|
|
if (pOld->GetClassName() == pNewInstance->GetClassName())
|
|
{
|
|
if (pOld->GetInstanceID() == pNewInstance->GetInstanceID())
|
|
{
|
|
return pOld;
|
|
}
|
|
}
|
|
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void CHistoryParser::CreateChangeStrings(CInstance* pOld, CInstance* pNew)
|
|
{
|
|
CTimeSpan tmsDelta;
|
|
COleDateTime olTime(pNew->m_tmstamp.GetTime());
|
|
if (!pOld )
|
|
{
|
|
ASSERT(pNew );
|
|
tmsDelta = CTime::GetCurrentTime() - pNew->m_tmstamp;
|
|
//change string should be "Delete"
|
|
m_pHistCat->InsertRemoveLine(pNew->m_tmstamp ,pNew->GetClassFriendlyName(),pNew->GetInstanceDescription());
|
|
|
|
m_fChangeLines = TRUE;
|
|
return;
|
|
}
|
|
else if (!pNew)
|
|
{
|
|
ASSERT(pOld);
|
|
tmsDelta = CTime::GetCurrentTime() - pOld->m_tmstamp;
|
|
//change string should be "New"
|
|
m_pHistCat->InsertAddLine(pNew->m_tmstamp,pOld->GetClassFriendlyName(),pOld->GetInstanceDescription());
|
|
//v-stlowe 3/12/2001
|
|
m_fChangeLines = TRUE;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
|
|
ASSERT(pOld && pNew && "both pointers can't be null");
|
|
tmsDelta = CTime::GetCurrentTime() - pNew->m_tmstamp;
|
|
//for each Name&Value pair, get the name, and then use it to examine
|
|
//the associated value in pCompare's map
|
|
CString strName, strValue,strCompareValue;
|
|
|
|
if (pNew->GetChangeType().CompareNoCase(_T("New")) == 0)
|
|
{
|
|
tmsDelta = CTime::GetCurrentTime() - pNew->m_tmstamp;
|
|
//change string should be "added"
|
|
m_pHistCat->InsertAddLine(pNew->m_tmstamp ,pNew->GetClassFriendlyName(),pNew->GetInstanceDescription());
|
|
m_fChangeLines = TRUE;
|
|
return;
|
|
}
|
|
else if (pNew->GetChangeType().CompareNoCase(_T("Delete")) == 0)
|
|
{
|
|
tmsDelta = CTime::GetCurrentTime() - pNew->m_tmstamp;
|
|
//change string should be "Deleted"
|
|
m_pHistCat->InsertRemoveLine(pNew->m_tmstamp,pNew->GetClassFriendlyName(),pNew->GetInstanceDescription());
|
|
m_fChangeLines = TRUE;
|
|
return;
|
|
}
|
|
|
|
for(POSITION pos = pNew->m_mapNameValue.GetStartPosition();;pNew->m_mapNameValue.GetNextAssoc(pos,strName, strValue))
|
|
{
|
|
strCompareValue = _T("");
|
|
if (!pOld->m_mapNameValue.Lookup(strName,strCompareValue))
|
|
{
|
|
//ASSERT(0 && "value not found in delta");
|
|
//return E_FAIL;
|
|
if (strName.CompareNoCase(_T("Change")) == 0)
|
|
{
|
|
VERIFY(pNew->m_mapNameValue.Lookup(strName,strCompareValue));
|
|
if (strCompareValue.CompareNoCase(_T("New")) == 0)
|
|
{
|
|
m_pHistCat->InsertAddLine(pNew->m_tmstamp,pNew->GetClassFriendlyName(),pNew->GetInstanceDescription());
|
|
m_fChangeLines = TRUE;
|
|
}
|
|
ASSERT(1);
|
|
}
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
pOld->m_mapNameValue.RemoveKey(strName);
|
|
}
|
|
|
|
if (strValue != strCompareValue)
|
|
{
|
|
|
|
m_pHistCat->InsertChangeLine(pNew->m_tmstamp,pNew->GetClassFriendlyName(),pNew->GetInstanceDescription(),strName,strValue,strCompareValue);
|
|
m_fChangeLines = TRUE;
|
|
|
|
}
|
|
if(!pos)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
//handle values that are mapOldInstance, and not the other map
|
|
if (!pOld->m_mapNameValue.IsEmpty())
|
|
{
|
|
for(pos = pOld->m_mapNameValue.GetStartPosition();;pOld->m_mapNameValue.GetNextAssoc(pos,strName, strValue))
|
|
{
|
|
pOld->m_mapNameValue.GetNextAssoc(pos,strName, strValue);
|
|
pNew->m_mapNameValue.SetAt(strName,strValue);
|
|
if (!pos)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//once the previous instance has been processed, previous instance should be removed and this instance should be added to list
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
void CHistoryParser::ResetInstance(CInstance* pOld, CInstance* pNew)
|
|
{
|
|
POSITION pos = this->m_listInstances.Find(pOld);
|
|
m_listInstances.SetAt(pos,pNew);
|
|
delete pOld;
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//Used to process a single instance from either history or snapshot
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
void CHistoryParser::ProcessInstance(CInstance* pNewInstance)
|
|
{
|
|
//see if instance is in list of instances
|
|
CInstance* pOld = FindPreviousInstance(pNewInstance);
|
|
if (pOld)
|
|
{
|
|
CreateChangeStrings(pOld,pNewInstance);
|
|
ResetInstance(pOld,pNewInstance);
|
|
}
|
|
//if this is from a Snapshot, just add it
|
|
//if it is from a Delta, it should have a change type of "add", and we
|
|
//want to create a change string for it.
|
|
else
|
|
{
|
|
CString strChange;
|
|
if (pNewInstance->GetValueFromMap(_T("Change"),strChange))
|
|
{
|
|
//we have new Delta instance
|
|
CreateChangeStrings(NULL,pNewInstance);
|
|
m_listInstances.AddTail(pNewInstance);
|
|
}
|
|
else
|
|
{
|
|
//Instance is in snapshot, so we don't generate change lines
|
|
m_listInstances.AddTail(pNewInstance);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
returns list of deltas and the snapshot node
|
|
/**************************************************************************/
|
|
HRESULT CHistoryParser::GetDeltaAndSnapshotNodes(CComPtr<IXMLDOMNodeList>& pDeltaList)
|
|
{
|
|
CComPtr<IXMLDOMNode> pDataCollNode;
|
|
HRESULT hr;
|
|
hr = GetDataCollectionNode(m_pDoc,pDataCollNode);
|
|
if (FAILED(hr) || !pDataCollNode)
|
|
{
|
|
//ASSERT(0 && "could not get datacollection node");
|
|
return E_FAIL;
|
|
}
|
|
//all nodes directly under DATACOLLECTION should be either deltas or the snapshot
|
|
hr = pDataCollNode->selectNodes(CComBSTR("*"),&pDeltaList);
|
|
if (FAILED(hr) || !pDeltaList)
|
|
{
|
|
ASSERT(0 && "could not get pDeltaList");
|
|
return E_FAIL;
|
|
}
|
|
#ifndef _DEBUG
|
|
return hr;
|
|
#endif
|
|
long ll;
|
|
hr = pDeltaList->get_length(&ll);
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//gets IXMLDOMNodeList of instances from a specific delta or snapshot node
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CHistoryParser::GetInstanceNodeList(CString strClass,CComPtr<IXMLDOMNode> pDeltaNode, CComPtr<IXMLDOMNodeList>& pInstanceList)
|
|
{
|
|
HRESULT hr;
|
|
//CComBSTR bstrQuery;
|
|
// the query will have to be in the form:
|
|
// CIM/DECLARATION/DECLGROUP.WITHPATH/VALUE.OBJECTWITHPATH/INSTANCE[@CLASSNAME $ieq$ "WIN32_CODECFILE"]
|
|
// or
|
|
// CIM/DECLARATION/DECLGROUP.WITHPATH/VALUE.OBJECTWITHPATH/INSTANCE[@CLASSNAME $ieq$ "Win32_ComputerSystem"]
|
|
// because we are querying a node, rather than a document (with which we could get
|
|
// away with specifying only INSTANCE in the query
|
|
|
|
//v-stlowe 1/29/2001 to fix Prefix whistler bug #279519
|
|
//bstrQuery += "CIM/DECLARATION/DECLGROUP.WITHPATH/VALUE.OBJECTWITHPATH/INSTANCE[@CLASSNAME $ieq$ ";
|
|
CComBSTR bstrQuery("CIM/DECLARATION/DECLGROUP.WITHPATH/VALUE.OBJECTWITHPATH/INSTANCE[@CLASSNAME $ieq$ ");
|
|
|
|
//end v-stlowe
|
|
bstrQuery += "\"";
|
|
bstrQuery += CComBSTR(strClass);
|
|
bstrQuery += "\"]";
|
|
hr = pDeltaNode->selectNodes(bstrQuery,&pInstanceList);
|
|
if (FAILED(hr) || !pInstanceList)
|
|
{
|
|
ASSERT(0 && "Could not get node list");
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(0 && "Could not get node list length");
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//for a given Snapshot or Delta node, get all instances of a given class
|
|
HRESULT CHistoryParser::ProcessDeltaNode(CComPtr<IXMLDOMNode> pDeltaNode,CString strClass)
|
|
{
|
|
CString strTime;
|
|
HRESULT hr;
|
|
int nTimeZone;
|
|
hr = GetTimeStampFromFromD_or_SNodeNode(pDeltaNode, &strTime,nTimeZone);
|
|
ASSERT(SUCCEEDED(hr) && "error getting timestamp for node");
|
|
CTime tmDelta = GetDateFromString(strTime,nTimeZone);
|
|
//TD: check for valid time range...
|
|
//get list of all nodes of given class
|
|
CComPtr<IXMLDOMNodeList> pInstanceNodeList;
|
|
hr = GetInstanceNodeList(strClass,pDeltaNode,pInstanceNodeList);
|
|
if (FAILED(hr) | ! pInstanceNodeList)
|
|
{
|
|
ASSERT(0 && "could not get instance list from Delta node");
|
|
return E_FAIL;
|
|
}
|
|
//step through list, getting each instance
|
|
long lListLen;
|
|
hr = pInstanceNodeList->get_length(&lListLen);
|
|
for(long i = 0;i < lListLen;i++)
|
|
{
|
|
CComPtr<IXMLDOMNode> pInstanceNode;
|
|
hr = pInstanceNodeList->nextNode(&pInstanceNode);
|
|
if (FAILED(hr) || ! pInstanceNode)
|
|
{
|
|
ASSERT(0 && "could not get node from instance list");
|
|
return E_FAIL;
|
|
}
|
|
CInstance * pInstance = new CInstance(tmDelta,pInstanceNode,strClass);
|
|
ProcessInstance(pInstance);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//*************************************************************************
|
|
//Takes a list of delta nodes, and the name of a class
|
|
//**************************************************************************
|
|
|
|
HRESULT CHistoryParser::ProcessDeltas(CComPtr<IXMLDOMNodeList> pDeltaList,CString strClassName,int nDeltasBack)
|
|
{
|
|
//for each node in list pNode
|
|
long lListLen;
|
|
HRESULT hr;
|
|
hr = pDeltaList->get_length(&lListLen);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(0 && "couldn't get list length");
|
|
}
|
|
if (0 == lListLen)
|
|
{
|
|
pDeltaList.Release();
|
|
return S_FALSE;
|
|
}
|
|
|
|
for (long i = 0;i < lListLen && i <= nDeltasBack;i++)
|
|
{
|
|
CComPtr<IXMLDOMNode> pNode;
|
|
hr= pDeltaList->nextNode(&pNode);
|
|
if (FAILED(hr) || !pNode)
|
|
{
|
|
ASSERT(0 && "could not get next delta node");
|
|
pDeltaList.Release();
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
// here's problem If we're using nDeltasBack method, do we need to compare dates?
|
|
/* CTime tmDelta = GetDeltaTime(pNode);
|
|
if (GetDeltaTime(pNode) >= this->m_tmBack)
|
|
{
|
|
*/
|
|
hr = ProcessDeltaNode(pNode,strClassName);
|
|
if (FAILED(hr))
|
|
{
|
|
pDeltaList.Release();
|
|
return hr;
|
|
}
|
|
// }
|
|
}
|
|
pDeltaList.Release();
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************************
|
|
//Gets the DATACOLLECTION node, beneath which both the SNAPSHOT and the DELTA nodes reside
|
|
//**************************************************************************
|
|
|
|
|
|
HRESULT GetDataCollectionNode(CComPtr<IXMLDOMDocument> pXMLDoc,CComPtr<IXMLDOMNode>& pDCNode)
|
|
{
|
|
//TD: find a way to do case-insensitive queries.
|
|
HRESULT hr;
|
|
if (!pXMLDoc)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
CComPtr<IXMLDOMNodeList> pNodeList;
|
|
|
|
//find a change property; that way we know we have a delta
|
|
hr = pXMLDoc->getElementsByTagName(CComBSTR("PROPERTY[@NAME $ieq$ \"CHANGE\"]"),&pNodeList);
|
|
if (FAILED(hr) || !pNodeList)
|
|
{
|
|
ASSERT(0 && "Could not get node list");
|
|
return E_FAIL;
|
|
}
|
|
CComPtr<IXMLDOMNode> pNode;
|
|
hr = pNodeList->nextNode(&pNode);
|
|
if (FAILED(hr) || !pNode)
|
|
{
|
|
// ASSERT(0 && "Could not get node from node list");
|
|
return E_FAIL;
|
|
}
|
|
//loop till we get a node called "DATACOLLECTION"
|
|
CComPtr<IXMLDOMNode> pParentNode;
|
|
for(int i = 0;;i++)
|
|
{
|
|
hr = pNode->get_parentNode(&pParentNode);
|
|
if (FAILED(hr) || !pParentNode)
|
|
{
|
|
ASSERT(0 && "Could not find DATACOLLECTION node");
|
|
pDCNode = NULL;
|
|
return E_FAIL;
|
|
}
|
|
pNode.Release();
|
|
CComBSTR bstrName;
|
|
pParentNode->get_nodeName(&bstrName);
|
|
USES_CONVERSION;
|
|
if (CString(bstrName).CompareNoCase(_T("DATACOLLECTION")) == 0)
|
|
{
|
|
pDCNode = pParentNode;
|
|
return S_OK;
|
|
}
|
|
pNode = pParentNode;
|
|
pParentNode.Release();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//get timestamp of a delta or snapshot node
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
CTime GetDeltaTime(CComPtr<IXMLDOMNode> pDorSNode)
|
|
{
|
|
CString strTime;
|
|
int nTimeZone;
|
|
GetTimeStampFromFromD_or_SNodeNode(pDorSNode,&strTime,nTimeZone);
|
|
return GetDateFromString(strTime,nTimeZone);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//takes string format used in XML blob, creates a CTime
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
HRESULT GetTimeStampFromFromD_or_SNodeNode(CComPtr<IXMLDOMNode> pDorSNode,CString* pString, int& nTimeZone)
|
|
{
|
|
HRESULT hr;
|
|
CComVariant varTS;
|
|
CComPtr<IXMLDOMElement> pTimestampElement;
|
|
hr = pDorSNode->QueryInterface(IID_IXMLDOMElement,(void**) &pTimestampElement);
|
|
if (FAILED(hr) || !pTimestampElement)
|
|
{
|
|
ASSERT(0 && "could not get attribute element");
|
|
}
|
|
hr = pTimestampElement->getAttribute(L"Timestamp_T0",&varTS);
|
|
if (FAILED(hr) )
|
|
{
|
|
ASSERT(0 && "could not get timestamp value from attribute");
|
|
}
|
|
if (1 == hr)
|
|
{
|
|
//this may be snapshot node...try "Timestamp"
|
|
hr = pTimestampElement->getAttribute(L"Timestamp",&varTS);
|
|
if (FAILED(hr) )
|
|
{
|
|
ASSERT(0 && "could not get timestamp value from attribute");
|
|
}
|
|
}
|
|
CComVariant varTzoneDeltaSeconds;
|
|
hr = pTimestampElement->getAttribute(L"TimeZone",&varTzoneDeltaSeconds);
|
|
if (FAILED(hr) ) //this will happen when loading WinME xml, which has no timezone info
|
|
{
|
|
varTzoneDeltaSeconds = 0;
|
|
}
|
|
//make sure we have an integer type
|
|
hr = varTzoneDeltaSeconds.ChangeType(VT_INT);
|
|
if (FAILED(hr) )
|
|
{
|
|
varTzoneDeltaSeconds = 0;
|
|
}
|
|
nTimeZone = varTzoneDeltaSeconds.intVal;
|
|
USES_CONVERSION;
|
|
pTimestampElement.Release();
|
|
*pString = OLE2T(varTS.bstrVal);
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// utility functions
|
|
//////////////////////////////////////////////////////////////////////
|
|
CTime GetDateFromString(const CString& strDate, int nTimeZone)
|
|
{
|
|
//requires linking to Shlwapi.lib
|
|
CString strDateCopy(strDate);
|
|
CString strDateSegment;
|
|
|
|
//year is the 4 leftmost digits of date string
|
|
strDateSegment = strDateCopy.Left(4);
|
|
int nYear;
|
|
VERIFY(StrToIntEx(strDateSegment,STIF_DEFAULT ,&nYear));
|
|
// ASSERT(nYear == 1999 || nYear == 2000);
|
|
strDateCopy = strDateCopy.Right(strDateCopy.GetLength() - 4);
|
|
|
|
//month is now the 2 leftmost digits of remaining date string
|
|
int nMonth;
|
|
strDateSegment = strDateCopy.Left(2);
|
|
VERIFY(StrToIntEx(strDateSegment,STIF_DEFAULT ,&nMonth));
|
|
ASSERT(nMonth >= 1 && nMonth <= 12);
|
|
strDateCopy = strDateCopy.Right(strDateCopy.GetLength() - 2);
|
|
|
|
|
|
//day is now the 2 leftmost digits of remaining date string
|
|
int nDay;
|
|
strDateSegment = strDateCopy.Left(2);
|
|
VERIFY(StrToIntEx(strDateSegment,STIF_DEFAULT ,&nDay));
|
|
ASSERT(nDay >= 1 && nDay <= 31);
|
|
strDateCopy = strDateCopy.Right(strDateCopy.GetLength() - 2);
|
|
|
|
//hour is now the 2 leftmost digits of remaining date string
|
|
int nHour;
|
|
strDateSegment = strDateCopy.Left(2);
|
|
VERIFY(StrToIntEx(strDateSegment,STIF_DEFAULT ,&nHour));
|
|
ASSERT(nHour >= 0 && nHour <= 24);
|
|
strDateCopy = strDateCopy.Right(strDateCopy.GetLength() - 2);
|
|
|
|
//Minute is now the 2 leftmost digits of remaining date string
|
|
int nMin;
|
|
strDateSegment = strDateCopy.Left(2);
|
|
VERIFY(StrToIntEx(strDateSegment,STIF_DEFAULT ,&nMin));
|
|
ASSERT(nMin >= 0 && nMin <= 59);
|
|
strDateCopy = strDateCopy.Right(strDateCopy.GetLength() - 2);
|
|
|
|
|
|
//Minute is now the 2 leftmost digits of remaining date string
|
|
int nSec;
|
|
strDateSegment = strDateCopy.Left(2);
|
|
VERIFY(StrToIntEx(strDateSegment,STIF_DEFAULT ,&nSec));
|
|
ASSERT(nSec >= 0 && nSec <= 59);
|
|
strDateCopy = strDateCopy.Right(strDateCopy.GetLength() - 2);
|
|
|
|
|
|
CTime tmTime(nYear,nMonth,nDay,nHour,nMin,nSec);
|
|
#ifdef _V_STLOWE
|
|
CString strFMT;
|
|
CString strTime;
|
|
strFMT.LoadString(IDS_TIME_FORMAT);
|
|
strTime =tmTime.FormatGmt("%A, %B %d, %Y");
|
|
|
|
#endif
|
|
//Adjust for time zone
|
|
CTimeSpan tspan(0,0,nTimeZone,0);
|
|
tmTime -= tspan;
|
|
|
|
#ifdef _V_STLOWE
|
|
strFMT.LoadString(IDS_TIME_FORMAT);
|
|
strTime =tmTime.FormatGmt("%A, %B %d, %Y");
|
|
|
|
#endif
|
|
return tmTime;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//finds timestamp string for a given delta or snapshot node
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CString GetPNPNameByID(CComPtr<IXMLDOMDocument> pDoc,CComBSTR bstrPNPID)
|
|
{
|
|
HRESULT hr;
|
|
CComPtr<IXMLDOMNodeList> pNodeList;
|
|
CComBSTR bstrQuery("INSTANCE[@CLASSNAME $ieq$ \"WIN32_PNPeNTITY\"] /PROPERTY[@NAME $ieq$ \"Description\"]");
|
|
hr = pDoc->getElementsByTagName(bstrQuery,&pNodeList);
|
|
if (FAILED(hr) || !pNodeList)
|
|
{
|
|
ASSERT(0 && "WIN32_PNPeNTITY error getting node list");
|
|
return "";
|
|
}
|
|
|
|
long lListLen;
|
|
hr = pNodeList->get_length(&lListLen);
|
|
ASSERT(lListLen > 0 && "No WIN32_PNPeNTITY nodes found to match query");
|
|
for(long i = 0; i < lListLen;i++)
|
|
{
|
|
CComPtr<IXMLDOMNode> pNode;
|
|
hr = pNodeList->nextNode(&pNode);
|
|
if (FAILED(hr) || !pNode)
|
|
{
|
|
ASSERT(0 && "could not get next node from list");
|
|
return "";
|
|
}
|
|
|
|
USES_CONVERSION;
|
|
CComPtr<IXMLDOMNode> pIDNode;
|
|
hr = pNode->get_nextSibling(&pIDNode);
|
|
if (FAILED(hr) || !pNode)
|
|
{
|
|
ASSERT(0 && "could not get next node from list");
|
|
return "";
|
|
}
|
|
//see if node's DeviceID subnode matches bstrPNPID
|
|
CComBSTR bstrDeviceID;
|
|
hr = pIDNode->get_text(&bstrDeviceID);
|
|
ASSERT(SUCCEEDED(hr) && "could not get text from ID node");
|
|
if (bstrDeviceID == bstrPNPID)
|
|
{
|
|
CComBSTR bstrDeviceDesc;
|
|
hr = pNode->get_text(&bstrDeviceDesc);
|
|
ASSERT(SUCCEEDED(hr) && "could not get text from Desc node");
|
|
return OLE2T(bstrDeviceDesc);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//returns true if any changes have been entered into CMSInfocategory data
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL CHistoryParser::AreThereChangeLines()
|
|
{
|
|
return this->m_fChangeLines;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//gets (from resources strings) a human-readable name for a the class wrapped the the instance
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CString CInstance::GetClassFriendlyName()
|
|
{
|
|
CString strClassName = GetClassName();
|
|
if (strClassName.CompareNoCase(_T("Win32_PNPAllocatedResource")) == 0)
|
|
{
|
|
VERIFY(m_mapNameValue.Lookup(_T("ANTECEDENT"),strClassName) && _T("Could not find antecedent"));
|
|
}
|
|
CString strFriendlyName;
|
|
if (strClassName.CompareNoCase(_T("Win32_CodecFile")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_CODEC_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_ComputerSystem")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_COMPUTERSYSTEM_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_LogicalMemoryConfiguration")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_LOGICALMEMEORY_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_LogicalDisk")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_LOGICALDISK_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_IRQResource")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_IRQRESOURCE_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_DriverVXD")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_DRIVERVXD_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_DMAChannel")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_DMACHANNEL_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_DeviceMemoryAddress")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_DEVICEMEMORYADDRESS_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_NetworkProtocol")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_NETWORKPROTOCOL_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_OperatingSystem")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_OPERATINGSYSTEM_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_PNPAllocatedResource")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_PNPALLOCATEDRESOURCE_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_PNPEntity")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_PNPENTITY_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_PortResource")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_PORTRESOURCE_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_Printer")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_PRINTER_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_ProgramGroup")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_PROGRAMGROUP_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
if (strClassName.CompareNoCase(_T("Win32_StartupCommand")) == 0)
|
|
{
|
|
VERIFY(strFriendlyName.LoadString(IDS_STARTUPCOMMAND_DESC) && _T("could not find string resource"));
|
|
return strFriendlyName;
|
|
}
|
|
ASSERT(0 && "Unknown strClassName");
|
|
return "";
|
|
}
|
|
|
|
|
|
|