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

📄 ptextend.c

📁 这个还是关于驱动与应用层通信的,主要是中间层的问题
💻 C
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES

#include "precomp.h"
#pragma hdrstop
#include "iocommon.h"

// Copyright And Configuration Management ----------------------------------
//
//              PassThru Driver Extensions Module - ptextend.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 ---------------------------------------------------------------------

VOID
PtRefAdapter( PADAPT pAdapt )
{
   NdisInterlockedIncrement( &pAdapt->RefCount );
}

VOID
PtDerefAdapter( PADAPT pAdapt )
{
   if( !pAdapt )
   {
      return;
   }

   if( NdisInterlockedDecrement( &pAdapt->RefCount) == 0 )
   {
      DBGPRINT(( "PtDerefAdapter: Adapter: 0x%8.8X\n", pAdapt ? (ULONG )pAdapt : 0 ));

      //
      //  Free all resources on this adapter structure.
      //
      if (pAdapt->RecvPacketPoolHandle != NULL)
      {
         //
         // Free the packet pool that is used to indicate receives
         //
         NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);

         pAdapt->RecvPacketPoolHandle = NULL;
      }

      if (pAdapt->SendPacketPoolHandle != NULL)
      {

         //
         //  Free the packet pool that is used to send packets below
         //

         NdisFreePacketPool(pAdapt->SendPacketPoolHandle);

         pAdapt->SendPacketPoolHandle = NULL;
      }

      NdisFreeMemory(pAdapt, 0, 0);
   }
}

PADAPT
PtLookupAdapterByName(
   IN PUCHAR   pNameBuffer,
   IN USHORT   NameBufferLength,
   IN BOOLEAN  bUseVirtualName
   )
{
   PADAPT *ppCursor, pAdapt = NULL;

   //
   // Sanity Checks
   //
   if( !pNameBuffer || !NameBufferLength )
   {
      return( NULL );
   }

   //
   // Walk The Adapter List
   // ---------------------
   // Hold the global lock while walking. Otherwise, the adapter list could be altered at any point in
   // the list processing sequence.
   //
   NdisAcquireSpinLock( &GlobalLock );

   for( ppCursor = &pAdaptList; *ppCursor != NULL;
      ppCursor = &(*ppCursor)->Next
      )
   {
      __try
      {
         if( bUseVirtualName )
         {
            //
            // Check For Match Against Virtual Adapter Name
            //
            if( ( (*ppCursor)->DeviceName.Length == NameBufferLength) &&
                  NdisEqualMemory( (*ppCursor)->DeviceName.Buffer, pNameBuffer, NameBufferLength ))
            {
               //
               // Return Pointer To Found Adapter
               //
               pAdapt = (*ppCursor);
               break;
            }
         }
         else
         {
            //
            // Check For Match Against Lower Adapter Name
            //
            if( ( (*ppCursor)->LowerDeviceName.Length == NameBufferLength) &&
                  NdisEqualMemory( (*ppCursor)->LowerDeviceName.Buffer, pNameBuffer, NameBufferLength))
            {
               //
               // Return Pointer To Found Adapter
               //
               pAdapt = (*ppCursor);
               break;
            }
         }
      }
      __except( EXCEPTION_EXECUTE_HANDLER )
      {
         pAdapt = NULL;
         break;
      }
   }

   //
   // Add Reference To Adapter Memory
   // -------------------------------
   // As soon as the spinlock is released (below) and before returning to the caller it is possible
   // for NDIS to unbind the selected adapter from the PassThru protocol. The reference counting scheme
   // insures that the memory pointed to by pAdapt will remain valid until the last call to
   // PtDerefAdapter.
   //
   if( pAdapt )
   {
	   PtRefAdapter( pAdapt );
   }

   NdisReleaseSpinLock( &GlobalLock );

   return( pAdapt );
}

VOID
DevRefOpenContext( POPEN_CONTEXT pOpenContext )
{
   PtRefAdapter( pOpenContext->pAdapt );

   NdisInterlockedIncrement( &pOpenContext->RefCount );
}

VOID
DevDerefOpenContext( POPEN_CONTEXT pOpenContext )
{
   PADAPT pAdapt = NULL;

   if( !pOpenContext )
   {
      return;
   }

   pAdapt = pOpenContext->pAdapt;

   if( NdisInterlockedDecrement( &pOpenContext->RefCount) == 0 )
   {
      DBGPRINT(( "DevDerefOpenContext: Context: 0x%8.8X\n", pOpenContext ? (ULONG )pOpenContext : 0 ));

      NdisFreeSpinLock( &pOpenContext->Lock );

      NdisFreeMemory(pOpenContext, 0, 0);
   }

   PtDerefAdapter( pAdapt );
}

