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

📄 ksutil.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:

   pDeviceObject = IoGetRelatedDeviceObject( pKS_Address->m_pFileObject );

   //
   // Allocate IRP For Receiving
   //
   pReceiveIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE );

   if( !pReceiveIrp )
   {
      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   Length = 0;
   pNextMdl = pReceiveMdl;

   while( pNextMdl )
   {
      Length += MmGetMdlByteCount( pNextMdl );
      pNextMdl = pNextMdl->Next;
   }

   TdiBuildReceiveDatagram(
      pReceiveIrp,
      pDeviceObject,
      pKS_Address->m_pFileObject,
      _I_KS_AddressRequestComplete,   // Completion routine
      pKS_RequestContext,   // Completion context
      pReceiveMdl,                  // the data buffer
      Length,                       // send buffer length
      pReceiveDatagramInfo,
      pReturnInfo,
      InFlags
      );

   //
   // Reference The Address Object
   //
   _I_KS_RefTransportAddress( pKS_RequestContext->m_pKS_Address );

   //
   // Submit the request
   //
   (pKS_RequestContext->m_pIoStatusBlock)->Status = STATUS_UNSUCCESSFUL;
   (pKS_RequestContext->m_pIoStatusBlock)->Information = 0;

   Status = IoCallDriver( pDeviceObject, pReceiveIrp );

   if( bSynchronous )
   {
      if( (Status == STATUS_SUCCESS) || (Status == STATUS_PENDING) )
      {
         ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

         Status = KeWaitForSingleObject(
                        &SyncEvent,  // Object to wait on.
                        Executive,  // Reason for waiting
                        KernelMode, // Processor mode
                        FALSE,      // Alertable
                        NULL        // Timeout
                        );

         if( NT_SUCCESS( Status ) )
         {
            Status = pReceiveIrp->IoStatus.Status;
         }
      }
   }

   if( !NT_SUCCESS( Status ) )
   {
      //
      // Handle Case Where Completion Function Will Not Be Called...
      //

      //
      // Dereference The Address Object
      //
      _I_KS_DerefTransportAddress( pKS_RequestContext->m_pKS_Address );

      //
      // Free Memory Allocated For Private Completion Context
      //
      NdisFreeMemory(
         pKS_RequestContext,
         sizeof( KS_ADDRESS_REQUEST_CONTEXT ),
         0
         );

      IoFreeIrp( pReceiveIrp );
   }

   return( Status );
}

/////////////////////////////////////////////////////////////////////////////
//// KS_QueryAddressInfo
//
// Purpose
// KS_QueryAddressInfo makes a TDI_QUERY_INFORMATION request for
// TDI_QUERY_ADDRESS_INFO for the transport address or connection endpoint
// specified by its file object pointer.
//
// Parameters
//   pFileObject
//      Can be either a TDI transport address file object (from KS_ADDRESS)
//      or TDI connection endpoint file object (from KS_ENDPOINT).
//
//    pInfoBuffer
//        Must point to a buffer sufficiently large to hold a TDI_ADDRESS_INFO
//        structure for a TDI_ADDRESS_IP.
//
//    pInfoBufferSize
//       Pointer to a ULONG. On entry, the ULONG pointed to by pInfoBufferSize
//       must be initialized with the size of the buffer at pInfoBuffer. On
//       return, the ULONG pointed to by pInfoBufferSize will be updated to
//       indicate the length of the data written to pInfoBuffer.
//
// Return Value
//
// Remarks
// This function is roughly the TDI equivalent of the Winsock getsockname
// function.
//
// Callers of KS_QueryAddressInfo must be running at IRQL PASSIVE_LEVEL.
//
// The information returned from TDI_QUERY_ADDRESS_INFO depends on the
// type of the file object:
//
//   Transport Address File Object:
//     in_addr: 0.0.0.0; sin_port: 1042 (0x412)
//
//   Connection Endpoint File Object:
//     in_addr: 172.16.1.130; sin_port: 1042 (0x412)
//
// On reflection, this makes sense. An address object has a unique port
// number, but can be used on multiple host IP addresses on a multihomed
// host. Hence, the IP address is zero.
//
// However, once a connection is established the network interface is
// also established. Hence, the IP address on a connected connection
// endpoint is non-zero.
//

NTSTATUS
KS_QueryAddressInfo(
   PFILE_OBJECT      pFileObject,
   PVOID             pInfoBuffer,
   PULONG            pInfoBufferSize
   )
{
   NTSTATUS          Status = STATUS_UNSUCCESSFUL;
   IO_STATUS_BLOCK   IoStatusBlock;
   PIRP              pIrp = NULL;
   PMDL              pMdl = NULL;
   PDEVICE_OBJECT    pDeviceObject;

   ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

   pDeviceObject = IoGetRelatedDeviceObject( pFileObject );

   RtlZeroMemory( pInfoBuffer, *pInfoBufferSize );

   //
   // Allocate IRP For The Query
   //
   pIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE );

   if( !pIrp )
   {
      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   pMdl = KS_AllocateAndProbeMdl(
            pInfoBuffer,      // Virtual address for MDL construction
            *pInfoBufferSize,  // size of the buffer
            FALSE,
            FALSE,
            NULL
            );

   if( !pMdl )
   {
      IoFreeIrp( pIrp );
      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   TdiBuildQueryInformation(
      pIrp,
      pDeviceObject,
      pFileObject,
      _I_KS_SimpleTdiRequestComplete,  // Completion routine
      NULL,                            // Completion context
      TDI_QUERY_ADDRESS_INFO,
      pMdl
      );

   //
   // Submit The Query To The Transport
   //
   Status = KS_MakeSimpleTdiRequest(
               pDeviceObject,
               pIrp
               );

   //
   // Free Allocated Resources
   //
   KS_UnlockAndFreeMdl(pMdl);

   *pInfoBufferSize = pIrp->IoStatus.Information;

   IoFreeIrp( pIrp );

   return( Status );
}

/////////////////////////////////////////////////////////////////////////////
//                    E N D P O I N T  F U N C T I O N S                   //
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//// _I_KS_OpenConnectionContext (INTERNAL/PRIVATE)
//
// Purpose
// Open a TDI connection context object on the specified transport
// device.
//
// Parameters
//   TransportDeviceNameW
//      Pointer to a zero-terminated wide character string that specifies
//      the transport device. An example would be: L"\\Device\\Tcp"
//
//
// Return Value
// Status
//
// Remarks
// See the NT DDK documentation topic "5.2 Opening a Connection Endpoint"
// for more information.
//
// It is important to note that the call to ZwCreateFile creates a
// client-process-specific file object that represents the connection
// endpoint object. This means that the m_hContext handle is only valid
// in the same client process that the ZwCreateFile call was made in.
//
// Fortunately, most TDI operations actually reference the file object
// pointer - not the handle. Operations that do not reference the connection
// context handle can be performed in arbitrary context unless there are
// other restrictions.
//
// The client process dependency of the connection context handle does effect
// the design of a TDI Client to some extent. In particular, the the client
// process that was used to create a connection contect object must
// continue to exist until the connection context object is eventually closed.
//
// There are several ways to insure that the client process continues
// to exist while the connection context object is in use. The most common
// is to create a thread that is attached to the system process. As long as
// the system process continues to exist, the connection context object
// handle will remain valid.
//
// Callers of _I_KS_OpenConnectionContext must be running at IRQL PASSIVE_LEVEL.
//

NTSTATUS
_I_KS_OpenConnectionContext(
   IN PWSTR       TransportDeviceNameW,// Zero-terminated String
   PKS_ENDPOINT   pKS_Endpoint,
   PVOID          pContext
  )
{
   NTSTATUS          Status = STATUS_SUCCESS;
   UNICODE_STRING    TransportDeviceName;
   OBJECT_ATTRIBUTES ObjectAttributes;
   IO_STATUS_BLOCK   IoStatusBlock;
   ULONG             TransportEaBufferLength;
   PFILE_FULL_EA_INFORMATION pConnectionContextEa;

   //
   // Initialize Context-Related Fields
   //
   pKS_Endpoint->m_nOpenStatus = STATUS_UNSUCCESSFUL;
   pKS_Endpoint->m_pFileObject = NULL;

   //
   // Setup Transport Device Name
   //
   NdisInitUnicodeString( &TransportDeviceName, TransportDeviceNameW );

   //
   // Build An EA Buffer For The Connection Context
   // ---------------------------------------------
   // The EaValue will be the ConnectionContext passed to various
   // TDI EventHandler routines.
   //
   Status = KS_BuildEaBuffer(
               TDI_CONNECTION_CONTEXT_LENGTH,   // EaName Length
               TdiConnectionContext,            // EaName
               sizeof( PVOID ),                 // EaValue Length
               &pContext,                       // EaValue
               &pConnectionContextEa,
               &TransportEaBufferLength
               );

   if( !NT_SUCCESS(Status) )
   {
      return( pKS_Endpoint->m_nOpenStatus = Status );
   }

   ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

   InitializeObjectAttributes(
      &ObjectAttributes,      // OBJECT_ATTRIBUTES instance
      &TransportDeviceName,   // Transport Device Name
      OBJ_CASE_INSENSITIVE,   // Attributes
      NULL,                   // RootDirectory
      NULL                    // SecurityDescriptor
      );

   ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

   //
   // Call Transport To Create Connection Endpoint Object
   //
   Status = ZwCreateFile(
               &pKS_Endpoint->m_hContext,                // Handle
               GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, // Desired Access
               &ObjectAttributes,                          // Object Attributes
               &IoStatusBlock,                             // Final I/O status block
               0,                                          // Allocation Size
               FILE_ATTRIBUTE_NORMAL,                      // Normal attributes
               FILE_SHARE_READ,                            // Sharing attributes
               FILE_OPEN_IF,                               // Create disposition
               0,                                          // CreateOptions
               pConnectionContextEa,                       // EA Buffer
               TransportEaBufferLength                     // EA length
               );

   if (NT_SUCCESS(Status))
   {
      //
      // Obtain a referenced pointer to the file object.
      //
      ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

      Status = ObReferenceObjectByHandle(
                  pKS_Endpoint->m_hContext,// Object Handle
                  FILE_ANY_ACCESS,           // Desired Access
                  NULL,                      // Object Type
                  KernelMode,                // Processor mode
                  (PVOID *)&pKS_Endpoint->m_pFileObject, // File Object pointer
                  NULL                       // Object Handle information
                  );
   }

   //
   // Free up the EA buffer allocated.
   //
   ExFreePool( (PVOID )pConnectionContextEa );

   return( pKS_Endpoint->m_nOpenStatus = Status );
}


/////////////////////////////////////////////////////////////////////////////
//// _I_KS_CloseConnectionContext (INTERNAL/PRIVATE)
//
// Purpose
// This routine closes the connection context (endpoint) object.
//
// Parameters
//
// Return Value
// Status
//
// Remarks
// Callers of _I_KS_CloseConnectionContext must be running at IRQL PASSIVE_LEVEL.
//

NTSTATUS
_I_KS_CloseConnectionContext(
   PKS_ENDPOINT   pKS_Endpoint
   )
{
   NTSTATUS Status = STATUS_SUCCESS;

   KdPrint(("_I_KS_CloseConnectionContext: Entry...\n"));

   ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

   //
   // Dereference The File Object
   //
   if( pKS_Endpoint->m_pFileObject != NULL )
   {
      ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
      ObDereferenceObject( pKS_Endpoint->m_pFileObject );

      ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
      ZwClose( pKS_Endpoint->m_hContext );
   }

   pKS_Endpoint->m_pFileObject = NULL;

   return Status;
}


/////////////////////////////////////////////////////////////////////////////
//// _I_KS_AssociateAddress (INTERNAL/PRIVATE)
//
// Purpose
//
// Parameters
//   pKS_Address
//      Pointer to the KS_ADDRESS structure that specifies the transport
//      address object to associated with a connection endpoint object.
//
// Return Value
// Status
//
// Remarks
//

NTSTATUS
_I_KS_AssociateAddress(
   PKS_ADDRESS    pKS_Address,
   PKS_ENDPOINT   pKS_Endpoint
   )

⌨️ 快捷键说明

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