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

/*****************************************************************************
* event.cpp - event support
*****************************************************************************
* Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
*/
#include "private.h"
/*****************************************************************************
* Functions
*/
#pragma code_seg("PAGE")
/*****************************************************************************
* PcHandleEnableEventWithTable()
*****************************************************************************
* Uses an event table to handle a KS enable event IOCTL.
*/
PORTCLASSAPI
NTSTATUS
NTAPI
PcHandleEnableEventWithTable
(
IN PIRP pIrp,
IN PEVENT_CONTEXT pContext
)
{
PAGED_CODE();
ASSERT(pIrp);
ASSERT(pContext);
PIO_STACK_LOCATION IrpStack;
ULONG InputBufferLength;
NTSTATUS ntStatus = STATUS_SUCCESS;
_DbgPrintF(DEBUGLVL_BLAB,("PcHandleEnableEventWithTable"));
// deal with possible node events
IrpStack = IoGetCurrentIrpStackLocation( pIrp );
InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
if( InputBufferLength >= sizeof(KSE_NODE) )
{
ULONG Flags;
__try {
// validate the pointers if we don't trust the client
if( pIrp->RequestorMode != KernelMode )
{
ProbeForRead( IrpStack->Parameters.DeviceIoControl.Type3InputBuffer,
InputBufferLength,
sizeof(BYTE));
}
// get the flags
Flags = ((PKSEVENT)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)->Flags;
if( Flags & KSEVENT_TYPE_TOPOLOGY )
{
// get the node id
pContext->pPropertyContext->ulNodeId =
((PKSE_NODE)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)->NodeId;
// mask off the flag bit
((PKSEVENT)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)->Flags &= ~KSEVENT_TYPE_TOPOLOGY;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
ntStatus = GetExceptionCode ();
}
}
if (NT_SUCCESS(ntStatus))
{
pIrp->Tail.Overlay.DriverContext[3] = pContext;
ntStatus = KsEnableEvent( pIrp,
pContext->ulEventSetCount,
pContext->pEventSets,
NULL,
KSEVENTS_NONE,
NULL );
// restore ulNodeId
pContext->pPropertyContext->ulNodeId = ULONG(-1);
}
return ntStatus;
}
/*****************************************************************************
* PcHandleDisableEventWithTable()
*****************************************************************************
* Uses an event table to handle a KS disable event IOCTL.
*/
PORTCLASSAPI
NTSTATUS
NTAPI
PcHandleDisableEventWithTable
(
IN PIRP pIrp,
IN PEVENT_CONTEXT pContext
)
{
PAGED_CODE();
ASSERT(pIrp);
ASSERT(pContext);
_DbgPrintF(DEBUGLVL_VERBOSE,("PcHandleDisableEventWithTable"));
pIrp->Tail.Overlay.DriverContext[3] = pContext;
return KsDisableEvent( pIrp,
&(pContext->pEventList->List),
KSEVENTS_SPINLOCK,
&(pContext->pEventList->ListLock) );
}
/*****************************************************************************
* EventItemAddHandler()
*****************************************************************************
* KS-sytle event handler that handles Adds using the
* PCEVENT_ITEM mechanism. Note that filter and pin events in the port do not
* utilize this AddHandler, only events exposed by the miniport.
*/
NTSTATUS
EventItemAddHandler
(
IN PIRP pIrp,
IN PKSEVENTDATA pEventData,
IN PKSEVENT_ENTRY pEventEntry
)
{
PAGED_CODE();
ASSERT(pIrp);
NTSTATUS ntStatus = STATUS_SUCCESS;
_DbgPrintF(DEBUGLVL_VERBOSE,("EventItemAddHandler"));
// get the IRP stack location
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp );
// get the event context
PEVENT_CONTEXT pContext = PEVENT_CONTEXT(pIrp->Tail.Overlay.DriverContext[3]);
// get the instance size
ULONG ulInstanceSize = irpSp->Parameters.DeviceIoControl.InputBufferLength;
ULONG AlignedBufferLength = (irpSp->Parameters.DeviceIoControl.OutputBufferLength +
FILE_QUAD_ALIGNMENT) &
~FILE_QUAD_ALIGNMENT;
//
// Setup event request structure
//
PPCEVENT_REQUEST pPcEventRequest = new(NonPagedPool,'rEcP') PCEVENT_REQUEST;
if( !pPcEventRequest )
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
//
// Copy target information from the context structure
//
pPcEventRequest->MajorTarget = pContext->pPropertyContext->pUnknownMajorTarget;
pPcEventRequest->MinorTarget = pContext->pPropertyContext->pUnknownMinorTarget;
pPcEventRequest->Node = pContext->pPropertyContext->ulNodeId;
pPcEventRequest->EventItem = NULL;
// get the filter descriptor
PPCFILTER_DESCRIPTOR pPcFilterDescriptor = pContext->pPropertyContext->pPcFilterDescriptor;
if( ULONG(-1) == pPcEventRequest->Node )
{
if( !pPcEventRequest->MinorTarget )
{
//
// FILTER EVENT
//
if( ( pPcFilterDescriptor ) &&
( pPcFilterDescriptor->AutomationTable ) )
{
// search the filter's automation table for the event
const PCAUTOMATION_TABLE *pPcAutomationTable =
pPcFilterDescriptor->AutomationTable;
const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
{
if( IsEqualGUIDAligned( *pPcEventItem->Set,
*pEventEntry->EventSet->Set ) &&
pPcEventItem->Id == pEventEntry->EventItem->EventId )
{
pPcEventRequest->EventItem = pPcEventItem;
break;
}
pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
}
}
}
else
{
//
// PIN EVENT
//
// validate the pin id
if( ( pPcFilterDescriptor ) &&
( pContext->ulPinId < pPcFilterDescriptor->PinCount ) &&
( pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable ) )
{
// search the pin's automation table for the event
const PCAUTOMATION_TABLE *pPcAutomationTable =
pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable;
const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
{
if( IsEqualGUIDAligned( *pPcEventItem->Set,
*pEventEntry->EventSet->Set ) &&
pPcEventItem->Id == pEventEntry->EventItem->EventId )
{
pPcEventRequest->EventItem = pPcEventItem;
break;
}
pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
}
}
}
}
else
{
//
// NODE EVENT
//
// validate the node id
if( ( pPcFilterDescriptor ) &&
( pPcEventRequest->Node < pPcFilterDescriptor->NodeCount ) &&
( pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable ) )
{
// search the node's automation table for the event
const PCAUTOMATION_TABLE *pPcAutomationTable =
pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable;
const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
{
if( IsEqualGUIDAligned( *pPcEventItem->Set,
*pEventEntry->EventSet->Set ) &&
pPcEventItem->Id == pEventEntry->EventItem->EventId )
{
pPcEventRequest->EventItem = pPcEventItem;
break;
}
pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
}
}
}
if( NT_SUCCESS(ntStatus) )
{
//
// call the handler if we have an event item with a handler
if( pPcEventRequest->EventItem &&
pPcEventRequest->EventItem->Handler )
{
PPCEVENT_ENTRY(pEventEntry)->EventItem = pPcEventRequest->EventItem;
PPCEVENT_ENTRY(pEventEntry)->PinId = pContext->ulPinId;
PPCEVENT_ENTRY(pEventEntry)->NodeId = pPcEventRequest->Node;
PPCEVENT_ENTRY(pEventEntry)->pUnknownMajorTarget = pPcEventRequest->MajorTarget;
PPCEVENT_ENTRY(pEventEntry)->pUnknownMinorTarget = pPcEventRequest->MinorTarget;
pPcEventRequest->Verb = PCEVENT_VERB_ADD;
pPcEventRequest->Irp = pIrp;
pPcEventRequest->EventEntry = pEventEntry;
//
// call the handler
//
ntStatus = pPcEventRequest->EventItem->Handler( pPcEventRequest );
}
else
{
ntStatus = STATUS_NOT_FOUND;
}
}
//
// delete the request structure unless we are pending
//
if( ntStatus != STATUS_PENDING )
{
delete pPcEventRequest;
}
else
{
//
// only requests with IRPs can be pending
//
ASSERT(pIrp);
}
}
return ntStatus;
}
/*****************************************************************************
* EventItemSupportHandler()
*****************************************************************************
* KS-sytle event handler that handles Supports using the
* PCEVENT_ITEM mechanism.
*/
NTSTATUS
EventItemSupportHandler
(
IN PIRP pIrp,
IN PKSIDENTIFIER pRequest,
IN OUT PVOID pData OPTIONAL
)
{
PAGED_CODE();
ASSERT(pIrp);
ASSERT(pRequest);
NTSTATUS ntStatus = STATUS_SUCCESS;
_DbgPrintF(DEBUGLVL_BLAB,("EventItemSupportHandler"));
// get the IRP stack location
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp );
// get the property/event context
PEVENT_CONTEXT pContext = PEVENT_CONTEXT(pIrp->Tail.Overlay.DriverContext[3]);
// get the instance size
ULONG ulInstanceSize = irpSp->Parameters.DeviceIoControl.InputBufferLength;
//
// Setup event request structure
//
PPCEVENT_REQUEST pPcEventRequest = new(NonPagedPool,'rEcP') PCEVENT_REQUEST;
if( !pPcEventRequest )
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
//
// Copy target information from the context structure
//
pPcEventRequest->MajorTarget = pContext->pPropertyContext->pUnknownMajorTarget;
pPcEventRequest->MinorTarget = pContext->pPropertyContext->pUnknownMinorTarget;
pPcEventRequest->Node = pContext->pPropertyContext->ulNodeId;
pPcEventRequest->EventItem = NULL;
// get the filter descriptor
PPCFILTER_DESCRIPTOR pPcFilterDescriptor = pContext->pPropertyContext->pPcFilterDescriptor;
if( ULONG(-1) == pPcEventRequest->Node )
{
if( !pPcEventRequest->MinorTarget )
{
//
// FILTER EVENT
//
if( ( pPcFilterDescriptor ) &&
( pPcFilterDescriptor->AutomationTable ) )
{
// search the filter's automation table for the event
const PCAUTOMATION_TABLE *pPcAutomationTable =
pPcFilterDescriptor->AutomationTable;
const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
{
if( IsEqualGUIDAligned( *pPcEventItem->Set,
pRequest->Set ) &&
pPcEventItem->Id == pRequest->Id )
{
pPcEventRequest->EventItem = pPcEventItem;
break;
}
pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
}
}
}
else
{
//
// PIN EVENT
//
// validate the pin id
if( ( pPcFilterDescriptor ) &&
( pContext->ulPinId < pPcFilterDescriptor->PinCount ) &&
( pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable ) )
{
// search the pin's automation table for the event
const PCAUTOMATION_TABLE *pPcAutomationTable =
pPcFilterDescriptor->Pins[pContext->ulPinId].AutomationTable;
const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
{
if( IsEqualGUIDAligned( *pPcEventItem->Set,
pRequest->Set ) &&
pPcEventItem->Id == pRequest->Id )
{
pPcEventRequest->EventItem = pPcEventItem;
break;
}
pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
}
}
}
}
else
{
//
// NODE EVENT
//
// validate the node id
if( ( pPcFilterDescriptor ) &&
( pPcEventRequest->Node < pPcFilterDescriptor->NodeCount ) &&
( pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable ) )
{
// search the node's automation table for the event
const PCAUTOMATION_TABLE *pPcAutomationTable =
pPcFilterDescriptor->Nodes[pPcEventRequest->Node].AutomationTable;
const PCEVENT_ITEM *pPcEventItem = pPcAutomationTable->Events;
for(ULONG ul = pPcAutomationTable->EventCount; ul--; )
{
if( IsEqualGUIDAligned( *pPcEventItem->Set,
pRequest->Set ) &&
pPcEventItem->Id == pRequest->Id )
{
pPcEventRequest->EventItem = pPcEventItem;
break;
}
pPcEventItem = PPCEVENT_ITEM( PBYTE(pPcEventItem) + pPcAutomationTable->EventItemSize);
}
}
}
if(NT_SUCCESS(ntStatus))
{
//
// call the handler if we have an event item with a handler
//
if( pPcEventRequest->EventItem &&
pPcEventRequest->EventItem->Handler )
{
pPcEventRequest->Verb = PCEVENT_VERB_SUPPORT;
pPcEventRequest->Irp = pIrp;
pPcEventRequest->EventEntry = NULL;
//
// call the handler
//
ntStatus = pPcEventRequest->EventItem->Handler( pPcEventRequest );
}
else
{
ntStatus = STATUS_NOT_FOUND;
}
}
//
// delete the request structure unless we are pending
//
if( ntStatus != STATUS_PENDING )
{
delete pPcEventRequest;
}
else
{
//
// only requests with IRPs can be pending
//
ASSERT(pIrp);
}
}
return ntStatus;
}
#pragma code_seg()
/*****************************************************************************
* EventItemRemoveHandler()
*****************************************************************************
*
*/
void
EventItemRemoveHandler
(
IN PFILE_OBJECT pFileObject,
IN PKSEVENT_ENTRY pEventEntry
)
{
ASSERT(pFileObject);
ASSERT(pEventEntry);
_DbgPrintF(DEBUGLVL_VERBOSE,("EventItemRemoveHandler"));
PPCEVENT_ENTRY pPcEventEntry = PPCEVENT_ENTRY(pEventEntry);
//
// Setup event request structure
//
PPCEVENT_REQUEST pPcEventRequest = new(NonPagedPool,'rEcP') PCEVENT_REQUEST;
if( pPcEventRequest )
{
//
// Fill out the event request for the miniport
//
pPcEventRequest->MajorTarget = pPcEventEntry->pUnknownMajorTarget;
pPcEventRequest->MinorTarget = pPcEventEntry->pUnknownMinorTarget;
pPcEventRequest->Node = pPcEventEntry->NodeId;
pPcEventRequest->EventItem = pPcEventEntry->EventItem;
pPcEventRequest->Verb = PCEVENT_VERB_REMOVE;
pPcEventRequest->Irp = NULL;
pPcEventRequest->EventEntry = pEventEntry;
if( ( pPcEventEntry->EventItem ) &&
( pPcEventEntry->EventItem->Handler ) )
{
pPcEventEntry->EventItem->Handler( pPcEventRequest );
}
delete pPcEventRequest;
}
RemoveEntryList( &(pEventEntry->ListEntry) );
}
#pragma code_seg("PAGE")
/*****************************************************************************
* PcCompletePendingEventRequest()
*****************************************************************************
* Completes a pending event request.
*/
PORTCLASSAPI
NTSTATUS
NTAPI
PcCompletePendingEventRequest
(
IN PPCEVENT_REQUEST EventRequest,
IN NTSTATUS NtStatus
)
{
PAGED_CODE();
ASSERT(EventRequest);
ASSERT(NtStatus != STATUS_PENDING);
if (!NT_ERROR(NtStatus))
{
EventRequest->Irp->IoStatus.Information = 0;
}
EventRequest->Irp->IoStatus.Status = NtStatus;
IoCompleteRequest(EventRequest->Irp,IO_NO_INCREMENT);
delete EventRequest;
return STATUS_SUCCESS;
}
/*****************************************************************************
* PcFreeEventTable()
*****************************************************************************
* Frees allocated memory in a EVENT_TABLE structure.
*/
PORTCLASSAPI
void
NTAPI
PcFreeEventTable
(
IN PEVENT_TABLE EventTable
)
{
_DbgPrintF(DEBUGLVL_VERBOSE,("PcFreeEventTable"));
PAGED_CODE();
ASSERT(EventTable);
ASSERT((!EventTable->EventSets) == (!EventTable->EventSetCount));
// EventSets and EventSetCount must be non-NULL/non-zero, or NULL/zero
ASSERT(EventTable->StaticSets == (!EventTable->StaticItems));
// StaticSets and StaticItems must be TRUE/NULL, or FALSE/non-null
PBOOLEAN staticItem = EventTable->StaticItems;
if (staticItem)
{
PKSEVENT_SET eventSet = EventTable->EventSets;
if (eventSet)
{
for( ULONG count = EventTable->EventSetCount;
count--;
eventSet++, staticItem++)
{
if ((! *staticItem) && eventSet->EventItem)
{
ExFreePool(PVOID(eventSet->EventItem));
}
}
}
ExFreePool(EventTable->StaticItems);
EventTable->StaticItems = NULL;
}
if (EventTable->EventSets && !EventTable->StaticSets)
{
EventTable->EventSetCount = 0;
ExFreePool(EventTable->EventSets);
EventTable->EventSets = NULL;
}
EventTable->StaticSets = TRUE;
}
/*****************************************************************************
* PcAddToEventTable()
*****************************************************************************
* Adds an EVENT_ITEM event table to a EVENT_TABLE structure.
*/
PORTCLASSAPI
NTSTATUS
NTAPI
PcAddToEventTable
(
IN OUT PEVENT_TABLE EventTable,
IN ULONG EventItemCount,
IN const PCEVENT_ITEM * EventItems,
IN ULONG EventItemSize,
IN BOOLEAN NodeTable
)
{
PAGED_CODE();
ASSERT(EventTable);
ASSERT(EventItems);
ASSERT(EventItemSize >= sizeof(PCEVENT_ITEM));
_DbgPrintF(DEBUGLVL_VERBOSE,("PcAddToEventTable"));
#define ADVANCE(item) (item = PPCEVENT_ITEM(PBYTE(item) + EventItemSize))
ASSERT((!EventTable->EventSets) == (!EventTable->EventSetCount));
// values must be non-NULL/non-zero, or NULL/zero.
//
// Determine how many sets we will end up with.
//
ULONG setCount = EventTable->EventSetCount;
const PCEVENT_ITEM *item = EventItems;
for (ULONG count = EventItemCount; count--; ADVANCE(item))
{
BOOLEAN countThis = TRUE;
//
// See if it's already in the table.
//
PKSEVENT_SET eventSet = EventTable->EventSets;
for
( ULONG count2 = EventTable->EventSetCount;
count2--;
eventSet++
)
{
if (IsEqualGUIDAligned(*item->Set,*eventSet->Set))
{
countThis = FALSE;
break;
}
}
if (countThis)
{
//
// See if it's appeared in the list previously.
//
for
(
const PCEVENT_ITEM *prevItem = EventItems;
prevItem != item;
ADVANCE(prevItem)
)
{
if (IsEqualGUIDAligned(*item->Set,*prevItem->Set))
{
countThis = FALSE;
break;
}
}
}
if (countThis)
{
setCount++;
}
}
NTSTATUS ntStatus = STATUS_SUCCESS;
//
// Make a new set table.
//
ASSERT(setCount);
ASSERT(setCount >= EventTable->EventSetCount);
//
// Allocate memory required for the set table.
//
PKSEVENT_SET newTable =
PKSEVENT_SET
(
ExAllocatePoolWithTag
(
NonPagedPool,
sizeof(KSEVENT_SET) * setCount,
'tEcP'
)
);
//
// Allocate memory for the static items flags.
//
PBOOLEAN newStaticItems = NULL;
if (newTable)
{
newStaticItems =
PBOOLEAN
(
ExAllocatePoolWithTag
(
PagedPool,
sizeof(BOOLEAN) * setCount,
'bScP'
)
);
if (! newStaticItems)
{
ExFreePool(newTable);
newTable = NULL;
}
}
if (newTable)
{
//
// Initialize the new set table.
//
RtlZeroMemory
(
PVOID(newTable),
sizeof(KSEVENT_SET) * setCount
);
if (EventTable->EventSetCount != 0)
{
RtlCopyMemory
(
PVOID(newTable),
PVOID(EventTable->EventSets),
sizeof(KSEVENT_SET) * EventTable->EventSetCount
);
}
//
// Initialize the new static items flags.
//
RtlFillMemory
(
PVOID(newStaticItems),
sizeof(BOOLEAN) * setCount,
0xff
);
if (EventTable->StaticItems && EventTable->EventSetCount)
{
//
// Flags existed before...copy them.
//
RtlCopyMemory
(
PVOID(newStaticItems),
PVOID(EventTable->StaticItems),
sizeof(BOOLEAN) * EventTable->EventSetCount
);
}
//
// Assign set GUIDs to the new set entries.
//
PKSEVENT_SET addHere =
newTable + EventTable->EventSetCount;
const PCEVENT_ITEM *item2 = EventItems;
for (ULONG count = EventItemCount; count--; ADVANCE(item2))
{
BOOLEAN addThis = TRUE;
//
// See if it's already in the table.
//
for( PKSEVENT_SET eventSet = newTable;
eventSet != addHere;
eventSet++)
{
if (IsEqualGUIDAligned(*item2->Set,*eventSet->Set))
{
addThis = FALSE;
break;
}
}
if (addThis)
{
addHere->Set = item2->Set;
addHere++;
}
}
ASSERT(addHere == newTable + setCount);
//
// Free old allocated tables.
//
if (EventTable->EventSets && (!EventTable->StaticSets))
{
ExFreePool(EventTable->EventSets);
}
if (EventTable->StaticItems)
{
ExFreePool(EventTable->StaticItems);
}
//
// Install the new tables.
//
EventTable->EventSetCount = setCount;
EventTable->EventSets = newTable;
EventTable->StaticSets = FALSE;
EventTable->StaticItems = newStaticItems;
}
else
{
// if allocations fail, return error and
// keep sets and items as they were.
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
//
// Now we have an event set table that contains all the sets we need.
//
if (NT_SUCCESS(ntStatus))
{
//
// For each set...
//
PKSEVENT_SET eventSet = EventTable->EventSets;
PBOOLEAN staticItem = EventTable->StaticItems;
for
( ULONG count = EventTable->EventSetCount;
count--;
eventSet++, staticItem++
)
{
//
// Check to see how many new items we have.
//
ULONG itemCount = eventSet->EventsCount;
const PCEVENT_ITEM *item2 = EventItems;
for (ULONG count2 = EventItemCount; count2--; ADVANCE(item2))
{
if (IsEqualGUIDAligned(*item2->Set,*eventSet->Set))
{
itemCount++;
}
}
ASSERT(itemCount >= eventSet->EventsCount);
if (itemCount != eventSet->EventsCount)
{
//
// Allocate memory required for the items table.
//
PKSEVENT_ITEM newTable2 =
PKSEVENT_ITEM
(
ExAllocatePoolWithTag
(
NonPagedPool,
sizeof(KSEVENT_ITEM) * itemCount,
'iEcP'
)
);
if (! newTable2)
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// Initialize the table.
//
RtlZeroMemory
(
PVOID(newTable2),
sizeof(KSEVENT_ITEM) * itemCount
);
if (eventSet->EventsCount)
{
RtlCopyMemory
(
PVOID(newTable2),
PVOID(eventSet->EventItem),
sizeof(KSEVENT_ITEM) * eventSet->EventsCount
);
}
//
// Create the new items.
//
PKSEVENT_ITEM addHere =
newTable2 + eventSet->EventsCount;
item2 = EventItems;
for (count2 = EventItemCount; count2--; ADVANCE(item2))
{
if (IsEqualGUIDAligned(*item2->Set,*eventSet->Set))
{
addHere->EventId = item2->Id;
addHere->DataInput = sizeof( KSEVENTDATA );
addHere->ExtraEntryData = sizeof( PCEVENT_ENTRY ) - sizeof( KSEVENT_ENTRY );
addHere->AddHandler = EventItemAddHandler;
addHere->RemoveHandler = EventItemRemoveHandler;
addHere->SupportHandler = EventItemSupportHandler;
addHere++;
}
}
ASSERT(addHere == newTable2 + itemCount);
//
// Free old allocated table.
//
if (eventSet->EventItem && ! *staticItem)
{
ExFreePool(PVOID(eventSet->EventItem));
}
//
// Install the new tables.
//
eventSet->EventsCount = itemCount;
eventSet->EventItem = newTable2;
*staticItem = FALSE;
}
}
}
return ntStatus;
}
#pragma code_seg()
/*****************************************************************************
* PcGenerateEventList()
*****************************************************************************
* Walks an event list and generates desired events.
*/
PORTCLASSAPI
void
NTAPI
PcGenerateEventList
(
IN PINTERLOCKED_LIST EventList,
IN GUID* Set OPTIONAL,
IN ULONG EventId,
IN BOOL PinEvent,
IN ULONG PinId,
IN BOOL NodeEvent,
IN ULONG NodeId
)
{
ASSERT(EventList);
KIRQL oldIrql;
PLIST_ENTRY ListEntry;
PKSEVENT_ENTRY EventEntry;
if( EventList )
{
ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL );
// acquire the event list lock
KeAcquireSpinLock( &(EventList->ListLock), &oldIrql );
// only walk a non-empty list
if( !IsListEmpty( &(EventList->List) ) )
{
for( ListEntry = EventList->List.Flink;
ListEntry != &(EventList->List);
ListEntry = ListEntry->Flink )
{
EventEntry = (PKSEVENT_ENTRY) CONTAINING_RECORD( ListEntry,
KSEVENT_ENTRY,
ListEntry );
if( ( !Set
||
IsEqualGUIDAligned( *Set, *(EventEntry->EventSet->Set) )
)
&&
( EventId == EventEntry->EventItem->EventId
)
&&
( !PinEvent
||
( PinId == PPCEVENT_ENTRY(EventEntry)->PinId )
)
&&
( !NodeEvent
||
( NodeId == PPCEVENT_ENTRY(EventEntry)->NodeId )
)
)
{
KsGenerateEvent( EventEntry );
}
}
}
// release the event list lock
KeReleaseSpinLock( &(EventList->ListLock), oldIrql );
}
}
/*****************************************************************************
* PcGenerateEventDeferredRoutine()
*****************************************************************************
* This DPC routine is used when GenerateEventList is called at greater
* that DISPATCH_LEVEL.
*/
PORTCLASSAPI
void
NTAPI
PcGenerateEventDeferredRoutine
(
IN PKDPC Dpc,
IN PVOID DeferredContext, // PEVENT_DPC_CONTEXT
IN PVOID SystemArgument1, // PINTERLOCKED_LIST
IN PVOID SystemArgument2
)
{
ASSERT(Dpc);
ASSERT(DeferredContext);
ASSERT(SystemArgument1);
PEVENT_DPC_CONTEXT Context = PEVENT_DPC_CONTEXT(DeferredContext);
PINTERLOCKED_LIST EventList = PINTERLOCKED_LIST(SystemArgument1);
if( Context && EventList )
{
PcGenerateEventList( EventList,
Context->Set,
Context->EventId,
Context->PinEvent,
Context->PinId,
Context->NodeEvent,
Context->NodeId );
Context->ContextInUse = FALSE;
}
}