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

  1. // Event.cpp
  2. #include "precomp.h"
  3. #include "buffer.h"
  4. #include "Connection.h"
  5. #include "Event.h"
  6. #include "NCDefs.h"
  7. #include <corex.h>
  8. #include <strutils.h>
  9. #define DEF_EVENT_DATA_SIZE 512
  10. #define DEF_EVENT_LAYOUT_SIZE 256
  11. #define DWORD_ALIGNED(x) ((DWORD)((((x) * 8) + 31) & (~31)) / 8)
  12. BOOL isunialpha(wchar_t c)
  13. {
  14. if(c == 0x5f || (0x41 <= c && c <= 0x5a) ||
  15. (0x61 <= c && c <= 0x7a) || (0x80 <= c && c <= 0xfffd))
  16. return TRUE;
  17. else
  18. return FALSE;
  19. }
  20. BOOL isunialphanum(wchar_t c)
  21. {
  22. if(isunialpha(c))
  23. return TRUE;
  24. else
  25. return wbem_iswdigit(c);
  26. }
  27. /////////////////////////////////////////////////////////////////////////////
  28. // CPropInfo
  29. BOOL CPropInfo::Init(CIMTYPE type)
  30. {
  31. m_bPointer = FALSE;
  32. switch(type & ~CIM_FLAG_ARRAY)
  33. {
  34. case CIM_STRING:
  35. case CIM_REFERENCE:
  36. case CIM_DATETIME:
  37. m_pFunc = CEvent::AddStringW;
  38. m_dwElementSize = 1;
  39. m_bCountPrefixNeeded = TRUE;
  40. m_bPointer = TRUE;
  41. break;
  42. case CIM_REAL32:
  43. // We can't use AddDWORD because the compiler converts 32-bit
  44. // floats to 64-bit doubles before pushing them on the stack.
  45. m_pFunc = CEvent::AddFloat;
  46. m_dwElementSize = sizeof(float);
  47. m_bCountPrefixNeeded = FALSE;
  48. break;
  49. case CIM_UINT32:
  50. case CIM_SINT32:
  51. m_pFunc = CEvent::AddDWORD;
  52. m_dwElementSize = sizeof(DWORD);
  53. m_bCountPrefixNeeded = FALSE;
  54. break;
  55. case CIM_UINT16:
  56. case CIM_SINT16:
  57. case CIM_CHAR16:
  58. case CIM_BOOLEAN:
  59. m_pFunc = CEvent::AddDWORD;
  60. m_dwElementSize = sizeof(DWORD);
  61. m_bCountPrefixNeeded = FALSE;
  62. break;
  63. case CIM_SINT64:
  64. case CIM_UINT64:
  65. case CIM_REAL64:
  66. m_pFunc = CEvent::AddDWORD64;
  67. m_dwElementSize = sizeof(__int64);
  68. m_bCountPrefixNeeded = FALSE;
  69. m_bPointer = TRUE;
  70. break;
  71. case CIM_UINT8:
  72. case CIM_SINT8:
  73. m_pFunc = CEvent::AddBYTE;
  74. m_dwElementSize = sizeof(BYTE);
  75. m_bCountPrefixNeeded = FALSE;
  76. break;
  77. case CIM_OBJECT:
  78. m_pFunc = CEvent::AddObject;
  79. m_dwElementSize = 1;
  80. m_bCountPrefixNeeded = TRUE;
  81. m_bPointer = TRUE;
  82. break;
  83. case CIM_IUNKNOWN:
  84. m_pFunc = CEvent::AddWmiObject;
  85. m_dwElementSize = 1;
  86. m_bCountPrefixNeeded = TRUE;
  87. m_bPointer = TRUE;
  88. break;
  89. default:
  90. // Bad type passed!
  91. return FALSE;
  92. }
  93. // Change some things if this is an array.
  94. if (type & CIM_FLAG_ARRAY)
  95. {
  96. m_bPointer = TRUE;
  97. // All arrays need to have the number of elements prefixed to the data.
  98. m_bCountPrefixNeeded = TRUE;
  99. if (m_pFunc == CEvent::AddStringW)
  100. m_pFunc = CEvent::AddStringArray;
  101. else if ( m_pFunc == CEvent::AddObject ||
  102. m_pFunc == CEvent::AddWmiObject )
  103. return FALSE;
  104. else
  105. m_pFunc = CEvent::AddScalarArray;
  106. }
  107. if (m_bPointer == FALSE)
  108. {
  109. // We no longer need element size, since it's the same as current size.
  110. // So, set current size and clear element size so we'll ignore it.
  111. m_dwCurrentSize = m_dwElementSize;
  112. m_dwElementSize = 0;
  113. }
  114. return TRUE;
  115. }
  116. void CPropInfo::InitCurrentSize(LPBYTE pData)
  117. {
  118. DWORD dwTotalSize;
  119. if (IsPointer())
  120. {
  121. DWORD dwItems = *(DWORD*)pData;
  122. if (m_pFunc != CEvent::AddStringArray)
  123. {
  124. // This works for all pointer types except for object and string
  125. // arrays.
  126. dwTotalSize = dwItems * m_dwElementSize + sizeof(DWORD);
  127. }
  128. else
  129. {
  130. // Account for the number in the array.
  131. dwTotalSize = sizeof(DWORD);
  132. // For each item in the array, get its size and add it to the total
  133. // length.
  134. for (DWORD i = 0; i < dwItems; i++)
  135. {
  136. dwTotalSize +=
  137. sizeof(DWORD) +
  138. DWORD_ALIGNED(*(DWORD*) (pData + dwTotalSize));
  139. }
  140. }
  141. }
  142. else
  143. dwTotalSize = m_dwElementSize;
  144. // Align the total size.
  145. m_dwCurrentSize = dwTotalSize;
  146. }
  147. /////////////////////////////////////////////////////////////////////////////
  148. // CEventWrap
  149. CEventWrap::CEventWrap(CSink *pSink, DWORD dwFlags) :
  150. m_bFreeEvent(TRUE)
  151. {
  152. m_pEvent = new CEvent(pSink, dwFlags);
  153. if ( NULL == m_pEvent )
  154. {
  155. throw CX_MemoryException();
  156. }
  157. pSink->AddEvent(m_pEvent);
  158. }
  159. CEventWrap::CEventWrap(CEvent *pEvent, int nIndexes, DWORD *pdwIndexes) :
  160. m_bFreeEvent(FALSE)
  161. {
  162. m_pEvent = pEvent;
  163. if ( !m_pIndexes.Init(nIndexes) )
  164. throw CX_MemoryException();
  165. for (int i = 0; i < nIndexes; i++)
  166. m_pIndexes.AddVal(pdwIndexes[i]);
  167. }
  168. CEventWrap::~CEventWrap()
  169. {
  170. if (m_bFreeEvent && m_pEvent)
  171. {
  172. if (m_pEvent->m_pSink)
  173. m_pEvent->m_pSink->RemoveEvent(m_pEvent);
  174. delete m_pEvent;
  175. }
  176. }
  177. /////////////////////////////////////////////////////////////////////////////
  178. // CEvent
  179. CEvent::CEvent(CSink *pSink, DWORD dwFlags) :
  180. m_pSink(pSink),
  181. CBuffer(DEF_EVENT_DATA_SIZE),
  182. m_bufferEventLayout(DEF_EVENT_LAYOUT_SIZE),
  183. m_bLayoutSent(FALSE),
  184. m_bEnabled(FALSE),
  185. m_pProps(0),
  186. m_dwFlags(dwFlags)
  187. {
  188. if (IsLockable())
  189. InitializeCriticalSection(&m_cs);
  190. }
  191. CEvent::~CEvent()
  192. {
  193. if (IsLockable())
  194. DeleteCriticalSection(&m_cs);
  195. }
  196. void CEvent::ResetEvent()
  197. {
  198. CCondInCritSec cs(&m_cs, IsLockable());
  199. // Clear all our data.
  200. m_pCurrent = (LPBYTE) m_pdwHeapData;
  201. // Zero out our null table to make everything null.
  202. ZeroMemory(m_pdwNullTable, m_pdwPropTable - m_pdwNullTable);
  203. }
  204. static DWORD g_dwEventIndex = 0;
  205. BOOL CEvent::PrepareEvent(
  206. LPCWSTR szEventName,
  207. DWORD nPropertyCount,
  208. LPCWSTR *pszPropertyNames,
  209. CIMTYPE *pPropertyTypes)
  210. {
  211. DWORD dwEventIndex = InterlockedExchangeAdd((long*) &g_dwEventIndex, 1);
  212. CCondInCritSec cs(&m_cs, IsLockable());
  213. // Setup the event layout buffer.
  214. m_bufferEventLayout.Reset();
  215. m_bufferEventLayout.Write((DWORD) NC_SRVMSG_EVENT_LAYOUT);
  216. // This serves as a place holder for the size of the message.
  217. m_bufferEventLayout.Write((DWORD) 0);
  218. m_bufferEventLayout.Write(dwEventIndex);
  219. m_bufferEventLayout.Write(m_pSink->GetSinkID());
  220. m_bufferEventLayout.Write(nPropertyCount);
  221. m_bufferEventLayout.WriteAlignedLenString(szEventName);
  222. // Make this upper case to simplify lookups.
  223. _wcsupr((LPWSTR) GetClassName());
  224. // Setup the main event buffer
  225. Reset();
  226. Write((DWORD) NC_SRVMSG_PREPPED_EVENT);
  227. // This serves as a place holder for the size of the message.
  228. Write((DWORD) 0);
  229. Write(dwEventIndex);
  230. // This will setup our table pointers.
  231. RecalcTables();
  232. // Set mask to indicate all values are null.
  233. ZeroMemory(m_pdwNullTable, (LPBYTE) m_pdwPropTable - (LPBYTE) m_pdwNullTable);
  234. // Point our buffer to where we'll put all the object data.
  235. m_pCurrent = (LPBYTE) m_pdwHeapData;
  236. m_pProps.Init(nPropertyCount);
  237. m_pProps.SetCount(nPropertyCount);
  238. for (DWORD i = 0; i < nPropertyCount; i++)
  239. {
  240. CPropInfo &info = m_pProps[i];
  241. if(!info.Init(pPropertyTypes[i]))
  242. return FALSE;
  243. m_bufferEventLayout.Write((DWORD) pPropertyTypes[i]);
  244. m_bufferEventLayout.WriteAlignedLenString(pszPropertyNames[i]);
  245. }
  246. return TRUE;
  247. }
  248. BOOL CEvent::FindProp(LPCWSTR szName, CIMTYPE* ptype, DWORD* pdwIndex)
  249. {
  250. CCondInCritSec cs(&m_cs, IsLockable());
  251. DWORD dwSize = 0;
  252. BYTE* pProps = NULL;
  253. GetLayoutBuffer(&pProps, &dwSize, FALSE);
  254. CBuffer Buffer(pProps, dwSize);
  255. //
  256. // Skip the name of the event
  257. //
  258. DWORD dwNumProps = Buffer.ReadDWORD();
  259. DWORD dwIgnore;
  260. Buffer.ReadAlignedLenString(&dwIgnore);
  261. for(DWORD i = 0; i < dwNumProps; i++)
  262. {
  263. *ptype = Buffer.ReadDWORD();
  264. LPCWSTR szThisName = Buffer.ReadAlignedLenString(&dwIgnore);
  265. if(!wbem_wcsicmp(szName, szThisName))
  266. {
  267. *pdwIndex = i;
  268. return TRUE;
  269. }
  270. }
  271. return FALSE;
  272. }
  273. BOOL CEvent::AddProp(LPCWSTR szName, CIMTYPE type, DWORD *pdwIndex)
  274. {
  275. //
  276. // Check the name for validity
  277. //
  278. if(szName[0] == 0)
  279. return FALSE;
  280. const WCHAR* pwc = szName;
  281. // Check the first letter
  282. // ======================
  283. if(!isunialpha(*pwc) || *pwc == '_')
  284. return FALSE;
  285. pwc++;
  286. // Check the rest
  287. // ==============
  288. while(*pwc)
  289. {
  290. if(!isunialphanum(*pwc))
  291. return FALSE;
  292. pwc++;
  293. }
  294. if(pwc[-1] == '_')
  295. return FALSE;
  296. //
  297. // Check the type for validity
  298. //
  299. CPropInfo info;
  300. if(!info.Init(type))
  301. return FALSE;
  302. CCondInCritSec cs(&m_cs, IsLockable());
  303. //
  304. // Check if the property is already there
  305. //
  306. CIMTYPE typeOld;
  307. DWORD dwOldIndex;
  308. if(FindProp(szName, &typeOld, &dwOldIndex))
  309. {
  310. return FALSE;
  311. }
  312. // Our layout changed, so make sure we resend it.
  313. ResetLayoutSent();
  314. DWORD nProps = GetPropertyCount();
  315. BOOL bExtraNullSpaceNeeded;
  316. DWORD dwHeapMove;
  317. // If the caller cares, return the index of this property.
  318. if (pdwIndex)
  319. *pdwIndex = nProps;
  320. // Increase the number of properties.
  321. SetPropertyCount(++nProps);
  322. // See if we need another DWORD for our null flags.
  323. bExtraNullSpaceNeeded = (nProps % 32) == 1 && nProps != 1;
  324. // Figure how many slots we need to move up the heap pointer.
  325. // Always one for the new property data/pointer, and maybe one
  326. // if we need more null space.
  327. dwHeapMove = 1 + bExtraNullSpaceNeeded;
  328. // Move the heap pointer;
  329. m_pdwHeapData += dwHeapMove;
  330. // Convert to number of bytes.
  331. dwHeapMove *= sizeof(DWORD);
  332. // Scoot all property pointers up by the number of bytes the heap moved.
  333. for (int i = 0; i < nProps - 1; i++)
  334. {
  335. if (m_pProps[i].IsPointer())
  336. m_pdwPropTable[i] += dwHeapMove;
  337. }
  338. // Move the current pointer up.
  339. MoveCurrent(dwHeapMove);
  340. // Slide the property data forward by dwHeapMove bytes.
  341. memmove(
  342. m_pdwHeapData,
  343. (LPBYTE) m_pdwHeapData - dwHeapMove,
  344. m_pCurrent - (LPBYTE) m_pdwHeapData);
  345. // See if we're going to require another DWORD in our null table once
  346. // we add this property. If so, we have some work to do.
  347. if (bExtraNullSpaceNeeded)
  348. {
  349. DWORD dwTableIndex;
  350. // Slide forward the tables by one DWORD.
  351. m_pdwPropTable++;
  352. dwTableIndex = nProps / 32;
  353. // Set our new entry in our table to 0 (all props null).
  354. m_pdwNullTable[dwTableIndex] = 0;
  355. // Slide forward the prop data by one slot.
  356. memmove(
  357. m_pdwPropTable,
  358. m_pdwPropTable - 1,
  359. (LPBYTE) m_pdwHeapData - (LPBYTE) m_pdwNullTable);
  360. }
  361. m_pProps.AddVal(info);
  362. m_bufferEventLayout.Write((DWORD) type);
  363. m_bufferEventLayout.WriteAlignedLenString(szName);
  364. return TRUE;
  365. }
  366. BOOL CEvent::SetSinglePropValue(DWORD dwIndex, va_list list)
  367. {
  368. PROP_FUNC pFunc;
  369. BOOL bRet;
  370. CCondInCritSec cs(&m_cs, IsLockable());
  371. //m_pStack = (LPVOID*) pStack;
  372. m_valist = list;
  373. m_iCurrentVar = dwIndex;
  374. pFunc = m_pProps[dwIndex].m_pFunc;
  375. bRet = (this->*pFunc)();
  376. return bRet;
  377. }
  378. BOOL CEvent::SetPropValues(CIntArray *pArr, va_list list)
  379. {
  380. BOOL bRet = TRUE;
  381. CCondInCritSec cs(&m_cs, IsLockable());
  382. // Is this a 'normal' event?
  383. if (!pArr)
  384. {
  385. DWORD nProps = GetPropertyCount();
  386. //m_pStack = (LPVOID*) pStack;
  387. m_valist = list;
  388. for (m_iCurrentVar = 0; m_iCurrentVar < nProps && bRet; m_iCurrentVar++)
  389. {
  390. PROP_FUNC pFunc = m_pProps[m_iCurrentVar].m_pFunc;
  391. bRet = (this->*pFunc)();
  392. }
  393. }
  394. // Must be a property subset.
  395. else
  396. {
  397. DWORD nProps = pArr->GetCount();
  398. //m_pStack = (LPVOID*) pStack;
  399. m_valist = list;
  400. for (DWORD i = 0; i < nProps && bRet; i++)
  401. {
  402. PROP_FUNC pFunc;
  403. int iRealIndex = (*pArr)[i];
  404. m_iCurrentVar = iRealIndex;
  405. pFunc = m_pProps[iRealIndex].m_pFunc;
  406. bRet = (this->*pFunc)();
  407. }
  408. }
  409. return bRet;
  410. }
  411. BOOL CEvent::SetPropValue(DWORD dwPropIndex, LPVOID pData, DWORD dwElements,
  412. DWORD dwSize)
  413. {
  414. if(dwPropIndex >= GetPropertyCount())
  415. {
  416. _ASSERT(FALSE);
  417. return FALSE;
  418. }
  419. if(dwSize == 0)
  420. {
  421. _ASSERT(FALSE);
  422. return FALSE;
  423. }
  424. CCondInCritSec cs(&m_cs, IsLockable());
  425. CPropInfo *pProp = &m_pProps[dwPropIndex];
  426. if (!pProp->IsPointer())
  427. {
  428. SetPropNull(dwPropIndex, FALSE);
  429. m_pdwPropTable[dwPropIndex] = *(DWORD*) pData;
  430. return TRUE;
  431. }
  432. BOOL bRet = FALSE;
  433. BOOL bLengthPrefixed = pProp->CountPrefixed();
  434. DWORD dwSizeNeeded = bLengthPrefixed ? dwSize + sizeof(DWORD) : dwSize;
  435. // Align the size.
  436. dwSizeNeeded = DWORD_ALIGNED(dwSizeNeeded);
  437. // If the value is null we'll have to make some room for the new value.
  438. if (IsPropNull(dwPropIndex))
  439. {
  440. LPBYTE pStart;
  441. // Increase our buffer size.
  442. MoveCurrent(dwSizeNeeded);
  443. // Make sure we get this after we call MoveCurrent, in case the
  444. // buffer is reallocated.
  445. pStart = m_pCurrent - dwSizeNeeded;
  446. // Copy in the new value.
  447. if (bLengthPrefixed)
  448. {
  449. *((DWORD*) pStart) = dwElements;
  450. if (pData)
  451. memcpy(pStart + sizeof(DWORD), pData, dwSize);
  452. }
  453. else
  454. {
  455. if (pData)
  456. memcpy(pStart, pData, dwSize);
  457. }
  458. // Set this value as non-null.
  459. SetPropNull(dwPropIndex, FALSE);
  460. // Point to our new data.
  461. m_pdwPropTable[dwPropIndex] = pStart - m_pBuffer;
  462. pProp->m_dwCurrentSize = dwSizeNeeded;
  463. bRet = TRUE;
  464. }
  465. else // Value is currently non-null.
  466. {
  467. // Does the old size match the new one? If so, just copy it in.
  468. if (pProp->m_dwCurrentSize == dwSizeNeeded)
  469. {
  470. if (pData)
  471. {
  472. DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
  473. LPBYTE pPropData = m_pBuffer + dwDataOffset;
  474. // We always have to copy this in because the elements can
  475. // vary for the same current size because of DWORD aligning.
  476. *((DWORD*) pPropData) = dwElements;
  477. if (bLengthPrefixed)
  478. memcpy(pPropData + sizeof(DWORD), pData, dwSize);
  479. else
  480. memcpy(pPropData, pData, dwSize);
  481. }
  482. bRet = TRUE;
  483. }
  484. else // If the sizes don't match we have a little more work to do.
  485. {
  486. int iSizeDiff = dwSizeNeeded - pProp->m_dwCurrentSize;
  487. DWORD dwOldCurrentOffset = m_pCurrent - m_pBuffer;
  488. // Change our buffer size.
  489. // This has to be done before we get the pointers below, because
  490. // MoveCurrent can potentially get our buffer reallocated.
  491. MoveCurrent(iSizeDiff);
  492. DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
  493. LPBYTE pPropData = m_pBuffer + dwDataOffset;
  494. LPBYTE pOldDataEnd = pPropData + pProp->m_dwCurrentSize;
  495. memmove(
  496. pOldDataEnd + iSizeDiff,
  497. pOldDataEnd,
  498. m_pBuffer + dwOldCurrentOffset - pOldDataEnd);
  499. // Copy in the new value.
  500. if (bLengthPrefixed)
  501. {
  502. *((DWORD*) pPropData) = dwElements;
  503. if (pData)
  504. memcpy(pPropData + sizeof(DWORD), pData, dwSize);
  505. }
  506. else
  507. {
  508. if (pData)
  509. memcpy(pPropData, pData, dwSize);
  510. }
  511. // Init this property's data.
  512. pProp->m_dwCurrentSize = dwSizeNeeded;
  513. // Increment all the data pointers by the amount we just added.
  514. CPropInfo *pProps = m_pProps.GetData();
  515. // We have to look at them all since we're now allowing properties
  516. // to store data in the heap non-sequentially (e.g. property 3
  517. // can point to data that comes after property 4's data).
  518. DWORD nProps = GetPropertyCount();
  519. for (DWORD i = 0; i < nProps; i++)
  520. {
  521. if (pProps[i].IsPointer() && m_pdwPropTable[i] > dwDataOffset)
  522. m_pdwPropTable[i] += iSizeDiff;
  523. }
  524. bRet = TRUE;
  525. }
  526. }
  527. return bRet;
  528. }
  529. BOOL CEvent::SetPropNull(DWORD dwPropIndex)
  530. {
  531. CCondInCritSec cs(&m_cs, IsLockable());
  532. if(dwPropIndex >= GetPropertyCount())
  533. {
  534. _ASSERT(FALSE);
  535. return FALSE;
  536. }
  537. // Only do something if the value isn't already null.
  538. if (!IsPropNull(dwPropIndex))
  539. {
  540. // Mark the given index as null.
  541. SetPropNull(dwPropIndex, TRUE);
  542. if (m_pProps[dwPropIndex].IsPointer())
  543. {
  544. CPropInfo *pProps = m_pProps.GetData();
  545. DWORD nProps = GetPropertyCount(),
  546. dwSizeToRemove = pProps[dwPropIndex].m_dwCurrentSize;
  547. DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
  548. LPBYTE pDataToRemove = m_pBuffer + dwDataOffset;
  549. // Slide up all the data that comes after the one we're nulling
  550. // out.
  551. memmove(
  552. pDataToRemove,
  553. pDataToRemove + dwSizeToRemove,
  554. m_pCurrent - pDataToRemove - dwSizeToRemove);
  555. // Reduce the size of our send buffer.
  556. MoveCurrent(-dwSizeToRemove);
  557. // Decrement all the data pointers by the amount we just removed.
  558. for (DWORD i = 0; i < nProps; i++)
  559. {
  560. if (pProps[i].IsPointer() &&
  561. m_pdwPropTable[i] > dwDataOffset)
  562. {
  563. m_pdwPropTable[i] -= dwSizeToRemove;
  564. }
  565. }
  566. }
  567. }
  568. return TRUE;
  569. }
  570. LPBYTE CEvent::GetPropData(DWORD dwPropIndex)
  571. {
  572. CPropInfo *pProp = &m_pProps[dwPropIndex];
  573. LPBYTE pData;
  574. if (pProp->IsPointer())
  575. {
  576. DWORD dwDataOffset = m_pdwPropTable[dwPropIndex];
  577. pData = m_pBuffer + dwDataOffset;
  578. }
  579. else
  580. pData = (LPBYTE) &m_pdwPropTable[dwPropIndex];
  581. return pData;
  582. }
  583. BOOL CEvent::GetPropValue(
  584. DWORD dwPropIndex,
  585. LPVOID pData,
  586. DWORD dwBufferSize,
  587. DWORD *pdwBytesRead)
  588. {
  589. CCondInCritSec cs(&m_cs, IsLockable());
  590. if(dwPropIndex >= GetPropertyCount())
  591. {
  592. _ASSERT(FALSE);
  593. return FALSE;
  594. }
  595. if(dwBufferSize == 0)
  596. {
  597. _ASSERT(FALSE);
  598. return FALSE;
  599. }
  600. BOOL bRet = FALSE;
  601. // If the value is non-null then read it.
  602. if (!IsPropNull(dwPropIndex))
  603. {
  604. CPropInfo *pProp = &m_pProps[dwPropIndex];
  605. DWORD dwSizeToRead = pProp->m_dwCurrentSize;
  606. LPBYTE pPropData = GetPropData(dwPropIndex);
  607. // Get rid of the prefix if there is any.
  608. if (pProp->CountPrefixed())
  609. {
  610. pPropData += sizeof(DWORD);
  611. dwSizeToRead -= sizeof(DWORD);
  612. }
  613. // Make sure we have enough room for the output data.
  614. if (dwBufferSize >= dwSizeToRead)
  615. {
  616. memcpy(pData, pPropData, dwSizeToRead);
  617. *pdwBytesRead = dwSizeToRead;
  618. bRet = TRUE;
  619. }
  620. }
  621. else
  622. {
  623. *pdwBytesRead = 0;
  624. bRet = TRUE;
  625. }
  626. return bRet;
  627. }
  628. BOOL CEvent::AddStringW()
  629. {
  630. BOOL bRet = TRUE;
  631. LPCWSTR szVal = va_arg(m_valist, LPCWSTR);
  632. if (!szVal)
  633. SetPropNull(m_iCurrentVar);
  634. else
  635. {
  636. DWORD dwLen = (wcslen(szVal) + 1) * sizeof(WCHAR);
  637. bRet =
  638. SetPropValue(
  639. m_iCurrentVar,
  640. (LPVOID) szVal,
  641. dwLen, // This will be written into the buffer as the size
  642. // of the string.
  643. dwLen); // The number of bytes we need.
  644. }
  645. //m_pStack++;
  646. return bRet;
  647. }
  648. BOOL CEvent::AddScalarArray()
  649. {
  650. BOOL bRet = TRUE;
  651. LPBYTE pData = va_arg(m_valist, LPBYTE);
  652. DWORD dwElements = va_arg(m_valist, DWORD);
  653. if (!pData)
  654. SetPropNull(m_iCurrentVar);
  655. else
  656. {
  657. DWORD dwSize;
  658. // The caller gives us the number of elements in the array. So,
  659. // multiply the number of elements by the element size.
  660. dwSize = m_pProps[m_iCurrentVar].m_dwElementSize * dwElements;
  661. bRet = SetPropValue(m_iCurrentVar, pData, dwElements, dwSize);
  662. // Moves past the LPVOID and the DWORD.
  663. //m_pStack += 2;
  664. }
  665. return bRet;
  666. }
  667. BOOL CEvent::AddStringArray()
  668. {
  669. BOOL bRet = TRUE;
  670. LPCWSTR *pszStrings = va_arg(m_valist, LPCWSTR*);
  671. DWORD dwItems = va_arg(m_valist, DWORD);
  672. if (!pszStrings)
  673. SetPropNull(m_iCurrentVar);
  674. else
  675. {
  676. // Copy the strings into our buffer.
  677. DWORD dwTotalLen = 0;
  678. // Calculate the total length.
  679. for (DWORD i = 0; i < dwItems; i++)
  680. {
  681. // The amount of buffer each string takes must be DWORD aligned.
  682. dwTotalLen += DWORD_ALIGNED(wcslen(pszStrings[i]) + 1) * sizeof(WCHAR);
  683. }
  684. // Account for the DWORDs before each string.
  685. dwTotalLen += sizeof(DWORD) * dwItems;
  686. // Use a NULL for the data pointer to just make room for the strings
  687. // without copying in the data.
  688. bRet = SetPropValue(m_iCurrentVar, NULL, dwItems, dwTotalLen);
  689. if (bRet)
  690. {
  691. // Copy the strings into our buffer.
  692. LPBYTE pCurrent = GetPropData(m_iCurrentVar) + sizeof(DWORD);
  693. for (DWORD i = 0; i < dwItems; i++)
  694. {
  695. DWORD dwLen = (wcslen(pszStrings[i]) + 1) * sizeof(WCHAR);
  696. // Add the prefixed size.
  697. *(DWORD*) pCurrent = dwLen;
  698. // Copy in the string. Don't use an aligned len because
  699. // we only copy exactly dwLen bytes.
  700. memcpy(pCurrent + sizeof(DWORD), pszStrings[i], dwLen);
  701. pCurrent +=
  702. sizeof(DWORD) +
  703. DWORD_ALIGNED(*(DWORD*) pCurrent);
  704. }
  705. // Moves past the LPVOID and the DWORD.
  706. //m_pStack += 2;
  707. }
  708. else
  709. bRet = FALSE;
  710. }
  711. return bRet;
  712. }
  713. BOOL CEvent::AddObject()
  714. {
  715. BOOL bRet = TRUE;
  716. HANDLE hEvent = va_arg(m_valist, HANDLE);
  717. if (!hEvent)
  718. SetPropNull(m_iCurrentVar);
  719. else
  720. {
  721. CEvent *pEvent = ((CEventWrap*) hEvent)->GetEvent();
  722. DWORD dwTotalLen,
  723. dwLayoutLen,
  724. dwDataLen;
  725. LPBYTE pLayout,
  726. pData;
  727. pEvent->GetLayoutBuffer(&pLayout, &dwLayoutLen, FALSE);
  728. pEvent->GetDataBuffer(&pData, &dwDataLen, FALSE);
  729. dwTotalLen = dwLayoutLen + dwDataLen;
  730. // Use a NULL for the data pointer to just make room for the event
  731. // buffers without copying in the data.
  732. // Note that because the property has m_bCountPrefixNeeded set to
  733. // TRUE, SetPropValue will write in the 3rd argument (the length of
  734. // the object) into the first DWORD.
  735. bRet =
  736. SetPropValue(
  737. m_iCurrentVar,
  738. NULL,
  739. // Aligned since this will represent the size of the buffer
  740. // taken by the object.
  741. DWORD_ALIGNED(dwTotalLen),
  742. // This one should not be aligned because it's the literal number
  743. // of bytes we're going to copy into the buffer.
  744. dwTotalLen);
  745. if (bRet)
  746. {
  747. // Now that we have some room, copy in the data.
  748. // The sizeof(DWORD) gets us past the length of the object.
  749. LPBYTE pDestData = GetPropData(m_iCurrentVar) + sizeof(DWORD);
  750. memcpy(pDestData, pLayout, dwLayoutLen);
  751. memcpy(pDestData + dwLayoutLen, pData, dwDataLen);
  752. }
  753. }
  754. //m_pStack++;
  755. return bRet;
  756. }
  757. BOOL CEvent::AddWmiObject()
  758. {
  759. BOOL bRet = TRUE;
  760. _IWmiObject *pObj =
  761. (_IWmiObject*) (IWbemClassObject*) va_arg(m_valist, IWbemClassObject*);
  762. if (!pObj)
  763. SetPropNull(m_iCurrentVar);
  764. else
  765. {
  766. DWORD dwTotalLen = 0;
  767. HRESULT hr;
  768. hr =
  769. pObj->GetObjectParts(
  770. NULL,
  771. 0,
  772. WBEM_OBJ_DECORATION_PART | WBEM_OBJ_INSTANCE_PART |
  773. WBEM_OBJ_CLASS_PART,
  774. &dwTotalLen);
  775. // This should never happen, but just in case...
  776. if (hr != WBEM_E_BUFFER_TOO_SMALL)
  777. return FALSE;
  778. // Use a NULL for the data pointer to just make room for the event
  779. // buffers without copying in the data.
  780. // Note that because the property has m_bCountPrefixNeeded set to
  781. // TRUE, SetPropValue will write in the 3rd argument (the length of
  782. // the object) into the first DWORD.
  783. bRet =
  784. SetPropValue(
  785. m_iCurrentVar,
  786. NULL,
  787. // Aligned since this will represent the size of the buffer
  788. // taken by the object.
  789. DWORD_ALIGNED(dwTotalLen),
  790. // This one should not be aligned because it's the literal number
  791. // of bytes we're going to copy into the buffer.
  792. dwTotalLen);
  793. if (bRet)
  794. {
  795. // Now that we have some room, copy in the data.
  796. // The sizeof(DWORD) gets us past the length of the object.
  797. LPBYTE pDestData = GetPropData(m_iCurrentVar) + sizeof(DWORD);
  798. hr =
  799. pObj->GetObjectParts(
  800. pDestData,
  801. dwTotalLen,
  802. WBEM_OBJ_DECORATION_PART | WBEM_OBJ_INSTANCE_PART |
  803. WBEM_OBJ_CLASS_PART,
  804. &dwTotalLen);
  805. bRet = SUCCEEDED(hr);
  806. }
  807. }
  808. return bRet;
  809. }
  810. BOOL CEvent::AddBYTE()
  811. {
  812. BYTE cData = va_arg(m_valist, BYTE);
  813. BOOL bRet = SetPropValue(m_iCurrentVar, &cData, 1, sizeof(BYTE));
  814. //m_pStack++;
  815. return bRet;
  816. }
  817. BOOL CEvent::AddWORD()
  818. {
  819. WORD wData = va_arg(m_valist, WORD);
  820. BOOL bRet =
  821. SetPropValue(m_iCurrentVar, &wData, 1, sizeof(WORD));
  822. //m_pStack++;
  823. return bRet;
  824. }
  825. BOOL CEvent::AddDWORD()
  826. {
  827. DWORD dwData = va_arg(m_valist, DWORD);
  828. BOOL bRet = SetPropValue(m_iCurrentVar, &dwData, 1, sizeof(DWORD));
  829. //m_pStack++;
  830. return bRet;
  831. }
  832. BOOL CEvent::AddFloat()
  833. {
  834. // The compiler pushes 64-bit doubles when passing floats, so we'll have
  835. // to first convert it to a 32-bit float.
  836. //float fValue = (float) *(double*) m_pStack;
  837. float fValue = va_arg(m_valist, double);
  838. BOOL bRet = SetPropValue(m_iCurrentVar, &fValue, 1, sizeof(float));
  839. // Account for the 64-bits passed on the stack.
  840. //m_pStack += 2;
  841. return bRet;
  842. }
  843. BOOL CEvent::AddDWORD64()
  844. {
  845. DWORD64 dwData = va_arg(m_valist, DWORD64);
  846. BOOL bRet = SetPropValue(m_iCurrentVar, &dwData, 1, sizeof(DWORD64));
  847. // To get past both DWORDs.
  848. //m_pStack += 2;
  849. return bRet;
  850. }
  851. BOOL CEvent::SendEvent()
  852. {
  853. BOOL bRet = FALSE;
  854. if (IsEnabled())
  855. {
  856. CCondInCritSec cs(&m_cs, IsLockable());
  857. if (!m_bLayoutSent)
  858. {
  859. DWORD dwLayoutSize = m_bufferEventLayout.GetUsedSize();
  860. // Embed the layout size in the message.
  861. ((DWORD*) m_bufferEventLayout.m_pBuffer)[1] = dwLayoutSize;
  862. m_bLayoutSent =
  863. m_pSink->GetConnection()->SendData(
  864. m_bufferEventLayout.m_pBuffer,
  865. dwLayoutSize);
  866. }
  867. if (m_bLayoutSent)
  868. {
  869. DWORD dwDataSize = GetUsedSize();
  870. // Embed the data buffer size in the message.
  871. ((DWORD*) m_pBuffer)[1] = dwDataSize;
  872. bRet = m_pSink->GetConnection()->SendData(m_pBuffer, dwDataSize);
  873. }
  874. }
  875. return bRet;
  876. }
  877. void CEvent::GetLayoutBuffer(
  878. LPBYTE *ppBuffer,
  879. DWORD *pdwSize,
  880. BOOL bIncludeHeader)
  881. {
  882. DWORD dwHeaderSize = bIncludeHeader ? 0 : sizeof(DWORD) * 4;
  883. // Get past the header stuff.
  884. *ppBuffer = m_bufferEventLayout.m_pBuffer + dwHeaderSize;
  885. // Subtract off the header stuff.
  886. *pdwSize = m_bufferEventLayout.GetUsedSize() - dwHeaderSize;
  887. }
  888. void CEvent::GetDataBuffer(
  889. LPBYTE *ppBuffer,
  890. DWORD *pdwSize,
  891. BOOL bIncludeHeader)
  892. {
  893. DWORD dwHeaderSize = bIncludeHeader ? 0 : sizeof(DWORD) * 3;
  894. // Get past the header stuff.
  895. *ppBuffer = m_pBuffer + dwHeaderSize;
  896. // Subtract off the header stuff.
  897. *pdwSize = GetUsedSize() - dwHeaderSize;
  898. }
  899. BOOL CEvent::SetLayoutAndDataBuffers(
  900. LPBYTE pLayoutBuffer,
  901. DWORD dwLayoutBufferSize,
  902. LPBYTE pDataBuffer,
  903. DWORD dwDataBufferSize)
  904. {
  905. DWORD dwEventIndex = InterlockedExchangeAdd((long*) &g_dwEventIndex, 1);
  906. int nProps;
  907. CCondInCritSec cs(&m_cs, IsLockable());
  908. // Setup the event layout buffer.
  909. m_bufferEventLayout.Reset();
  910. // Set the layout buffer.
  911. m_bufferEventLayout.Write(pLayoutBuffer, dwLayoutBufferSize);
  912. // Add the new index we just created.
  913. *(((DWORD*) m_bufferEventLayout.m_pBuffer) + 1) = dwEventIndex;
  914. // Get the number of props from the layout buffer.
  915. nProps = GetPropertyCount();
  916. // Setup the main event buffer
  917. Reset();
  918. Write(pDataBuffer, dwDataBufferSize);
  919. // Add the new index we just created.
  920. *(((DWORD*) m_pBuffer) + 1) = dwEventIndex;
  921. m_pProps.Init(nProps);
  922. m_pProps.SetCount(nProps);
  923. // Setup our data tables.
  924. RecalcTables();
  925. LPBYTE pLayoutCurrent =
  926. // Get past the header and property count.
  927. (m_bufferEventLayout.m_pBuffer + sizeof(DWORD) * 5);
  928. // Get past the event name.
  929. pLayoutCurrent += sizeof(DWORD) + DWORD_ALIGNED(*(DWORD*) pLayoutCurrent);
  930. // For each non-null pointer property, figure out the property's size.
  931. for (DWORD i = 0; i < nProps; i++)
  932. {
  933. CPropInfo &info = m_pProps[i];
  934. CIMTYPE dwType = *(DWORD*) pLayoutCurrent;
  935. info.Init(dwType);
  936. // Get past the type, the length of the property name, and the property
  937. // name itself.
  938. pLayoutCurrent +=
  939. sizeof(DWORD) * 2 +
  940. DWORD_ALIGNED(*(DWORD*) (pLayoutCurrent + sizeof(DWORD)));
  941. if (!IsPropNull(i) && info.IsPointer())
  942. {
  943. LPBYTE pData = GetPropData(i);
  944. info.InitCurrentSize(pData);
  945. }
  946. }
  947. return TRUE;
  948. }
  949. #define DEF_HEAP_EXTRA 256
  950. void CEvent::RecalcTables()
  951. {
  952. DWORD nProps = GetPropertyCount(),
  953. dwNullSize;
  954. m_pdwNullTable = (DWORD*) (m_pBuffer + sizeof(DWORD) * 3);
  955. dwNullSize = (nProps + 31) / 32;
  956. if (!dwNullSize)
  957. dwNullSize = 1;
  958. m_pdwPropTable = m_pdwNullTable + dwNullSize;
  959. m_pdwHeapData = m_pdwPropTable + nProps;
  960. DWORD dwSize = (LPBYTE) m_pdwHeapData - m_pCurrent;
  961. if ((LPBYTE) m_pdwHeapData - m_pBuffer > m_dwSize)
  962. Resize((LPBYTE) m_pdwHeapData - m_pBuffer + DEF_HEAP_EXTRA);
  963. dwSize = m_pCurrent - (LPBYTE) m_pdwHeapData;
  964. }