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

📄 tcpserver.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
		);
}

VOID
TCPS_ReceiveCompletion(
    PVOID UserCompletionContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    ULONG Reserved
    )
{
   PTCPS_SESSION  pSession = (PTCPS_SESSION )UserCompletionContext;
   PTCPS_SERVER   pServer = (PTCPS_SERVER )pSession->m_pServer;
   NTSTATUS       Status = IoStatusBlock->Status;
	ULONG          nByteCount = IoStatusBlock->Information;

   if( NT_SUCCESS( Status ) )
   {
      KdPrint(( "TCPS_ReceiveCompletion: Received %d Bytes\n", nByteCount ));
   }
   else
   {
      KdPrint(( "TCPS_ReceiveCompletion: Status 0x%8.8X\n", Status ));
   }

   //
	// Check On State
	//

   //
	// Handle Disconnect Or Transfer Failure
   //
//	if( !NT_SUCCESS( Status ) || !nByteCount )
	if( !nByteCount )
	{
      //
      // Build Disconnect Call
      //
      Status = KS_Disconnect(
                  &pSession->m_KS_Endpoint,
                  NULL,       // UserCompletionEvent
                  TCPS_DisconnectCallback,    // UserCompletionRoutine
                  pSession,   // UserCompletionContext
                  NULL,       // pIoStatusBlock
                  0           // Disconnect Flags
                  );

		return;
   }

   //
   // Update Statistics
   //
   pSession->m_nBytesReceived += nByteCount;

   //
	// Start Another Receive On Same Buffer
   //
   (pSession->m_pReceiveMdl)->Next = NULL;   // IMPORTANT!!!

   Status = KS_ReceiveOnEndpoint(
               &pSession->m_KS_Endpoint,
               NULL,       // User Completion Event
               TCPS_ReceiveCompletion,// User Completion Routine
               pSession,   // User Completion Context
               &pSession->m_pReceiveIoStatus,
               pSession->m_pReceiveMdl,
               0           // Flags
               );
}


/////////////////////////////////////////////////////////////////////////////
//                    T D I  E V E N T  H A N D L E R S                    //
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//// TCPS_DisconnectEventHandler (Session Event Handler)
//
// Purpose
//
// Parameters
//   TdiEventContext - Pointer to TCPS_SESSION structure for the session.
//
// Return Value
//
// Remarks
// Disconnection indication prototype. This is invoked when a connection is
// being disconnected for a reason other than the user requesting it. Note
// that this is a change from TDI V1, which indicated only when the remote
// caused a disconnection. Any non-directed disconnection will cause this
// indication.
//

NTSTATUS TCPS_DisconnectEventHandler(
   IN PVOID TdiEventContext,     // Context From SetEventHandler
   IN CONNECTION_CONTEXT ConnectionContext,
   IN LONG DisconnectDataLength,
   IN PVOID DisconnectData,
   IN LONG DisconnectInformationLength,
   IN PVOID DisconnectInformation,
   IN ULONG DisconnectFlags
   )
{
   KdPrint(("TCPS_DisconnectEventHandler: Entry; EventContext: 0x%8.8X; ConnectionContext: 0x%8.8X; Flags: 0x%8.8X\n",
      (ULONG )TdiEventContext, (ULONG)ConnectionContext, DisconnectFlags)
      );

   return( STATUS_SUCCESS );
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_ServerErrorEventHandler (Server Event Handler)
//
// Purpose
//
// Parameters
//   TdiEventContext - Pointer to TCPS_SERVER structure for the server.
//
// Return Value
//
// Remarks
// A protocol error has occurred when this indication happens. This indication
// occurs only for errors of the worst type; the address this indication is
// delivered to is no longer usable for protocol-related operations, and
// should not be used for operations henceforth. All connections associated
// it are invalid.
// For NetBIOS-type providers, this indication is also delivered when a name
// in conflict or duplicate name occurs.
//

NTSTATUS TCPS_ServerErrorEventHandler(
   IN PVOID TdiEventContext,  // The endpoint's file object.
   IN NTSTATUS Status         // Status code indicating error type.
   )
{
   KdPrint(("TCPS_ServerErrorEventHandler: Status: 0x%8.8X\n", Status) );

   return( STATUS_SUCCESS );
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_SessionErrorEventHandler (Server Event Handler)
//
// Purpose
//
// Parameters
//   TdiEventContext - Pointer to TCPS_SERVER structure for the server.
//
// Return Value
//
// Remarks
// A protocol error has occurred when this indication happens. This indication
// occurs only for errors of the worst type; the address this indication is
// delivered to is no longer usable for protocol-related operations, and
// should not be used for operations henceforth. All connections associated
// it are invalid.
// For NetBIOS-type providers, this indication is also delivered when a name
// in conflict or duplicate name occurs.
//

NTSTATUS TCPS_SessionErrorEventHandler(
   IN PVOID TdiEventContext,  // The endpoint's file object.
   IN NTSTATUS Status         // Status code indicating error type.
   )
{
   KdPrint(("TCPS_SessionErrorEventHandler: Status: 0x%8.8X\n", Status) );

   return( STATUS_SUCCESS );
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_ReceiveExpeditedEventHandler (Session Event Handler)
//
// Purpose
//
// Parameters
//   TdiEventContext - Pointer to TCPS_SESSION structure for the session.
//
// Return Value
//
// Remarks
// This indication is delivered if expedited data is received on the connection.
// This will only occur in providers that support expedited data.
//

NTSTATUS TCPS_ReceiveExpeditedEventHandler(
   IN PVOID TdiEventContext,     // Context From SetEventHandler
   IN CONNECTION_CONTEXT ConnectionContext,
   IN ULONG ReceiveFlags,          //
   IN ULONG BytesIndicated,        // number of bytes in this indication
   IN ULONG BytesAvailable,        // number of bytes in complete Tsdu
   OUT ULONG *BytesTaken,          // number of bytes used by indication routine
   IN PVOID Tsdu,                  // pointer describing this TSDU, typically a lump of bytes
   OUT PIRP *IoRequestPacket        // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
   )
{
   KdPrint(("TCPS_ReceiveExpeditedEventHandler: Entry...\n") );

   KdPrint(("  Bytes Indicated: %d; BytesAvailable: %d; Flags: 0x%8.8x\n",
      BytesIndicated, BytesAvailable, ReceiveFlags));

   return( STATUS_SUCCESS );
}

/////////////////////////////////////////////////////////////////////////////
//// TCPS_FreeSession
//
// Purpose
//
// Parameters
//
// Return Value
//
// Remarks
// Callers of TCPS_FreeSession must be running at IRQL PASSIVE_LEVEL.
//

VOID
TCPS_FreeSession(
   PTCPS_SESSION  pSession
   )
{
   ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

   if( pSession )
   {
      KS_CloseConnectionEndpoint( &pSession->m_KS_Endpoint );

      if( pSession->m_pListenIrp )
      {
         IoFreeIrp( pSession->m_pListenIrp );
      }

      if( pSession->m_pReceiveMdl )
      {
         KS_UnlockAndFreeMdl( pSession->m_pReceiveMdl );
      }

      pSession->m_pReceiveMdl = NULL;

      if( pSession->m_pReceiveBuffer )
      {
         NdisFreeMemory(
            pSession->m_pReceiveBuffer,
            pSession->m_ReceiveBufferSize,
            0
            );
      }

      pSession->m_pReceiveBuffer = NULL;

      NdisFreeMemory( pSession, sizeof( TCPS_SESSION ), 0 );
   }
}

/////////////////////////////////////////////////////////////////////////////
//// TCPS_AllocateSession
//
// Purpose
//
// Parameters
//
// Return Value
//
// Remarks
// Callers of TCPS_AllocateSession must be running at IRQL PASSIVE_LEVEL.
//

NTSTATUS
TCPS_AllocateSession(
   PTCPS_SERVER   pServer,
   PTCPS_SESSION  *hSession
   )
{
   NTSTATUS       Status;
   PTCPS_SESSION  pSession;
   PDEVICE_OBJECT pDeviceObject;

   ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

   //
   // Allocate Session Memory
   //
   Status = NdisAllocateMemory(
               &pSession,
               sizeof( TCPS_SESSION ),
               0,       // Allocate non-paged system-space memory
               HighestAcceptableMax
               );

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

   NdisZeroMemory( pSession, sizeof( TCPS_SESSION ) );

   pSession->m_pServer = pServer;

   //
   // Allocate The Receive Buffer
   //
   pSession->m_ReceiveBufferSize = (pSession->m_pServer)->m_TestParams.m_nBufferSize;

   Status = NdisAllocateMemory(
               &pSession->m_pReceiveBuffer,
               pSession->m_ReceiveBufferSize,
               0,       // Allocate non-paged system-space memory
               HighestAcceptableMax
               );

   if( !NT_SUCCESS( Status ) )
   {
      TCPS_FreeSession( pSession );

      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   NdisZeroMemory(
      pSession->m_pReceiveBuffer,
      pSession->m_ReceiveBufferSize
      );

   pSession->m_pReceiveMdl = KS_AllocateAndProbeMdl(
                              pSession->m_pReceiveBuffer,   // Virtual Address
                              pSession->m_ReceiveBufferSize,
                              FALSE,
                              FALSE,
                              NULL
                              );

   if( !pSession->m_pReceiveMdl )
   {
      TCPS_FreeSession( pSession );

      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   //
   // Create The Connection Endpoint
   //
   Status = KS_OpenConnectionEndpoint(
                  TCP_DEVICE_NAME_W,
                  &pServer->m_KS_Address,
                  &pSession->m_KS_Endpoint,
                  &pSession->m_KS_Endpoint    // Context
                  );

   // BUGBUG!!! Resources Aren't Being Freed Systematically!!!
   // Use TCPS_FreeSession....

   if( !NT_SUCCESS( Status ) )
   {
      //
      // Connection Endpoint Could Not Be Created
      //
      KS_CloseConnectionEndpoint( &pSession->m_KS_Endpoint );

      NdisFreeMemory( pSession, sizeof( TCPS_SESSION ), 0 );

      return( Status );
   }

   KdPrint(("TCPS_AllocateSession: Created Local TDI Connection Endpoint\n") );

   pDeviceObject = IoGetRelatedDeviceObject(
                     pSession->m_KS_Endpoint.m_pFileObject
                     );
   //
   // Allocate Irp For Use In Listening For A Connection
   //
   pSession->m_pListenIrp = IoAllocateIrp(
                              pDeviceObject->StackSize,
                              FALSE
                              );

   if( !pSession->m_pListenIrp )
   {
      KS_CloseConnectionEndpoint( &pSession->m_KS_Endpoint );
      return( STATUS_INSUFFICIENT_RESOURCES );
   }

   //
	// Build The Listen Request
   //
	pSession->m_RemoteConnectionInfo.UserDataLength = 0;
	pSession->m_RemoteConnectionInfo.UserData = NULL;

	pSession->m_RemoteConnectionInfo.OptionsLength = 0;
	pSession->m_RemoteConnectionInfo.Options = NULL;

	pSession->m_RemoteConnectionInfo.RemoteAddressLength = sizeof( TA_IP_ADDRESS );
	pSession->m_RemoteConnectionInfo.RemoteAddress = &pSession->m_RemoteAddress;

   //
   // Start Listening On The Session
   //
   TdiBuildListen(
      pSession->m_pListenIrp,
      pDeviceObject,
      pSession->m_KS_Endpoint.m_pFileObject,
      TCPS_ConnectedCallback, // Completion Routine
      pSession,               // Completion Context
      0,                      // Flags
      NULL,                   // Request Connection Info
		&pSession->m_RemoteConnectionInfo
      );

   Status = IoCallDriver( pDeviceObject, pSession->m_pListenIrp );

   *hSession = pSession;

   KdPrint(( "Created Session: 0x%8.8X\n", (ULONG )pSession ));

   return( Status );
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_FreeSessionPool
//
// Purpose
//
// Parameters
//
// Return Value
//
// Remarks
//

VOID
TCPS_FreeSessionPool(
   PTCPS_SERVER   pServer
   )
{
   PTCPS_SESSION  pSession;

   while( !IsListEmpty( &pServer->m_FreeSessionList ) )
   {
      pSession = (PTCPS_SESSION )RemoveHeadList( &pServer->m_FreeSessionList );

      TCPS_FreeSession( pSession );
   }
}


/////////////////////////////////////////////////////////////////////////////
//// TCPS_AllocateSessionPool
//

⌨️ 快捷键说明

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