// EventInfo.cpp #include "precomp.h" #include "ProvInfo.h" #include "EventInfo.h" #include "NCProv.h" #include "NCProvider.h" #include #define COUNTOF(x) (sizeof(x)/sizeof(x[0])) #define DWORD_ALIGNED(x) ((DWORD)((((x) * 8) + 31) & (~31)) / 8) ///////////////////////////////////////////////////////////////////////////// // CEventInfo CEventInfo::CEventInfo() : m_pPropFuncs(0) { } CEventInfo::~CEventInfo() { } BOOL GetClassQualifier( IWbemClassObject *pObj, LPCWSTR szQualifier, VARIANT *pVal) { IWbemQualifierSet *pSet = NULL; BOOL bRet = FALSE; if (SUCCEEDED(pObj->GetQualifierSet(&pSet))) { if (SUCCEEDED(pSet->Get(szQualifier, 0, pVal, NULL))) bRet = TRUE; pSet->Release(); } return bRet; } BOOL GetClassPropertyQualifier( IWbemClassObject *pObj, LPCWSTR szProperty, LPCWSTR szQualifier, VARIANT *pVal) { IWbemQualifierSet *pSet = NULL; BOOL bRet = FALSE; if (SUCCEEDED(pObj->GetPropertyQualifierSet(szProperty, &pSet))) { if (SUCCEEDED(pSet->Get(szQualifier, 0, pVal, NULL))) bRet = TRUE; pSet->Release(); } return bRet; } #define MAX_EVENT_PROPS 1024 BOOL CEventInfo::InitFromBuffer(CClientInfo *pInfo, CBuffer *pBuffer) { WCHAR *pszEvent; DWORD nProps, dwStrSize; BOOL bRet = FALSE; m_pInfo = pInfo; // Get the number of properties for this event layout. nProps = pBuffer->ReadDWORD(); if ( nProps > MAX_EVENT_PROPS ) return FALSE; pszEvent = pBuffer->ReadAlignedLenString(&dwStrSize); if ( dwStrSize == 0 ) return FALSE; // Prepare the array of property functions. m_pPropFuncs.Init(nProps); LPWSTR *pszProps = new LPWSTR[nProps]; if (pszProps) { for (DWORD i = 0; i < nProps; i++) { DWORD type = pBuffer->ReadDWORD(); DWORD dwSize; LPCWSTR szProp = pBuffer->ReadAlignedLenString(&dwSize); PROP_FUNC pFunc = TypeToPropFunc(type); if ( pFunc == NULL || !m_pPropFuncs.AddVal(pFunc) ) { delete [] pszProps; return FALSE; } pszProps[i] = (BSTR) szProp; } bRet = Init( pInfo->m_pProvider->m_pProv->GetNamespace(), pszEvent, (LPCWSTR*) pszProps, nProps, FAILED_PROP_TRY_ARRAY); delete [] pszProps; } return bRet; } BOOL CEventInfo::SetPropsWithBuffer(CBuffer *pBuffer) { if (!m_pObj) return FALSE; DWORD nProps = m_pPropFuncs.GetCount(); BOOL bRet = TRUE; DWORD *pNullTable = (DWORD*) pBuffer->m_pCurrent; if ( PBYTE(pNullTable + nProps/32) > (pBuffer->m_pBuffer + pBuffer->m_dwSize) ) return FALSE; // We need this as the offsets are relative from the beginning // of the object packet (including the 2 DWORDs of header stuff). m_pBitsBase = (LPBYTE) (pNullTable - 3); _ASSERT( m_pBitsBase < pBuffer->m_pBuffer + pBuffer->m_dwSize ); m_cBitsBase = pBuffer->m_pBuffer + pBuffer->m_dwSize - m_pBitsBase; m_pdwPropTable = pNullTable + (nProps / 32 + ((nProps % 32) != 0)); if ( PBYTE(m_pdwPropTable + nProps) > (pBuffer->m_pBuffer + pBuffer->m_dwSize) ) return FALSE; // // here we should be safe to use the prop table now, but the // use of bits base is checked against buffer overflow on a case by // case basis. // for (m_iCurrentVar = 0; m_iCurrentVar < nProps && bRet; m_iCurrentVar++) { if ((pNullTable[m_iCurrentVar / 32] & (1 << (m_iCurrentVar % 32)))) { PROP_FUNC pFunc = m_pPropFuncs[m_iCurrentVar]; _ASSERT(pFunc != NULL); bRet = (this->*pFunc)(); _ASSERT(bRet); } #ifdef NO_WINMGMT else WriteNULL(m_iCurrentVar); #endif } return bRet; } PROP_FUNC CEventInfo::TypeToPropFunc(DWORD type) { PROP_FUNC pRet; BOOL bNonArray = (type & CIM_FLAG_ARRAY) == 0; switch(type & ~CIM_FLAG_ARRAY) { case CIM_STRING: case CIM_REFERENCE: case CIM_DATETIME: pRet = bNonArray ? ProcessString : ProcessStringArray; break; case CIM_UINT32: case CIM_SINT32: case CIM_REAL32: pRet = bNonArray ? ProcessDWORD : ProcessArray4; break; case CIM_UINT16: case CIM_SINT16: case CIM_CHAR16: case CIM_BOOLEAN: pRet = bNonArray ? ProcessWORD : ProcessArray2; break; case CIM_SINT8: case CIM_UINT8: pRet = bNonArray ? ProcessBYTE : ProcessArray1; break; case CIM_SINT64: case CIM_UINT64: case CIM_REAL64: pRet = bNonArray ? ProcessDWORD64 : ProcessArray8; break; case CIM_OBJECT: pRet = bNonArray ? ProcessObject : NULL; break; // We'll use this for _IWmiObjects. case CIM_IUNKNOWN: pRet = bNonArray ? ProcessWmiObject : NULL; break; default: // Bad type! _ASSERT(FALSE); pRet = NULL; } return pRet; } BOOL CEventInfo::ProcessString() { DWORD cData; LPBYTE pData = GetPropDataPointer(m_iCurrentVar, cData ); if ( cData < sizeof(DWORD) ) return FALSE; DWORD dwSize = *(DWORD*) pData; BOOL bRet; if ( dwSize > cData - sizeof(DWORD) ) return FALSE; #ifndef NO_WINMGMT bRet = WriteData( m_iCurrentVar, pData + sizeof(DWORD), dwSize ); #else bRet = TRUE; #endif return bRet; } #define MAX_ARRAY_SIZE 4096 BOOL CEventInfo::ProcessStringArray() { DWORD cData; LPBYTE pData = GetPropDataPointer(m_iCurrentVar, cData); if ( cData < sizeof(DWORD) ) return FALSE; DWORD nStrings = *(DWORD*) pData; BOOL bRet; VARIANT vValue; SAFEARRAYBOUND sabound; if ( nStrings > MAX_ARRAY_SIZE ) return FALSE; sabound.lLbound = 0; sabound.cElements = nStrings; pData += sizeof(DWORD); cData -= sizeof(DWORD); if ((V_ARRAY(&vValue) = SafeArrayCreate(VT_BSTR, 1, &sabound)) != NULL) { BSTR *pStrings = (BSTR*) vValue.parray->pvData; vValue.vt = VT_BSTR | VT_ARRAY; for (DWORD i = 0; i < nStrings; i++) { if ( cData < sizeof(DWORD) ) break; DWORD cLen = DWORD_ALIGNED(*(DWORD*)pData); pData += sizeof(DWORD); cData -= sizeof(DWORD); if ( cLen > cData ) break; pStrings[i] = SysAllocString((BSTR)pData); if ( pStrings[i] == NULL ) break; pData += cLen; cData -= cLen; } if ( i != nStrings ) { SafeArrayDestroy(V_ARRAY(&vValue)); return FALSE; } #ifndef NO_WINMGMT HRESULT hr; hr = m_pObj->Put( m_pProps[m_iCurrentVar].m_strName, 0, &vValue, 0); bRet = SUCCEEDED(hr); if (!bRet) bRet = TRUE; #else bRet = TRUE; #endif SafeArrayDestroy(V_ARRAY(&vValue)); } else bRet = FALSE; return bRet; } BOOL CEventInfo::ProcessDWORD() { #ifndef NO_WINMGMT return WriteDWORD(m_iCurrentVar, m_pdwPropTable[m_iCurrentVar]); #else //m_pBuffer->ReadDWORD(); return TRUE; #endif } BOOL CEventInfo::ProcessBYTE() { BYTE cData = m_pdwPropTable[m_iCurrentVar]; #ifndef NO_WINMGMT return WriteData(m_iCurrentVar, &cData, sizeof(cData)); #else return TRUE; #endif } BOOL CEventInfo::ProcessDWORD64() { DWORD cData; DWORD64 *pdwData = (DWORD64*) GetPropDataPointer(m_iCurrentVar,cData); if ( cData < sizeof(DWORD64) ) return FALSE; #ifndef NO_WINMGMT return WriteData(m_iCurrentVar, pdwData, sizeof(*pdwData)); #else return TRUE; #endif } BOOL CEventInfo::ProcessWORD() { WORD wData = m_pdwPropTable[m_iCurrentVar]; #ifndef NO_WINMGMT return WriteData(m_iCurrentVar, &wData, sizeof(wData)); #else return TRUE; #endif } BOOL CEventInfo::ProcessScalarArray(DWORD dwItemSize) { DWORD cBits; LPBYTE pBits = GetPropDataPointer(m_iCurrentVar,cBits); BOOL bRet; if ( cBits < sizeof(DWORD) ) return FALSE; cBits -= sizeof(DWORD); if ( cBits < (*(DWORD*)pBits) * dwItemSize ) return FALSE; #ifndef NO_WINMGMT bRet = WriteArrayData(m_iCurrentVar, pBits, dwItemSize); #else bRet = TRUE; #endif return bRet; } BOOL CEventInfo::ProcessArray1() { return ProcessScalarArray(1); } BOOL CEventInfo::ProcessArray2() { return ProcessScalarArray(2); } BOOL CEventInfo::ProcessArray4() { return ProcessScalarArray(4); } BOOL CEventInfo::ProcessArray8() { return ProcessScalarArray(8); } // Digs out an embedded object from the current buffer. BOOL CEventInfo::GetEmbeddedObject(IUnknown **ppObj, LPBYTE pBits, DWORD cBits ) { *ppObj = NULL; CEventInfo* pEvent = new CEventInfo; if ( pEvent == NULL ) return FALSE; BOOL bRet = FALSE; if ( cBits > sizeof(DWORD) ) { DWORD dwSize = *(DWORD*)pBits; cBits -= sizeof(DWORD); if ( dwSize <= cBits ) { CBuffer bufferObj( pBits+sizeof(DWORD), dwSize, CBuffer::ALIGN_NONE ); bRet = pEvent->InitFromBuffer(m_pInfo, &bufferObj) && pEvent->SetPropsWithBuffer(&bufferObj); } } if (bRet) { bRet = SUCCEEDED(pEvent->m_pObj->QueryInterface( IID_IUnknown, (LPVOID*) ppObj)); } delete pEvent; return bRet; } BOOL CEventInfo::ProcessObject() { _variant_t vObj; BOOL bRet = FALSE; LPBYTE pObjBegin = m_pBitsBase + m_pdwPropTable[m_iCurrentVar]; DWORD cObjBits = m_cBitsBase - m_pdwPropTable[m_iCurrentVar]; if (GetEmbeddedObject(&vObj.punkVal, pObjBegin, cObjBits)) { vObj.vt = VT_UNKNOWN; bRet = SUCCEEDED(m_pObj->Put( m_pProps[m_iCurrentVar].m_strName, 0, &vObj, 0)); } return bRet; } // Digs out an embedded object from the current buffer. BOOL CEventInfo::GetWmiObject(_IWmiObject **ppObj, LPBYTE pBits, DWORD cBits ) { if (m_pObjSpawner == NULL) { HRESULT hr; hr = m_pInfo->m_pProvider->m_pProv->GetNamespace()->GetObject( CWbemBSTR( L"__NAMESPACE" ), 0, NULL, (IWbemClassObject**) (_IWmiObject**) &m_pObjSpawner, NULL); if (FAILED(hr)) return FALSE; } BOOL bRet = FALSE; _IWmiObject *pObjTemp = NULL; if (SUCCEEDED(m_pObjSpawner->SpawnInstance(0, (IWbemClassObject**) &pObjTemp))) { if ( cBits >= sizeof(DWORD ) ) { DWORD dwSize = *(DWORD*) pBits; cBits -= sizeof(DWORD); if ( dwSize <= cBits ) { LPVOID pMem = CoTaskMemAlloc(dwSize); if (pMem) { memcpy(pMem, pBits + sizeof(DWORD), dwSize); if (SUCCEEDED(pObjTemp->SetObjectMemory(pMem, dwSize))) { *ppObj = pObjTemp; bRet = TRUE; } } } } if ( !bRet ) pObjTemp->Release(); } return bRet; } BOOL CEventInfo::ProcessWmiObject() { BOOL bRet; LPBYTE pObjBegin = m_pBitsBase + m_pdwPropTable[m_iCurrentVar]; DWORD cObjBits = m_cBitsBase - m_pdwPropTable[m_iCurrentVar]; _IWmiObject *pObj = NULL; if (GetWmiObject(&pObj, pObjBegin, cObjBits)) { CProp &prop = m_pProps[m_iCurrentVar]; HRESULT hr; hr = m_pWmiObj->SetPropByHandle( prop.m_lHandle, 0, sizeof(_IWmiObject*), &pObj); pObj->Release(); bRet = SUCCEEDED(hr); } else bRet = FALSE; return bRet; } ///////////////////////////////////////////////////////////////////////////// // CEventInfoMap CEventInfoMap::~CEventInfoMap() { while (m_mapNormalEvents.size()) { CNormalInfoMapIterator item = m_mapNormalEvents.begin(); delete (*item).second; m_mapNormalEvents.erase(item); } } CEventInfo *CEventInfoMap::GetNormalEventInfo(DWORD dwIndex) { CEventInfo *pInfo; CNormalInfoMapIterator item = m_mapNormalEvents.find(dwIndex); if (item != m_mapNormalEvents.end()) pInfo = (*item).second; else pInfo = NULL; return pInfo; } BOOL CEventInfoMap::AddNormalEventInfo(DWORD dwIndex, CEventInfo *pInfo) { m_mapNormalEvents[dwIndex] = pInfo; return TRUE; } HRESULT CEventInfo::Indicate() { HRESULT hr; hr = m_pSink->Indicate(1, &m_pObj); return hr; }