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

📄 ksutil.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
   IoFreeIrp( pIrp );

   return STATUS_MORE_PROCESSING_REQUIRED;
}


/////////////////////////////////////////////////////////////////////////////
//// KS_SendDatagramOnAddress
//
// Purpose
// Send a chain of MDLs as a datagram on the transport address object.
//
// Parameters
//    pSendMdl
//       Pointer to the first Memory Descriptor List (MDL) of the datagram
//       to be sent.
//
//    pKS_Address
//       Pointer to the KS_ADDRESS structure that specifies the transport
//       address object that the datagram will be sent on.
//
//    pIoStatusBlock
//       Pointer to a caller provided IO_STATUS_BLOCK structure that received
//       final completion status and sent byte count.
//
//    UserCompletionRoutine
//       Specifies the entry point for the caller-supplied completion routine
//       to be called when the lower-level TDI driver completes the operation.
//       This routine is declared as follows:
//
//          VOID
//          (*PKS_REQUEST_COMPLETION_ROUTINE) (
//             PVOID UserCompletionContext,
//             PIO_STATUS_BLOCK IoStatusBlock,
//             ULONG Reserved
//             );//
//
//    UserCompletionContext
//        The value to be passed to UserCompletionRoutine.
//
// Remarks
// This function sends a chain of MDLs that represent the datagram to be sent.
// The number of bytes to be sent is specified is the sum of the MDL byte
// counts for all MDLs in the chain. Having the Next field set to NULL
// identifies the last MDL in the chain. The byte count of each MDL in the
// chain is queried using MmGetMdlByteCount.
//
// Each of the MDLs in the chain must have been probed and locked before
// calling KS_SendDatagramOnAddress.
//
// Synchronous/Asynchronous Operation
// ----------------------------------
// Synchronous Send
//    If UserCompletionEvent and UserCompletionRoutine are both NULL the send will
//    be performed synchronously.
//
// Asynchronous Send (Event Wait)
//    If a UserCompletionEvent is specified then the send will be performed
//    asynchronously. The framework will set the specified event when the
//    send is completed.
//
//    If UserCompletionEvent is specified, then UserCompletionRoutine and
//    UserCompletionContext are ignored.
//
// Asynchronous Send (Completion Routine)
//    If a UserCompletionEvent is NOT specified (i.e., it is NULL) and a
//    UserCompletionRoutine is specified, then the send will be performed
//    asynchronously. The framework will call the specified completion
//    routine when the send is completed and pass UserCompletionContext
//    as the context.
//
// In this implementation it is an error to specify both a UserCompletionEvent
// and a UserCompletionRoutine. Only one of these two methods can be used.
//
// If the synchronous mode of operation is employed, then the caller of
// KS_SendDatagramOnAddress must be running at IRQL PASSIVE_LEVEL. If the
// caller intends to wait on the event specified by UserCompletionEvent,
// then the waiting must be performed at IRQL PASSIVE_LEVEL.
//
// For all methods the IO_STATUS_BLOCK pointed to by pIoStatusBlock will
// receive the final completion status and information about the requested
// send operation.
//

