|
|
/*++
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); } }
|