/*++
Module Name:
Filter.c
Abstract:
Sample NDIS Lightweight filter driver
--*/
#include "precomp.h"
#define __FILENUMBER 'PNPF'
// This directive puts the DriverEntry function into the INIT segment of the
// driver. To conserve memory, the code will be discarded when the driver's
// DriverEntry function returns. You can declare other functions used only
// during initialization here.
#pragma NDIS_INIT_FUNCTION(DriverEntry)
//
// Global variables
//
NDIS_HANDLE FilterDriverHandle; // NDIS handle for filter driver
NDIS_HANDLE FilterDriverObject;
NDIS_HANDLE NdisFilterDeviceHandle = NULL;
PDEVICE_OBJECT NdisDeviceObject = NULL;
FILTER_LOCK FilterListLock;
LIST_ENTRY FilterModuleList;
NDIS_FILTER_PARTIAL_CHARACTERISTICS DefaultChars = {
{ 0, 0, 0},
0,
FilterSendNetBufferLists,
FilterSendNetBufferListsComplete,
NULL,
FilterReceiveNetBufferLists,
FilterReturnNetBufferLists
};
_Use_decl_annotations_
NTSTATUS
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
First entry point to be called, when this driver is loaded.
Register with NDIS as a filter driver and create a device
for communication with user-mode.
Arguments:
DriverObject - pointer to the system's driver object structure
for this driver
RegistryPath - system's registry path for this driver
Return Value:
STATUS_SUCCESS if all initialization is successful, STATUS_XXX
error code if not.
--*/
{
NDIS_STATUS Status;
NDIS_FILTER_DRIVER_CHARACTERISTICS FChars;
NDIS_STRING ServiceName = RTL_CONSTANT_STRING(FILTER_SERVICE_NAME);
NDIS_STRING UniqueName = RTL_CONSTANT_STRING(FILTER_UNIQUE_NAME);
NDIS_STRING FriendlyName = RTL_CONSTANT_STRING(FILTER_FRIENDLY_NAME);
BOOLEAN bFalse = FALSE;
UNREFERENCED_PARAMETER(RegistryPath);
DEBUGP(DL_TRACE, "===>DriverEntry...\n");
FilterDriverObject = DriverObject;
do
{
NdisZeroMemory(&FChars, sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS));
FChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;
FChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS);
#if NDIS_SUPPORT_NDIS61
FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_2;
#else
FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_1;
#endif
FChars.MajorNdisVersion = FILTER_MAJOR_NDIS_VERSION;
FChars.MinorNdisVersion = FILTER_MINOR_NDIS_VERSION;
FChars.MajorDriverVersion = 1;
FChars.MinorDriverVersion = 0;
FChars.Flags = 0;
FChars.FriendlyName = FriendlyName;
FChars.UniqueName = UniqueName;
FChars.ServiceName = ServiceName;
//
// TODO: Most handlers are optional, however, this sample includes them
// all for illustrative purposes. If you do not need a particular
// handler, set it to NULL and NDIS will more efficiently pass the
// operation through on your behalf.
//
FChars.SetOptionsHandler = FilterRegisterOptions;
FChars.AttachHandler = FilterAttach;
FChars.DetachHandler = FilterDetach;
FChars.RestartHandler = FilterRestart;
FChars.PauseHandler = FilterPause;
FChars.SetFilterModuleOptionsHandler = FilterSetModuleOptions;
FChars.OidRequestHandler = FilterOidRequest;
FChars.OidRequestCompleteHandler = FilterOidRequestComplete;
FChars.CancelOidRequestHandler = FilterCancelOidRequest;
FChars.SendNetBufferListsHandler = FilterSendNetBufferLists;
FChars.ReturnNetBufferListsHandler = FilterReturnNetBufferLists;
FChars.SendNetBufferListsCompleteHandler = FilterSendNetBufferListsComplete;
FChars.ReceiveNetBufferListsHandler = FilterReceiveNetBufferLists;
FChars.DevicePnPEventNotifyHandler = FilterDevicePnPEventNotify;
FChars.NetPnPEventHandler = FilterNetPnPEvent;
FChars.StatusHandler = FilterStatus;
FChars.CancelSendNetBufferListsHandler = FilterCancelSendNetBufferLists;
DriverObject->DriverUnload = FilterUnload;
FilterDriverHandle = NULL;
//
// Initialize spin locks
//
FILTER_INIT_LOCK(&FilterListLock);
InitializeListHead(&FilterModuleList);
Status = NdisFRegisterFilterDriver(DriverObject,
(NDIS_HANDLE)FilterDriverObject,
&FChars,
&FilterDriverHandle);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, "Register filter driver failed.\n");
break;
}
Status = PoseidonRegisterDevice();
if (Status != NDIS_STATUS_SUCCESS)
{
NdisFDeregisterFilterDriver(FilterDriverHandle);
FILTER_FREE_LOCK(&FilterListLock);
DEBUGP(DL_WARN, "Register device for the filter driver failed.\n");
break;
}
}
while(bFalse);
DEBUGP(DL_TRACE, "<===DriverEntry, Status = %8x\n", Status);
return Status;
}
_Use_decl_annotations_
NDIS_STATUS
FilterRegisterOptions(
NDIS_HANDLE NdisFilterDriverHandle,
NDIS_HANDLE FilterDriverContext
)
/*++
Routine Description:
Register optional handlers with NDIS. This sample does not happen to
have any optional handlers to register, so this routine does nothing
and could simply have been omitted. However, for illustrative purposes,
it is presented here.
Arguments:
NdisFilterDriverHandle - pointer the driver handle received from
NdisFRegisterFilterDriver
FilterDriverContext - pointer to our context passed into
NdisFRegisterFilterDriver
Return Value:
NDIS_STATUS_SUCCESS
--*/
{
DEBUGP(DL_TRACE, "===>FilterRegisterOptions\n");
ASSERT(NdisFilterDriverHandle == FilterDriverHandle);
ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject);
if ((NdisFilterDriverHandle != (NDIS_HANDLE)FilterDriverHandle) ||
(FilterDriverContext != (NDIS_HANDLE)FilterDriverObject))
{
return NDIS_STATUS_INVALID_PARAMETER;
}
DEBUGP(DL_TRACE, "<===FilterRegisterOptions\n");
return NDIS_STATUS_SUCCESS;
}
_Use_decl_annotations_
NDIS_STATUS
FilterAttach(
NDIS_HANDLE NdisFilterHandle,
NDIS_HANDLE FilterDriverContext,
PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters
)
/*++
Routine Description:
Filter attach routine.
Create filter's context, allocate NetBufferLists and NetBuffer pools and any
other resources, and read configuration if needed.
Arguments:
NdisFilterHandle - Specify a handle identifying this instance of the filter. FilterAttach
should save this handle. It is a required parameter in subsequent calls
to NdisFxxx functions.
FilterDriverContext - Filter driver context passed to NdisFRegisterFilterDriver.
AttachParameters - attach parameters
Return Value:
NDIS_STATUS_SUCCESS: FilterAttach successfully allocated and initialize data structures
for this filter instance.
NDIS_STATUS_RESOURCES: FilterAttach failed due to insufficient resources.
NDIS_STATUS_FAILURE: FilterAttach could not set up this instance of this filter and it has called
NdisWriteErrorLogEntry with parameters specifying the reason for failure.
N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
layer can