POPEN_CONTEXT
DevAllocateOpenContext( PADAPT pAdapt )
{
   POPEN_CONTEXT pOpenContext = NULL;

   NdisAllocateMemoryWithTag( &pOpenContext, sizeof( OPEN_CONTEXT ), TAG );

   if( !pOpenContext )
   {
      return( NULL );
   }

   //
   // Initialize The Open Context Structure
   //
   NdisZeroMemory( pOpenContext, sizeof( OPEN_CONTEXT ) );

   NdisAllocateSpinLock( &pOpenContext->Lock );

   NdisInitializeEvent( &pOpenContext->LocalRequest.RequestEvent );

   //
   // Add Initial Reference To Open Context
   // -------------------------------------
   // Note that we already have added an implicit reference to the adapter
   // because of the PtLookupAdapterByName call.
   //
   pOpenContext->RefCount = 1;

   pOpenContext->pAdapt = pAdapt;

   return( pOpenContext );
}

NTSTATUS
DevEnumerateBindings(
   IN PDEVICE_OBJECT    pDeviceObject,
   IN PIRP              pIrp
   )
{
   PIO_STACK_LOCATION  pIrpSp;
   NTSTATUS            NtStatus = STATUS_SUCCESS;
   ULONG               BytesReturned = 0;
   PUCHAR              ioBuffer = NULL;
   ULONG               inputBufferLength;
   ULONG               outputBufferLength, Remaining;
   PADAPT              *ppCursor;

   UNREFERENCED_PARAMETER(pDeviceObject);

   pIrpSp = IoGetCurrentIrpStackLocation(pIrp);

   ioBuffer = pIrp->AssociatedIrp.SystemBuffer;
   inputBufferLength  = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
   outputBufferLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
   Remaining = outputBufferLength;

   DBGPRINT(("==>Pt DevEnumerateBindings: FileObject %p\n", pIrpSp->FileObject ));


   //
   // Sanity Check On Length
   //
   if( sizeof( UNICODE_NULL ) > Remaining )
   {
      BytesReturned = 0;
      NtStatus = NDIS_STATUS_BUFFER_OVERFLOW;
      goto CompleteTheIRP;
   }

   //
   // Walk The Adapter List
   //
   NdisAcquireSpinLock( &GlobalLock );

   __try
   {
      //
      // Insert List-Terminating NULL
      //
      *((PWCHAR )ioBuffer) = UNICODE_NULL;

      BytesReturned = sizeof( UNICODE_NULL );
      Remaining -= sizeof( UNICODE_NULL );

      for( ppCursor = &pAdaptList; *ppCursor != NULL;
         ppCursor = &(*ppCursor)->Next
         )
      {
         //
         // Sanity Check On Length
         //
         if( (*ppCursor)->DeviceName.Length + sizeof( UNICODE_NULL) > Remaining )
         {
            BytesReturned = 0;
            NtStatus = NDIS_STATUS_BUFFER_OVERFLOW;
            break;
         }

         //
         // Add The Virtual DeviceName To The Buffer
         // ----------------------------------------
         // This name passed to NdisIMInitializeDeviceInstanceEx.
         //
         NdisMoveMemory(
            ioBuffer,
            (*ppCursor)->DeviceName.Buffer,
            (*ppCursor)->DeviceName.Length
            );

         DBGPRINT(( "Adding VA Name : %d, %d, \042%*.*ws\042\n",
            (*ppCursor)->DeviceName.Length,
            (*ppCursor)->DeviceName.MaximumLength,
            (*ppCursor)->DeviceName.Length/sizeof( wchar_t ),
            (*ppCursor)->DeviceName.Length/sizeof( wchar_t ),
            (*ppCursor)->DeviceName.Buffer
            ));

         //
         // Move Past Virtual DeviceName In Buffer
         //
         Remaining -= (*ppCursor)->DeviceName.Length;
         BytesReturned += (*ppCursor)->DeviceName.Length;
         ioBuffer += (*ppCursor)->DeviceName.Length;

         //
         // Add Name-Terminating NULL
         //
         *((PWCHAR )ioBuffer) = UNICODE_NULL;

         Remaining -= sizeof( UNICODE_NULL );
         BytesReturned += sizeof( UNICODE_NULL );
         ioBuffer += sizeof( UNICODE_NULL );

         //
         // Sanity Check On Length
         //
         if( (*ppCursor)->LowerDeviceName.Length + sizeof( UNICODE_NULL ) > Remaining )
         {
            BytesReturned = 0;
            NtStatus = NDIS_STATUS_BUFFER_OVERFLOW;
            break;
         }

         //
         // Add The Lower DeviceName To The Buffer
         // --------------------------------------
         // This name passed to NdisOpenAdapter.
         //
         NdisMoveMemory(
            ioBuffer,
            (*ppCursor)->LowerDeviceName.Buffer,
            (*ppCursor)->LowerDeviceName.Length
            );

         DBGPRINT(( "Adding LA Name : %d, %d, \042%*.*ws\042\n",
            (*ppCursor)->LowerDeviceName.Length,
            (*ppCursor)->LowerDeviceName.MaximumLength,
            (*ppCursor)->LowerDeviceName.Length/sizeof( wchar_t ),
            (*ppCursor)->LowerDeviceName.Length/sizeof( wchar_t ),
            (*ppCursor)->LowerDeviceName.Buffer
            ));

         //
         // Move Past Lower DeviceName In Buffer
         //
         Remaining -= (*ppCursor)->LowerDeviceName.Length;
         BytesReturned += (*ppCursor)->LowerDeviceName.Length;
         ioBuffer += (*ppCursor)->LowerDeviceName.Length;

         //
         // Add Name-Terminating NULL
         //
         *((PWCHAR )ioBuffer) = UNICODE_NULL;

         Remaining -= sizeof( UNICODE_NULL );
         BytesReturned += sizeof( UNICODE_NULL );
         ioBuffer += sizeof( UNICODE_NULL );

         //
         // Add List-Terminating NULL
         // -------------------------
         // Space is already accomodated for this.
         //
         *((PWCHAR )ioBuffer) = UNICODE_NULL;
      }
   }
   __except( EXCEPTION_EXECUTE_HANDLER )
   {
      BytesReturned = 0;
      NtStatus = STATUS_INVALID_PARAMETER;
   }

   NdisReleaseSpinLock( &GlobalLock );

CompleteTheIRP:
   if (NtStatus != STATUS_PENDING)
   {
      pIrp->IoStatus.Information = BytesReturned;
      pIrp->IoStatus.Status = NtStatus;
      IoCompleteRequest(pIrp, IO_NO_INCREMENT);
   }

   DBGPRINT(("<== Pt DevEnumerateBindings\n"));

   return NtStatus;
}

