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.
 
 
 
 
 
 

2872 lines
71 KiB

/*++
Copyright (C) 1997-2001 Microsoft Corporation
Module Name:
Abstract:
History:
--*/
// OpWrap.cpp
#include "stdafx.h"
#include "OpWrap.h"
#include "resource.h"
#include "OpView.h"
#include "MainFrm.h"
void Trace(LPCTSTR szFormat, ...)
{
va_list ap;
TCHAR szMessage[512];
va_start(ap, szFormat);
_vstprintf(szMessage, szFormat, ap);
va_end(ap);
lstrcat(szMessage, _T("\n"));
OutputDebugString(szMessage);
}
CString GetEmbeddedObjectText(IUnknown *pUnk)
{
IWbemClassObjectPtr pObj;
CString strRet;
if (pUnk)
{
pUnk->QueryInterface(
IID_IWbemClassObject,
(LPVOID*) &pObj);
if (pObj != NULL)
{
CObjInfo obj;
obj.SetObj(pObj);
strRet = obj.GetObjText();
}
}
else
strRet.LoadString(IDS_NULL);
return strRet;
}
/////////////////////////////////////////////////////////////////////////////
// CObjInfo
CObjInfo::~CObjInfo()
{
}
BOOL CObjInfo::GetPropValue(int iIndex, CString &strValue, BOOL bTranslate)
{
BOOL bRet;
_variant_t var;
CPropInfo &prop = (*m_ppProps)[iIndex];
ValueToVariant(iIndex, &var);
bRet = prop.VariantToString(&var, strValue, bTranslate);
// Otherwise the destructor freaks out because it doesn't know what to do
// with VT_I8.
if (var.vt == VT_I8)
var.vt = VT_I4;
return bRet;
}
CString CObjInfo::GetStringPropValue(int iIndex)
{
_bstr_t strProp = m_ppProps->GetData()[iIndex].m_strName;
return GetStringPropValue(strProp);
}
CString CObjInfo::GetStringPropValue(LPCWSTR szName)
{
CString strRet;
_variant_t var;
if (m_pObj != NULL)
{
m_pObj->Get(
szName,
0,
&var,
NULL,
NULL);
}
if (var.vt == VT_BSTR)
strRet = var.bstrVal;
return strRet;
}
#define KEY_PROP_FORMAT _T("\t\t%s (%s)* = %s\n")
#define NON_KEY_PROP_FORMAT _T("\t\t%s (%s) = %s\n")
void CObjInfo::Export(CStdioFile *pFile, BOOL bShowSystem, BOOL bTranslate,
int iLevel)
{
#ifdef _DEBUG
// Don't leave this in here! It's a hack I'm using to check out the
// internal layout of IWbemClassObject.
DoDebugStuff();
#endif
CPropInfo *pProps;
int nItems;
// Get out if the object isn't valid (like on an object where the
// refresh failed).
if (m_pObj == NULL)
return;
pProps = GetProps()->GetData();
nItems = GetProps()->GetSize();
// Add the object path.
for (int i = 0; i <= iLevel; i++)
pFile->Write(_T("\t"), sizeof(TCHAR));
pFile->WriteString(GetObjText());
pFile->Write(_T("\n"), sizeof(TCHAR));
for (i = 0; i < nItems; i++)
{
if (bShowSystem || pProps[i].m_iFlavor != WBEM_FLAVOR_ORIGIN_SYSTEM)
{
CString strLine,
strType,
strValue;
_variant_t vValue;
IUnknown **pUnks = NULL;
int nUnks = 0,
iImage;
BOOL bArray;
pProps[i].GetPropType(strType, &iImage);
ValueToVariant(i, &vValue);
if (vValue.vt == VT_UNKNOWN)
{
bArray = FALSE;
nUnks = 1;
pUnks = &vValue.punkVal;
}
else if (vValue.vt == ((int) VT_UNKNOWN | VT_ARRAY))
{
bArray = TRUE;
nUnks = vValue.parray->rgsabound[0].cElements;
pUnks = (IUnknown**) vValue.parray->pvData;
}
else
pProps[i].VariantToString(&vValue, strValue, bTranslate, TRUE);
strLine.Format(
pProps[i].m_bKey ? KEY_PROP_FORMAT : NON_KEY_PROP_FORMAT,
(LPCTSTR) pProps[i].m_strName,
(LPCTSTR) strType,
(LPCTSTR) strValue);
// Add some additional space if we're in a nested level.
for (int i = 0; i < iLevel; i++)
pFile->Write(_T("\t"), sizeof(TCHAR));
pFile->WriteString(strLine);
// Now do the embedded object stuff.
if (nUnks)
{
for (int i = 0; i < nUnks; i++)
{
IWbemClassObjectPtr pObj;
HRESULT hr;
hr =
pUnks[i]->QueryInterface(
IID_IWbemClassObject,
(LPVOID*) &pObj);
if (SUCCEEDED(hr))
{
CObjInfo info;
info.SetObj(pObj);
info.SetBaseImage(IMAGE_OBJECT);
info.LoadProps(NULL);
info.Export(pFile, bShowSystem, bTranslate, iLevel + 2);
// This looks bad, but normally this is done by a
// controlling COpWrap. In this case we faked one, so
// we have to get rid of it ourselves.
delete info.GetProps();
}
}
}
// Otherwise the destructor freaks out because it doesn't know what to do
// with VT_I8.
if (vValue.vt == VT_I8)
vValue.vt = VT_I4;
}
}
// Leave room for another one.
pFile->Write(_T("\n"), sizeof(TCHAR));
}
CString CObjInfo::GetObjText()
{
CString strRet = GetStringPropValue(L"__RELPATH");
if (strRet.IsEmpty())
{
CString strClass = GetStringPropValue(L"__CLASS");
if (!strClass.IsEmpty())
strRet.Format(IDS_CLASS_NO_KEY, (LPCTSTR) strClass);
else
strRet.LoadString(IDS_NO_KEY);
}
return strRet;
}
#define MAX_STR_SIZE 4096
BOOL CObjInfo::ValueToVariant(int iIndex, VARIANT *pVar)
{
CPropInfo &prop = (*m_ppProps)[iIndex];
BOOL bRet = FALSE;
VariantClear(pVar);
pVar->vt = VT_NULL;
if (prop.m_iHandle && !(prop.m_type & CIM_FLAG_ARRAY))
{
BOOL bString = prop.m_vt == VT_BSTR;
long nRead = 0;
if (bString)
{
WCHAR szBuff[MAX_STR_SIZE];
bRet =
SUCCEEDED(m_pAccess->ReadPropertyValue(
prop.m_iHandle,
prop.m_dwExpectedSize,
&nRead,
(LPBYTE) szBuff)) && nRead != 0;
if (bRet)
{
pVar->vt = VT_BSTR;
V_BSTR(pVar) = SysAllocString(szBuff);
}
}
else
{
bRet =
SUCCEEDED(m_pAccess->ReadPropertyValue(
prop.m_iHandle,
prop.m_dwExpectedSize,
&nRead,
(LPBYTE) &V_BSTR(pVar))) &&
(nRead == prop.m_dwExpectedSize);
if (bRet)
pVar->vt = prop.m_vt;
}
}
else
{
bRet = SUCCEEDED(m_pObj->Get(
_bstr_t(prop.m_strName),
0,
pVar,
NULL,
NULL));
}
return bRet;
}
CString GetStringPropType(int iIndex);
void CObjInfo::GetPropInfo(
int iIndex,
CString &strValue,
CString &strType,
int *piImage,
int *piFlavor,
BOOL bTranslate)
{
CPropInfo &info = (*m_ppProps)[iIndex];
info.GetPropType(strType, piImage);
strValue = _T("");
*piFlavor = info.m_iFlavor;
GetPropValue(iIndex, strValue, bTranslate);
}
void CObjInfo::SetObj(IWbemClassObject *pObj)
{
m_pObj = pObj;
pObj->QueryInterface(
IID_IWbemObjectAccess,
(LPVOID*) &m_pAccess);
}
BOOL IsVarStringArray(VARIANT *pVar)
{
return pVar->vt == (VT_BSTR | VT_ARRAY) &&
pVar->parray->rgsabound[0].cElements != 0;
}
// This converts a BitMap qualifier value string into a bitmask scalar value.
// If the number is a decimal number we have to shift it (e.g. convert '3',
// or bit 3 (zero based), into 0x8.
// If the number is hex, just use wcstoul to convert it into a DWORD.
DWORD CObjInfo::BitmaskStrToValue(LPCWSTR szStr)
{
WCHAR *szBad;
if (szStr[0] && towupper(szStr[1]) != 'X')
return 1 << wcstoul(szStr, &szBad, 0);
else
return wcstoul(szStr, &szBad, 0);
}
HRESULT CObjInfo::LoadProps(IWbemServices *pNamespace)
{
// We need to get the class definition for the amended qualifiers.
IWbemClassObjectPtr pClass;
CString strClass = GetStringPropValue(L"__CLASS");
if (!m_ppProps)
m_ppProps = new CPropInfoArray;
if (pNamespace)
{
pNamespace->GetObject(
_bstr_t(strClass),
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
&pClass,
NULL);
}
SAFEARRAY *pArr = NULL;
HRESULT hr;
CMap<CString, LPCTSTR, BOOL, BOOL>
mapNameToKey;
_variant_t vTrue(true);
// Find our key properties
if (SUCCEEDED(m_pObj->GetNames(
L"KEY",
WBEM_FLAG_ONLY_IF_IDENTICAL,
&vTrue,
&pArr)) && pArr->rgsabound[0].cElements != 0)
{
BSTR *pNames = (BSTR*) pArr->pvData;
for (int i = 0;
i < pArr->rgsabound[0].cElements;
i++)
{
mapNameToKey.SetAt(_bstr_t(pNames[i]), TRUE);
}
SafeArrayDestroy(pArr);
}
// Find out how big we need to make our array.
if (SUCCEEDED(hr = m_pObj->GetNames(
NULL,
WBEM_FLAG_ALWAYS,
NULL,
&pArr)) && pArr->rgsabound[0].cElements != 0)
{
BSTR *pNames = (BSTR*) pArr->pvData;
m_ppProps->SetSize(pArr->rgsabound[0].cElements);
for (int i = 0;
i < pArr->rgsabound[0].cElements && SUCCEEDED(hr);
i++)
{
BOOL bKey; // This value isn't really used, but we need it for the
// mapNameToKey.Lookup call.
CPropInfo &info = (*m_ppProps)[i];
CIMTYPE type;
m_pObj->Get(pNames[i], 0, NULL, &type, &info.m_iFlavor);
info.m_strName = (LPCWSTR) _bstr_t(pNames[i]);
BOOL bSystemProp = info.m_iFlavor == WBEM_FLAVOR_ORIGIN_SYSTEM;
// Don't bother getting the handle for system props since they don't
// exist.
if (!bSystemProp)
m_pAccess->GetPropertyHandle(pNames[i], NULL, &info.m_iHandle);
info.SetType(type);
if (mapNameToKey.Lookup(info.m_strName, bKey))
info.m_bKey = TRUE;
// Load up the valuemap/bitmap values.
IWbemQualifierSetPtr pQuals;
if (pClass != NULL &&
SUCCEEDED(pClass->GetPropertyQualifierSet(pNames[i], &pQuals)))
{
_variant_t vValues;
// Try to get the Values/Valuemap stuff.
if (SUCCEEDED(pQuals->Get(L"Values", 0, &vValues, NULL)) &&
IsVarStringArray(&vValues))
{
_variant_t vMap;
BOOL bUsingMap;
bUsingMap = SUCCEEDED(pQuals->Get(L"ValueMap", 0, &vMap, NULL)) &&
IsVarStringArray(&vMap) &&
vMap.parray->rgsabound[0].cElements ==
vValues.parray->rgsabound[0].cElements;
// Indicate whether this property will be using
// m_mapValues.
info.m_bValueMap =
vValues.parray->rgsabound[0].cElements != 0;
// Clear this out in case we're refreshing our data.
info.m_mapValues.RemoveAll();
for (int i = 0; i < vValues.parray->rgsabound[0].cElements;
i++)
{
CString strKey,
strValue;
if (bUsingMap)
strKey = ((BSTR*)(vMap.parray->pvData))[i];
else
strKey.Format(_T("%d"), i);
strValue = ((BSTR*)(vValues.parray->pvData))[i];
info.m_mapValues.SetAt(strKey, strValue);
}
}
// Try to get the Values/Valuemap stuff.
if (SUCCEEDED(pQuals->Get(L"BitValues", 0, &vValues, NULL)) &&
IsVarStringArray(&vValues))
{
_variant_t vMap;
BOOL bUsingBitmap;
bUsingBitmap = SUCCEEDED(pQuals->Get(L"BitMap", 0, &vMap, NULL)) &&
IsVarStringArray(&vMap) &&
vMap.parray->rgsabound[0].cElements ==
vValues.parray->rgsabound[0].cElements;
// Indicate whether this property will be using
// m_bitmaskValues.
info.m_bBitmask =
vValues.parray->rgsabound[0].cElements != 0;
if (info.m_bBitmask)
info.m_bitmaskValues.SetSize(
vValues.parray->rgsabound[0].cElements);
for (int i = 0; i < vValues.parray->rgsabound[0].cElements;
i++)
{
CString strValue;
CBitmaskInfo &value = info.m_bitmaskValues[i];
if (bUsingBitmap)
value.m_dwBitmaskValue =
BitmaskStrToValue(((BSTR*)(vMap.parray->pvData))[i]);
else
value.m_dwBitmaskValue = 1 << i;
value.m_strName = ((BSTR*)(vValues.parray->pvData))[i];
}
}
}
}
SafeArrayDestroy(pArr);
}
// Load up the methods.
m_ppProps->LoadMethods(pClass);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// COpWrap
COpWrap::COpWrap() :
m_nCount(0),
m_status(WBEM_STATUS_COMPLETE),
m_nExpectedStatusCalls(0),
m_lRef(0)
{
}
COpWrap::COpWrap(
WMI_OP_TYPE type,
LPCTSTR szText,
BOOL bOption) :
m_nCount(0),
m_strOpText(szText),
m_type(type),
m_status(WBEM_STATUS_COMPLETE),
m_bOption(bOption),
m_nExpectedStatusCalls(0),
m_lRef(0)
{
Init();
}
COpWrap::~COpWrap()
{
}
STDMETHODIMP_(ULONG) CObjSink::AddRef(void)
{
LONG lRet = InterlockedIncrement(&m_lRef);
//Trace("Addref = %d", m_lRef);
return lRet;
}
STDMETHODIMP_(ULONG) CObjSink::Release(void)
{
LONG lRet = InterlockedDecrement(&m_lRef);
//Trace("Release = %d", m_lRef);
if (lRet == 0)
delete this;
return lRet;
}
HRESULT STDMETHODCALLTYPE CObjSink::Indicate(
LONG lObjectCount,
IWbemClassObject **ppObjArray)
{
return m_pWrap->Indicate(lObjectCount, ppObjArray);
}
HRESULT STDMETHODCALLTYPE CObjSink::SetStatus(
LONG lFlags,
HRESULT hResult,
BSTR strParam,
IWbemClassObject *pObjParam)
{
return m_pWrap->SetStatus(lFlags, hResult, strParam, pObjParam);
}
const COpWrap& COpWrap::operator=(const COpWrap &other)
{
m_strOpText = other.m_strOpText;
m_type = other.m_type;
m_bOption = other.m_bOption;
return *this;
}
HRESULT COpWrap::Execute(IWbemServices *pNamespace)
{
_bstr_t strWQL = L"WQL",
strText = m_strOpText;
m_hr = S_OK;
m_pNamespace = pNamespace;
m_nCount = 0;
m_status = WBEM_STATUS_PROGRESS;
m_strProps.RemoveAll();
m_piDisplayCols.RemoveAll();
m_mapClassToProps.Flush();
m_hr = S_OK;
m_nExpectedStatusCalls++;
CObjSink *pSink = new CObjSink(this);
m_pObjSink = pSink;
// It seems like WMI never does this. Why?
//pSink->AddRef();
switch(m_type)
{
case WMI_QUERY:
m_hr =
pNamespace->ExecQueryAsync(
strWQL,
strText,
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
m_pObjSink);
//(IWbemObjectSink*) this);
break;
case WMI_EVENT_QUERY:
m_hr =
pNamespace->ExecNotificationQueryAsync(
strWQL,
strText,
WBEM_FLAG_USE_AMENDED_QUALIFIERS |
(m_bOption ? WBEM_FLAG_MONITOR : 0),
NULL,
m_pObjSink);
//(IWbemObjectSink*) this);
break;
case WMI_ENUM_OBJ:
m_hr =
pNamespace->CreateInstanceEnumAsync(
strText,
//WBEM_FLAG_FORWARD_ONLY | // WMI doesn't seem to like this. Why?
WBEM_FLAG_USE_AMENDED_QUALIFIERS |
(m_bOption ? WBEM_FLAG_DEEP : WBEM_FLAG_SHALLOW),
NULL,
m_pObjSink);
//(IWbemObjectSink*) this);
break;
case WMI_GET_OBJ:
m_hr =
pNamespace->GetObjectAsync(
strText,
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
m_pObjSink);
//(IWbemObjectSink*) this);
break;
case WMI_ENUM_CLASS:
{
// First see if we can get the class. If we do, set m_strOpText
// to be the 'pretty' class name.
IWbemClassObject *pClass = NULL;
m_hr =
pNamespace->GetObject(
strText,
0,
NULL,
&pClass,
NULL);
if (SUCCEEDED(m_hr))
{
_variant_t var;
pClass->Get(
L"__CLASS",
0,
&var,
NULL,
NULL);
if (var.vt == VT_BSTR)
m_strOpText = var.bstrVal;
pClass->Release();
}
m_hr =
pNamespace->CreateClassEnumAsync(
strText,
//WBEM_FLAG_FORWARD_ONLY | // WMI doesn't seem to like this. Why?
WBEM_FLAG_USE_AMENDED_QUALIFIERS |
m_bOption ? WBEM_FLAG_DEEP : WBEM_FLAG_SHALLOW,
NULL,
m_pObjSink);
//(IWbemObjectSink*) this);
break;
}
case WMI_GET_CLASS:
m_hr =
pNamespace->GetObjectAsync(
strText,
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
m_pObjSink);
//(IWbemObjectSink*) this);
break;
case WMI_CREATE_CLASS:
{
BSTR bstrClass = *(LPCWSTR) strText == 0 ? NULL :
(BSTR) strText;
IWbemClassObject *pSuperClass = NULL;
// Get the superclass.
m_hr =
pNamespace->GetObject(
bstrClass,
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
&pSuperClass,
NULL);
if (SUCCEEDED(m_hr))
{
IWbemClassObject *pClass = NULL;
// If bstrClass isn't null then we didn't get a top-level
// class, which means we now need to spawn a derived class.
if (bstrClass)
{
m_hr =
pSuperClass->SpawnDerivedClass(
0,
&pClass);
if (SUCCEEDED(m_hr))
{
Indicate(1, &pClass);
// Show the user this object already needs to be saved.
m_objInfo.SetModified(TRUE);
pClass->Release();
// Fake the status callback.
SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, NULL);
}
}
else
{
Indicate(1, &pSuperClass);
// Fake the status callback.
SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, NULL);
}
pSuperClass->Release();
}
break;
}
case WMI_CREATE_OBJ:
{
IWbemClassObject *pClass = NULL;
// Get the superclass.
m_hr =
pNamespace->GetObject(
strText,
WBEM_FLAG_USE_AMENDED_QUALIFIERS,
NULL,
&pClass,
NULL);
if (SUCCEEDED(m_hr))
{
IWbemClassObject *pObject = NULL;
m_hr =
pClass->SpawnInstance(
0,
&pObject);
if (SUCCEEDED(m_hr))
{
Indicate(1, &pObject);
// Show the user this object already needs to be saved.
m_objInfo.SetModified(TRUE);
pObject->Release();
// Fake the status callback.
SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, NULL);
}
pClass->Release();
}
break;
}
}
if (FAILED(m_hr))
{
IWbemClassObjectPtr pErrorObj;
pErrorObj.Attach(GetWMIErrorObject(), FALSE);
if (!m_nExpectedStatusCalls)
m_nExpectedStatusCalls = 1;
SetStatus(WBEM_STATUS_COMPLETE, m_hr, NULL, pErrorObj);
}
return m_hr;
}
HRESULT COpWrap::RefreshPropInfo(CObjInfo *pInfo)
{
if (!pInfo->IsInstance())
{
HRESULT hr = pInfo->LoadProps(m_pNamespace);
if (SUCCEEDED(hr))
AddPropsToGlobalIndex(pInfo);
return hr;
}
else
return S_OK;
}
HRESULT COpWrap::LoadPropInfo(CObjInfo *pInfo)
{
CString strClass = pInfo->GetStringPropValue(L"__CLASS");
m_cs.Lock();
CPropInfoArray *pProps;
if (!m_mapClassToProps.Lookup(strClass, pProps))
{
// Since it's not in our map it must have gotten deleted.
pInfo->SetProps(NULL);
pInfo->LoadProps(m_pNamespace);
pProps = pInfo->GetProps();
m_mapClassToProps.SetAt(strClass, pProps);
AddPropsToGlobalIndex(pInfo);
}
else
pInfo->SetProps(pProps);
m_cs.Unlock();
return S_OK;
}
HRESULT STDMETHODCALLTYPE COpWrap::Indicate(
LONG lObjectCount,
IWbemClassObject **ppObjArray)
{
for (LONG i = 0; i < lObjectCount; i++, m_nCount++)
{
CObjPtr ptr(ppObjArray[i]);
m_listObj.AddTail(ptr);
CObjInfo *pInfo;
if (!IsObject())
pInfo = new CObjInfo;
else
pInfo = &m_objInfo;
pInfo->SetObj(ppObjArray[i]);
pInfo->SetBaseImage(m_iChildImage);
LoadPropInfo(pInfo);
g_pOpView->PostMessage(WM_OBJ_INDICATE, (WPARAM) this, (LPARAM) pInfo);
}
return S_OK;
}
CString COpWrap::GetWbemErrorText(HRESULT hres)
{
CString strRet,
strError,
strFacility;
IWbemStatusCodeText *pStatus = NULL;
SCODE sc = CoCreateInstance(
CLSID_WbemStatusCodeText,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemStatusCodeText,
(LPVOID *) &pStatus);
if (sc == S_OK)
{
BSTR bstr = NULL;
if (SUCCEEDED(pStatus->GetErrorCodeText(hres, 0, 0, &bstr)))
{
strError = bstr;
SysFreeString(bstr);
}
if (SUCCEEDED(pStatus->GetFacilityCodeText(hres, 0, 0, &bstr)))
{
strFacility = bstr;
SysFreeString(bstr);
}
pStatus->Release();
}
if (!strError.IsEmpty() && !strFacility.IsEmpty())
{
strRet.FormatMessage(
IDS_ERROR_FORMAT,
hres,
(LPCSTR) strFacility,
(LPCSTR) strError);
}
else
{
strRet.FormatMessage(IDS_ERROR_FAILED, hres);
}
return strRet;
}
HRESULT STDMETHODCALLTYPE COpWrap::SetStatus(
LONG lFlags,
HRESULT hResult,
BSTR strParam,
IWbemClassObject *pObjParam)
{
if (m_nExpectedStatusCalls)
{
m_status = lFlags;
m_hr = hResult;
if (SUCCEEDED(hResult))
m_strErrorText.Empty();
else
m_strErrorText = GetWbemErrorText(hResult);
g_pOpView->PostMessage(WM_OP_STATUS, (WPARAM) this, 0);
m_nExpectedStatusCalls--;
m_pErrorObj = pObjParam;
}
return S_OK;
}
void COpWrap::SetHoldsObjects()
{
switch(m_type)
{
case WMI_QUERY:
{
CString strQuery = m_strOpText;
strQuery.MakeUpper();
strQuery.TrimLeft();
if (strQuery.Find(_T("ASSOCIATORS")) != -1 ||
strQuery.Find(_T("REFERENCES")) != -1)
m_bShowPathsOnly = TRUE;
else
m_bShowPathsOnly = FALSE;
break;
}
case WMI_ENUM_OBJ:
case WMI_GET_OBJ:
case WMI_EVENT_QUERY:
case WMI_CREATE_OBJ:
m_bShowPathsOnly = FALSE;
break;
default:
case WMI_ENUM_CLASS:
case WMI_GET_CLASS:
case WMI_CREATE_CLASS:
m_bShowPathsOnly = TRUE;
}
}
void COpWrap::GetPropValue(
CObjInfo *pInfo,
int iGlobalIndex,
CString &strValue,
BOOL bTranslate)
{
int iIndex;
if (pInfo->GetProps()->m_mapGlobalToLocalIndex.Lookup(iGlobalIndex, iIndex))
pInfo->GetPropValue(iIndex, strValue, bTranslate);
}
CString COpWrap::GetClassName()
{
CString strRet;
if (m_type != WMI_ENUM_CLASS)
{
if (m_listObj.GetCount())
{
CObjPtr &pObj = m_listObj.GetAt(m_listObj.GetHeadPosition());
_variant_t var;
if (SUCCEEDED(pObj->Get(
L"__CLASS",
0,
&var,
NULL,
NULL)) && var.vt == VT_BSTR)
{
strRet = var.bstrVal;
}
}
}
else
{
return m_strOpText;
}
return strRet;
}
CString COpWrap::GetCaption()
{
CString strRet;
switch(m_type)
{
case WMI_CREATE_CLASS:
if (!m_strOpText.IsEmpty())
strRet.Format(IDS_SUBCLASS_OF, (LPCTSTR) m_strOpText);
else
strRet.LoadString(IDS_TOPLEVEL_CLASS);
break;
case WMI_GET_CLASS:
strRet = GetClassName();
if (strRet.IsEmpty())
strRet = m_strOpText;
break;
case WMI_ENUM_CLASS:
if (!m_strOpText.IsEmpty())
strRet.Format(IDS_ENUM_CLASS_CAPTION, (LPCTSTR) m_strOpText);
else
strRet.LoadString(m_bOption ? IDS_ALL_CLASSES :
IDS_TOP_LEVEL_CLASSES);
break;
case WMI_GET_OBJ:
case WMI_EVENT_QUERY:
case WMI_QUERY:
strRet = m_strOpText;
break;
case WMI_CREATE_OBJ:
strRet.Format(IDS_INSTANCE_OF, (LPCTSTR) m_strOpText);
break;
case WMI_ENUM_OBJ:
{
CString strClass = GetClassName();
if (strClass.IsEmpty())
strClass = m_strOpText;
strRet.Format(IDS_ENUM_OBJ_CAPTION, (LPCTSTR) strClass);
break;
}
}
return strRet;
}
#define DEF_MAX_COLS 100
#define DEF_COL_SIZE 100
int COpWrap::GetPropIndex(LPCTSTR szName, BOOL bAddToDisplay)
{
for (int i = 0; i <= m_strProps.GetUpperBound(); i++)
{
if (m_strProps[i] == szName)
return i;
}
m_strProps.Add(szName);
if (bAddToDisplay)
{
m_piDisplayCols.Add(i);
if (m_piDisplayCols.GetUpperBound() >
m_piDisplayColsWidth.GetUpperBound())
{
m_piDisplayColsWidth.Add(DEF_COL_SIZE);
}
}
return i;
}
void COpWrap::AddPropsToGlobalIndex(CObjInfo *pInfo)
{
CPropInfoArray *ppProps = pInfo->GetProps();
if (ppProps)
{
CPropInfo *pProps = ppProps->GetData();
int nItems = ppProps->GetSize();
for (int i = 0; i < nItems; i++)
{
int iGlobalIndex = GetPropIndex(pProps[i].m_strName,
!(pProps[i].m_iFlavor == WBEM_FLAVOR_ORIGIN_SYSTEM));
ppProps->m_mapGlobalToLocalIndex.SetAt(iGlobalIndex, i);
}
}
}
void CPropInfoArray::LoadMethods(IWbemClassObject *pClass)
{
HRESULT hr;
// Flush the list.
while(m_listMethods.GetCount())
m_listMethods.RemoveHead();
m_nStaticMethods = 0;
if (pClass && SUCCEEDED(hr = pClass->BeginMethodEnumeration(0)))
{
BSTR pName = NULL;
while(1)
{
hr =
pClass->NextMethod(
0,
&pName,
NULL,
NULL);
if (FAILED(hr) || hr == WBEM_S_NO_MORE_DATA)
break;
IWbemQualifierSetPtr pQuals;
CMethodInfo method;
method.m_strName = pName;
SysFreeString(pName);
if (SUCCEEDED(hr = pClass->GetMethodQualifierSet(
pName,
&pQuals)))
{
_variant_t vStatic;
if (SUCCEEDED(hr = pQuals->Get(
L"static",
0,
&vStatic,
NULL)) && vStatic.vt == VT_BOOL && (bool) vStatic == true)
{
method.m_bStatic = TRUE;
m_nStaticMethods++;
}
_variant_t vDesc;
if (SUCCEEDED(hr = pQuals->Get(
L"Description",
0,
&vDesc,
NULL)) && vDesc.vt == VT_BSTR)
{
method.m_strDescription = vDesc.bstrVal;
}
m_listMethods.AddTail(method);
}
}
}
}
int COpWrap::GetImage()
{
if (m_status == WBEM_STATUS_PROGRESS)
return m_iImageBase + 1; // + 1 == busy
else
{
if (SUCCEEDED(m_hr))
// If we're an object, use our m_objInfo to get the image.
return IsObject() ? m_objInfo.GetImage() : m_iImageBase;
else
// + 2 == error
return m_iImageBase + 2;
}
}
void COpWrap::CancelOp(IWbemServices *pNamespace)
{
if (m_status == WBEM_STATUS_PROGRESS)
{
HRESULT hr;
if (FAILED(hr = pNamespace->CancelAsyncCall(m_pObjSink)))
{
//((IWbemObjectSink*) this)->Release();
SetStatus(
WBEM_STATUS_COMPLETE,
hr,
NULL,
NULL);
}
}
}
IMPLEMENT_SERIAL(COpWrap, CObject, VERSIONABLE_SCHEMA|1)
void COpWrap::Serialize(CArchive &archive)
{
if (archive.IsLoading())
{
int type;
archive >> type;
m_type = (WMI_OP_TYPE) type;
archive >> m_strOpText;
archive >> m_bOption;
int nCols;
archive >> nCols;
if (nCols > 0)
{
m_piDisplayColsWidth.SetSize(nCols);
for (int i = 0; i < nCols; i++)
{
int iVal;
archive >> iVal;
m_piDisplayColsWidth[i] = iVal;
}
}
Init();
}
else
{
archive.SetObjectSchema(1);
archive << (int) m_type;
archive << m_strOpText;
archive << m_bOption;
int nCols = m_piDisplayColsWidth.GetUpperBound() + 1;
archive << nCols;
for (int i = 0; i < nCols; i++)
archive << m_piDisplayColsWidth[i];
}
}
void COpWrap::Init()
{
m_hr = S_OK;
SetHoldsObjects();
switch(m_type)
{
case WMI_QUERY:
m_iImageBase = IMAGE_QUERY;
m_iChildImage = IMAGE_OBJECT;
break;
case WMI_ENUM_OBJ:
m_iImageBase = IMAGE_ENUM_OBJ;
m_iChildImage = IMAGE_OBJECT;
break;
case WMI_CREATE_OBJ:
case WMI_GET_OBJ:
m_iImageBase = IMAGE_OBJECT;
m_iChildImage = IMAGE_OBJECT;
break;
case WMI_EVENT_QUERY:
m_iImageBase = IMAGE_EVENT_QUERY;
m_iChildImage = IMAGE_OBJECT;
break;
case WMI_ENUM_CLASS:
m_iImageBase = IMAGE_ENUM_CLASS;
m_iChildImage = IMAGE_CLASS;
break;
case WMI_CREATE_CLASS:
case WMI_GET_CLASS:
m_iImageBase = IMAGE_CLASS;
m_iChildImage = IMAGE_CLASS;
break;
}
}
/////////////////////////////////////////////////////////////////////////////
// CClassToProps
CClassToProps::~CClassToProps()
{
Flush();
}
void CClassToProps::Flush()
{
POSITION pos = GetStartPosition();
CPropInfoArray *pProps;
CString strClass;
while (pos)
{
GetNextAssoc(pos, strClass, pProps);
delete pProps;
}
RemoveAll();
}
/////////////////////////////////////////////////////////////////////////////
// CPropInfo
// Copy constructor.
CPropInfo::CPropInfo(const CPropInfo& other)
{
*this = other;
}
const CPropInfo& CPropInfo::operator=(const CPropInfo& other)
{
m_strName = other.m_strName;
m_iHandle = other.m_iHandle;
m_type = other.m_type;
m_iFlavor = other.m_iFlavor;
m_bKey = other.m_bKey;
m_dwExpectedSize = other.m_dwExpectedSize;
m_vt = other.m_vt;
m_bSigned = other.m_bSigned;
m_bValueMap = other.m_bValueMap;
m_bBitmask = other.m_bBitmask;
// Copy the m_mapValues member.
POSITION pos = other.m_mapValues.GetStartPosition();
m_mapValues.RemoveAll();
while (pos)
{
CString strKey,
strValue;
other.m_mapValues.GetNextAssoc(pos, strKey, strValue);
m_mapValues.SetAt(strKey, strValue);
}
// Copy the m_bitmaskValues member.
int nItems = other.m_bitmaskValues.GetSize();
m_bitmaskValues.SetSize(nItems);
for (int i = 0; i < nItems; i++)
m_bitmaskValues[i] = other.m_bitmaskValues[i];
return *this;
}
void CPropInfo::SetType(CIMTYPE type)
{
m_type = type;
m_bSigned = FALSE;
switch(m_type & ~CIM_FLAG_ARRAY)
{
default:
case CIM_EMPTY:
m_dwExpectedSize = 0;
//m_dwArrayItemSize = 0;
m_vt = VT_EMPTY;
break;
case CIM_SINT8:
m_bSigned = TRUE;
m_dwExpectedSize = 1;
// Fall through...
case CIM_UINT8:
m_dwExpectedSize = 1;
//m_dwArrayItemSize = 1;
m_vt = VT_UI1;
break;
case CIM_SINT16:
m_bSigned = TRUE;
// Fall through...
case CIM_CHAR16:
case CIM_UINT16:
m_dwExpectedSize = 2;
//m_dwArrayItemSize = 4;
m_vt = VT_I2;
break;
case CIM_SINT64:
m_bSigned = TRUE;
// Fall through...
case CIM_UINT64:
m_dwExpectedSize = sizeof(__int64);
//m_dwArrayItemSize = sizeof(__int64);
m_vt = VT_I8;
break;
case CIM_REAL32:
m_dwExpectedSize = sizeof(float);
//m_dwArrayItemSize = sizeof(float);
m_vt = VT_R4;
break;
case CIM_REAL64:
m_dwExpectedSize = sizeof(double);
//m_dwArrayItemSize = sizeof(double);
m_vt = VT_R8;
break;
case CIM_BOOLEAN:
m_dwExpectedSize = sizeof(short);
//m_dwArrayItemSize = sizeof(short);
m_vt = VT_BOOL;
break;
case CIM_STRING:
case CIM_DATETIME:
case CIM_REFERENCE:
m_dwExpectedSize = MAX_STR_SIZE;
//m_dwArrayItemSize = sizeof(BSTR*);
m_vt = VT_BSTR;
break;
case CIM_OBJECT:
m_dwExpectedSize = sizeof(LPVOID);
//m_dwArrayItemSize = sizeof(BSTR*);
m_vt = VT_UNKNOWN;
break;
case CIM_SINT32:
m_bSigned = TRUE;
// Fall through...
case CIM_UINT32:
m_dwExpectedSize = sizeof(DWORD);
//m_dwArrayItemSize = sizeof(DWORD);
m_vt = VT_I4;
break;
}
if (m_type & CIM_FLAG_ARRAY)
m_vt = (VARENUM) ((int) m_vt | VT_ARRAY);
}
void CPropInfo::GetPropType(
CString &strType,
int *piImage,
BOOL bIgnoreArrayFlag)
{
DWORD dwStrID;
*piImage = IMAGE_PROP_BINARY;
switch(m_type & ~CIM_FLAG_ARRAY)
{
default:
case CIM_EMPTY:
dwStrID = IDS_CIM_EMPTY;
break;
case CIM_SINT8:
dwStrID = IDS_CIM_SINT8;
break;
case CIM_UINT8:
dwStrID = IDS_CIM_UINT8;
break;
case CIM_SINT16:
dwStrID = IDS_CIM_SINT16;
break;
case CIM_UINT16:
dwStrID = IDS_CIM_UINT16;
break;
case CIM_SINT64:
dwStrID = IDS_CIM_SINT64;
break;
case CIM_UINT64:
dwStrID = IDS_CIM_UINT64;
break;
case CIM_REAL32:
dwStrID = IDS_CIM_REAL32;
break;
case CIM_REAL64:
dwStrID = IDS_CIM_REAL64;
break;
case CIM_BOOLEAN:
dwStrID = IDS_CIM_BOOLEAN;
break;
case CIM_DATETIME:
dwStrID = IDS_CIM_DATETIME;
break;
case CIM_REFERENCE:
dwStrID = IDS_CIM_REFERENCE;
*piImage = IMAGE_PROP_OBJECT;
break;
case CIM_CHAR16:
dwStrID = IDS_CIM_CHAR16;
break;
case CIM_OBJECT:
dwStrID = IDS_CIM_OBJECT;
break;
case CIM_STRING:
dwStrID = IDS_CIM_STRING;
*piImage = IMAGE_PROP_TEXT;
break;
case CIM_UINT32:
dwStrID = IDS_CIM_UINT32;
break;
case CIM_SINT32:
dwStrID = IDS_CIM_SINT32;
break;
}
strType.LoadString(dwStrID);
if ((m_type & CIM_FLAG_ARRAY) && !bIgnoreArrayFlag)
{
CString strArray;
strArray.LoadString(IDS_CIM_ARRAY);
strType += _T(" | ");
strType += strArray;
}
if (m_bKey)
*piImage = *piImage + 1;
}
DWORD64 ato64u(LPCTSTR szVal)
{
DWORD64 dwRet = 0;
_stscanf(szVal, _T("%I64u"), &dwRet);
return dwRet;
}
BOOL CPropInfo::SetArrayItem(VARIANT *pVar, DWORD dwIndex, DWORD dwValue)
{
ASSERT(m_vt & VT_ARRAY);
ASSERT(pVar->vt & VT_ARRAY);
ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
LPBYTE pDest = (LPBYTE) pVar->parray->pvData + (dwArrayItemSize * dwIndex);
BOOL bRet = TRUE;
switch(dwArrayItemSize)
{
case 1:
*(char*) pDest = dwValue;
break;
case 2:
*(short*) pDest = dwValue;
break;
case 4:
*(int*) pDest = dwValue;
break;
default:
bRet = FALSE;
}
return bRet;
}
DWORD CPropInfo::GetArrayItem(VARIANT *pVar, DWORD dwIndex)
{
ASSERT(m_vt & VT_ARRAY);
ASSERT(pVar->vt & VT_ARRAY);
ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
LPBYTE pSrc = (LPBYTE) pVar->parray->pvData +
(dwArrayItemSize * dwIndex);
DWORD dwRet = 0;
switch(dwArrayItemSize)
{
case 1:
dwRet = *(char*) pSrc;
break;
case 2:
dwRet = *(short*) pSrc;
break;
case 4:
dwRet = *(int*) pSrc;
break;
}
return dwRet;
}
// This one doesn't handle arrays since we'll never go from a single string to
// an array.
BOOL CPropInfo::StringToVariant(LPCSTR szValue, VARIANT *pVar, BOOL bTranslate)
{
BOOL bRet;
VARENUM typeRaw = (VARENUM) (m_vt & ~VT_ARRAY);
VariantClear(pVar);
pVar->vt = typeRaw;
if (pVar->vt == VT_I8)
pVar->vt = VT_BSTR;
LPVOID pData = &V_BSTR(pVar);
bRet = StringToVariantBlob(szValue, pData, bTranslate);
return bRet;
}
// TODO: Need to be able to accept dates with month names.
LPTSTR IntToDMTF(LPTSTR szOut, int iValue, int iDigits)
{
_ASSERT(iDigits <= 6 && iDigits >= 0);
if (iValue == -1)
{
memcpy(szOut, _T("******"), iDigits * sizeof(TCHAR));
szOut[iDigits] = 0;
}
else
{
char szFormat[100] = _T("%0*d");
szFormat[2] = '0' + iDigits;
wsprintf(szOut, szFormat, iValue);
}
return szOut;
}
enum LOCALE_TOKEN
{
L_UNKNOWN,
L_MONTH_1,
L_MONTH_2,
L_MONTH_3,
L_MONTH_4,
L_MONTH_5,
L_MONTH_6,
L_MONTH_7,
L_MONTH_8,
L_MONTH_9,
L_MONTH_10,
L_MONTH_11,
L_MONTH_12,
L_DATE_SEP,
L_TIME_SEP,
L_AM,
L_PM,
L_UTC
};
class CLocaleInfo
{
public:
TCHAR szDateSep[MAX_PATH],
szTimeSep[MAX_PATH],
szPM[MAX_PATH],
szAM[MAX_PATH],
szUTC[MAX_PATH],
szLongMonths[12][MAX_PATH],
szShortMonths[12][MAX_PATH];
CLocaleInfo() { Init(); }
void Init();
LOCALE_TOKEN GetNextToken(LPCTSTR *ppszCurrent);
protected:
BOOL CheckAndIncrement(LPCTSTR szCheckAgainst, LPCTSTR *ppszCurrent);
};
LOCALE_TOKEN CLocaleInfo::GetNextToken(LPCTSTR *ppszCurrent)
{
if (CheckAndIncrement(szDateSep, ppszCurrent))
return L_DATE_SEP;
else if (CheckAndIncrement(szTimeSep, ppszCurrent))
return L_TIME_SEP;
else if (CheckAndIncrement(szAM, ppszCurrent))
return L_AM;
else if (CheckAndIncrement(szPM, ppszCurrent))
return L_PM;
else if (CheckAndIncrement(szUTC, ppszCurrent))
return L_UTC;
else
{
for (int i = 0; i < 12; i++)
{
if (CheckAndIncrement(szLongMonths[i], ppszCurrent))
return (LOCALE_TOKEN) (L_MONTH_1 + i);
}
for (i = 0; i < 12; i++)
{
if (CheckAndIncrement(szShortMonths[i], ppszCurrent))
return (LOCALE_TOKEN) (L_MONTH_1 + i);
}
}
return L_UNKNOWN;
}
BOOL CLocaleInfo::CheckAndIncrement(LPCTSTR szCheckAgainst, LPCTSTR *ppszCurrent)
{
// Get past the spaces.
while (isspace(**ppszCurrent))
(*ppszCurrent)++;
int nLen = _tcslen(szCheckAgainst);
BOOL bRet;
if (!_tcsncmp(szCheckAgainst, *ppszCurrent, nLen))
{
bRet = TRUE;
*ppszCurrent += nLen;
}
else
bRet = FALSE;
return bRet;
}
void CLocaleInfo::Init()
{
GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_SDATE,
szDateSep,
sizeof(szDateSep) / sizeof(TCHAR));
_tcsupr(szDateSep);
GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_STIME,
szTimeSep,
sizeof(szTimeSep) / sizeof(TCHAR));
_tcsupr(szTimeSep);
GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_S2359,
szPM,
sizeof(szPM) / sizeof(TCHAR));
_tcsupr(szPM);
GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_S1159,
szAM,
sizeof(szAM) / sizeof(TCHAR));
_tcsupr(szAM);
for (int i = 0; i < 12; i++)
{
GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_SMONTHNAME1 + i,
szLongMonths[i],
sizeof(szLongMonths[0]) / sizeof(TCHAR));
_tcsupr(szLongMonths[i]);
GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_SABBREVMONTHNAME1 + i,
szShortMonths[i],
sizeof(szShortMonths[0]) / sizeof(TCHAR));
_tcsupr(szShortMonths[i]);
}
CString strUTC;
strUTC.LoadString(IDS_UTC_TOKEN);
lstrcpy(szUTC, strUTC);
}
enum DATE_STATE
{
S_BEGIN,
S_MONTH,
S_DAY,
S_YEAR,
S_HOUR,
S_MINUTE,
S_SECOND,
S_NEED_UTC,
};
BOOL DoAMPM(LOCALE_TOKEN token, int *piHour, DATE_STATE *pState)
{
BOOL bRet;
ASSERT(*piHour != -1);
if (*pState == S_HOUR || *pState == S_MINUTE || *pState == S_SECOND)
{
bRet = TRUE;
if (*piHour == 12 && token == L_AM)
*piHour = 0;
else if (*piHour < 12 && token == L_PM)
*piHour += 12;
*pState = S_NEED_UTC;
}
else
bRet = FALSE;
return bRet;
}
BOOL DoUTC(int *piOffset, LPCTSTR *pszCurrent, TCHAR *pcOffsetSign, DATE_STATE *pState)
{
// Until we prove otherwise...
BOOL bRet = FALSE;
TCHAR cSign = **pszCurrent;
if (cSign == '+' || cSign == '-')
{
// Get past the sign.
(*pszCurrent)++;
if (isdigit(**pszCurrent))
{
*piOffset = _ttoi(*pszCurrent) * 60;
// Get past the number.
while (isdigit(**pszCurrent))
(*pszCurrent)++;
if (**pszCurrent != ')')
{
// Get past the separator.
while (!isdigit(**pszCurrent) && **pszCurrent)
(*pszCurrent)++;
*piOffset += _ttoi(*pszCurrent);
}
// Find the end of this thing.
while (**pszCurrent != ')' && **pszCurrent)
(*pszCurrent)++;
if (**pszCurrent == ')')
{
*pcOffsetSign = cSign;
*pState = S_BEGIN;
(*pszCurrent)++;
bRet = TRUE;
}
}
}
return bRet;
}
BOOL StringDateTimeToDMTF(LPCTSTR szDateTime, CString &strDateTime)
{
CLocaleInfo info;
DATE_STATE state = S_BEGIN;
BOOL bMonthFromString = FALSE,
bPM = FALSE,
bAM = FALSE;
int iDay = -1,
iMonth = -1,
iYear = -1,
iHour = -1,
iMin = -1,
iSec = -1,
iMicro = -1,
iOffset = -1;
char szOffsetSign[2] = _T("*");
BOOL bRet = TRUE;
CString strTemp = szDateTime;
// So we can do case insensitive compares.
strTemp.MakeUpper();
LPCTSTR szCurrent = strTemp;
while (*szCurrent && bRet)
{
while (isspace(*szCurrent))
szCurrent++;
////////////////////////////////////////////////////
// State action == number found
if (isdigit(*szCurrent))
{
// Reset if we were potentially looking for a UTC and we didn't get it.
if (state == S_NEED_UTC)
state = S_BEGIN;
int iNumber = _ttoi(szCurrent);
// Get past the current number.
while (isdigit(*szCurrent))
szCurrent++;
LOCALE_TOKEN token = info.GetNextToken(&szCurrent);
switch(state)
{
////////////////////////////////////////////////////
// Begin state
case S_BEGIN:
if (token == L_TIME_SEP)
{
iHour = iNumber;
state = S_HOUR;
}
else if (token == L_DATE_SEP || token == L_UNKNOWN)
{
iMonth = iNumber;
state = S_MONTH;
}
else if (token == L_AM || token == L_PM)
{
iHour = iNumber;
state = S_HOUR;
bRet = DoAMPM(token, &iHour, &state);
//bAM = token == L_AM;
//bPM = !bAM;
//state = S_NEED_UTC;
}
else
bRet = FALSE;
break;
////////////////////////////////////////////////////
// Date states
case S_MONTH:
if (token == L_DATE_SEP)
{
iDay = iNumber;
state = S_DAY;
}
else if (token == L_UNKNOWN)
{
iYear = iNumber;
state = S_BEGIN;
}
else
bRet = FALSE;
break;
case S_DAY:
if (token == L_UNKNOWN)
{
iYear = iNumber;
state = S_BEGIN;
}
else
bRet = FALSE;
break;
//case S_YEAR:
// iYear = iNumber;
// state = S_BEGIN;
// break;
////////////////////////////////////////////////////
// Time states
case S_HOUR:
iMin = iNumber;
if (token == L_TIME_SEP)
state = S_MINUTE;
else if (token == L_AM || token == L_PM)
bRet = DoAMPM(token, &iHour, &state);
else if (token == L_UTC)
bRet = DoUTC(&iOffset, &szCurrent, &szOffsetSign[0], &state);
else
bRet = FALSE;
break;
case S_MINUTE:
iSec = iNumber;
if (token == L_AM || token == L_PM)
bRet = DoAMPM(token, &iHour, &state);
else if (token == L_UTC)
bRet = DoUTC(&iOffset, &szCurrent, &szOffsetSign[0], &state);
else
bRet = FALSE;
break;
default:
bRet = FALSE;
break;
}
} // End of state action == number found.
else
{
////////////////////////////////////////////////////
// State action == some token
LOCALE_TOKEN token = info.GetNextToken(&szCurrent);
// Reset if we were potentially looking for a UTC and we didn't get it.
if (state == S_NEED_UTC && token != L_UTC)
state = S_BEGIN;
// token == string month found
if (token >= L_MONTH_1 && token <= L_MONTH_12)
{
// Move past any non-digits beyond the string date, such as a
// separator or a comma, etc.
while (!isdigit(*szCurrent) && *szCurrent)
szCurrent++;
if (state == S_BEGIN)
{
iMonth = token - L_MONTH_1 + 1;
state = S_MONTH;
bMonthFromString = TRUE;
}
else if (state == S_MONTH && !bMonthFromString)
{
iDay = iMonth;
iMonth = token - L_MONTH_1 + 1;
state = S_DAY;
}
else
bRet = FALSE;
}
else if (token == L_AM || token == L_PM)
{
if (state == S_HOUR || state == S_MINUTE || state == S_SECOND)
{
//bAM = token == L_AM;
//bPM = !bAM;
bRet = DoAMPM(token, &iHour, &state);
//state = S_NEED_UTC;
}
else
bRet = FALSE;
}
else if (state == S_NEED_UTC)
{
bRet = DoUTC(&iOffset, &szCurrent, &szOffsetSign[0], &state);
}
else if (token == L_UNKNOWN)
szCurrent++;
else
bRet = FALSE;
}
}
// At this point, we may need to juggle our day and month around, depending
// on what the order is for the current locale.
if (iDay != -1 && iMonth != -1 && iYear != -1)
{
TCHAR szOrder[2] = _T("0");
GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_IDATE,
szOrder,
sizeof(szOrder) / sizeof(TCHAR));
// dd/mm/yy
if (*szOrder == '1')
{
int iTemp = iDay;
iDay = iMonth;
iMonth = iDay;
}
// yy/mm/dd
else if (*szOrder == '2')
{
int iTemp = iDay;
iDay = iYear;
iYear = iDay;
}
}
// Finally, splice it all together.
TCHAR szOut[100] = _T(""),
szTemp[20];
lstrcat(szOut, IntToDMTF(szTemp, iYear, 4));
lstrcat(szOut, IntToDMTF(szTemp, iMonth, 2));
lstrcat(szOut, IntToDMTF(szTemp, iDay, 2));
lstrcat(szOut, IntToDMTF(szTemp, iHour, 2));
lstrcat(szOut, IntToDMTF(szTemp, iMin, 2));
lstrcat(szOut, IntToDMTF(szTemp, iSec, 2));
lstrcat(szOut, _T("."));
lstrcat(szOut, IntToDMTF(szTemp, iMicro, 6));
lstrcat(szOut, szOffsetSign);
lstrcat(szOut, IntToDMTF(szTemp, iOffset, 3));
strDateTime = szOut;
return TRUE;
}
BOOL IsDMTF(LPCTSTR szDate)
{
for (int i = 0; i < 14; i++)
{
if (!isdigit(szDate[i]) && szDate[i] != '*')
return FALSE;
}
if (szDate[14] != '.')
return FALSE;
for (i = 15; i < 21; i++)
{
if (!isdigit(szDate[i]) && szDate[i] != '*')
return FALSE;
}
if (szDate[21] != '-' && szDate[21] != '+' && szDate[21] != '*')
return FALSE;
for (i = 22; i < 25; i++)
{
if (!isdigit(szDate[i]) && szDate[i] != '*')
return FALSE;
}
return TRUE;
}
BOOL CPropInfo::StringToVariantBlob(LPCTSTR szValue, LPVOID pData,
BOOL bTranslate)
{
BOOL bRet = TRUE;
char *szTemp;
CString strValue;
VARENUM typeRaw = (VARENUM) (m_vt & ~VT_ARRAY);
// This one is special-cased from the others because the value will
// usually be in a localized form, even if bTranslate == FALSE.
if (typeRaw == VT_BOOL)
{
CString strTrue;
strTrue.LoadString(IDS_TRUE);
if (!lstrcmpi(strTrue, szValue))
*(short*) pData = VARIANT_TRUE;
else
*(short*) pData = atoi(szValue) ? VARIANT_TRUE : VARIANT_FALSE;
}
else
{
// Translate if necessary.
if (bTranslate && m_bValueMap)
{
// TODO: We could make this faster if we added a reverse lookup
// map. For now we'll do a sequential search.
POSITION pos = m_mapValues.GetStartPosition();
CString strKey;
while(pos)
{
m_mapValues.GetNextAssoc(pos, strKey, strValue);
if (!lstrcmpi(szValue, strValue))
{
szValue = strKey;
break;
}
}
}
switch(typeRaw)
{
case VT_I8:
case VT_BSTR:
{
if (GetRawCIMType() != CIM_DATETIME)
*(BSTR*) pData = _bstr_t(szValue).copy();
else
{
if (!IsDMTF(szValue))
{
CString strRet;
StringDateTimeToDMTF(szValue, strRet);
_ASSERT(IsDMTF(strRet));
*(BSTR*) pData = strRet.AllocSysString();
}
else
*(BSTR*) pData = _bstr_t(szValue).copy();
}
break;
}
case VT_R8:
*(double*) pData = atof(szValue);
break;
case VT_R4:
*(float*) pData = atof(szValue);
break;
case VT_UI1:
*(char*) pData = m_bSigned ? atoi(szValue) : strtoul(szValue, &szTemp, 10);
break;
case VT_I2:
*(short*) pData = m_bSigned ? atoi(szValue) : strtoul(szValue, &szTemp, 10);
break;
case VT_I4:
*(int*) pData = m_bSigned ? atoi(szValue) : strtoul(szValue, &szTemp, 10);
break;
//case VT_I8:
// *(DWORD64*) pData = m_bSigned ? _atoi64(szValue) : ato64u(szValue);
// break;
}
}
return bRet;
}
// We have to pass the vt as contained on the actual variant because WMI sometimes
// uses a different VARENUM for Gets/Puts (go figure).
BOOL CPropInfo::VariantBlobToString(VARENUM vt, LPVOID pData, CString &strValue,
BOOL bTranslate, BOOL bQuoteStrings)
{
VARENUM vtRaw = (VARENUM) (vt & ~VT_ARRAY);
strValue.Empty();
switch(vtRaw)
{
case VT_BSTR:
strValue = *(BSTR*) pData;
break;
case VT_R8:
strValue.Format(_T("%.5f"), *(double*) pData);
break;
case VT_R4:
strValue.Format(_T("%.5f"), *(float*) pData);
break;
case VT_UI1:
{
if (m_bSigned)
strValue.Format(_T("%d"), *(char*) pData);
else
strValue.Format(_T("%u"), *(BYTE*) pData);
break;
}
case VT_I2:
{
if (m_bSigned)
strValue.Format(_T("%d"), *(short*) pData);
else
strValue.Format(_T("%u"), *(WORD*) pData);
break;
}
case VT_I4:
{
if (m_bSigned)
strValue.Format(_T("%d"), *(int*) pData);
else
strValue.Format(_T("%u"), *(DWORD*) pData);
break;
}
case VT_I8:
{
if (m_bSigned)
strValue.Format(_T("%I64d"), *(__int64*) pData);
else
strValue.Format(_T("%I64u"), *(DWORD64*) pData);
break;
}
case VT_BOOL:
strValue.LoadString(*(short*) pData ? IDS_TRUE : IDS_FALSE);
break;
case VT_UNKNOWN:
//strValue.Format(IDS_EMBEDDED_OBJECT, *(IUnknown*) pData);
strValue = GetEmbeddedObjectText(*(IUnknown**) pData);
break;
}
if (bTranslate && !strValue.IsEmpty())
{
if (m_bValueMap)
{
CString strKey = strValue;
m_mapValues.Lookup(strKey, strValue);
}
else if (m_bBitmask)
{
DWORD nSize = m_bitmaskValues.GetSize(),
dwValue = *(DWORD*) pData;
// Clear this out.
strValue.Empty();
for (int i = 0; i < nSize; i++)
{
CString strPart;
if (dwValue & m_bitmaskValues[i].m_dwBitmaskValue)
{
if (!strValue.IsEmpty())
strValue += _T(" | ");
strValue += m_bitmaskValues[i].m_strName;
}
}
}
else if (GetRawCIMType() == CIM_DATETIME)
{
struct DATETIME_INFO
{
TCHAR szYear[5],
szMonth[3],
szDay[3],
szHour[3],
szMin[3],
szSec[3],
szMicro[7],
cSep,
szOffset[4];
} datetime;
ZeroMemory(&datetime, sizeof(datetime));
if (_stscanf(
strValue,
_T("%4c%2c%2c%2c%2c%2c.%6c%c%3c"),
datetime.szYear,
datetime.szMonth,
datetime.szDay,
datetime.szHour,
datetime.szMin,
datetime.szSec,
datetime.szMicro,
&datetime.cSep,
datetime.szOffset) == 9)
{
SYSTEMTIME systime;
TCHAR szDate[100] = _T(""),
szTime[100] = _T("");
// _stscanf seems to be screwing this up, so fix it.
datetime.szOffset[3] = 0;
ZeroMemory(&systime, sizeof(systime));
// Figure out the date.
if (*datetime.szYear != '*' && *datetime.szMonth != '*')
{
DWORD dwFlag;
TCHAR szFormat[10],
*pszFormat;
systime.wYear = (WORD) _ttoi(datetime.szYear);
systime.wMonth = (WORD) _ttoi(datetime.szMonth);
if (*datetime.szDay == '*')
{
// This would have been nice to use, but it only lives
// on W2K.
//dwFlag = DATE_YEARMONTH;
TCHAR szSep[100];
if (GetLocaleInfo(
LOCALE_USER_DEFAULT,
LOCALE_SDATE,
szSep,
sizeof(szSep) / sizeof(TCHAR)))
{
// Otherwise GetDateFormat will fail, even though
// it doesn't need it!
systime.wDay = 1;
wsprintf(szFormat, _T("MM%syyyy"), szSep);
dwFlag = 0;
pszFormat = szFormat;
}
}
else
{
dwFlag = DATE_SHORTDATE;
pszFormat = NULL;
systime.wDay = (WORD) _ttoi(datetime.szDay);
}
GetDateFormat(
LOCALE_USER_DEFAULT,
dwFlag,
&systime,
pszFormat,
szDate,
sizeof(szDate) / sizeof(TCHAR));
}
// Figure out the time.
if (*datetime.szHour != '*')
{
DWORD dwFlag = 0;
systime.wHour = (WORD) _ttoi(datetime.szHour);
if (*datetime.szMin == '*')
dwFlag = TIME_NOMINUTESORSECONDS;
else
{
systime.wMinute = (WORD) _ttoi(datetime.szMin);
if (*datetime.szSec == '*')
dwFlag = TIME_NOSECONDS;
else
systime.wSecond = (WORD) _ttoi(datetime.szSec);
}
GetTimeFormat(
LOCALE_USER_DEFAULT,
dwFlag,
&systime,
NULL,
szTime,
sizeof(szTime) / sizeof(TCHAR));
if (*szTime &&
(datetime.cSep == '-' || datetime.cSep == '+') &&
*datetime.szOffset != '*')
{
CString strOffset;
DWORD dwMinutes = _ttoi(datetime.szOffset);
strOffset.FormatMessage(
IDS_UTC, datetime.cSep, dwMinutes / 60,
dwMinutes % 60);
strcat(szTime, strOffset);
}
}
strValue = szDate;
if (*szTime)
{
if (!strValue.IsEmpty())
strValue += _T(" ");
strValue += szTime;
}
}
}
}
if (bQuoteStrings && GetRawCIMType() == CIM_STRING)
{
CString strTemp;
strTemp.Format(_T("\"%s\""), (LPCTSTR) strValue);
strValue = strTemp;
}
return TRUE;
}
DWORD CPropInfo::GetArrayItemCount(VARIANT *pVar)
{
return pVar->parray->rgsabound[0].cElements;
}
BOOL CPropInfo::ArrayItemToString(VARIANT *pVar, DWORD dwIndex,
CString &strValue, BOOL bTranslate)
{
ASSERT(m_vt & VT_ARRAY);
ASSERT(pVar->vt & VT_ARRAY);
ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
BOOL bRet = TRUE;
LPBYTE pData = (LPBYTE) pVar->parray->pvData;
CString strItem;
DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
if (VariantBlobToString(
(VARENUM) pVar->vt,
pData + (dwArrayItemSize * dwIndex),
strItem,
bTranslate,
FALSE))
strValue = strItem;
return bRet;
}
BOOL CPropInfo::PrepArrayVar(VARIANT *pVar, DWORD dwSize)
{
BOOL bRet = FALSE;
ASSERT((m_vt & VT_ARRAY) != 0);
VariantClear(pVar);
if (dwSize > 0)
{
SAFEARRAYBOUND bound;
pVar->vt = m_vt;
if (pVar->vt == (VT_I8 | VT_ARRAY))
pVar->vt = VT_BSTR | VT_ARRAY;
bound.lLbound = 0;
bound.cElements = dwSize;
pVar->parray = SafeArrayCreate(pVar->vt & ~VT_ARRAY, 1, &bound);
bRet = pVar->parray != NULL;
}
else
{
pVar->vt = VT_NULL;
bRet = TRUE;
}
return bRet;
}
BOOL CPropInfo::StringToArrayItem(LPCTSTR szItem, VARIANT *pVar, DWORD dwIndex,
BOOL bTranslate)
{
//ASSERT(m_vt & VT_ARRAY);
ASSERT(pVar->vt & VT_ARRAY);
ASSERT(dwIndex < pVar->parray->rgsabound[0].cElements);
BOOL bRet = TRUE;
LPBYTE pData = (LPBYTE) pVar->parray->pvData;
DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
bRet =
StringToVariantBlob(szItem, pData + (dwArrayItemSize * dwIndex),
bTranslate);
return bRet;
}
int CPropInfo::GetArrayItemSize(VARENUM vt)
{
switch(vt & ~VT_ARRAY)
{
case VT_UI1:
case VT_I1:
return 1;
case VT_BOOL:
case VT_I2:
return 2;
case VT_I4:
return 4;
case VT_I8:
return 8;
case VT_UNKNOWN:
case VT_BSTR:
return sizeof(BSTR*);
case VT_R4:
return sizeof(float);
case VT_R8:
return sizeof(double);
default:
// This shouldn't happen! If it does, add another case statement.
ASSERT(FALSE);
return 0;
}
}
BOOL CPropInfo::VariantToString(VARIANT *pVar, CString &strValue,
BOOL bTranslate, BOOL bQuoteStrings)
{
BOOL bRet = TRUE;
if (pVar->vt != VT_NULL)
{
if (pVar->vt & VT_ARRAY)
{
DWORD dwArrayItemSize = GetArrayItemSize((VARENUM) pVar->vt);
strValue.Empty();
LPBYTE pData = (LPBYTE) pVar->parray->pvData;
CString strItem;
for (int i = 0; i < pVar->parray->rgsabound[0].cElements;
i++, pData += dwArrayItemSize)
{
VariantBlobToString((VARENUM) pVar->vt, pData, strItem,
bTranslate, bQuoteStrings);
if (i != 0)
strValue += _T(", ");
strValue += strItem;
}
}
else
{
LPVOID pData = &V_BSTR(pVar);
VariantBlobToString((VARENUM) pVar->vt, pData, strValue,
bTranslate, bQuoteStrings);
}
}
else
strValue.LoadString(IDS_NULL);
return bRet;
}
// Use this to get __ExtendedStatus.
IWbemClassObject *GetWMIErrorObject()
{
IWbemClassObject *pObj = NULL;
IErrorInfo *pInfo = NULL;
if (SUCCEEDED(GetErrorInfo(0, &pInfo)) && pInfo != NULL)
{
pInfo->QueryInterface(IID_IWbemClassObject, (LPVOID*) &pObj);
pInfo->Release();
}
return pObj;
}
// Wbemcomn.dll prototypes.
typedef HRESULT (IWbemClassObject::*FPGET_PROPERTY_HANDLE_EX)(LPCWSTR, CIMTYPE*, long*);
typedef LPVOID (IWbemClassObject::*FPGET_ARRAY_BY_HANDLE)(long);
void CObjInfo::DoDebugStuff()
{
// I tried doing directly (from GetProcAddress into memember vars) but
// I couldn't come up with a conversion the compiler would let me do.
// So, do it the hardway.
HINSTANCE hWbemComn = GetModuleHandle(_T("wbemcomn.dll"));
FARPROC fpGetPropertyHandleEx =
GetProcAddress(
hWbemComn,
"?GetPropertyHandleEx@CWbemObject@@QAEJPBGPAJ1@Z");
FARPROC fpGetArrayByHandle =
GetProcAddress(
hWbemComn,
"?GetArrayByHandle@CWbemObject@@QAEPAVCUntypedArray@@J@Z");
FPGET_PROPERTY_HANDLE_EX
m_fpGetPropertyHandleEx;
FPGET_ARRAY_BY_HANDLE
m_fpGetArrayByHandle;
memcpy(
&m_fpGetPropertyHandleEx,
&fpGetPropertyHandleEx,
sizeof(fpGetPropertyHandleEx));
memcpy(
&m_fpGetArrayByHandle,
&fpGetArrayByHandle,
sizeof(fpGetArrayByHandle));
SAFEARRAY *pArr = NULL;
if (SUCCEEDED(m_pObj->GetNames(NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &pArr)))
{
BSTR *pNames = (BSTR*) pArr->pvData;
int nItems = pArr->rgsabound[0].cElements;
for (int i = 0; i < nItems; i++)
{
CIMTYPE type;
long handle;
if (SUCCEEDED(
(m_pObj->*m_fpGetPropertyHandleEx)(
pNames[i],
&type,
&handle)))
{
LPVOID pData = (m_pObj->*m_fpGetArrayByHandle)(handle);
int x;
x = 3;
HRESULT hr;
_variant_t vValue;
hr =
m_pObj->Get(
pNames[i],
0,
&vValue,
&type,
NULL);
BSTR *pStrings = NULL;
if (vValue.vt == (VT_BSTR | VT_ARRAY))
pStrings = (BSTR*) vValue.parray->pvData;
hr =
m_pObj->Put(
pNames[i],
0,
&vValue,
0);
}
}
SafeArrayDestroy(pArr);
}
}