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.

1116 lines
34 KiB

  1. /*****************************************************************************
  2. * event.cpp - event support
  3. *****************************************************************************
  4. * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
  5. */
  6. #include "private.h"
  7. /*****************************************************************************
  8. * Functions
  9. */
  10. #pragma code_seg("PAGE")
  11. /*****************************************************************************
  12. * PcHandleEnableEventWithTable()
  13. *****************************************************************************
  14. * Uses an event table to handle a KS enable event IOCTL.
  15. */
  16. PORTCLASSAPI
  17. NTSTATUS
  18. NTAPI
  19. PcHandleEnableEventWithTable
  20. (
  21. IN PIRP pIrp,
  22. IN PEVENT_CONTEXT pContext
  23. )
  24. {
  25. PAGED_CODE();
  26. ASSERT(pIrp);
  27. ASSERT(pContext);
  28. PIO_STACK_LOCATION IrpStack;
  29. ULONG InputBufferLength;
  30. NTSTATUS ntStatus = STATUS_SUCCESS;
  31. _DbgPrintF(DEBUGLVL_BLAB,("PcHandleEnableEventWithTable"));
  32. // deal with possible node events
  33. IrpStack = IoGetCurrentIrpStackLocation( pIrp );
  34. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  35. if( InputBufferLength >= sizeof(KSE_NODE) )
  36. {
  37. ULONG Flags;
  38. __try {
  39. // validate the pointers if we don't trust the client
  40. if( pIrp->RequestorMode != KernelMode )
  41. {
  42. ProbeForRead( IrpStack->Parameters.DeviceIoControl.Type3InputBuffer,
  43. InputBufferLength,
  44. sizeof(BYTE));
  45. }
  46. // get the flags
  47. Flags = ((PKSEVENT)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)->Flags;
  48. if( Flags & KSEVENT_TYPE_TOPOLOGY )
  49. {
  50. // get the node id
  51. pContext->pPropertyContext->ulNodeId =
  52. ((PKSE_NODE)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)->NodeId;
  53. // mask off the flag bit
  54. ((PKSEVENT)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)->Flags &= ~KSEVENT_TYPE_TOPOLOGY;
  55. }
  56. }
  57. __except (EXCEPTION_EXECUTE_HANDLER) {
  58. ntStatus = GetExceptionCode ();
  59. }
  60. }
  61. if (NT_SUCCESS(ntStatus))
  62. {
  63. pIrp->Tail.Overlay.DriverContext[3] = pContext;
  64. ntStatus = KsEnableEvent( pIrp,
  65. pContext->ulEventSetCount,
  66. pContext->pEventSets,
  67. NULL,
  68. KSEVENTS_NONE,
  69. NULL );
  70. // restore ulNodeId
  71. pContext->pPropertyContext->ulNodeId = ULONG(-1);
  72. }
  73. return ntStatus;
  74. }
  75. /*****************************************************************************
  76. * PcHandleDisableEventWithTable()
  77. *****************************************************************************
  78. * Uses an event table to handle a KS disable event IOCTL.
  79. */
  80. PORTCLASSAPI
  81. NTSTATUS
  82. NTAPI
  83. PcHandleDisableEventWithTable
  84. (
  85. IN PIRP pIrp,
  86. IN PEVENT_CONTEXT pContext
  87. )
  88. {
  89. PAGED_CODE();
  90. ASSERT(pIrp);
  91. ASSERT(pContext);
  92. _DbgPrintF(DEBUGLVL_VERBOSE,("PcHandleDisableEventWithTable"));
  93. pIrp->Tail.Overlay.DriverContext[3] = pContext;
  94. return KsDisableEvent( pIrp,
  95. &(pContext->pEventList->List),
  96. KSEVENTS_SPINLOCK,
  97. &(pContext->pEventList->ListLock) );
  98. }
  99. /*****************************************************************************
  100. * EventItemAddHandler()
  101. *****************************************************************************
  102. * KS-sytle event handler that handles Adds using the
  103. * PCEVENT_ITEM mechanism. Note that filter and pin events in the port do not
  104. * utilize this AddHandler, only events exposed by the miniport.
  105. */
  106. NTSTATUS
  107. EventItemAddHandler
  108. (
  109. IN PIRP pIrp,
  110. IN PKSEVENTDATA pEventData,
  111. IN PKSEVENT_ENTRY pEventEntry
  112. )
  113. {
  114. PAGED_CODE();
  115. ASSERT(pIrp);
  116. NTSTATUS ntStatus = STATUS_SUCCESS;
  117. _DbgPrintF(DEBUGLVL_VERBOSE,("EventItemAddHandler"));
  118. // get the IRP stack location
  119. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp );
  120. // get the event context
  121. PEVENT_CONTEXT pContext = PEVENT_CONTEXT(pIrp->Tail.Overlay.DriverContext[3]);
  122. // get the instance size
  123. ULONG ulInstanceSize = irpSp->Parameters.DeviceIoControl.InputBufferLength;
  124. ULONG AlignedBufferLength = (irpSp->Parameters.DeviceIoControl.OutputBufferLength +
  125. FILE_QUAD_ALIGNMENT) &
  126. ~FILE_QUAD_ALIGNMENT;
  127. //
  128. // Setup event request structure
  129. //
  130. PPCEVENT_REQUEST pPcEventRequest = new(NonPagedPool,'rEcP') PCEVENT_REQUEST;
  131. if( !pPcEventRequest )
  132. {
  133. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  134. }
  135. else
  136. {
  137. //
  138. // Copy target information from the context structure
  139. //
  140. pPcEventRequest->MajorTarget = pContext->pPropertyContext->pUnknownMajorTarget;
  141. pPcEventRequest->MinorTarget = pContext->pPropertyContext->pUnknownMinorTarget;
  142. pPcEventRequest->Node = pContext->pPropertyContext->ulNodeId;
  143. pPcEventRequest->EventItem = NULL;
  144. // get the filter descriptor
  145. PPCFILTER_DESCRIPTOR pPcFilterDescriptor = pContext->pPropertyContext->pPcFilterDescriptor;
  146. if( ULONG(-1) == pPcEventRequest->Node )
  147. {
  148. if( !pPcEventRequest->MinorTarget )
  149. {
  150. //
  151. // FILTER EVENT
  152. //
  153. if( ( pPcFilterDescriptor ) &&
  154. ( pPcFilterDescriptor->AutomationTable ) )
  155. {
  156. // search the filter's automation table for the event
  157. const PCAUTOMATION_TABLE *pPcAutomationTable =
  158. pPcFilterDescriptor->AutomationTable;
  159. const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
  160. for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
  161. {
  162. if( IsEqualGUIDAligned( *pPcEventItem->Set,
  163. *pEventEntry->EventSet->Set ) &&
  164. pPcEventItem->Id == pEventEntry->EventItem->EventId )
  165. {
  166. pPcEventRequest->EventItem = pPcEventItem;
  167. break;
  168. }
  169. pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
  170. }
  171. }
  172. }
  173. else
  174. {
  175. //
  176. // PIN EVENT
  177. //
  178. // validate the pin id
  179. if( ( pPcFilterDescriptor ) &&
  180. ( pContext->ulPinId < pPcFilterDescriptor->PinCount ) &&
  181. ( pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable ) )
  182. {
  183. // search the pin's automation table for the event
  184. const PCAUTOMATION_TABLE *pPcAutomationTable =
  185. pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable;
  186. const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
  187. for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
  188. {
  189. if( IsEqualGUIDAligned( *pPcEventItem->Set,
  190. *pEventEntry->EventSet->Set ) &&
  191. pPcEventItem->Id == pEventEntry->EventItem->EventId )
  192. {
  193. pPcEventRequest->EventItem = pPcEventItem;
  194. break;
  195. }
  196. pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
  197. }
  198. }
  199. }
  200. }
  201. else
  202. {
  203. //
  204. // NODE EVENT
  205. //
  206. // validate the node id
  207. if( ( pPcFilterDescriptor ) &&
  208. ( pPcEventRequest->Node < pPcFilterDescriptor->NodeCount ) &&
  209. ( pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable ) )
  210. {
  211. // search the node's automation table for the event
  212. const PCAUTOMATION_TABLE *pPcAutomationTable =
  213. pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable;
  214. const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
  215. for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
  216. {
  217. if( IsEqualGUIDAligned( *pPcEventItem->Set,
  218. *pEventEntry->EventSet->Set ) &&
  219. pPcEventItem->Id == pEventEntry->EventItem->EventId )
  220. {
  221. pPcEventRequest->EventItem = pPcEventItem;
  222. break;
  223. }
  224. pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
  225. }
  226. }
  227. }
  228. if( NT_SUCCESS(ntStatus) )
  229. {
  230. //
  231. // call the handler if we have an event item with a handler
  232. if( pPcEventRequest->EventItem &&
  233. pPcEventRequest->EventItem->Handler )
  234. {
  235. PPCEVENT_ENTRY(pEventEntry)->EventItem = pPcEventRequest->EventItem;
  236. PPCEVENT_ENTRY(pEventEntry)->PinId = pContext->ulPinId;
  237. PPCEVENT_ENTRY(pEventEntry)->NodeId = pPcEventRequest->Node;
  238. PPCEVENT_ENTRY(pEventEntry)->pUnknownMajorTarget = pPcEventRequest->MajorTarget;
  239. PPCEVENT_ENTRY(pEventEntry)->pUnknownMinorTarget = pPcEventRequest->MinorTarget;
  240. pPcEventRequest->Verb = PCEVENT_VERB_ADD;
  241. pPcEventRequest->Irp = pIrp;
  242. pPcEventRequest->EventEntry = pEventEntry;
  243. //
  244. // call the handler
  245. //
  246. ntStatus = pPcEventRequest->EventItem->Handler( pPcEventRequest );
  247. }
  248. else
  249. {
  250. ntStatus = STATUS_NOT_FOUND;
  251. }
  252. }
  253. //
  254. // delete the request structure unless we are pending
  255. //
  256. if( ntStatus != STATUS_PENDING )
  257. {
  258. delete pPcEventRequest;
  259. }
  260. else
  261. {
  262. //
  263. // only requests with IRPs can be pending
  264. //
  265. ASSERT(pIrp);
  266. }
  267. }
  268. return ntStatus;
  269. }
  270. /*****************************************************************************
  271. * EventItemSupportHandler()
  272. *****************************************************************************
  273. * KS-sytle event handler that handles Supports using the
  274. * PCEVENT_ITEM mechanism.
  275. */
  276. NTSTATUS
  277. EventItemSupportHandler
  278. (
  279. IN PIRP pIrp,
  280. IN PKSIDENTIFIER pRequest,
  281. IN OUT PVOID pData OPTIONAL
  282. )
  283. {
  284. PAGED_CODE();
  285. ASSERT(pIrp);
  286. ASSERT(pRequest);
  287. NTSTATUS ntStatus = STATUS_SUCCESS;
  288. _DbgPrintF(DEBUGLVL_BLAB,("EventItemSupportHandler"));
  289. // get the IRP stack location
  290. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp );
  291. // get the property/event context
  292. PEVENT_CONTEXT pContext = PEVENT_CONTEXT(pIrp->Tail.Overlay.DriverContext[3]);
  293. // get the instance size
  294. ULONG ulInstanceSize = irpSp->Parameters.DeviceIoControl.InputBufferLength;
  295. //
  296. // Setup event request structure
  297. //
  298. PPCEVENT_REQUEST pPcEventRequest = new(NonPagedPool,'rEcP') PCEVENT_REQUEST;
  299. if( !pPcEventRequest )
  300. {
  301. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  302. }
  303. else
  304. {
  305. //
  306. // Copy target information from the context structure
  307. //
  308. pPcEventRequest->MajorTarget = pContext->pPropertyContext->pUnknownMajorTarget;
  309. pPcEventRequest->MinorTarget = pContext->pPropertyContext->pUnknownMinorTarget;
  310. pPcEventRequest->Node = pContext->pPropertyContext->ulNodeId;
  311. pPcEventRequest->EventItem = NULL;
  312. // get the filter descriptor
  313. PPCFILTER_DESCRIPTOR pPcFilterDescriptor = pContext->pPropertyContext->pPcFilterDescriptor;
  314. if( ULONG(-1) == pPcEventRequest->Node )
  315. {
  316. if( !pPcEventRequest->MinorTarget )
  317. {
  318. //
  319. // FILTER EVENT
  320. //
  321. if( ( pPcFilterDescriptor ) &&
  322. ( pPcFilterDescriptor->AutomationTable ) )
  323. {
  324. // search the filter's automation table for the event
  325. const PCAUTOMATION_TABLE *pPcAutomationTable =
  326. pPcFilterDescriptor->AutomationTable;
  327. const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
  328. for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
  329. {
  330. if( IsEqualGUIDAligned( *pPcEventItem->Set,
  331. pRequest->Set ) &&
  332. pPcEventItem->Id == pRequest->Id )
  333. {
  334. pPcEventRequest->EventItem = pPcEventItem;
  335. break;
  336. }
  337. pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
  338. }
  339. }
  340. }
  341. else
  342. {
  343. //
  344. // PIN EVENT
  345. //
  346. // validate the pin id
  347. if( ( pPcFilterDescriptor ) &&
  348. ( pContext->ulPinId < pPcFilterDescriptor->PinCount ) &&
  349. ( pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable ) )
  350. {
  351. // search the pin's automation table for the event
  352. const PCAUTOMATION_TABLE *pPcAutomationTable =
  353. pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable;
  354. const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
  355. for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
  356. {
  357. if( IsEqualGUIDAligned( *pPcEventItem->Set,
  358. pRequest->Set ) &&
  359. pPcEventItem->Id == pRequest->Id )
  360. {
  361. pPcEventRequest->EventItem = pPcEventItem;
  362. break;
  363. }
  364. pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
  365. }
  366. }
  367. }
  368. }
  369. else
  370. {
  371. //
  372. // NODE EVENT
  373. //
  374. // validate the node id
  375. if( ( pPcFilterDescriptor ) &&
  376. ( pPcEventRequest->Node < pPcFilterDescriptor->NodeCount ) &&
  377. ( pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable ) )
  378. {
  379. // search the node's automation table for the event
  380. const PCAUTOMATION_TABLE *pPcAutomationTable =
  381. pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable;
  382. const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
  383. for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
  384. {
  385. if( IsEqualGUIDAligned( *pPcEventItem->Set,
  386. pRequest->Set ) &&
  387. pPcEventItem->Id == pRequest->Id )
  388. {
  389. pPcEventRequest->EventItem = pPcEventItem;
  390. break;
  391. }
  392. pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
  393. }
  394. }
  395. }
  396. if(NT_SUCCESS(ntStatus))
  397. {
  398. //
  399. // call the handler if we have an event item with a handler
  400. //
  401. if( pPcEventRequest->EventItem &&
  402. pPcEventRequest->EventItem->Handler )
  403. {
  404. pPcEventRequest->Verb = PCEVENT_VERB_SUPPORT;
  405. pPcEventRequest->Irp = pIrp;
  406. pPcEventRequest->EventEntry = NULL;
  407. //
  408. // call the handler
  409. //
  410. ntStatus = pPcEventRequest->EventItem->Handler( pPcEventRequest );
  411. }
  412. else
  413. {
  414. ntStatus = STATUS_NOT_FOUND;
  415. }
  416. }
  417. //
  418. // delete the request structure unless we are pending
  419. //
  420. if( ntStatus != STATUS_PENDING )
  421. {
  422. delete pPcEventRequest;
  423. }
  424. else
  425. {
  426. //
  427. // only requests with IRPs can be pending
  428. //
  429. ASSERT(pIrp);
  430. }
  431. }
  432. return ntStatus;
  433. }
  434. #pragma code_seg()
  435. /*****************************************************************************
  436. * EventItemRemoveHandler()
  437. *****************************************************************************
  438. *
  439. */
  440. void
  441. EventItemRemoveHandler
  442. (
  443. IN PFILE_OBJECT pFileObject,
  444. IN PKSEVENT_ENTRY pEventEntry
  445. )
  446. {
  447. ASSERT(pFileObject);
  448. ASSERT(pEventEntry);
  449. _DbgPrintF(DEBUGLVL_VERBOSE,("EventItemRemoveHandler"));
  450. PPCEVENT_ENTRY pPcEventEntry = PPCEVENT_ENTRY(pEventEntry);
  451. //
  452. // Setup event request structure
  453. //
  454. PPCEVENT_REQUEST pPcEventRequest = new(NonPagedPool,'rEcP') PCEVENT_REQUEST;
  455. if( pPcEventRequest )
  456. {
  457. //
  458. // Fill out the event request for the miniport
  459. //
  460. pPcEventRequest->MajorTarget = pPcEventEntry->pUnknownMajorTarget;
  461. pPcEventRequest->MinorTarget = pPcEventEntry->pUnknownMinorTarget;
  462. pPcEventRequest->Node = pPcEventEntry->NodeId;
  463. pPcEventRequest->EventItem = pPcEventEntry->EventItem;
  464. pPcEventRequest->Verb = PCEVENT_VERB_REMOVE;
  465. pPcEventRequest->Irp = NULL;
  466. pPcEventRequest->EventEntry = pEventEntry;
  467. if( ( pPcEventEntry->EventItem ) &&
  468. ( pPcEventEntry->EventItem->Handler ) )
  469. {
  470. pPcEventEntry->EventItem->Handler( pPcEventRequest );
  471. }
  472. delete pPcEventRequest;
  473. }
  474. RemoveEntryList( &(pEventEntry->ListEntry) );
  475. }
  476. #pragma code_seg("PAGE")
  477. /*****************************************************************************
  478. * PcCompletePendingEventRequest()
  479. *****************************************************************************
  480. * Completes a pending event request.
  481. */
  482. PORTCLASSAPI
  483. NTSTATUS
  484. NTAPI
  485. PcCompletePendingEventRequest
  486. (
  487. IN PPCEVENT_REQUEST EventRequest,
  488. IN NTSTATUS NtStatus
  489. )
  490. {
  491. PAGED_CODE();
  492. ASSERT(EventRequest);
  493. ASSERT(NtStatus != STATUS_PENDING);
  494. if (!NT_ERROR(NtStatus))
  495. {
  496. EventRequest->Irp->IoStatus.Information = 0;
  497. }
  498. EventRequest->Irp->IoStatus.Status = NtStatus;
  499. IoCompleteRequest(EventRequest->Irp,IO_NO_INCREMENT);
  500. delete EventRequest;
  501. return STATUS_SUCCESS;
  502. }
  503. /*****************************************************************************
  504. * PcFreeEventTable()
  505. *****************************************************************************
  506. * Frees allocated memory in a EVENT_TABLE structure.
  507. */
  508. PORTCLASSAPI
  509. void
  510. NTAPI
  511. PcFreeEventTable
  512. (
  513. IN PEVENT_TABLE EventTable
  514. )
  515. {
  516. _DbgPrintF(DEBUGLVL_VERBOSE,("PcFreeEventTable"));
  517. PAGED_CODE();
  518. ASSERT(EventTable);
  519. ASSERT((!EventTable->EventSets) == (!EventTable->EventSetCount));
  520. // EventSets and EventSetCount must be non-NULL/non-zero, or NULL/zero
  521. ASSERT(EventTable->StaticSets == (!EventTable->StaticItems));
  522. // StaticSets and StaticItems must be TRUE/NULL, or FALSE/non-null
  523. PBOOLEAN staticItem = EventTable->StaticItems;
  524. if (staticItem)
  525. {
  526. PKSEVENT_SET eventSet = EventTable->EventSets;
  527. if (eventSet)
  528. {
  529. for( ULONG count = EventTable->EventSetCount;
  530. count--;
  531. eventSet++, staticItem++)
  532. {
  533. if ((! *staticItem) && eventSet->EventItem)
  534. {
  535. ExFreePool(PVOID(eventSet->EventItem));
  536. }
  537. }
  538. }
  539. ExFreePool(EventTable->StaticItems);
  540. EventTable->StaticItems = NULL;
  541. }
  542. if (EventTable->EventSets && !EventTable->StaticSets)
  543. {
  544. EventTable->EventSetCount = 0;
  545. ExFreePool(EventTable->EventSets);
  546. EventTable->EventSets = NULL;
  547. }
  548. EventTable->StaticSets = TRUE;
  549. }
  550. /*****************************************************************************
  551. * PcAddToEventTable()
  552. *****************************************************************************
  553. * Adds an EVENT_ITEM event table to a EVENT_TABLE structure.
  554. */
  555. PORTCLASSAPI
  556. NTSTATUS
  557. NTAPI
  558. PcAddToEventTable
  559. (
  560. IN OUT PEVENT_TABLE EventTable,
  561. IN ULONG EventItemCount,
  562. IN const PCEVENT_ITEM * EventItems,
  563. IN ULONG EventItemSize,
  564. IN BOOLEAN NodeTable
  565. )
  566. {
  567. PAGED_CODE();
  568. ASSERT(EventTable);
  569. ASSERT(EventItems);
  570. ASSERT(EventItemSize >= sizeof(PCEVENT_ITEM));
  571. _DbgPrintF(DEBUGLVL_VERBOSE,("PcAddToEventTable"));
  572. #define ADVANCE(item) (item = PPCEVENT_ITEM(PBYTE(item) + EventItemSize))
  573. ASSERT((!EventTable->EventSets) == (!EventTable->EventSetCount));
  574. // values must be non-NULL/non-zero, or NULL/zero.
  575. //
  576. // Determine how many sets we will end up with.
  577. //
  578. ULONG setCount = EventTable->EventSetCount;
  579. const PCEVENT_ITEM *item = EventItems;
  580. for (ULONG count = EventItemCount; count--; ADVANCE(item))
  581. {
  582. BOOLEAN countThis = TRUE;
  583. //
  584. // See if it's already in the table.
  585. //
  586. PKSEVENT_SET eventSet = EventTable->EventSets;
  587. for
  588. ( ULONG count2 = EventTable->EventSetCount;
  589. count2--;
  590. eventSet++
  591. )
  592. {
  593. if (IsEqualGUIDAligned(*item->Set,*eventSet->Set))
  594. {
  595. countThis = FALSE;
  596. break;
  597. }
  598. }
  599. if (countThis)
  600. {
  601. //
  602. // See if it's appeared in the list previously.
  603. //
  604. for
  605. (
  606. const PCEVENT_ITEM *prevItem = EventItems;
  607. prevItem != item;
  608. ADVANCE(prevItem)
  609. )
  610. {
  611. if (IsEqualGUIDAligned(*item->Set,*prevItem->Set))
  612. {
  613. countThis = FALSE;
  614. break;
  615. }
  616. }
  617. }
  618. if (countThis)
  619. {
  620. setCount++;
  621. }
  622. }
  623. NTSTATUS ntStatus = STATUS_SUCCESS;
  624. //
  625. // Make a new set table.
  626. //
  627. ASSERT(setCount);
  628. ASSERT(setCount >= EventTable->EventSetCount);
  629. //
  630. // Allocate memory required for the set table.
  631. //
  632. PKSEVENT_SET newTable =
  633. PKSEVENT_SET
  634. (
  635. ExAllocatePoolWithTag
  636. (
  637. NonPagedPool,
  638. sizeof(KSEVENT_SET) * setCount,
  639. 'tEcP'
  640. )
  641. );
  642. //
  643. // Allocate memory for the static items flags.
  644. //
  645. PBOOLEAN newStaticItems = NULL;
  646. if (newTable)
  647. {
  648. newStaticItems =
  649. PBOOLEAN
  650. (
  651. ExAllocatePoolWithTag
  652. (
  653. PagedPool,
  654. sizeof(BOOLEAN) * setCount,
  655. 'bScP'
  656. )
  657. );
  658. if (! newStaticItems)
  659. {
  660. ExFreePool(newTable);
  661. newTable = NULL;
  662. }
  663. }
  664. if (newTable)
  665. {
  666. //
  667. // Initialize the new set table.
  668. //
  669. RtlZeroMemory
  670. (
  671. PVOID(newTable),
  672. sizeof(KSEVENT_SET) * setCount
  673. );
  674. if (EventTable->EventSetCount != 0)
  675. {
  676. RtlCopyMemory
  677. (
  678. PVOID(newTable),
  679. PVOID(EventTable->EventSets),
  680. sizeof(KSEVENT_SET) * EventTable->EventSetCount
  681. );
  682. }
  683. //
  684. // Initialize the new static items flags.
  685. //
  686. RtlFillMemory
  687. (
  688. PVOID(newStaticItems),
  689. sizeof(BOOLEAN) * setCount,
  690. 0xff
  691. );
  692. if (EventTable->StaticItems && EventTable->EventSetCount)
  693. {
  694. //
  695. // Flags existed before...copy them.
  696. //
  697. RtlCopyMemory
  698. (
  699. PVOID(newStaticItems),
  700. PVOID(EventTable->StaticItems),
  701. sizeof(BOOLEAN) * EventTable->EventSetCount
  702. );
  703. }
  704. //
  705. // Assign set GUIDs to the new set entries.
  706. //
  707. PKSEVENT_SET addHere =
  708. newTable + EventTable->EventSetCount;
  709. const PCEVENT_ITEM *item2 = EventItems;
  710. for (ULONG count = EventItemCount; count--; ADVANCE(item2))
  711. {
  712. BOOLEAN addThis = TRUE;
  713. //
  714. // See if it's already in the table.
  715. //
  716. for( PKSEVENT_SET eventSet = newTable;
  717. eventSet != addHere;
  718. eventSet++)
  719. {
  720. if (IsEqualGUIDAligned(*item2->Set,*eventSet->Set))
  721. {
  722. addThis = FALSE;
  723. break;
  724. }
  725. }
  726. if (addThis)
  727. {
  728. addHere->Set = item2->Set;
  729. addHere++;
  730. }
  731. }
  732. ASSERT(addHere == newTable + setCount);
  733. //
  734. // Free old allocated tables.
  735. //
  736. if (EventTable->EventSets && (!EventTable->StaticSets))
  737. {
  738. ExFreePool(EventTable->EventSets);
  739. }
  740. if (EventTable->StaticItems)
  741. {
  742. ExFreePool(EventTable->StaticItems);
  743. }
  744. //
  745. // Install the new tables.
  746. //
  747. EventTable->EventSetCount = setCount;
  748. EventTable->EventSets = newTable;
  749. EventTable->StaticSets = FALSE;
  750. EventTable->StaticItems = newStaticItems;
  751. }
  752. else
  753. {
  754. // if allocations fail, return error and
  755. // keep sets and items as they were.
  756. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  757. }
  758. //
  759. // Now we have an event set table that contains all the sets we need.
  760. //
  761. if (NT_SUCCESS(ntStatus))
  762. {
  763. //
  764. // For each set...
  765. //
  766. PKSEVENT_SET eventSet = EventTable->EventSets;
  767. PBOOLEAN staticItem = EventTable->StaticItems;
  768. for
  769. ( ULONG count = EventTable->EventSetCount;
  770. count--;
  771. eventSet++, staticItem++
  772. )
  773. {
  774. //
  775. // Check to see how many new items we have.
  776. //
  777. ULONG itemCount = eventSet->EventsCount;
  778. const PCEVENT_ITEM *item2 = EventItems;
  779. for (ULONG count2 = EventItemCount; count2--; ADVANCE(item2))
  780. {
  781. if (IsEqualGUIDAligned(*item2->Set,*eventSet->Set))
  782. {
  783. itemCount++;
  784. }
  785. }
  786. ASSERT(itemCount >= eventSet->EventsCount);
  787. if (itemCount != eventSet->EventsCount)
  788. {
  789. //
  790. // Allocate memory required for the items table.
  791. //
  792. PKSEVENT_ITEM newTable2 =
  793. PKSEVENT_ITEM
  794. (
  795. ExAllocatePoolWithTag
  796. (
  797. NonPagedPool,
  798. sizeof(KSEVENT_ITEM) * itemCount,
  799. 'iEcP'
  800. )
  801. );
  802. if (! newTable2)
  803. {
  804. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  805. break;
  806. }
  807. //
  808. // Initialize the table.
  809. //
  810. RtlZeroMemory
  811. (
  812. PVOID(newTable2),
  813. sizeof(KSEVENT_ITEM) * itemCount
  814. );
  815. if (eventSet->EventsCount)
  816. {
  817. RtlCopyMemory
  818. (
  819. PVOID(newTable2),
  820. PVOID(eventSet->EventItem),
  821. sizeof(KSEVENT_ITEM) * eventSet->EventsCount
  822. );
  823. }
  824. //
  825. // Create the new items.
  826. //
  827. PKSEVENT_ITEM addHere =
  828. newTable2 + eventSet->EventsCount;
  829. item2 = EventItems;
  830. for (count2 = EventItemCount; count2--; ADVANCE(item2))
  831. {
  832. if (IsEqualGUIDAligned(*item2->Set,*eventSet->Set))
  833. {
  834. addHere->EventId = item2->Id;
  835. addHere->DataInput = sizeof( KSEVENTDATA );
  836. addHere->ExtraEntryData = sizeof( PCEVENT_ENTRY ) - sizeof( KSEVENT_ENTRY );
  837. addHere->AddHandler = EventItemAddHandler;
  838. addHere->RemoveHandler = EventItemRemoveHandler;
  839. addHere->SupportHandler = EventItemSupportHandler;
  840. addHere++;
  841. }
  842. }
  843. ASSERT(addHere == newTable2 + itemCount);
  844. //
  845. // Free old allocated table.
  846. //
  847. if (eventSet->EventItem && ! *staticItem)
  848. {
  849. ExFreePool(PVOID(eventSet->EventItem));
  850. }
  851. //
  852. // Install the new tables.
  853. //
  854. eventSet->EventsCount = itemCount;
  855. eventSet->EventItem = newTable2;
  856. *staticItem = FALSE;
  857. }
  858. }
  859. }
  860. return ntStatus;
  861. }
  862. #pragma code_seg()
  863. /*****************************************************************************
  864. * PcGenerateEventList()
  865. *****************************************************************************
  866. * Walks an event list and generates desired events.
  867. */
  868. PORTCLASSAPI
  869. void
  870. NTAPI
  871. PcGenerateEventList
  872. (
  873. IN PINTERLOCKED_LIST EventList,
  874. IN GUID* Set OPTIONAL,
  875. IN ULONG EventId,
  876. IN BOOL PinEvent,
  877. IN ULONG PinId,
  878. IN BOOL NodeEvent,
  879. IN ULONG NodeId
  880. )
  881. {
  882. ASSERT(EventList);
  883. KIRQL oldIrql;
  884. PLIST_ENTRY ListEntry;
  885. PKSEVENT_ENTRY EventEntry;
  886. if( EventList )
  887. {
  888. ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL );
  889. // acquire the event list lock
  890. KeAcquireSpinLock( &(EventList->ListLock), &oldIrql );
  891. // only walk a non-empty list
  892. if( !IsListEmpty( &(EventList->List) ) )
  893. {
  894. for( ListEntry = EventList->List.Flink;
  895. ListEntry != &(EventList->List);
  896. ListEntry = ListEntry->Flink )
  897. {
  898. EventEntry = (PKSEVENT_ENTRY) CONTAINING_RECORD( ListEntry,
  899. KSEVENT_ENTRY,
  900. ListEntry );
  901. if( ( !Set
  902. ||
  903. IsEqualGUIDAligned( *Set, *(EventEntry->EventSet->Set) )
  904. )
  905. &&
  906. ( EventId == EventEntry->EventItem->EventId
  907. )
  908. &&
  909. ( !PinEvent
  910. ||
  911. ( PinId == PPCEVENT_ENTRY(EventEntry)->PinId )
  912. )
  913. &&
  914. ( !NodeEvent
  915. ||
  916. ( NodeId == PPCEVENT_ENTRY(EventEntry)->NodeId )
  917. )
  918. )
  919. {
  920. KsGenerateEvent( EventEntry );
  921. }
  922. }
  923. }
  924. // release the event list lock
  925. KeReleaseSpinLock( &(EventList->ListLock), oldIrql );
  926. }
  927. }
  928. /*****************************************************************************
  929. * PcGenerateEventDeferredRoutine()
  930. *****************************************************************************
  931. * This DPC routine is used when GenerateEventList is called at greater
  932. * that DISPATCH_LEVEL.
  933. */
  934. PORTCLASSAPI
  935. void
  936. NTAPI
  937. PcGenerateEventDeferredRoutine
  938. (
  939. IN PKDPC Dpc,
  940. IN PVOID DeferredContext, // PEVENT_DPC_CONTEXT
  941. IN PVOID SystemArgument1, // PINTERLOCKED_LIST
  942. IN PVOID SystemArgument2
  943. )
  944. {
  945. ASSERT(Dpc);
  946. ASSERT(DeferredContext);
  947. ASSERT(SystemArgument1);
  948. PEVENT_DPC_CONTEXT Context = PEVENT_DPC_CONTEXT(DeferredContext);
  949. PINTERLOCKED_LIST EventList = PINTERLOCKED_LIST(SystemArgument1);
  950. if( Context && EventList )
  951. {
  952. PcGenerateEventList( EventList,
  953. Context->Set,
  954. Context->EventId,
  955. Context->PinEvent,
  956. Context->PinId,
  957. Context->NodeEvent,
  958. Context->NodeId );
  959. Context->ContextInUse = FALSE;
  960. }
  961. }