NTSTATUS
KS_SendDatagramOnAddress(
   PKS_ADDRESS                      pKS_Address,
   HANDLE                           UserCompletionEvent,    // Optional
   PKS_REQUEST_COMPLETION_ROUTINE   UserCompletionRoutine,  // Optional
   PVOID                            UserCompletionContext,  // Optional
   PIO_STATUS_BLOCK                 pIoStatusBlock,         // Required
   PMDL                             pSendMdl,
   PTDI_CONNECTION_INFORMATION      pSendDatagramInfo
   )
{
   NTSTATUS                      Status;
   PIRP                          pSendIrp;
   ULONG                         Length;
   KEVENT                        SyncEvent;
   BOOLEAN                       bSynchronous = FALSE;
   PKS_ADDRESS_REQUEST_CONTEXT   pKS_RequestContext = NULL;
   PDEVICE_OBJECT                pDeviceObject;
   PMDL                          pNextMdl;

   ASSERT( pKS_Address );

   //
   // Allocate Memory For Private Completion Context
   //
   Status = NdisAllocateMemory(
                  &pKS_RequestContext,
                  sizeof( KS_ADDRESS_REQUEST_CONTEXT ),
                  0,       // Allocate non-paged system-space memory
                  HighestAcceptableMax
                  );

   if( !NT_SUCCESS( Status ) )
   {
      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   RtlZeroMemory( pKS_RequestContext, sizeof( KS_ADDRESS_REQUEST_CONTEXT ) );

   if( pIoStatusBlock )
   {
      pKS_RequestContext->m_pIoStatusBlock = pIoStatusBlock;
   }
   else
   {
      pKS_RequestContext->m_pIoStatusBlock = &pKS_RequestContext->m_SafeIoStatusBlock;
   }

   pKS_RequestContext->m_pKS_Address = pKS_Address;

   if( UserCompletionRoutine )
   {
      pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
      pKS_RequestContext->m_CompletionRoutine = UserCompletionRoutine;
      pKS_RequestContext->m_CompletionContext = UserCompletionContext;

      bSynchronous = FALSE;
   }
   else if( UserCompletionEvent )
   {
      pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
      KeResetEvent( pKS_RequestContext->m_CompletionEvent );

      pKS_RequestContext->m_CompletionRoutine = NULL;
      pKS_RequestContext->m_CompletionContext = NULL;

      bSynchronous = FALSE;
   }
   else
   {
      pKS_RequestContext->m_CompletionEvent = &SyncEvent;

      ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

      KeInitializeEvent(
         pKS_RequestContext->m_CompletionEvent,
         NotificationEvent,
         FALSE
         );

      pKS_RequestContext->m_CompletionRoutine = NULL;
      pKS_RequestContext->m_CompletionContext = NULL;

      bSynchronous = TRUE;
   }

   pDeviceObject = IoGetRelatedDeviceObject( pKS_Address->m_pFileObject );

   //
   // Allocate IRP For Sending
   //
   pSendIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE );

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

   Length = 0;
   pNextMdl = pSendMdl;

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

   TdiBuildSendDatagram(
      pSendIrp,
      pDeviceObject,
      pKS_Address->m_pFileObject,
      _I_KS_AddressRequestComplete, // Completion routine
      pKS_RequestContext,           // Completion context
      pSendMdl,                     // the data buffer
      Length,                       // send buffer length
      pSendDatagramInfo
      );

   //
   // 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, pSendIrp );

   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 = pSendIrp->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( pSendIrp );
   }

   return( Status );
}


/////////////////////////////////////////////////////////////////////////////
//// KS_ReceiveDatagramOnAddress
//
// Purpose
// Requests the underlying TDI transport to indicate a received datagram on
// the specified transport address.
//
// Parameters
//    pReceiveMdl
//       Pointer to the first Memory Descriptor List (MDL), in a possible
//       chain of MDLs, that will be filled with the received datagram.
//
//    pKS_Address
//       Pointer to the KS_ADDRESS structure that specifies the transport
//       address object that the datagram will be received on.
//
//    pIoStatusBlock
//       Pointer to a caller provided IO_STATUS_BLOCK structure that received
//       final completion status and received byte count.
//
//    UserCompletionRoutine
//       Specifies the entry point for the caller-supplied completion routine
//       to be called when the lower-level TDI driver completes the operation.
//       This routine is declared as follows:
//
//          VOID
//          (*PKS_REQUEST_COMPLETION_ROUTINE) (
//             PVOID UserCompletionContext,
//             PIO_STATUS_BLOCK IoStatusBlock,
//             ULONG Reserved
//             );//
//
//    UserCompletionContext
//        The value to be passed to UserCompletionRoutine.
//
// Remarks
// This function passes a chain of MDLs to the underlying TDI transport.
// The TDI transport will fill the memory wrapped by these MDLs with a datagram
// received on the specified transport address. The maximum datagram size that
// can be received is the sum of the MDL byte counts for all MDLs in the chain.
// Having the Next field set to NULL identifies the last MDL in the chain. The
// byte count of each MDL in the chain is queried using MmGetMdlByteCount.
//
// Each of the MDLs in the chain must have been probed and locked before calling
// KS_ReceiveDatagramOnAddress.
//
// Synchronous/Asynchronous Operation
// ----------------------------------
// Synchronous Receive
//    If UserCompletionEvent and UserCompletionRoutine are both NULL the receive
//    will be performed synchronously.
//
// Asynchronous Receive (Event Wait)
//    If a UserCompletionEvent is specified then the receive will be performed
//    asynchronously. The framework will set the specified event when the
//    datagram is received.
//
//    If UserCompletionEvent is specified, then UserCompletionRoutine and
//    UserCompletionContext are ignored.
//
// Asynchronous Receive (Completion Routine)
//    If a UserCompletionEvent is NOT specified (i.e., it is NULL) and a
//    UserCompletionRoutine is specified, then the receive will be performed
//    asynchronously. The framework will call the specified completion
//    routine when the datagram is received and pass UserCompletionContext
//    as the context.
//
// In this implementation it is an error to specify both a UserCompletionEvent
// and a UserCompletionRoutine. Only one of these two methods can be used.
//
// If the synchronous mode of operation is employed, then the caller of
// KS_ReceiveDatagramOnAddress must be running at IRQL PASSIVE_LEVEL. If the
// caller intends to wait on the event specified by UserCompletionEvent,
// then the waiting must be performed at IRQL PASSIVE_LEVEL.
//
// For all methods the IO_STATUS_BLOCK pointed to by pIoStatusBlock will
// receive the final completion status and information about the requested
// send operation.
//

