⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filter.c

📁 James Antognini和Tom Divine提供的PASSTHRU的编成实例。
💻 C
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////
//// 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 + -