// Event.cpp #include "precomp.h" #include "buffer.h" #include "Connection.h" #include "Event.h" #include "NCDefs.h" #include #include #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; }