Leaked source code of windows server 2003
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

// 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;
}