NTSTATUS
KS_ReceiveDatagramOnAddress(
   PKS_ADDRESS                      pKS_Address,
   HANDLE                           UserCompletionEvent,    // Optional
   PKS_REQUEST_COMPLETION_ROUTINE   UserCompletionRoutine,  // Optional
   PVOID                            UserCompletionContext,  // Optional
   PIO_STATUS_BLOCK                 pIoStatusBlock,         // Required
   PMDL                             pReceiveMdl,
   PTDI_CONNECTION_INFORMATION      pReceiveDatagramInfo,
   PTDI_CONNECTION_INFORMATION      pReturnInfo,
   ULONG                            InFlags
   )
{
   NTSTATUS                      Status;
   PIRP                          pReceiveIrp;
   ULONG                         Length;
   KEVENT                        SyncEvent;
   BOOLEAN                       bSynchronous = FALSE;
   PKS_ADDRESS_REQUEST_CONTEXT   pKS_RequestContext = NULL;
   PDEVICE_OBJECT                pDeviceObject;
   PMDL                          pNextMdl;

   ASSERT( pKS_Address );

   //
   // Allocate Memory For Private Completion Context
   //
   Status = NdisAllocateMemory(
                  &pKS_RequestContext,
                  sizeof( KS_ADDRESS_REQUEST_CONTEXT ),
                  0,       // Allocate non-paged system-space memory
                  HighestAcceptableMax
                  );

   if( !NT_SUCCESS( Status ) )
   {
      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   RtlZeroMemory( pKS_RequestContext, sizeof( KS_ADDRESS_REQUEST_CONTEXT ) );

   if( pIoStatusBlock )
   {
      pKS_RequestContext->m_pIoStatusBlock = pIoStatusBlock;
   }
   else
   {
      pKS_RequestContext->m_pIoStatusBlock = &pKS_RequestContext->m_SafeIoStatusBlock;
   }

   pKS_RequestContext->m_pKS_Address = pKS_Address;

   if( UserCompletionRoutine )
   {
      pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
      pKS_RequestContext->m_CompletionRoutine = UserCompletionRoutine;
      pKS_RequestContext->m_CompletionContext = UserCompletionContext;

      bSynchronous = FALSE;
   }
   else if( UserCompletionEvent )
   {
      pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
      KeResetEvent( pKS_RequestContext->m_CompletionEvent );

      pKS_RequestContext->m_CompletionRoutine = NULL;
      pKS_RequestContext->m_CompletionContext = NULL;

      bSynchronous = FALSE;
   }
   else
   {
      pKS_RequestContext->m_CompletionEvent = &SyncEvent;

      ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

      KeInitializeEvent(
         pKS_RequestContext->m_CompletionEvent,
         NotificationEvent,
         FALSE
         );

      pKS_RequestContext->m_CompletionRoutine = NULL;
      pKS_RequestContext->m_CompletionContext = NULL;

      bSynchronous = TRUE;
   }

⌨️ 快捷键说明

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