NTSTATUS
DevOpenAdapter(
   IN PDEVICE_OBJECT    pDeviceObject,
   IN PIRP              pIrp,
   IN BOOLEAN           bUseVirtualName
   )
{
   PIO_STACK_LOCATION  pIrpSp;
   NTSTATUS            NtStatus = STATUS_SUCCESS;
   ULONG               BytesReturned = 0;
   PUCHAR              pNameBuffer = NULL;
   ULONG               NameBufferLength;
   PADAPT              pAdapt;
   POPEN_CONTEXT       pOpenContext;

   UNREFERENCED_PARAMETER(pDeviceObject);

   pIrpSp = IoGetCurrentIrpStackLocation(pIrp);

   DBGPRINT(("==>Pt DevOpenAdapter: FileObject %p\n", pIrpSp->FileObject));
   
   pNameBuffer = pIrp->AssociatedIrp.SystemBuffer;
   NameBufferLength  = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;

   DBGPRINT(( "   Looking For Name : \042%*.*ws\042\n",
      NameBufferLength/sizeof( wchar_t ),
      NameBufferLength/sizeof( wchar_t ),
      pNameBuffer
      ));

   //
   // Lookup Adapter By Name
   // ----------------------
   // If successful the lookup function has added a ref count to the found ADAPT
   // structure.
   //
   pAdapt = PtLookupAdapterByName( pNameBuffer, (USHORT )NameBufferLength, bUseVirtualName );

   if( !pAdapt )
   {
      DBGPRINT(( "      Adapter Not Found\n" ));
      
      NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;
      goto CompleteTheIRP;
   }

   DBGPRINT(( "      Found Adapter\n" ));

   //
   // Fail Open If Unbind Is In Progress
   //
   NdisAcquireSpinLock(&pAdapt->Lock);
   if( pAdapt->UnbindingInProcess )
   {
      NdisReleaseSpinLock(&pAdapt->Lock);
      DBGPRINT(( "      Unbind In Process\n" ));
      PtDerefAdapter( pAdapt );

      NtStatus = STATUS_INVALID_DEVICE_STATE;
      goto CompleteTheIRP;
   }
   NdisReleaseSpinLock(&pAdapt->Lock);

   if( pAdapt->pOpenContext )
   {
      DBGPRINT(( "      Handle Already Associated(1)\n" ));
      PtDerefAdapter( pAdapt );

      NtStatus = STATUS_DEVICE_BUSY;
      goto CompleteTheIRP;
   }

   pOpenContext = DevAllocateOpenContext( pAdapt );

   if( !pOpenContext )
   {
      DBGPRINT(( "      Unable To Allocate Open Context\n" ));
      PtDerefAdapter( pAdapt );

      NtStatus = STATUS_INSUFFICIENT_RESOURCES;
      goto CompleteTheIRP;
   }

   //
   // Sanity Check For Concurrent Open Race Condition
   // -----------------------------------------------
   // At this point we enforce exclusive access on a per-binding basis.
   //
   // This logic deals with the situation where two concurrent adapter
   // opens could be in progress. We want an atomic mechanism that insures
   // that only one of the opens will be successful.
   //
   // This InterlockedXXX function performs an atomic operation: First it
   // compares pAdapt->pOpenContext with NULL, if they are equal, the function
   // puts pOpenContext into pAdapt->pOpenContext, and return NULL. Otherwise,
   // it return existing pAdapt->pOpenContext without changing anything.
   //
   // NOTE: This implementation is borrowed from the NDISPROT sample from
   // the Windows DDK.
   // 
   
   if ( InterlockedCompareExchangePointer (& (pAdapt->pOpenContext), pOpenContext, NULL) != NULL)
   {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -