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.
1243 lines
33 KiB
1243 lines
33 KiB
// Event.cpp
|
|
#include "precomp.h"
|
|
#include "buffer.h"
|
|
#include "Connection.h"
|
|
#include "Event.h"
|
|
#include "NCDefs.h"
|
|
#include <corex.h>
|
|
|
|
#include <strutils.h>
|
|
|
|
|
|
#define DEF_EVENT_DATA_SIZE 512
|
|
#define DEF_EVENT_LAYOUT_SIZE 256
|
|
|
|
#define DWORD_ALIGNED(x) ((DWORD)((((x) * 8) + 31) & (~31)) / 8)
|
|
|
|
|
|
BOOL isunialpha(wchar_t c)
|
|
{
|
|
if(c == 0x5f || (0x41 <= c && c <= 0x5a) ||
|
|
(0x61 <= c && c <= 0x7a) || (0x80 <= c && c <= 0xfffd))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL isunialphanum(wchar_t c)
|
|
{
|
|
if(isunialpha(c))
|
|
return TRUE;
|
|
else
|
|
return wbem_iswdigit(c);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPropInfo
|
|
|
|
BOOL CPropInfo::Init(CIMTYPE type)
|
|
{
|
|
m_bPointer = FALSE;
|
|
|
|
switch(type & ~CIM_FLAG_ARRAY)
|
|
{
|
|
case CIM_STRING:
|
|
case CIM_REFERENCE:
|
|
case CIM_DATETIME:
|
|
m_pFunc = CEvent::AddStringW;
|
|
m_dwElementSize = 1;
|
|
m_bCountPrefixNeeded = TRUE;
|
|
m_bPointer = TRUE;
|
|
break;
|
|
|
|
case CIM_REAL32:
|
|
// We can't use AddDWORD because the compiler converts 32-bit
|
|
// floats to 64-bit doubles before pushing them on the stack.
|
|
m_pFunc = CEvent::AddFloat;
|
|
m_dwElementSize = sizeof(float);
|
|
m_bCountPrefixNeeded = FALSE;
|
|
break;
|
|
|
|
case CIM_UINT32:
|
|
case CIM_SINT32:
|
|
m_pFunc = CEvent::AddDWORD;
|
|
m_dwElementSize = sizeof(DWORD);
|
|
m_bCountPrefixNeeded = FALSE;
|
|
break;
|
|
|
|
case CIM_UINT16:
|
|
case CIM_SINT16:
|
|
case CIM_CHAR16:
|
|
case CIM_BOOLEAN:
|
|
m_pFunc = CEvent::AddDWORD;
|
|
m_dwElementSize = sizeof(DWORD);
|
|
m_bCountPrefixNeeded = FALSE;
|
|
break;
|
|
|
|
case CIM_SINT64:
|
|
case CIM_UINT64:
|
|
case CIM_REAL64:
|
|
m_pFunc = CEvent::AddDWORD64;
|
|
m_dwElementSize = sizeof(__int64);
|
|
m_bCountPrefixNeeded = FALSE;
|
|
m_bPointer = TRUE;
|
|
break;
|
|
|
|
case CIM_UINT8:
|
|
case CIM_SINT8:
|
|
m_pFunc = CEvent::AddBYTE;
|
|
m_dwElementSize = sizeof(BYTE);
|
|
m_bCountPrefixNeeded = FALSE;
|
|
break;
|
|
|
|
case CIM_OBJECT:
|
|
m_pFunc = CEvent::AddObject;
|
|
m_dwElementSize = 1;
|
|
m_bCountPrefixNeeded = TRUE;
|
|
m_bPointer = TRUE;
|
|
break;
|
|
|
|
case CIM_IUNKNOWN:
|
|
m_pFunc = CEvent::AddWmiObject;
|
|
m_dwElementSize = 1;
|
|
m_bCountPrefixNeeded = TRUE;
|
|
m_bPointer = TRUE;
|
|
break;
|
|
|
|
default:
|
|
// Bad type passed!
|
|
return FALSE;
|
|
}
|
|
|
|
// Change some things if this is an array.
|
|
if (type & CIM_FLAG_ARRAY)
|
|
{
|
|
m_bPointer = TRUE;
|
|
|
|
// All arrays need to have the number of elements prefixed to the data.
|
|
m_bCountPrefixNeeded = TRUE;
|
|
|
|
if (m_pFunc == CEvent::AddStringW)
|
|
m_pFunc = CEvent::AddStringArray;
|
|
else if ( m_pFunc == CEvent::AddObject ||
|
|
m_pFunc == CEvent::AddWmiObject )
|
|
return FALSE;
|
|
else
|
|
m_pFunc = CEvent::AddScalarArray;
|
|
}
|
|
|
|
if (m_bPointer == FALSE)
|
|
{
|
|
// We no longer need element size, since it's the same as current size.
|
|
// So, set current size and clear element size so we'll ignore it.
|
|
m_dwCurrentSize = m_dwElementSize;
|
|
m_dwElementSize = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CPropInfo::InitCurrentSize(LPBYTE pData)
|
|
{
|
|
DWORD dwTotalSize;
|
|
|
|
if (IsPointer())
|
|
{
|
|
DWORD dwItems = *(DWORD*)pData;
|
|
|
|
if (m_pFunc != CEvent::AddStringArray)
|
|
{
|
|
// This works for all pointer types except for object and string
|
|
// arrays.
|
|
dwTotalSize = dwItems * m_dwElementSize + sizeof(DWORD);
|
|
}
|
|
else
|
|
{
|
|
// Account for the number in the array.
|
|
dwTotalSize = sizeof(DWORD);
|
|
|
|
// For each item in the array, get its size and add it to the total
|
|
// length.
|
|
for (DWORD i = 0; i < dwItems; i++)
|
|
{
|
|
dwTotalSize +=
|
|
sizeof(DWORD) +
|
|
DWORD_ALIGNED(*(DWORD*) (pData + dwTotalSize));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
dwTotalSize = m_dwElementSize;
|
|
|
|
// Align the total size.
|
|
m_dwCurrentSize = dwTotalSize;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEventWrap
|
|
|
|
CEventWrap::CEventWrap(CSink *pSink, DWORD dwFlags) :
|
|
m_bFreeEvent(TRUE)
|
|
{
|
|
m_pEvent = new CEvent(pSink, dwFlags);
|
|
|
|
if ( NULL == m_pEvent )
|
|
{
|
|
throw CX_MemoryException();
|
|
}
|
|
|
|
pSink->AddEvent(m_pEvent);
|
|
}
|
|
|
|
CEventWrap::CEventWrap(CEvent *pEvent, int nIndexes, DWORD *pdwIndexes) :
|
|
m_bFreeEvent(FALSE)
|
|
{
|
|
m_pEvent = pEvent;
|
|
|
|
if ( !m_pIndexes.Init(nIndexes) )
|
|
throw CX_MemoryException();
|
|
|
|
for (int i = 0; i < nIndexes; i++)
|
|
m_pIndexes.AddVal(pdwIndexes[i]);
|
|
}
|
|
|
|
CEventWrap::~CEventWrap()
|
|
{
|
|
if (m_bFreeEvent && m_pEvent)
|
|
{
|
|
if (m_pEvent->m_pSink)
|
|
m_pEvent->m_pSink->RemoveEvent(m_pEvent);
|
|
|
|
delete m_pEvent;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CEvent
|
|
|
|
CEvent::CEvent(CSink *pSink, DWORD dwFlags) :
|
|
m_pSink(pSink),
|
|
CBuffer(DEF_EVENT_DATA_SIZE),
|
|
m_bufferEventLayout(DEF_EVENT_LAYOUT_SIZE),
|
|
m_bLayoutSent(FALSE),
|
|
m_bEnabled(FALSE),
|
|
m_pProps(0),
|
|
m_dwFlags(dwFlags)
|
|
{
|
|
if (IsLockable())
|
|
InitializeCriticalSection(&m_cs);
|
|
}
|
|
|
|
CEvent::~CEvent()
|
|
{
|
|
if (IsLockable())
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
void CEvent::ResetEvent()
|
|
{
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
// Clear all our data.
|
|
m_pCurrent = (LPBYTE) m_pdwHeapData;
|
|
|
|
// Zero out our null table to make everything null.
|
|
ZeroMemory(m_pdwNullTable, m_pdwPropTable - m_pdwNullTable);
|
|
}
|
|
|
|
static DWORD g_dwEventIndex = 0;
|
|
|
|
BOOL CEvent::PrepareEvent(
|
|
LPCWSTR szEventName,
|
|
DWORD nPropertyCount,
|
|
LPCWSTR *pszPropertyNames,
|
|
CIMTYPE *pPropertyTypes)
|
|
{
|
|
DWORD dwEventIndex = InterlockedExchangeAdd((long*) &g_dwEventIndex, 1);
|
|
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
// Setup the event layout buffer.
|
|
m_bufferEventLayout.Reset();
|
|
|
|
m_bufferEventLayout.Write((DWORD) NC_SRVMSG_EVENT_LAYOUT);
|
|
|
|
// This serves as a place holder for the size of the message.
|
|
m_bufferEventLayout.Write((DWORD) 0);
|
|
|
|
m_bufferEventLayout.Write(dwEventIndex);
|
|
|
|
m_bufferEventLayout.Write(m_pSink->GetSinkID());
|
|
|
|
m_bufferEventLayout.Write(nPropertyCount);
|
|
|
|
m_bufferEventLayout.WriteAlignedLenString(szEventName);
|
|
|
|
|
|
// Make this upper case to simplify lookups.
|
|
_wcsupr((LPWSTR) GetClassName());
|
|
|
|
// Setup the main event buffer
|
|
Reset();
|
|
|
|
Write((DWORD) NC_SRVMSG_PREPPED_EVENT);
|
|
|
|
// This serves as a place holder for the size of the message.
|
|
Write((DWORD) 0);
|
|
|
|
Write(dwEventIndex);
|
|
|
|
// This will setup our table pointers.
|
|
RecalcTables();
|
|
|
|
// Set mask to indicate all values are null.
|
|
ZeroMemory(m_pdwNullTable, (LPBYTE) m_pdwPropTable - (LPBYTE) m_pdwNullTable);
|
|
|
|
// Point our buffer to where we'll put all the object data.
|
|
m_pCurrent = (LPBYTE) m_pdwHeapData;
|
|
|
|
m_pProps.Init(nPropertyCount);
|
|
m_pProps.SetCount(nPropertyCount);
|
|
|
|
for (DWORD i = 0; i < nPropertyCount; i++)
|
|
{
|
|
CPropInfo &info = m_pProps[i];
|
|
|
|
if(!info.Init(pPropertyTypes[i]))
|
|
return FALSE;
|
|
|
|
m_bufferEventLayout.Write((DWORD) pPropertyTypes[i]);
|
|
m_bufferEventLayout.WriteAlignedLenString(pszPropertyNames[i]);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CEvent::FindProp(LPCWSTR szName, CIMTYPE* ptype, DWORD* pdwIndex)
|
|
{
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
DWORD dwSize = 0;
|
|
BYTE* pProps = NULL;
|
|
|
|
GetLayoutBuffer(&pProps, &dwSize, FALSE);
|
|
CBuffer Buffer(pProps, dwSize);
|
|
|
|
//
|
|
// Skip the name of the event
|
|
//
|
|
|
|
DWORD dwNumProps = Buffer.ReadDWORD();
|
|
|
|
DWORD dwIgnore;
|
|
Buffer.ReadAlignedLenString(&dwIgnore);
|
|
|
|
for(DWORD i = 0; i < dwNumProps; i++)
|
|
{
|
|
*ptype = Buffer.ReadDWORD();
|
|
LPCWSTR szThisName = Buffer.ReadAlignedLenString(&dwIgnore);
|
|
|
|
if(!wbem_wcsicmp(szName, szThisName))
|
|
{
|
|
*pdwIndex = i;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CEvent::AddProp(LPCWSTR szName, CIMTYPE type, DWORD *pdwIndex)
|
|
{
|
|
//
|
|
// Check the name for validity
|
|
//
|
|
|
|
if(szName[0] == 0)
|
|
return FALSE;
|
|
|
|
const WCHAR* pwc = szName;
|
|
|
|
// Check the first letter
|
|
// ======================
|
|
|
|
if(!isunialpha(*pwc) || *pwc == '_')
|
|
return FALSE;
|
|
pwc++;
|
|
|
|
// Check the rest
|
|
// ==============
|
|
|
|
while(*pwc)
|
|
{
|
|
if(!isunialphanum(*pwc))
|
|
return FALSE;
|
|
pwc++;
|
|
}
|
|
|
|
if(pwc[-1] == '_')
|
|
return FALSE;
|
|
|
|
//
|
|
// Check the type for validity
|
|
//
|
|
|
|
CPropInfo info;
|
|
|
|
if(!info.Init(type))
|
|
return FALSE;
|
|
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
//
|
|
// Check if the property is already there
|
|
//
|
|
|
|
CIMTYPE typeOld;
|
|
DWORD dwOldIndex;
|
|
if(FindProp(szName, &typeOld, &dwOldIndex))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Our layout changed, so make sure we resend it.
|
|
ResetLayoutSent();
|
|
|
|
DWORD nProps = GetPropertyCount();
|
|
BOOL bExtraNullSpaceNeeded;
|
|
DWORD dwHeapMove;
|
|
|
|
// If the caller cares, return the index of this property.
|
|
if (pdwIndex)
|
|
*pdwIndex = nProps;
|
|
|
|
// Increase the number of properties.
|
|
SetPropertyCount(++nProps);
|
|
|
|
// See if we need another DWORD for our null flags.
|
|
bExtraNullSpaceNeeded = (nProps % 32) == 1 && nProps != 1;
|
|
|
|
// Figure how many slots we need to move up the heap pointer.
|
|
// Always one for the new property data/pointer, and maybe one
|
|
// if we need more null space.
|
|
dwHeapMove = 1 + bExtraNullSpaceNeeded;
|
|
|
|
// Move the heap pointer;
|
|
m_pdwHeapData += dwHeapMove;
|
|
|
|
// Convert to number of bytes.
|
|
dwHeapMove *= sizeof(DWORD);
|
|
|
|
// Scoot all property pointers up by the number of bytes the heap moved.
|
|
for (int i = 0; i < nProps - 1; i++)
|
|
{
|
|
if (m_pProps[i].IsPointer())
|
|
m_pdwPropTable[i] += dwHeapMove;
|
|
}
|
|
|
|
// Move the current pointer up.
|
|
MoveCurrent(dwHeapMove);
|
|
|
|
// Slide the property data forward by dwHeapMove bytes.
|
|
memmove(
|
|
m_pdwHeapData,
|
|
(LPBYTE) m_pdwHeapData - dwHeapMove,
|
|
m_pCurrent - (LPBYTE) m_pdwHeapData);
|
|
|
|
// See if we're going to require another DWORD in our null table once
|
|
// we add this property. If so, we have some work to do.
|
|
if (bExtraNullSpaceNeeded)
|
|
{
|
|
DWORD dwTableIndex;
|
|
|
|
// Slide forward the tables by one DWORD.
|
|
m_pdwPropTable++;
|
|
|
|
dwTableIndex = nProps / 32;
|
|
|
|
// Set our new entry in our table to 0 (all props null).
|
|
m_pdwNullTable[dwTableIndex] = 0;
|
|
|
|
// Slide forward the prop data by one slot.
|
|
memmove(
|
|
m_pdwPropTable,
|
|
m_pdwPropTable - 1,
|
|
(LPBYTE) m_pdwHeapData - (LPBYTE) m_pdwNullTable);
|
|
}
|
|
|
|
m_pProps.AddVal(info);
|
|
|
|
m_bufferEventLayout.Write((DWORD) type);
|
|
m_bufferEventLayout.WriteAlignedLenString(szName);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CEvent::SetSinglePropValue(DWORD dwIndex, va_list list)
|
|
{
|
|
PROP_FUNC pFunc;
|
|
BOOL bRet;
|
|
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
//m_pStack = (LPVOID*) pStack;
|
|
m_valist = list;
|
|
m_iCurrentVar = dwIndex;
|
|
|
|
pFunc = m_pProps[dwIndex].m_pFunc;
|
|
|
|
bRet = (this->*pFunc)();
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::SetPropValues(CIntArray *pArr, va_list list)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
// Is this a 'normal' event?
|
|
if (!pArr)
|
|
{
|
|
DWORD nProps = GetPropertyCount();
|
|
|
|
//m_pStack = (LPVOID*) pStack;
|
|
m_valist = list;
|
|
|
|
for (m_iCurrentVar = 0; m_iCurrentVar < nProps && bRet; m_iCurrentVar++)
|
|
{
|
|
PROP_FUNC pFunc = m_pProps[m_iCurrentVar].m_pFunc;
|
|
|
|
bRet = (this->*pFunc)();
|
|
}
|
|
}
|
|
// Must be a property subset.
|
|
else
|
|
{
|
|
DWORD nProps = pArr->GetCount();
|
|
|
|
//m_pStack = (LPVOID*) pStack;
|
|
m_valist = list;
|
|
|
|
for (DWORD i = 0; i < nProps && bRet; i++)
|
|
{
|
|
PROP_FUNC pFunc;
|
|
int iRealIndex = (*pArr)[i];
|
|
|
|
m_iCurrentVar = iRealIndex;
|
|
|
|
pFunc = m_pProps[iRealIndex].m_pFunc;
|
|
|
|
bRet = (this->*pFunc)();
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::SetPropValue(DWORD dwPropIndex, LPVOID pData, DWORD dwElements,
|
|
DWORD dwSize)
|
|
{
|
|
if(dwPropIndex >= GetPropertyCount())
|
|
{
|
|
_ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
if(dwSize == 0)
|
|
{
|
|
_ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
CPropInfo *pProp = &m_pProps[dwPropIndex];
|
|
|
|
if (!pProp->IsPointer())
|
|
{
|
|
SetPropNull(dwPropIndex, FALSE);
|
|
|
|
m_pdwPropTable[dwPropIndex] = *(DWORD*) pData;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL bRet = FALSE;
|
|
BOOL bLengthPrefixed = pProp->CountPrefixed();
|
|
DWORD dwSizeNeeded = bLengthPrefixed ? dwSize + sizeof(DWORD) : dwSize;
|
|
|
|
// Align the size.
|
|
dwSizeNeeded = DWORD_ALIGNED(dwSizeNeeded);
|
|
|
|
// If the value is null we'll have to make some room for the new value.
|
|
if (IsPropNull(dwPropIndex))
|
|
{
|
|
LPBYTE pStart;
|
|
|
|
// Increase our buffer size.
|
|
MoveCurrent(dwSizeNeeded);
|
|
|
|
// Make sure we get this after we call MoveCurrent, in case the
|
|
// buffer is reallocated.
|
|
pStart = m_pCurrent - dwSizeNeeded;
|
|
|
|
// Copy in the new value.
|
|
if (bLengthPrefixed)
|
|
{
|
|
*((DWORD*) pStart) = dwElements;
|
|
|
|
if (pData)
|
|
memcpy(pStart + sizeof(DWORD), pData, dwSize);
|
|
}
|
|
else
|
|
{
|
|
if (pData)
|
|
memcpy(pStart, pData, dwSize);
|
|
}
|
|
|
|
// Set this value as non-null.
|
|
SetPropNull(dwPropIndex, FALSE);
|
|
|
|
// Point to our new data.
|
|
m_pdwPropTable[dwPropIndex] = pStart - m_pBuffer;
|
|
|
|
pProp->m_dwCurrentSize = dwSizeNeeded;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else // Value is currently non-null.
|
|
{
|
|
// Does the old size match the new one? If so, just copy it in.
|
|
if (pProp->m_dwCurrentSize == dwSizeNeeded)
|
|
{
|
|
if (pData)
|
|
{
|
|
DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
|
|
LPBYTE pPropData = m_pBuffer + dwDataOffset;
|
|
|
|
// We always have to copy this in because the elements can
|
|
// vary for the same current size because of DWORD aligning.
|
|
*((DWORD*) pPropData) = dwElements;
|
|
|
|
if (bLengthPrefixed)
|
|
memcpy(pPropData + sizeof(DWORD), pData, dwSize);
|
|
else
|
|
memcpy(pPropData, pData, dwSize);
|
|
}
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else // If the sizes don't match we have a little more work to do.
|
|
{
|
|
int iSizeDiff = dwSizeNeeded - pProp->m_dwCurrentSize;
|
|
DWORD dwOldCurrentOffset = m_pCurrent - m_pBuffer;
|
|
|
|
// Change our buffer size.
|
|
// This has to be done before we get the pointers below, because
|
|
// MoveCurrent can potentially get our buffer reallocated.
|
|
MoveCurrent(iSizeDiff);
|
|
|
|
DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
|
|
LPBYTE pPropData = m_pBuffer + dwDataOffset;
|
|
LPBYTE pOldDataEnd = pPropData + pProp->m_dwCurrentSize;
|
|
|
|
memmove(
|
|
pOldDataEnd + iSizeDiff,
|
|
pOldDataEnd,
|
|
m_pBuffer + dwOldCurrentOffset - pOldDataEnd);
|
|
|
|
// Copy in the new value.
|
|
if (bLengthPrefixed)
|
|
{
|
|
*((DWORD*) pPropData) = dwElements;
|
|
|
|
if (pData)
|
|
memcpy(pPropData + sizeof(DWORD), pData, dwSize);
|
|
}
|
|
else
|
|
{
|
|
if (pData)
|
|
memcpy(pPropData, pData, dwSize);
|
|
}
|
|
|
|
// Init this property's data.
|
|
pProp->m_dwCurrentSize = dwSizeNeeded;
|
|
|
|
// Increment all the data pointers by the amount we just added.
|
|
CPropInfo *pProps = m_pProps.GetData();
|
|
|
|
// We have to look at them all since we're now allowing properties
|
|
// to store data in the heap non-sequentially (e.g. property 3
|
|
// can point to data that comes after property 4's data).
|
|
DWORD nProps = GetPropertyCount();
|
|
|
|
for (DWORD i = 0; i < nProps; i++)
|
|
{
|
|
if (pProps[i].IsPointer() && m_pdwPropTable[i] > dwDataOffset)
|
|
m_pdwPropTable[i] += iSizeDiff;
|
|
}
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::SetPropNull(DWORD dwPropIndex)
|
|
{
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
if(dwPropIndex >= GetPropertyCount())
|
|
{
|
|
_ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
// Only do something if the value isn't already null.
|
|
if (!IsPropNull(dwPropIndex))
|
|
{
|
|
// Mark the given index as null.
|
|
SetPropNull(dwPropIndex, TRUE);
|
|
|
|
if (m_pProps[dwPropIndex].IsPointer())
|
|
{
|
|
CPropInfo *pProps = m_pProps.GetData();
|
|
DWORD nProps = GetPropertyCount(),
|
|
dwSizeToRemove = pProps[dwPropIndex].m_dwCurrentSize;
|
|
DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
|
|
LPBYTE pDataToRemove = m_pBuffer + dwDataOffset;
|
|
|
|
// Slide up all the data that comes after the one we're nulling
|
|
// out.
|
|
memmove(
|
|
pDataToRemove,
|
|
pDataToRemove + dwSizeToRemove,
|
|
m_pCurrent - pDataToRemove - dwSizeToRemove);
|
|
|
|
// Reduce the size of our send buffer.
|
|
MoveCurrent(-dwSizeToRemove);
|
|
|
|
// Decrement all the data pointers by the amount we just removed.
|
|
for (DWORD i = 0; i < nProps; i++)
|
|
{
|
|
if (pProps[i].IsPointer() &&
|
|
m_pdwPropTable[i] > dwDataOffset)
|
|
{
|
|
m_pdwPropTable[i] -= dwSizeToRemove;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LPBYTE CEvent::GetPropData(DWORD dwPropIndex)
|
|
{
|
|
CPropInfo *pProp = &m_pProps[dwPropIndex];
|
|
LPBYTE pData;
|
|
|
|
if (pProp->IsPointer())
|
|
{
|
|
DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
|
|
|
|
pData = m_pBuffer + dwDataOffset;
|
|
}
|
|
else
|
|
pData = (LPBYTE) &m_pdwPropTable[dwPropIndex];
|
|
|
|
return pData;
|
|
}
|
|
|
|
BOOL CEvent::GetPropValue(
|
|
DWORD dwPropIndex,
|
|
LPVOID pData,
|
|
DWORD dwBufferSize,
|
|
DWORD *pdwBytesRead)
|
|
{
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
if(dwPropIndex >= GetPropertyCount())
|
|
{
|
|
_ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
if(dwBufferSize == 0)
|
|
{
|
|
_ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
// If the value is non-null then read it.
|
|
if (!IsPropNull(dwPropIndex))
|
|
{
|
|
CPropInfo *pProp = &m_pProps[dwPropIndex];
|
|
DWORD dwSizeToRead = pProp->m_dwCurrentSize;
|
|
LPBYTE pPropData = GetPropData(dwPropIndex);
|
|
|
|
// Get rid of the prefix if there is any.
|
|
if (pProp->CountPrefixed())
|
|
{
|
|
pPropData += sizeof(DWORD);
|
|
dwSizeToRead -= sizeof(DWORD);
|
|
}
|
|
|
|
// Make sure we have enough room for the output data.
|
|
if (dwBufferSize >= dwSizeToRead)
|
|
{
|
|
memcpy(pData, pPropData, dwSizeToRead);
|
|
*pdwBytesRead = dwSizeToRead;
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pdwBytesRead = 0;
|
|
bRet = TRUE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddStringW()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
LPCWSTR szVal = va_arg(m_valist, LPCWSTR);
|
|
|
|
if (!szVal)
|
|
SetPropNull(m_iCurrentVar);
|
|
else
|
|
{
|
|
DWORD dwLen = (wcslen(szVal) + 1) * sizeof(WCHAR);
|
|
|
|
bRet =
|
|
SetPropValue(
|
|
m_iCurrentVar,
|
|
(LPVOID) szVal,
|
|
dwLen, // This will be written into the buffer as the size
|
|
// of the string.
|
|
dwLen); // The number of bytes we need.
|
|
}
|
|
|
|
//m_pStack++;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddScalarArray()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
LPBYTE pData = va_arg(m_valist, LPBYTE);
|
|
DWORD dwElements = va_arg(m_valist, DWORD);
|
|
|
|
if (!pData)
|
|
SetPropNull(m_iCurrentVar);
|
|
else
|
|
{
|
|
DWORD dwSize;
|
|
|
|
// The caller gives us the number of elements in the array. So,
|
|
// multiply the number of elements by the element size.
|
|
dwSize = m_pProps[m_iCurrentVar].m_dwElementSize * dwElements;
|
|
|
|
bRet = SetPropValue(m_iCurrentVar, pData, dwElements, dwSize);
|
|
|
|
// Moves past the LPVOID and the DWORD.
|
|
//m_pStack += 2;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL CEvent::AddStringArray()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
LPCWSTR *pszStrings = va_arg(m_valist, LPCWSTR*);
|
|
DWORD dwItems = va_arg(m_valist, DWORD);
|
|
|
|
if (!pszStrings)
|
|
SetPropNull(m_iCurrentVar);
|
|
else
|
|
{
|
|
// Copy the strings into our buffer.
|
|
DWORD dwTotalLen = 0;
|
|
|
|
// Calculate the total length.
|
|
for (DWORD i = 0; i < dwItems; i++)
|
|
{
|
|
// The amount of buffer each string takes must be DWORD aligned.
|
|
dwTotalLen += DWORD_ALIGNED(wcslen(pszStrings[i]) + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
// Account for the DWORDs before each string.
|
|
dwTotalLen += sizeof(DWORD) * dwItems;
|
|
|
|
// Use a NULL for the data pointer to just make room for the strings
|
|
// without copying in the data.
|
|
bRet = SetPropValue(m_iCurrentVar, NULL, dwItems, dwTotalLen);
|
|
|
|
if (bRet)
|
|
{
|
|
// Copy the strings into our buffer.
|
|
LPBYTE pCurrent = GetPropData(m_iCurrentVar) + sizeof(DWORD);
|
|
|
|
for (DWORD i = 0; i < dwItems; i++)
|
|
{
|
|
DWORD dwLen = (wcslen(pszStrings[i]) + 1) * sizeof(WCHAR);
|
|
|
|
// Add the prefixed size.
|
|
*(DWORD*) pCurrent = dwLen;
|
|
|
|
// Copy in the string. Don't use an aligned len because
|
|
// we only copy exactly dwLen bytes.
|
|
memcpy(pCurrent + sizeof(DWORD), pszStrings[i], dwLen);
|
|
|
|
pCurrent +=
|
|
sizeof(DWORD) +
|
|
DWORD_ALIGNED(*(DWORD*) pCurrent);
|
|
}
|
|
|
|
// Moves past the LPVOID and the DWORD.
|
|
//m_pStack += 2;
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddObject()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
HANDLE hEvent = va_arg(m_valist, HANDLE);
|
|
|
|
if (!hEvent)
|
|
SetPropNull(m_iCurrentVar);
|
|
else
|
|
{
|
|
CEvent *pEvent = ((CEventWrap*) hEvent)->GetEvent();
|
|
DWORD dwTotalLen,
|
|
dwLayoutLen,
|
|
dwDataLen;
|
|
LPBYTE pLayout,
|
|
pData;
|
|
|
|
pEvent->GetLayoutBuffer(&pLayout, &dwLayoutLen, FALSE);
|
|
pEvent->GetDataBuffer(&pData, &dwDataLen, FALSE);
|
|
|
|
dwTotalLen = dwLayoutLen + dwDataLen;
|
|
|
|
// Use a NULL for the data pointer to just make room for the event
|
|
// buffers without copying in the data.
|
|
// Note that because the property has m_bCountPrefixNeeded set to
|
|
// TRUE, SetPropValue will write in the 3rd argument (the length of
|
|
// the object) into the first DWORD.
|
|
bRet =
|
|
SetPropValue(
|
|
m_iCurrentVar,
|
|
NULL,
|
|
// Aligned since this will represent the size of the buffer
|
|
// taken by the object.
|
|
DWORD_ALIGNED(dwTotalLen),
|
|
// This one should not be aligned because it's the literal number
|
|
// of bytes we're going to copy into the buffer.
|
|
dwTotalLen);
|
|
|
|
if (bRet)
|
|
{
|
|
// Now that we have some room, copy in the data.
|
|
// The sizeof(DWORD) gets us past the length of the object.
|
|
LPBYTE pDestData = GetPropData(m_iCurrentVar) + sizeof(DWORD);
|
|
|
|
memcpy(pDestData, pLayout, dwLayoutLen);
|
|
memcpy(pDestData + dwLayoutLen, pData, dwDataLen);
|
|
}
|
|
}
|
|
|
|
//m_pStack++;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL CEvent::AddWmiObject()
|
|
{
|
|
BOOL bRet = TRUE;
|
|
_IWmiObject *pObj =
|
|
(_IWmiObject*) (IWbemClassObject*) va_arg(m_valist, IWbemClassObject*);
|
|
|
|
if (!pObj)
|
|
SetPropNull(m_iCurrentVar);
|
|
else
|
|
{
|
|
DWORD dwTotalLen = 0;
|
|
HRESULT hr;
|
|
|
|
hr =
|
|
pObj->GetObjectParts(
|
|
NULL,
|
|
0,
|
|
WBEM_OBJ_DECORATION_PART | WBEM_OBJ_INSTANCE_PART |
|
|
WBEM_OBJ_CLASS_PART,
|
|
&dwTotalLen);
|
|
|
|
// This should never happen, but just in case...
|
|
if (hr != WBEM_E_BUFFER_TOO_SMALL)
|
|
return FALSE;
|
|
|
|
// Use a NULL for the data pointer to just make room for the event
|
|
// buffers without copying in the data.
|
|
// Note that because the property has m_bCountPrefixNeeded set to
|
|
// TRUE, SetPropValue will write in the 3rd argument (the length of
|
|
// the object) into the first DWORD.
|
|
bRet =
|
|
SetPropValue(
|
|
m_iCurrentVar,
|
|
NULL,
|
|
// Aligned since this will represent the size of the buffer
|
|
// taken by the object.
|
|
DWORD_ALIGNED(dwTotalLen),
|
|
// This one should not be aligned because it's the literal number
|
|
// of bytes we're going to copy into the buffer.
|
|
dwTotalLen);
|
|
|
|
if (bRet)
|
|
{
|
|
// Now that we have some room, copy in the data.
|
|
// The sizeof(DWORD) gets us past the length of the object.
|
|
LPBYTE pDestData = GetPropData(m_iCurrentVar) + sizeof(DWORD);
|
|
|
|
hr =
|
|
pObj->GetObjectParts(
|
|
pDestData,
|
|
dwTotalLen,
|
|
WBEM_OBJ_DECORATION_PART | WBEM_OBJ_INSTANCE_PART |
|
|
WBEM_OBJ_CLASS_PART,
|
|
&dwTotalLen);
|
|
|
|
bRet = SUCCEEDED(hr);
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddBYTE()
|
|
{
|
|
BYTE cData = va_arg(m_valist, BYTE);
|
|
BOOL bRet = SetPropValue(m_iCurrentVar, &cData, 1, sizeof(BYTE));
|
|
|
|
//m_pStack++;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddWORD()
|
|
{
|
|
WORD wData = va_arg(m_valist, WORD);
|
|
BOOL bRet =
|
|
SetPropValue(m_iCurrentVar, &wData, 1, sizeof(WORD));
|
|
|
|
//m_pStack++;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddDWORD()
|
|
{
|
|
DWORD dwData = va_arg(m_valist, DWORD);
|
|
BOOL bRet = SetPropValue(m_iCurrentVar, &dwData, 1, sizeof(DWORD));
|
|
|
|
//m_pStack++;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddFloat()
|
|
{
|
|
// The compiler pushes 64-bit doubles when passing floats, so we'll have
|
|
// to first convert it to a 32-bit float.
|
|
//float fValue = (float) *(double*) m_pStack;
|
|
float fValue = va_arg(m_valist, double);
|
|
BOOL bRet = SetPropValue(m_iCurrentVar, &fValue, 1, sizeof(float));
|
|
|
|
// Account for the 64-bits passed on the stack.
|
|
//m_pStack += 2;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::AddDWORD64()
|
|
{
|
|
DWORD64 dwData = va_arg(m_valist, DWORD64);
|
|
BOOL bRet = SetPropValue(m_iCurrentVar, &dwData, 1, sizeof(DWORD64));
|
|
|
|
// To get past both DWORDs.
|
|
//m_pStack += 2;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL CEvent::SendEvent()
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
if (IsEnabled())
|
|
{
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
if (!m_bLayoutSent)
|
|
{
|
|
DWORD dwLayoutSize = m_bufferEventLayout.GetUsedSize();
|
|
|
|
// Embed the layout size in the message.
|
|
((DWORD*) m_bufferEventLayout.m_pBuffer)[1] = dwLayoutSize;
|
|
|
|
m_bLayoutSent =
|
|
m_pSink->GetConnection()->SendData(
|
|
m_bufferEventLayout.m_pBuffer,
|
|
dwLayoutSize);
|
|
}
|
|
|
|
if (m_bLayoutSent)
|
|
{
|
|
DWORD dwDataSize = GetUsedSize();
|
|
|
|
// Embed the data buffer size in the message.
|
|
((DWORD*) m_pBuffer)[1] = dwDataSize;
|
|
|
|
bRet = m_pSink->GetConnection()->SendData(m_pBuffer, dwDataSize);
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
void CEvent::GetLayoutBuffer(
|
|
LPBYTE *ppBuffer,
|
|
DWORD *pdwSize,
|
|
BOOL bIncludeHeader)
|
|
{
|
|
DWORD dwHeaderSize = bIncludeHeader ? 0 : sizeof(DWORD) * 4;
|
|
|
|
// Get past the header stuff.
|
|
*ppBuffer = m_bufferEventLayout.m_pBuffer + dwHeaderSize;
|
|
|
|
// Subtract off the header stuff.
|
|
*pdwSize = m_bufferEventLayout.GetUsedSize() - dwHeaderSize;
|
|
}
|
|
|
|
void CEvent::GetDataBuffer(
|
|
LPBYTE *ppBuffer,
|
|
DWORD *pdwSize,
|
|
BOOL bIncludeHeader)
|
|
{
|
|
DWORD dwHeaderSize = bIncludeHeader ? 0 : sizeof(DWORD) * 3;
|
|
|
|
// Get past the header stuff.
|
|
*ppBuffer = m_pBuffer + dwHeaderSize;
|
|
|
|
// Subtract off the header stuff.
|
|
*pdwSize = GetUsedSize() - dwHeaderSize;
|
|
}
|
|
|
|
BOOL CEvent::SetLayoutAndDataBuffers(
|
|
LPBYTE pLayoutBuffer,
|
|
DWORD dwLayoutBufferSize,
|
|
LPBYTE pDataBuffer,
|
|
DWORD dwDataBufferSize)
|
|
{
|
|
DWORD dwEventIndex = InterlockedExchangeAdd((long*) &g_dwEventIndex, 1);
|
|
int nProps;
|
|
|
|
CCondInCritSec cs(&m_cs, IsLockable());
|
|
|
|
// Setup the event layout buffer.
|
|
m_bufferEventLayout.Reset();
|
|
|
|
// Set the layout buffer.
|
|
m_bufferEventLayout.Write(pLayoutBuffer, dwLayoutBufferSize);
|
|
|
|
// Add the new index we just created.
|
|
*(((DWORD*) m_bufferEventLayout.m_pBuffer) + 1) = dwEventIndex;
|
|
|
|
// Get the number of props from the layout buffer.
|
|
nProps = GetPropertyCount();
|
|
|
|
// Setup the main event buffer
|
|
Reset();
|
|
Write(pDataBuffer, dwDataBufferSize);
|
|
|
|
// Add the new index we just created.
|
|
*(((DWORD*) m_pBuffer) + 1) = dwEventIndex;
|
|
|
|
m_pProps.Init(nProps);
|
|
m_pProps.SetCount(nProps);
|
|
|
|
// Setup our data tables.
|
|
RecalcTables();
|
|
|
|
LPBYTE pLayoutCurrent =
|
|
// Get past the header and property count.
|
|
(m_bufferEventLayout.m_pBuffer + sizeof(DWORD) * 5);
|
|
|
|
// Get past the event name.
|
|
pLayoutCurrent += sizeof(DWORD) + DWORD_ALIGNED(*(DWORD*) pLayoutCurrent);
|
|
|
|
// For each non-null pointer property, figure out the property's size.
|
|
for (DWORD i = 0; i < nProps; i++)
|
|
{
|
|
CPropInfo &info = m_pProps[i];
|
|
CIMTYPE dwType = *(DWORD*) pLayoutCurrent;
|
|
|
|
info.Init(dwType);
|
|
|
|
// Get past the type, the length of the property name, and the property
|
|
// name itself.
|
|
pLayoutCurrent +=
|
|
sizeof(DWORD) * 2 +
|
|
DWORD_ALIGNED(*(DWORD*) (pLayoutCurrent + sizeof(DWORD)));
|
|
|
|
if (!IsPropNull(i) && info.IsPointer())
|
|
{
|
|
LPBYTE pData = GetPropData(i);
|
|
|
|
info.InitCurrentSize(pData);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#define DEF_HEAP_EXTRA 256
|
|
|
|
void CEvent::RecalcTables()
|
|
{
|
|
DWORD nProps = GetPropertyCount(),
|
|
dwNullSize;
|
|
|
|
m_pdwNullTable = (DWORD*) (m_pBuffer + sizeof(DWORD) * 3);
|
|
dwNullSize = (nProps + 31) / 32;
|
|
if (!dwNullSize)
|
|
dwNullSize = 1;
|
|
|
|
m_pdwPropTable = m_pdwNullTable + dwNullSize;
|
|
|
|
m_pdwHeapData = m_pdwPropTable + nProps;
|
|
|
|
DWORD dwSize = (LPBYTE) m_pdwHeapData - m_pCurrent;
|
|
|
|
if ((LPBYTE) m_pdwHeapData - m_pBuffer > m_dwSize)
|
|
Resize((LPBYTE) m_pdwHeapData - m_pBuffer + DEF_HEAP_EXTRA);
|
|
|
|
dwSize = m_pCurrent - (LPBYTE) m_pdwHeapData;
|
|
}
|
|
|