📄 filter.c
字号:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES
#include "precomp.h"
#pragma hdrstop
#include "iocommon.h"
// Copyright And Configuration Management ----------------------------------
//
// Implementation for PassThru Driver Filtering Module - filter.c
//
// Companion Sample Code for the Article
//
// "Extending the Microsoft PassThru NDIS Intermediate Driver"
//
// Copyright (c) 2003 Printing Communications Associates, Inc. (PCAUSA)
// http://www.pcausa.com
//
// The right to use this code in your own derivative works is granted so long
// as 1.) your own derivative works include significant modifications of your
// own, 2.) you retain the above copyright notices and this paragraph in its
// entirety within sources derived from this code.
// This product includes software developed by PCAUSA. The name of PCAUSA
// may not be used to endorse or promote products derived from this software
// without specific prior written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// End ---------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////
// Structure Definitions //
////////////////////////////////////////////////////////////////////////////
//
// FilterReserved Part of ADAPT Structure
// --------------------------------------
// This structure will be zero-initialized when the ADAPT structure is
// allocated.
//
// Hold Appropriate Spin Lock When Accessing FilterReserved Data
// -------------------------------------------------------------
// Acquiring a spin lock raises the IRQL to IRQL DISPATCH_LEVEL. Running
// at IRQL DISPATCH level insures that the filter data (contained
// somewhere in the FilterReserved area of the ADAPT structure) cannot
// be changed by one routine while it is being actively used by another.
//
// In this simple sample we can just use the Adapter spin lock for
// synchronization.
//
typedef struct _ADAPT_FILTER_RSVD
{
BOOLEAN bFilterInitDone;
//
// More Per-Adapter Filter-Specific Members
// ----------------------------------------
// Probably would contain the filter data or a pointer to it. Possibly
// filter statistics, state variables, whatever...
//
IPv4AddrStats IPv4Stats;
PIPv4BlockAddrArray pIPv4BlockAddrArray;
}
ADAPT_FILTER_RSVD, *PADAPT_FILTER_RSVD;
C_ASSERT(sizeof(ADAPT_FILTER_RSVD) <= sizeof(((PADAPT)0)->FilterReserved));
//
// FilterReserved Part of OPEN_CONTEXT Structure
// ---------------------------------------------
// This structure will be zero-initialized when the OPEN_CONTEXT structure
// is allocated.
//
typedef struct _OPEN_CONTEXT_FILTER_RSVD
{
BOOLEAN bFilterInitDone;
//
// More Per-Open-Handle Filter-Specific Members
// --------------------------------------------
// Probably would contain the filter data or a pointer to it. Possibly
// filter statistics, state variables, whatever...
//
}
OPEN_FILTER_RSVD, *POPEN_FILTER_RSVD;
C_ASSERT(sizeof(OPEN_FILTER_RSVD) <= sizeof(((POPEN_CONTEXT)0)->FilterReserved));
////////////////////////////////////////////////////////////////////////////
// Per-Open Filter Functions //
////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// FltDevIoControl
//
// Purpose
// This is the handler for filter-specific IOCTL function codes.
//
// Parameters
// DeviceObject - pointer to a device object
// pIrp - pointer to an I/O Request Packet
//
// Return Value
// Status is returned.
//
// Remarks
// Passthru call from main DevIoControl handler for IOCTL functions
// that are not recognized there.
//
NTSTATUS
FltDevIoControl(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION pIrpSp;
NTSTATUS NtStatus = STATUS_NOT_SUPPORTED;
ULONG BytesReturned = 0;
ULONG FunctionCode;
PUCHAR ioBuffer = NULL;
ULONG inputBufferLength;
ULONG outputBufferLength;
PADAPT pAdapt = NULL;
PADAPT_FILTER_RSVD pFilterContext = NULL;
POPEN_CONTEXT pOpenContext;
UNREFERENCED_PARAMETER(pDeviceObject);
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
DBGPRINT(("==>FLT DevIoControl: FileObject %p\n", pIrpSp->FileObject));
FunctionCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
ioBuffer = pIrp->AssociatedIrp.SystemBuffer;
inputBufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
pOpenContext = pIrpSp->FileObject->FsContext;
if( !pOpenContext )
{
DBGPRINT(( " Invalid Handle\n" ));
NtStatus = STATUS_INVALID_HANDLE;
goto CompleteTheIRP;
}
DBGPRINT(( " Found Open Context\n" ));
pAdapt = pOpenContext->pAdapt;
if( !pAdapt )
{
DBGPRINT(( " Adapter Not Found\n" ));
NtStatus = STATUS_INVALID_HANDLE;
goto CompleteTheIRP;
}
pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;
//
// Fail IOCTL If Unbind Is In Progress
//
NdisAcquireSpinLock(&pAdapt->Lock);
if( pAdapt->UnbindingInProcess )
{
NdisReleaseSpinLock(&pAdapt->Lock);
DBGPRINT(( " Unbind In Process\n" ));
NtStatus = STATUS_INVALID_DEVICE_STATE;
goto CompleteTheIRP;
}
//
// Fail IOCTL If Adapter Is Powering Down
//
if (pAdapt->StandingBy == TRUE)
{
NdisReleaseSpinLock(&pAdapt->Lock);
DBGPRINT(( " Miniport Powering Down\n" ));
NtStatus = STATUS_INVALID_DEVICE_STATE;
goto CompleteTheIRP;
}
//
// Hold Appropriate Spin Lock When Changing Filter Data
// ----------------------------------------------------
// This is just a reminder. Code for changing filter is not yet
// implemented. It would be in one (or more) of the IOCTL function
// handlers.
//
// See note at ADAPT_FILTER_RSVD structure declaration.
//
//
// Now (Finally) Handle The IOCTL
//
switch (FunctionCode)
{
case IOCTL_PTUSERIO_QUERY_IPv4_BLOCK_STATISTICS:
{
BytesReturned = sizeof( IPv4AddrStats );
if( outputBufferLength < BytesReturned )
{
NtStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
NdisMoveMemory(
ioBuffer,
&pFilterContext->IPv4Stats,
BytesReturned
);
NtStatus = STATUS_SUCCESS;
}
break;
case IOCTL_PTUSERIO_RESET_IPv4_BLOCK_STATISTICS:
NdisZeroMemory(
&pFilterContext->IPv4Stats,
sizeof( IPv4AddrStats )
);
NtStatus = STATUS_SUCCESS;
break;
case IOCTL_PTUSERIO_SET_IPv4_BLOCK_FILTER:
{
ULONG nExpectedBufferSize = 0;
PIPv4BlockAddrArray pNewIPv4BlockAddrArray = NULL;
PIPv4BlockAddrArray pOldIPv4BlockAddrArray;
pOldIPv4BlockAddrArray = pFilterContext->pIPv4BlockAddrArray;
if( ioBuffer && inputBufferLength
&& inputBufferLength >= sizeof( IPv4BlockAddrArray )
)
{
pNewIPv4BlockAddrArray = (PIPv4BlockAddrArray )ioBuffer;
nExpectedBufferSize = sizeof( ULONG ) * pNewIPv4BlockAddrArray->NumberElements;
nExpectedBufferSize += sizeof( ULONG );
if( nExpectedBufferSize > inputBufferLength )
{
NtStatus = STATUS_INVALID_PARAMETER;
break;
}
pNewIPv4BlockAddrArray = NULL;
}
//
// Allocate And Initialize The New IP Block Address Array
//
if( nExpectedBufferSize )
{
NDIS_STATUS nNdisStatus;
nNdisStatus = NdisAllocateMemoryWithTag(
&pNewIPv4BlockAddrArray,
nExpectedBufferSize,
TAG
);
if( nNdisStatus == NDIS_STATUS_SUCCESS )
{
//
// Copy The IP Block Address Array
//
NdisMoveMemory(
pNewIPv4BlockAddrArray, ioBuffer, nExpectedBufferSize );
NtStatus = STATUS_SUCCESS;
}
else
{
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
//
// Set The New IP Block Address Array
//
pFilterContext->pIPv4BlockAddrArray = pNewIPv4BlockAddrArray;
//
// Free The Old IP Block Address Array
//
if( pOldIPv4BlockAddrArray )
{
NdisFreeMemory( pOldIPv4BlockAddrArray, 0, 0);
}
}
break;
default:
// ...Fail with STATUS_NOT_SUPPORTED for now... // TEMPORARY!!!
NtStatus = STATUS_NOT_SUPPORTED; // TEMPORARY!!!
break;
}
NdisReleaseSpinLock(&pAdapt->Lock);
//
// Complete The IRP
//
CompleteTheIRP:
if (NtStatus != STATUS_PENDING)
{
pIrp->IoStatus.Information = BytesReturned;
pIrp->IoStatus.Status = NtStatus;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
DBGPRINT(("<== FLT DevIoControl\n"));
return NtStatus;
}
VOID
FltOnInitOpenContext(
IN POPEN_CONTEXT pOpenContext
)
{
POPEN_FILTER_RSVD pFilterContext;
//
// Initialize FilterReserved Area In OPEN_CONTEXT Structure
//
pFilterContext = (POPEN_FILTER_RSVD )&pOpenContext->FilterReserved;
}
VOID
FltOnDeinitOpenContext(
IN POPEN_CONTEXT pOpenContext
)
{
POPEN_FILTER_RSVD pFilterContext;
//
// Deinitialize FilterReserved Area In OPEN_CONTEXT Structure
//
pFilterContext = (POPEN_FILTER_RSVD )&pOpenContext->FilterReserved;
}
////////////////////////////////////////////////////////////////////////////
// Per-Adapter Filter Functions //
////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// FltOnInitAdapter
//
// Purpose
// Called to initialize the FilterReserved area in a newly-allocated
// ADAPT structure.
//
// Parameters
// pAdapt - pointer to ADAPT structure being initialized.
//
// Return Value
// Nothing.
//
// Remarks
// Called from PtBindAdapter just prior to making the call to
// NdisOpenAdapter.
//
VOID
FltOnInitAdapter(
IN PADAPT pAdapt
)
{
PADAPT_FILTER_RSVD pFilterContext;
//
// Initialize FilterReserved Area In ADAPT Structure
//
pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;
}
/////////////////////////////////////////////////////////////////////////////
//// FltOnDeinitAdapter
//
// Purpose
// Called to free resources associated with the FilterReserved area in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -