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.

970 lines
24 KiB

  1. // Connection.cpp
  2. #include "precomp.h"
  3. #include "Connection.h"
  4. #include "Event.h"
  5. #include "Transport.h"
  6. #include "NamedPipe.h"
  7. #include "NCDefs.h"
  8. #include "dutils.h"
  9. #define DEF_BATCH_BUFFER_SIZE 131072
  10. #define DEF_SEND_LATENCY 1000
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CSink
  13. CSink::CSink()
  14. {
  15. InitializeCriticalSection(&m_cs);
  16. }
  17. CSink::~CSink()
  18. {
  19. // Make sure none of the still alive events are referencing us.
  20. {
  21. CInCritSec cs(&m_cs);
  22. for (CEventListIterator event = m_listEvents.begin();
  23. event != m_listEvents.end(); event++)
  24. {
  25. CEvent *pEvent = *event;
  26. pEvent->m_pSink = NULL;
  27. }
  28. }
  29. DeleteCriticalSection(&m_cs);
  30. }
  31. BOOL CSink::Init(
  32. CConnection *pConnection,
  33. DWORD dwSinkID,
  34. LPVOID pUserData,
  35. LPEVENT_SOURCE_CALLBACK pCallback)
  36. {
  37. m_pConnection = pConnection;
  38. m_dwSinkID = dwSinkID;
  39. m_pUserData = pUserData;
  40. m_pCallback = pCallback;
  41. return TRUE;
  42. }
  43. void CSink::AddEvent(CEvent *pEvent)
  44. {
  45. CInCritSec cs(&m_cs);
  46. m_listEvents.push_back(pEvent);
  47. }
  48. void CSink::RemoveEvent(CEvent *pEvent)
  49. {
  50. CInCritSec cs(&m_cs);
  51. m_listEvents.remove(pEvent);
  52. }
  53. void CSink::ResetEventBufferLayoutSent()
  54. {
  55. CInCritSec cs(&m_cs);
  56. for (CEventListIterator i = m_listEvents.begin();
  57. i != m_listEvents.end(); i++)
  58. {
  59. CEvent *pEvent = *i;
  60. pEvent->ResetLayoutSent();
  61. pEvent->SetEnabled(FALSE);
  62. }
  63. }
  64. void CSink::EnableAndDisableEvents()
  65. {
  66. // For each event, set its enabled value.
  67. for (CEventListIterator i = m_listEvents.begin();
  68. i != m_listEvents.end();
  69. i++)
  70. {
  71. CEvent *pEvent = *i;
  72. EnableEventUsingList(pEvent);
  73. }
  74. }
  75. void CSink::AddToEnabledEventList(CBuffer *pBuffer)
  76. {
  77. DWORD dwLen;
  78. DWORD dwNumEnabled = pBuffer->ReadDWORD();
  79. // Add the event names to our enabled map.
  80. for( DWORD i=0; i < dwNumEnabled; i++ )
  81. {
  82. LPCWSTR szCurrentEvent = pBuffer->ReadAlignedLenString(&dwLen);
  83. m_mapEnabledEvents[szCurrentEvent] = 1;
  84. TRACE("Enabled: %S", szCurrentEvent);
  85. }
  86. EnableAndDisableEvents();
  87. }
  88. void CSink::RemoveFromEnabledEventList(CBuffer *pBuffer)
  89. {
  90. DWORD dwLen;
  91. DWORD dwNumDisabled = pBuffer->ReadDWORD();
  92. // Add the event names to our enabled map.
  93. for( DWORD i=0; i < dwNumDisabled; i++ )
  94. {
  95. LPCWSTR szCurrentEvent = pBuffer->ReadAlignedLenString(&dwLen);
  96. m_mapEnabledEvents.erase(szCurrentEvent);
  97. TRACE("Disabled: %S", szCurrentEvent);
  98. }
  99. EnableAndDisableEvents();
  100. }
  101. BOOL CSink::IsEventClassEnabled(LPCWSTR szEventClass)
  102. {
  103. BOOL bEnable;
  104. WCHAR szTempClassName[256];
  105. if (szEventClass)
  106. {
  107. StringCchCopyW(szTempClassName, 256, szEventClass);
  108. _wcsupr(szTempClassName);
  109. bEnable =
  110. m_mapEnabledEvents.find(szTempClassName) != m_mapEnabledEvents.end();
  111. }
  112. else
  113. bEnable = FALSE;
  114. return bEnable;
  115. }
  116. void CSink::EnableEventUsingList(CEvent *pEvent)
  117. {
  118. BOOL bEnable;
  119. bEnable = IsEventClassEnabled(pEvent->GetClassName());
  120. pEvent->SetEnabled(bEnable);
  121. }
  122. /////////////////////////////////////////////////////////////////////////////
  123. // CConnection
  124. CConnection::CConnection(BOOL bBatchSend, DWORD dwBatchBufferSize,
  125. DWORD dwMaxSendLatency) :
  126. m_bDone(FALSE),
  127. m_bUseBatchSend(bBatchSend),
  128. m_dwSendLatency(dwMaxSendLatency ? dwMaxSendLatency : DEF_SEND_LATENCY),
  129. m_heventBufferNotFull(NULL),
  130. m_heventBufferFull(NULL),
  131. m_heventEventsPending(NULL),
  132. m_heventDone(NULL),
  133. m_hthreadSend(NULL),
  134. m_pTransport(NULL),
  135. m_hthreadWMIInit(NULL),
  136. m_heventWMIInit(NULL),
  137. m_bWMIResync(TRUE),
  138. m_dwNextSinkID(1)
  139. {
  140. if (bBatchSend)
  141. {
  142. if (dwBatchBufferSize == 0)
  143. dwBatchBufferSize = DEF_BATCH_BUFFER_SIZE;
  144. m_bufferSend.Reset(dwBatchBufferSize);
  145. }
  146. else
  147. m_bufferSend.Reset(DEF_BATCH_BUFFER_SIZE);
  148. }
  149. CConnection::~CConnection()
  150. {
  151. Deinit();
  152. }
  153. void CConnection::GetBaseName(LPCWSTR szName, LPWSTR szBase)
  154. {
  155. StringCchCopyW(szBase, MAX_PATH*2, szName);
  156. _wcsupr(szBase);
  157. // Get rid of the '\' chars since we can't use it in OS object names.
  158. for (WCHAR *szCurrent = szBase; *szCurrent; szCurrent++)
  159. {
  160. if (*szCurrent == '\\')
  161. *szCurrent = '/';
  162. }
  163. }
  164. BOOL CConnection::Init(
  165. LPCWSTR szNamespace,
  166. LPCWSTR szProviderName,
  167. LPVOID pUserData,
  168. LPEVENT_SOURCE_CALLBACK pCallback)
  169. {
  170. if (!m_sinkMain.Init(this, 0, pUserData, pCallback))
  171. return FALSE;
  172. GetBaseName(szNamespace, m_szBaseNamespace);
  173. GetBaseName(szProviderName, m_szBaseProviderName);
  174. try
  175. {
  176. InitializeCriticalSection(&m_cs);
  177. // The rest of these are for batch sending.
  178. InitializeCriticalSection(&m_csBuffer);
  179. }
  180. catch(...)
  181. {
  182. return FALSE;
  183. }
  184. m_heventDone =
  185. CreateEvent(
  186. NULL,
  187. TRUE,
  188. FALSE,
  189. NULL);
  190. if(m_heventDone == NULL)
  191. return FALSE;
  192. m_heventBufferNotFull =
  193. CreateEvent(
  194. NULL,
  195. TRUE,
  196. TRUE,
  197. NULL);
  198. if(m_heventBufferNotFull == NULL)
  199. return FALSE;
  200. m_heventBufferFull =
  201. CreateEvent(
  202. NULL,
  203. TRUE,
  204. FALSE,
  205. NULL);
  206. if(m_heventBufferFull == NULL)
  207. return FALSE;
  208. m_heventEventsPending =
  209. CreateEvent(
  210. NULL,
  211. TRUE,
  212. FALSE,
  213. NULL);
  214. if(m_heventEventsPending == NULL)
  215. return FALSE;
  216. if(!StartWaitWMIInitThread())
  217. return FALSE;
  218. return TRUE;
  219. }
  220. BOOL CConnection::StartWaitWMIInitThread()
  221. {
  222. TRACE("Entered StartWaitWMIInitThread.");
  223. m_heventWMIInit =
  224. OpenEventW(
  225. SYNCHRONIZE,
  226. FALSE,
  227. WMI_INIT_EVENT_NAME);
  228. if (!m_heventWMIInit)
  229. {
  230. PSECURITY_DESCRIPTOR pSD = NULL;
  231. DWORD dwSize;
  232. if ( !ConvertStringSecurityDescriptorToSecurityDescriptorW(
  233. ESS_EVENT_SDDL, // security descriptor string
  234. SDDL_REVISION_1, // revision level
  235. &pSD, // SD
  236. &dwSize) )
  237. return FALSE;
  238. SECURITY_ATTRIBUTES sa = { sizeof(sa), pSD, FALSE };
  239. m_heventWMIInit =
  240. CreateEventW(
  241. &sa,
  242. TRUE,
  243. FALSE,
  244. WMI_INIT_EVENT_NAME);
  245. if (pSD)
  246. LocalFree((HLOCAL) pSD);
  247. if (!m_heventWMIInit)
  248. {
  249. TRACE("Couldn't create ESS ready event: %d", GetLastError());
  250. return FALSE;
  251. }
  252. }
  253. if (WaitForSingleObject(m_heventWMIInit, 0) == 0)
  254. {
  255. TRACE("ESS event was already set, so going to init transport...");
  256. if(!InitTransport())
  257. return FALSE;
  258. }
  259. else
  260. {
  261. DWORD dwID;
  262. TRACE("Creating WaitWMIInitThreadProc thread.");
  263. m_hthreadWMIInit =
  264. CreateThread(
  265. NULL,
  266. 0,
  267. (LPTHREAD_START_ROUTINE) WaitWMIInitThreadProc,
  268. this,
  269. 0,
  270. &dwID);
  271. if(m_hthreadWMIInit == NULL)
  272. return FALSE;
  273. }
  274. return TRUE;
  275. }
  276. #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
  277. BOOL CConnection::InitTransport()
  278. {
  279. if ( m_pTransport != NULL )
  280. {
  281. return TRUE;
  282. }
  283. TRACE("Entered InitTransport.");
  284. try
  285. {
  286. m_pTransport = new CNamedPipeClient;
  287. }
  288. catch(...)
  289. {
  290. // this page intentionally left blank - m_pTransport will still be NULL.
  291. }
  292. BOOL bRet;
  293. if (m_pTransport)
  294. {
  295. m_pTransport->SetConnection(this);
  296. m_pTransport->Init(m_szBaseNamespace, m_szBaseProviderName);
  297. bRet = TRUE;
  298. }
  299. else
  300. bRet = FALSE;
  301. return bRet;
  302. }
  303. DWORD CConnection::WaitWMIInitThreadProc(CConnection *pThis)
  304. {
  305. try
  306. {
  307. TRACE("Entered WaitWMIInitThreadProc");
  308. HANDLE hWait[2] = { pThis->m_heventDone, pThis->m_heventWMIInit };
  309. DWORD dwWait;
  310. dwWait = WaitForMultipleObjects(2, hWait, FALSE, INFINITE);
  311. if (dwWait == 1)
  312. {
  313. TRACE("ESS event fired, going to init transport");
  314. // If WMI is now ready, startup our transport.
  315. pThis->InitTransport();
  316. pThis->m_bWMIResync = FALSE;
  317. }
  318. else
  319. {
  320. TRACE("dwWait in WaitWMIInitThreadProc = %d", dwWait);
  321. }
  322. }
  323. catch( CX_MemoryException )
  324. {
  325. return ERROR_OUTOFMEMORY;
  326. }
  327. return ERROR_SUCCESS;
  328. }
  329. BOOL CConnection::ResyncWithWMI()
  330. {
  331. m_bWMIResync = TRUE;
  332. StopThreads();
  333. ResetEvent( m_heventDone) ;
  334. m_hthreadWMIInit = CreateThread(
  335. NULL,
  336. 0,
  337. (LPTHREAD_START_ROUTINE)WaitWMIInitThreadProc,
  338. this,
  339. 0,
  340. NULL );
  341. return m_hthreadWMIInit != NULL ? TRUE : FALSE;
  342. }
  343. void CConnection::StopThreads()
  344. {
  345. if (m_hthreadSend)
  346. {
  347. BOOL bDoneSending;
  348. do
  349. {
  350. Lock();
  351. bDoneSending = m_bufferSend.GetUsedSize() == 0;
  352. // If there's still stuff left to send, make sure it
  353. // gets sent.
  354. if (bDoneSending)
  355. {
  356. SetEvent(m_heventDone);
  357. Unlock();
  358. WaitForSingleObject(m_hthreadSend, INFINITE);
  359. CloseHandle(m_hthreadSend);
  360. m_hthreadSend = NULL;
  361. }
  362. else
  363. {
  364. SetEvent(m_heventBufferFull);
  365. Unlock();
  366. // Sleep a little to give the send thread a chance to do its
  367. // thing.
  368. Sleep(1);
  369. }
  370. } while (!bDoneSending);
  371. }
  372. if ( m_hthreadWMIInit != NULL )
  373. {
  374. SetEvent(m_heventDone);
  375. WaitForSingleObject(m_hthreadWMIInit, INFINITE);
  376. CloseHandle(m_hthreadWMIInit);
  377. }
  378. m_hthreadWMIInit = NULL;
  379. m_hthreadSend = NULL;
  380. }
  381. void CConnection::Deinit()
  382. {
  383. m_bDone = TRUE;
  384. StopThreads();
  385. if (m_heventWMIInit)
  386. CloseHandle(m_heventWMIInit);
  387. CloseHandle(m_heventDone);
  388. CloseHandle(m_heventBufferNotFull);
  389. CloseHandle(m_heventBufferFull);
  390. CloseHandle(m_heventEventsPending);
  391. // Give the transport a chance to clean up.
  392. if (m_pTransport)
  393. m_pTransport->Deinit();
  394. // Make sure no sinks are referencing us anymore.
  395. for (CSinkMapIterator i = m_mapSink.begin();
  396. i != m_mapSink.end();
  397. i++)
  398. {
  399. CSink *pSink = (*i).second;
  400. pSink->m_pConnection = NULL;
  401. }
  402. DeleteCriticalSection(&m_csBuffer);
  403. DeleteCriticalSection(&m_cs);
  404. }
  405. BOOL CConnection::StartSendThread()
  406. {
  407. DWORD dwID;
  408. m_hthreadSend =
  409. CreateThread(
  410. NULL,
  411. 0,
  412. (LPTHREAD_START_ROUTINE) SendThreadProc,
  413. this,
  414. 0,
  415. &dwID);
  416. if(m_hthreadSend == NULL)
  417. return FALSE;
  418. return TRUE;
  419. }
  420. BOOL CConnection::SendMessagesOverTransport( PBYTE pData, DWORD cData )
  421. {
  422. CBuffer buffer( pData, cData );
  423. //
  424. // walk the messages until we hit our max message size for
  425. // the transport. Keep doing this until no more messages.
  426. //
  427. PBYTE pTransportMsg = buffer.m_pBuffer;
  428. DWORD cTransportMsg = 0;
  429. while (!buffer.IsEOF())
  430. {
  431. _ASSERT( pTransportMsg != NULL );
  432. _ASSERT( cTransportMsg < MAX_MSG_SIZE );
  433. //
  434. // process one message from the buffer
  435. //
  436. DWORD dwMsg = buffer.ReadDWORD();
  437. if ( dwMsg != NC_SRVMSG_EVENT_LAYOUT &&
  438. dwMsg != NC_SRVMSG_PREPPED_EVENT )
  439. {
  440. _ASSERT( FALSE );
  441. return FALSE;
  442. }
  443. DWORD cMsg = buffer.ReadDWORD();
  444. if ( cMsg <= MAX_MSG_SIZE )
  445. {
  446. if ( cTransportMsg + cMsg >= MAX_MSG_SIZE )
  447. {
  448. //
  449. // send what we have so far.
  450. //
  451. if ( !SendDataOverTransports( pTransportMsg, cTransportMsg ) )
  452. return FALSE;
  453. //
  454. // set up new transport msg.
  455. //
  456. pTransportMsg = buffer.m_pCurrent - 8;
  457. cTransportMsg = cMsg;
  458. }
  459. else
  460. {
  461. //
  462. // add to transport msg
  463. //
  464. cTransportMsg += cMsg;
  465. }
  466. }
  467. else
  468. {
  469. //
  470. // this means a mesage was too big to send. skip it.
  471. //
  472. }
  473. buffer.m_pCurrent += cMsg - 8;
  474. }
  475. if ( cTransportMsg > 0 )
  476. {
  477. return SendDataOverTransports( pTransportMsg, cTransportMsg );
  478. }
  479. return TRUE;
  480. }
  481. DWORD WINAPI CConnection::SendThreadProc(CConnection *pThis)
  482. {
  483. try
  484. {
  485. HANDLE hWait[2] = { pThis->m_heventDone, pThis->m_heventEventsPending },
  486. hwaitSendLatency[2] = { pThis->m_heventDone, pThis->m_heventBufferFull },
  487. heventBufferNotFull = pThis->m_heventBufferNotFull;
  488. DWORD dwSendLatency = pThis->m_dwSendLatency;
  489. LPBYTE pData = pThis->m_bufferSend.m_pBuffer;
  490. CBuffer *pBuffer = &pThis->m_bufferSend;
  491. CRITICAL_SECTION *pCS = &pThis->m_csBuffer;
  492. while (WaitForMultipleObjects(2, hWait, FALSE, INFINITE) != 0)
  493. {
  494. // If we have a send latency, wait for that time or until the send
  495. // buffer is full. If the done event fires, get out.
  496. if (dwSendLatency)
  497. {
  498. if (WaitForMultipleObjects(2, hwaitSendLatency, FALSE,
  499. dwSendLatency) == 0)
  500. break;
  501. // Reset m_heventBufferFull.
  502. ResetEvent(hwaitSendLatency[1]);
  503. }
  504. EnterCriticalSection(pCS);
  505. pThis->SendMessagesOverTransport(
  506. pData,
  507. pBuffer->GetUsedSize());
  508. pBuffer->Reset();
  509. SetEvent(heventBufferNotFull);
  510. // Reset m_heventEventsPending
  511. ResetEvent(hWait[1]);
  512. LeaveCriticalSection(pCS);
  513. }
  514. }
  515. catch( CX_MemoryException )
  516. {
  517. return ERROR_OUTOFMEMORY;
  518. }
  519. return 0;
  520. }
  521. //#define NO_SEND
  522. BOOL CConnection::IndicateProvEnabled()
  523. {
  524. // Get out if we're already done.
  525. if (m_bDone)
  526. return TRUE;
  527. CInCritSec cs(&m_cs);
  528. // Tell the callback that the provider is now activated.
  529. if (m_sinkMain.m_pCallback)
  530. m_sinkMain.m_pCallback(
  531. (HANDLE) this, ESM_START_SENDING_EVENTS, m_sinkMain.m_pUserData, NULL);
  532. // Tell the server about us.
  533. if(!SendInitInfo())
  534. return FALSE;
  535. // See if we've buffered any events while we were waiting for WMI to come
  536. // up. If we did, send them on their way.
  537. DWORD dwSize;
  538. EnterCriticalSection(&m_csBuffer);
  539. dwSize = m_bufferSend.GetUsedSize();
  540. if (dwSize)
  541. {
  542. m_pTransport->SendData(m_bufferSend.m_pBuffer, dwSize);
  543. m_bufferSend.Reset();
  544. }
  545. LeaveCriticalSection(&m_csBuffer);
  546. if (m_bUseBatchSend && m_hthreadSend == NULL)
  547. return StartSendThread();
  548. else
  549. return TRUE;
  550. }
  551. void CConnection::IndicateProvDisabled()
  552. {
  553. // Get out if we're already done.
  554. if (m_bDone)
  555. return;
  556. CInCritSec cs(&m_cs);
  557. for (CSinkMapIterator i = m_mapSink.begin();
  558. i != m_mapSink.end();
  559. i++)
  560. {
  561. CSink *pSink = (*i).second;
  562. pSink->ResetEventBufferLayoutSent();
  563. if (pSink->m_pCallback)
  564. {
  565. pSink->m_pCallback(
  566. (HANDLE) pSink,
  567. ESM_STOP_SENDING_EVENTS,
  568. pSink->m_pUserData,
  569. NULL);
  570. }
  571. }
  572. // Tell the callback that the provider is now deactivated.
  573. m_sinkMain.ResetEventBufferLayoutSent();
  574. if (m_sinkMain.m_pCallback)
  575. {
  576. m_sinkMain.m_pCallback(
  577. (HANDLE) &m_sinkMain,
  578. ESM_STOP_SENDING_EVENTS,
  579. m_sinkMain.m_pUserData,
  580. NULL);
  581. }
  582. ResyncWithWMI();
  583. }
  584. BOOL CConnection::SendData(LPBYTE pBuffer, DWORD dwSize)
  585. {
  586. BOOL bRet = FALSE;
  587. // Make sure this event isn't too big.
  588. if (dwSize > m_bufferSend.m_dwSize)
  589. return FALSE;
  590. if (m_bUseBatchSend || WaitingForWMIInit())
  591. {
  592. BOOL bContinue;
  593. do
  594. {
  595. EnterCriticalSection(&m_csBuffer);
  596. bContinue = FALSE;
  597. // See if we have enough room to add our event.
  598. if (dwSize <= m_bufferSend.GetUnusedSize())
  599. {
  600. BOOL bWasEmpty = m_bufferSend.GetUsedSize() == 0;
  601. m_bufferSend.Write(pBuffer, dwSize);
  602. if (bWasEmpty)
  603. SetEvent(m_heventEventsPending);
  604. LeaveCriticalSection(&m_csBuffer);
  605. bRet = TRUE;
  606. break;
  607. }
  608. else
  609. {
  610. // If we're not waiting for WMI to initialize, we just need to
  611. // wait for the send thread to finish sending what's in our
  612. // buffer.
  613. if (!WaitingForWMIInit())
  614. {
  615. // Wake up the send latency thread if necessary.
  616. if (m_dwSendLatency)
  617. SetEvent(m_heventBufferFull);
  618. // So we'll block until the send thread sets the event.
  619. ResetEvent(m_heventBufferNotFull);
  620. LeaveCriticalSection(&m_csBuffer);
  621. WaitForSingleObject(m_heventBufferNotFull, INFINITE);
  622. bContinue = TRUE;
  623. }
  624. // If we're still waiting for WMI to initialize but our buffer
  625. // is full, drop it.
  626. else
  627. {
  628. LeaveCriticalSection(&m_csBuffer);
  629. bRet = FALSE;
  630. }
  631. } // else from if (dwSize <= m_bufferSend.GetUnusedSize())
  632. } while( bContinue );
  633. }
  634. else
  635. {
  636. bRet = SendDataOverTransports(pBuffer, dwSize);
  637. }
  638. return bRet;
  639. }
  640. BOOL CConnection::SendDataOverTransports(LPBYTE pBuffer, DWORD dwSize)
  641. {
  642. if (m_pTransport->IsReady())
  643. m_pTransport->SendData(pBuffer, dwSize);
  644. return TRUE;
  645. }
  646. BOOL CConnection::SendInitInfo()
  647. {
  648. BYTE cBuffer[sizeof(DWORD) * 2];
  649. CBuffer buffer(cBuffer, sizeof(cBuffer), CBuffer::ALIGN_DWORD);
  650. BOOL bRet;
  651. buffer.Write((DWORD) NC_SRVMSG_CLIENT_INFO);
  652. buffer.Write((DWORD) (m_bUseBatchSend ? m_bufferSend.m_dwSize : MAX_MSG_SIZE));
  653. if(!m_pTransport->InitCallback())
  654. return FALSE;
  655. return m_pTransport->SendData(cBuffer, buffer.GetUsedSize());
  656. }
  657. HRESULT CConnection::ProcessMessage(LPBYTE pData, DWORD dwSize)
  658. {
  659. // Get out if we're already done.
  660. if (m_bDone)
  661. return S_OK;
  662. if ( dwSize <= sizeof(DWORD)*2+sizeof(DWORD_PTR) )
  663. return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  664. DWORD *pdwMsg = (DWORD*) pData;
  665. DWORD *pdwSinkID = (DWORD*) (pdwMsg + 1);
  666. DWORD_PTR dwMsgCookie;
  667. memcpy( &dwMsgCookie, pdwMsg+2, sizeof(dwMsgCookie) );
  668. LPBYTE pMsgBits = (LPBYTE)(pData+sizeof(DWORD)*2+sizeof(DWORD_PTR));
  669. CBuffer buffer(pMsgBits, dwSize - sizeof(DWORD)*2 - sizeof(DWORD_PTR));
  670. HRESULT hr = S_OK;
  671. DWORD dwLen;
  672. switch(*pdwMsg)
  673. {
  674. case NC_CLIMSG_ACCESS_CHECK_REQ:
  675. {
  676. ES_ACCESS_CHECK check;
  677. check.szQueryLanguage = buffer.ReadAlignedLenString(&dwLen);
  678. check.szQuery = buffer.ReadAlignedLenString(&dwLen);
  679. check.dwSidLen = buffer.ReadDWORD();
  680. if ( check.dwSidLen <= buffer.GetUnusedSize() )
  681. {
  682. if (check.dwSidLen != 0)
  683. check.pSid = buffer.m_pCurrent;
  684. else
  685. check.pSid = NULL;
  686. if (m_sinkMain.m_pCallback)
  687. {
  688. hr =
  689. m_sinkMain.m_pCallback(
  690. (HANDLE) &m_sinkMain,
  691. ESM_ACCESS_CHECK,
  692. m_sinkMain.m_pUserData,
  693. &check);
  694. }
  695. }
  696. else
  697. {
  698. hr = E_FAIL;
  699. }
  700. NC_SRVMSG_REPLY reply = { NC_SRVMSG_ACCESS_CHECK_REPLY,
  701. hr, dwMsgCookie };
  702. m_pTransport->SendMsgReply(&reply);
  703. break;
  704. }
  705. case NC_CLIMSG_NEW_QUERY_REQ:
  706. {
  707. ES_NEW_QUERY query;
  708. CSink *pSink = GetSink(*pdwSinkID);
  709. if (pSink)
  710. {
  711. query.dwID = buffer.ReadDWORD();
  712. query.szQueryLanguage = buffer.ReadAlignedLenString(&dwLen);
  713. query.szQuery = buffer.ReadAlignedLenString(&dwLen);
  714. // This is the list of event class names that are now
  715. // enabled thanks to this query.
  716. pSink->AddToEnabledEventList(&buffer);
  717. if (pSink->m_pCallback)
  718. {
  719. hr =
  720. pSink->m_pCallback(
  721. (HANDLE) pSink, ESM_NEW_QUERY, pSink->m_pUserData, &query);
  722. }
  723. }
  724. else
  725. TRACE("Sink %d not found.", *pdwSinkID);
  726. m_pTransport->SendMsgReply(NULL);
  727. break;
  728. }
  729. case NC_CLIMSG_CANCEL_QUERY_REQ:
  730. {
  731. ES_CANCEL_QUERY query;
  732. CSink *pSink = GetSink(*pdwSinkID);
  733. if (pSink)
  734. {
  735. query.dwID = buffer.ReadDWORD();
  736. // This is the list of event class names that are now
  737. // disabled thanks to this query.
  738. pSink->RemoveFromEnabledEventList(&buffer);
  739. if (pSink->m_pCallback)
  740. {
  741. hr =
  742. pSink->m_pCallback(
  743. (HANDLE) pSink, ESM_CANCEL_QUERY, pSink->m_pUserData,
  744. &query);
  745. m_pTransport->SendMsgReply(NULL);
  746. break;
  747. }
  748. else
  749. hr = S_OK;
  750. }
  751. else
  752. TRACE("Sink %d not found.", *pdwSinkID);
  753. break;
  754. }
  755. case NC_CLIMSG_PROVIDER_UNLOADING:
  756. TRACE("Got the NC_CLIMSG_PROVIDER_UNLOADING message.");
  757. // Give our named pipe client a chance to go see if it
  758. // should deactivate itself (if the server doesn't need
  759. // us anymore).
  760. m_pTransport->SignalProviderDisabled();
  761. hr = S_OK;
  762. break;
  763. default:
  764. TRACE("Bad message from server!");
  765. break;
  766. } // switch(*(DWORD*)cBuffer)
  767. return hr;
  768. }
  769. CSink *CConnection::GetSink(DWORD dwID)
  770. {
  771. return &m_sinkMain;
  772. }