3)因为 Filter Module 不像中间层驱动(intermediate driver)那样提供一个虚拟的微口,也
不与某个设备对象联结,所以在微端口适配器(miniport adapter)之上的 Filter Module 功
能相当于一个修过过版本的微端口适配器(miniport adapter)。 原文:Because filter drivers
do not implement virtual miniports like an intermediate driver, filter drivers are not
associated with a device object. A miniport adapter with overlying filter modules functions as
a modified version of the miniport adapter.)
7)Filter Drivers 可以过滤下层网络适配器上绝大部分的通信。Filter Module 不联结某特定的
绑定(Filter modules are not associated with any particular binding between overlying
protocol drivers and the miniport adapter.)
8)Filter Drivers 可以选择为过滤服务也可以选择为分流的不过滤服务,选择为哪一种是可
以动态配置的(Filter drivers can select the services that are filtered and can be bypassed for
the services that are not filtered. The selection of the services that are bypassed and the
services that are filtered can be reconfigured dynamically.)
NDIS_STATUS
NdisFRegisterFilterDriver(
IN PDRIVER_OBJECT DriverObject,
IN NDIS_HANDLE FilterDriverContext,
IN PNDIS_FILTER_DRIVER_CHARACTERISTICS FilterCharacteristics,
OUT PNDIS_HANDLE NdisFilterDriverHandle
);
VOID
FilterUnload(
IN PDRIVER_OBJECT DriverObject
)
{
DEBUGP(DL_TRACE, ("===>FilterUnload\n"));
//
// Should free the filter context list
//
FilterDeregisterDevice();
NdisFDeregisterFilterDriver(FilterDriverHandle);
#if DBG
FILTER_ACQUIRE_LOCK(&FilterListLock, FALSE);
ASSERT(IsListEmpty(&FilterModuleList));
FILTER_RELEASE_LOCK(&FilterListLock, FALSE);
#endif
FILTER_FREE_LOCK(&FilterListLock);
DEBUGP(DL_TRACE, ("<===FilterUnload\n"));
return;
}
NDIS_STATUS
FilterAttach(
IN NDIS_HANDLE NdisFilterHandle,
IN NDIS_HANDLE FilterDriverContext,
IN PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters
);
NDIS_STATUS
NdisFSetAttributes(
IN NDIS_HANDLE NdisFilterHandle,
IN NDIS_HANDLE FilterModuleContext,
IN PNDIS_FILTER_ATTRIBUTES FilterAttributes
);
NDIS_STATUS
FilterAttach(
IN NDIS_HANDLE NdisFilterHandle,
IN NDIS_HANDLE FilterDriverContext,
IN PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters
)
{
PMS_FILTER pFilter = NULL;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PFL_NDIS_FILTER_LIST FilterHandleEntry;
NDIS_FILTER_ATTRIBUTES FilterAttributes;
ULONG Size;
DEBUGP(DL_TRACE, ("===>FilterAttach: NdisFilterHandle %p\n",
NdisFilterHandle));
do
{
ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject);
if (FilterDriverContext != (NDIS_HANDLE)FilterDriverObject)
{
Status = NDIS_STATUS_INVALID_PARAMETER;
break;
}
if (AttachParameters->MiniportMediaType != NdisMedium802_3)
{
DEBUGP(DL_ERROR, ("MSFilter: Doesn't support media type other than
NdisMedium802_3.\n"));
Status = NDIS_STATUS_INVALID_PARAMETER;
break;
}
Size = sizeof(MS_FILTER) +
AttachParameters->FilterModuleGuidName->Length +
AttachParameters->BaseMiniportInstanceName->Length +
AttachParameters->BaseMiniportName->Length;
pFilter = (PMS_FILTER)FILTER_ALLOC_MEM(NdisFilterHandle, Size);
if (pFilter == NULL)
{
DEBUGP(DL_WARN, ("MSFilter: Failed to allocate context
structure.\n"));
Status = NDIS_STATUS_RESOURCES;
break;
}
NdisZeroMemory(pFilter, sizeof(MS_FILTER));
pFilter->FilterModuleName.Length =
pFilter->FilterModuleName.MaximumLength =
AttachParameters->FilterModuleGuidName->Length;
pFilter->FilterModuleName.Buffer = (PWSTR)((PUCHAR)pFilter +
sizeof(MS_FILTER));
NdisMoveMemory(pFilter->FilterModuleName.Buffer,
AttachParameters->FilterModuleGuidName->Buffer,
pFilter->FilterModuleName.Length);
pFilter->MiniportFriendlyName.Length =
pFilter->MiniportFriendlyName.MaximumLength =
AttachParameters->BaseMiniportInstanceName->Length;
pFilter->MiniportFriendlyName.Buffer =
(PWSTR)((PUCHAR)pFilter->FilterModuleName.Buffer +
pFilter->FilterModuleName.Length);
NdisMoveMemory(pFilter->MiniportFriendlyName.Buffer,
AttachParameters->BaseMiniportInstanceName->Buffer,
pFilter->MiniportFriendlyName.Length);
pFilter->MiniportName.Length = pFilter->MiniportName.MaximumLength =
AttachParameters->BaseMiniportName->Length;
pFilter->MiniportName.Buffer =
(PWSTR)((PUCHAR)pFilter->MiniportFriendlyName.Buffer +
pFilter->MiniportFriendlyName.Length);
NdisMoveMemory(pFilter->MiniportName.Buffer,
AttachParameters->BaseMiniportName->Buffer,
pFilter->MiniportName.Length);
pFilter->MiniportIfIndex = AttachParameters->BaseMiniportIfIndex;
//
// The filter should intialize NoTrackReceives and NoTrackSends properly,
for this
// driver, since its default characteristic has both send and receive
handler, they
// are initiazed to FALSE.
//
pFilter->TrackReceives = TRUE;
pFilter->TrackSends = TRUE;
pFilter->FilterHandle = NdisFilterHandle;
NdisZeroMemory(&FilterAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));
FilterAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
FilterAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);
FilterAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
FilterAttributes.Flags = 0;
Status = NdisFSetAttributes(NdisFilterHandle,
pFilter,
&FilterAttributes);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("MSFilter: Failed to set attributes.\n"));
break;
}
pFilter->State = FilterPaused;
FILTER_ACQUIRE_LOCK(&FilterListLock, FALSE);
InsertHeadList(&FilterModuleList, &pFilter->FilterModuleLink);
FILTER_RELEASE_LOCK(&FilterListLock, FALSE);
}
while (FALSE);
if (Status != NDIS_STATUS_SUCCESS)
{
if (pFilter != NULL)
{
FILTER_FREE_MEM(pFilter);
}
}
DEBUGP(DL_TRACE, ("<===FilterAttach:
Status %x\n", Status));
return Status;
}
VOID
FilterDetach(
IN NDIS_HANDLE FilterModuleContext
)
{
PMS_FILTER
PFL_NDIS_FILTER_LIST
PLIST_ENTRY
pFilter = (PMS_FILTER)FilterModuleContext;
pEntry;
pLink;
DEBUGP(DL_TRACE, ("===>FilterDetach:
FilterInstance %p\n",
FilterModuleContext));
//
// Filter must be in paused state
//
FILTER_ASSERT(pFilter->State == FilterPaused);
//
// Don't come up anything that would prevent the filter from detaching
//
//
// Free filter instance name if allocated.
//
if (pFilter->FilterName.Buffer != NULL)
{
FILTER_FREE_MEM(pFilter->FilterName.Buffer);
}
FILTER_ACQUIRE_LOCK(&FilterListLock, FALSE);
RemoveEntryList(&pFilter->FilterModuleLink);
FILTER_RELEASE_LOCK(&FilterListLock, FALSE);
//
// Free the memory allocated
FILTER_FREE_MEM(pFilter);
//
// Alway return success
//
DEBUGP(DL_TRACE, ("<===FilterDetach Successfully\n"));
return;
}
NDIS_STATUS
FilterRestart(
IN NDIS_HANDLE FilterModuleContext,
IN PNDIS_FILTER_RESTART_PARAMETERS RestartParameters
)
{
NDIS_STATUS Status;
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; // BUGBUG, the cast
may be wrong
NDIS_HANDLE ConfigurationHandle = NULL;
PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;
PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes;
NDIS_CONFIGURATION_OBJECT ConfigObject;
DEBUGP(DL_TRACE, ("===>FilterRestart:
FilterModuleContext %p\n",
FilterModuleContext));
FILTER_ASSERT(pFilter->State == FilterPaused);
ConfigObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
ConfigObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
ConfigObject.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);
ConfigObject.NdisHandle = FilterDriverHandle;
ConfigObject.Flags = 0;
Status = NdisOpenConfigurationEx(&ConfigObject, &ConfigurationHandle);
if (Status != NDIS_STATUS_SUCCESS)
{
//
// Filter driver can choose to fail the restart if it cannot open the
configuration
//
#if 0
//
// The code is here just to demonstrate how to call NDIS to write an eventlog.
If drivers need to write
// an event log.
//
PWCHAR
ErrorString = L"NdisMon";
DEBUGP(DL_WARN, ("FilterRestart: Cannot open configuration.\n"));
NdisWriteEventLogEntry(FilterDriverObject,
EVENT_NDIS_DRIVER_FAILURE,
0,
1,
&ErrorString,
sizeof(Status),
&Status);
#endif
}
if (Status == NDIS_STATUS_SUCCESS)
{
NdisCloseConfiguration(ConfigurationHandle);
}
NdisRestartAttributes = RestartParameters->RestartAttributes;
//
// If NdisRestartAttributes is not NULL, then miniport can modify generic
attributes and add
// new media specific info attributes at the end. Otherwise, NDIS restarts the
miniport because
// of other reason, miniport should not try to modify/add attributes
//
if (NdisRestartAttributes != NULL)
{
PNDIS_RESTART_ATTRIBUTES NextAttributes;
ASSERT(NdisRestartAttributes->Oid ==
OID_GEN_MINIPORT_RESTART_ATTRIBUTES);
NdisGeneralAttributes =
(PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data;
//
// Check to see if we need to change any attributes, for example, the driver
can change the current
// MAC address here. Or the driver can add media specific info attributes.
//
NdisGeneralAttributes->LookaheadSize = 128;
//
// Check the next attributes to see whether the filter need to modify
//
NextAttributes = NdisRestartAttributes->Next;
while (NextAttributes != NULL)
{
//
// If somehow the filter needs to change a attributes which requires
more space then
// the current attributes:
// 1. Remove the attribute from the Attributes list:
// TempAttributes = NextAttributes;
// NextAttributes = NextAttributes->Next;
// 2. Free the memory for the current attributes:
NdisFreeMemory(TempAttributes, 0 , 0);
// 3. Dynamically allocate the memory for the new attributes by calling
// NdisAllocateMemoryWithTagPriority:
// NewAttributes = NdisAllocateMemoryWithTagPriority(Handle, size,
Priority);
// 4. Fill in the new attribute
// 5. NewAttributes->Next = NextAttributes;
// 6. NextAttributes = NewAttributes; // Just to make the next statement
works.
//
NextAttributes = NextAttributes->Next;
}
//
}
//
// If everything is OK, set the filter in running state
// If it get preempted, it doesn't matter
//
pFilter->State = FilterRunning; // when successful
Status = NDIS_STATUS_SUCCESS;
if (Status != NDIS_STATUS_SUCCESS)
{
pFilter->State = FilterPaused;
}
DEBUGP(DL_TRACE, ("<===FilterRestart: FilterModuleContext %p, Status %x\n",
FilterModuleContext, Status));
return Status;
}
NDIS_STATUS
FilterPause(
IN NDIS_HANDLE FilterModuleContext,
IN PNDIS_FILTER_PAUSE_PARAMETERS PauseParameters
)
{
PMS_FILTER pFilter = (PMS_FILTER)(FilterModuleContext);
NDIS_STATUS Status;
UNREFERENCED_PARAMETER(PauseParameters);
DEBUGP(DL_TRACE, ("===>NDISMON FilterPause: FilterInstance %p\n",
FilterModuleContext));
//
// Set the flag that the filter is going to pause
//
FILTER_ASSERT(pFilter->State == FilterRunning);
FILTER_ACQUIRE_LOCK(&pFilter->Lock, FALSE);
pFilter->State = FilterPausing;
FILTER_RELEASE_LOCK(&pFilter->Lock, FALSE);
Status = NDIS_STATUS_SUCCESS;
pFilter->State = FilterPaused;
DEBUGP(DL_TRACE, ("<===FilterPause: Status %x\n", Status));
return Status;
}
Class = NetService
ClassGUID = {4D36E974‐E325‐11CE‐BFC1‐08002BE10318}