📄 filter.c
字号:
If provided, this function process receive indications made by underlying
NIC or lower level filter drivers. This function can also be called as a
result of loopback. If this handler is NULL, NDIS will skip calling this
filter when processing a receive indication and will call the next upper
filter in the stack with a non-NULL FitlerReceiveNetBufferLists handler
or the procotol driver. A filter that doesn't provide a
FilterReceiveNetBufferLists handler can not provided a
FilterReturnNetBufferLists handler or a initiate a receive indication on
its own.
Arguments:
FilterModuleContext: Pointer to our filter context area.
NetBufferLists: A linked list of NetBufferLists allocated by underlying driver each containing
one NetBuffer.
PortNumber: Port on which the Receive is indicated
ReceiveFlags: Flags associated with the Receive such as whether the filter
can pend the receive
Return Value:
None
--*/
{
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
NDIS_STATUS ReturnStatus = NDIS_STATUS_SUCCESS;
PNET_BUFFER_LIST NextNetBufferList;
BOOLEAN DispatchLevel;
ULONG ReturnFlags;
ULONG Ref;
DEBUGP(DL_TRACE, ("===>ReceiveNetBufferList: NetBufferLists = %p.\n", NetBufferLists));
do
{
DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags);
#if DBG
FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
if (pFilter->State != FilterRunning)
{
FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags))
{
ReturnFlags = 0;
if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags))
{
NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL);
}
NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags);
}
break;
}
FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
#endif
ASSERT(NumberOfNetBufferLists >= 1);
//
// If necessary, queue the NetBufferList in a local structure for later processing.
// We may need to travel the list, some of them may not need post processing
//
if (pFilter->TrackReceives)
{
FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
pFilter->OutstandingRcvs += NumberOfNetBufferLists;
Ref = pFilter->OutstandingRcvs;
FILTER_LOG_RCV_REF(1, pFilter, NetBufferLists, Ref);
FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
}
NdisFIndicateReceiveNetBufferLists(
pFilter->FilterHandle,
NetBufferLists,
PortNumber,
NumberOfNetBufferLists,
ReceiveFlags);
if (NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags) &&
pFilter->TrackReceives)
{
FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
pFilter->OutstandingRcvs -= NumberOfNetBufferLists;
Ref = pFilter->OutstandingRcvs;
FILTER_LOG_RCV_REF(2, pFilter, NetBufferLists, Ref);
FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
}
} while (FALSE);
DEBUGP(DL_TRACE, ("<===ReceiveNetBufferList: Flags = %8x.\n", ReceiveFlags));
}
VOID
FilterCancelSendNetBufferLists(
IN NDIS_HANDLE FilterModuleContext,
IN PVOID CancelId
)
/*++
Routine Description:
This function cancels any NET_BUFFER_LISTs pended in the filter and then
calls the NdisFCancelSendNetBufferLists to propagate the CancelSend to the next filter
miniport
Arguments:
Return Value:
None
*/
{
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
NdisFCancelSendNetBufferLists(pFilter->FilterHandle,CancelId);
}
NDIS_STATUS
FilterSetModuleOptions(
IN NDIS_HANDLE FilterModuleContext
)
/*++
Routine Description:
This function set the optional handlers for on the filter
Arguments:
NetBufferLists: Pointer to the NetBufferList to be freed.
DispatchLevel: A Boolean specifying if the caller is at DISPATCH_LEVEL
Return Value:
None
NOTE: NetBufferList has to be allocated by the fitler
--*/
{
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
NDIS_FILTER_PARTIAL_CHARACTERISTICS OptionalHandlers;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
//
// Demonstrate how to change send/receive handlers at runtime.
//
if (FALSE)
{
UINT i;
pFilter->CallsRestart++;
i = pFilter->CallsRestart % 8;
pFilter->TrackReceives = TRUE;
pFilter->TrackSends = TRUE;
NdisMoveMemory(&OptionalHandlers, &DefaultChars, sizeof(OptionalHandlers));
OptionalHandlers.Header.Type = NDIS_OBJECT_TYPE_FILTER_PARTIAL_CHARACTERISTICS;
OptionalHandlers.Header.Size = sizeof(OptionalHandlers);
switch (i)
{
case 0:
OptionalHandlers.ReceiveNetBufferListsHandler = NULL;
pFilter->TrackReceives = FALSE;
break;
case 1:
OptionalHandlers.ReturnNetBufferListsHandler = NULL;
pFilter->TrackReceives = FALSE;
break;
case 2:
OptionalHandlers.SendNetBufferListsHandler = NULL;
pFilter->TrackSends = FALSE;
break;
case 3:
OptionalHandlers.SendNetBufferListsCompleteHandler = NULL;
pFilter->TrackSends = FALSE;
break;
case 4:
OptionalHandlers.ReceiveNetBufferListsHandler = NULL;
OptionalHandlers.ReturnNetBufferListsHandler = NULL;
break;
case 5:
OptionalHandlers.SendNetBufferListsHandler = NULL;
OptionalHandlers.SendNetBufferListsCompleteHandler = NULL;
break;
case 6:
OptionalHandlers.ReceiveNetBufferListsHandler = NULL;
OptionalHandlers.ReturnNetBufferListsHandler = NULL;
OptionalHandlers.SendNetBufferListsHandler = NULL;
OptionalHandlers.SendNetBufferListsCompleteHandler = NULL;
break;
case 7:
break;
}
Status = NdisSetOptionalHandlers(pFilter->FilterHandle, (PNDIS_DRIVER_OPTIONAL_HANDLERS)&OptionalHandlers );
}
return Status;
}
NDIS_STATUS
filterDoInternalRequest(
IN PMS_FILTER FilterModuleContext,
IN NDIS_REQUEST_TYPE RequestType,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
IN ULONG OutputBufferLength, OPTIONAL
IN ULONG MethodId, OPTIONAL
OUT PULONG pBytesProcessed
)
/*++
Routine Description:
Utility routine that forms and sends an NDIS_OID_REQUEST to the
miniport, waits for it to complete, and returns status
to the caller.
NOTE: this assumes that the calling routine ensures validity
of the filter handle until this returns.
Arguments:
FilterModuleContext - pointer to our filter module context
RequestType - NdisRequest[Set|Query|method]Information
Oid - the object being set/queried
InformationBuffer - data for the request
InformationBufferLength - length of the above
OutputBufferLength - valid only for method request
MethodId - valid only for method request
pBytesProcessed - place to return bytes read/written
Return Value:
Status of the set/query request
--*/
{
FILTER_REQUEST FilterRequest;
PNDIS_OID_REQUEST NdisRequest = &FilterRequest.Request;
NDIS_STATUS Status;
NdisZeroMemory(NdisRequest, sizeof(NDIS_OID_REQUEST));
NdisInitializeEvent(&FilterRequest.ReqEvent);
NdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
NdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
NdisRequest->Header.Size = sizeof(NDIS_OID_REQUEST);
NdisRequest->RequestType = RequestType;
switch (RequestType)
{
case NdisRequestQueryInformation:
NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
InformationBuffer;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
case NdisRequestSetInformation:
NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
InformationBuffer;
NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
case NdisRequestMethod:
NdisRequest->DATA.METHOD_INFORMATION.Oid = Oid;
NdisRequest->DATA.METHOD_INFORMATION.MethodId = MethodId;
NdisRequest->DATA.METHOD_INFORMATION.InformationBuffer =
InformationBuffer;
NdisRequest->DATA.METHOD_INFORMATION.InputBufferLength =
InformationBufferLength;
NdisRequest->DATA.METHOD_INFORMATION.OutputBufferLength = OutputBufferLength;
break;
default:
FILTER_ASSERT(FALSE);
break;
}
NdisRequest->RequestId = (PVOID)FILTER_REQUEST_ID;
Status = NdisFOidRequest(FilterModuleContext->FilterHandle,
NdisRequest);
if (Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&FilterRequest.ReqEvent, 0);
Status = FilterRequest.Status;
}
if (Status == NDIS_STATUS_SUCCESS)
{
if (RequestType == NdisRequestSetInformation)
{
*pBytesProcessed = NdisRequest->DATA.SET_INFORMATION.BytesRead;
}
if (RequestType == NdisRequestQueryInformation)
{
*pBytesProcessed = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
}
if (RequestType == NdisRequestMethod)
{
*pBytesProcessed = NdisRequest->DATA.METHOD_INFORMATION.BytesWritten;
}
//
// The driver below should set the correct value to BytesWritten
// or BytesRead. But now, we just truncate the value to InformationBufferLength
//
if (RequestType == NdisRequestMethod)
{
if (*pBytesProcessed > OutputBufferLength)
{
*pBytesProcessed = OutputBufferLength;
}
}
else
{
if (*pBytesProcessed > InformationBufferLength)
{
*pBytesProcessed = InformationBufferLength;
}
}
}
return (Status);
}
VOID
filterInternalRequestComplete(
IN NDIS_HANDLE FilterModuleContext,
IN PNDIS_OID_REQUEST NdisRequest,
IN NDIS_STATUS Status
)
/*++
Routine Description:
NDIS entry point indicating completion of a pended NDIS_OID_REQUEST.
Arguments:
FilterModuleContext - pointer to filter module context
NdisRequest - pointer to NDIS request
Status - status of request completion
Return Value:
None
--*/
{
PFILTER_REQUEST FilterRequest;
UNREFERENCED_PARAMETER(FilterModuleContext);
//
// Get at the request context.
//
FilterRequest = CONTAINING_RECORD(NdisRequest, FILTER_REQUEST, Request);
//
// Save away the completion status.
//
FilterRequest->Status = Status;
//
// Wake up the thread blocked for this request to complete.
//
NdisSetEvent(&FilterRequest->ReqEvent);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -