📄 tcpecho.c
字号:
&pTCPS_Packet->Reserved.m_ListElement
);
//
// Possibly Send Another Packet
//
TCPS_EchoTcpPackets( pConnection );
return;
}
#endif // USE_RECEIVE_EVENT_HANDLER
/////////////////////////////////////////////////////////////////////////////
// D I S C O N N E C T R O U T I N E S //
/////////////////////////////////////////////////////////////////////////////
VOID
TCPS_DisconnectCallback(
PVOID UserCompletionContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
)
{
PTCPS_Connection pConnection = (PTCPS_Connection )UserCompletionContext;
NTSTATUS nFinalStatus = IoStatusBlock->Status;
#if DBG
DbgPrint( "TCPS_DisconnectCallback: FinalStatus: %d\n", nFinalStatus );
#endif
//
// Mark As Not Connected
//
pConnection->m_bIsConnected = FALSE;
//
// Empty the ReceivedTcpPacketList
// ----------------------------
// TCPS_EchoTcpPackets will empty the list if pConnection->m_bIsConnected
// is FALSE.
//
TCPS_EchoTcpPackets( pConnection );
if( pConnection->m_pWaitEvent )
{
#if DBG
DbgPrint( "TCPS_DisconnectCallback: Setting Wait Event\n" );
#endif
KeSetEvent( pConnection->m_pWaitEvent, 0, FALSE );
pConnection->m_pWaitEvent = NULL;
}
//
// Return Connection To Free List
//
TCPS_FreeConnection( pConnection );
}
/////////////////////////////////////////////////////////////////////////////
//// TCPS_DisconnectEventHandler
//
// Purpose
// Called by the TDI to indicate that a remote client is closing a
// connection.
//
// Parameters
//
// Return Value
//
// Remarks
//
NTSTATUS
TCPS_DisconnectEventHandler(
IN PVOID TdiEventContext, // Context From SetEventHandler
IN CONNECTION_CONTEXT ConnectionContext, // As passed to TdiOpenConnection
IN LONG DisconnectDataLength,
IN PVOID DisconnectData,
IN LONG DisconnectInformationLength,
IN PVOID DisconnectInformation,
IN ULONG DisconnectFlags
)
{
PTCPS_Connection pConnection;
TDI_STATUS nTdiStatus;
#if DBG
DbgPrint( "TCPS_DisconnectEventHandler Entry...\n" );
#endif
pConnection = (PTCPS_Connection )ConnectionContext;
//
// Remove From Open Connection List
//
RemoveEntryList( &pConnection->m_ListElement );
switch( DisconnectFlags )
{
case TDI_DISCONNECT_WAIT: // Used For Disconnect Notification
#if DBG
DbgPrint( "Disconnect: Wait\n" );
#endif
//
// Return Connection To Free List
//
TCPS_FreeConnection( pConnection );
break;
case TDI_DISCONNECT_ABORT: // Immediately Terminate Connection
#if DBG
DbgPrint( "Disconnect: Abort\n" );
#endif
//
// Return Connection To Free List
//
TCPS_FreeConnection( pConnection );
break;
case TDI_DISCONNECT_RELEASE: // Initiate Graceful Disconnect
#if DBG
DbgPrint( "Disconnect: Release\n" );
#endif
nTdiStatus = KS_Disconnect(
&pConnection->m_KS_Endpoint,
NULL, // UserCompletionEvent
TCPS_DisconnectCallback,
pConnection,
NULL,
0
);
break;
default:
#if DBG
DbgPrint( "Unexpected Flags: 0x%X\n", DisconnectFlags );
#endif
break;
}
return( STATUS_SUCCESS );
}
/////////////////////////////////////////////////////////////////////////////
//// TCPS_Startup
//
// Purpose
// Startup the ECHO server.
//
// Parameters
//
// Return Value
//
// Remarks
//
NTSTATUS
TCPS_Startup( PDEVICE_OBJECT pDeviceObject )
{
NTSTATUS nTdiStatus;
NDIS_STATUS nNdisStatus;
TA_IP_ADDRESS ECHOAddress;
int i;
#if DBG
DbgPrint( "TCPS_Startup Entry...\n" );
DbgPrint( "pDeviceObject: 0x%X\n", pDeviceObject );
#endif
if( g_nTCPS_UseCount > 0 )
{
++g_nTCPS_UseCount;
return( STATUS_SUCCESS );
}
g_bAddressOpen = FALSE;
//
// Initialize Connection Lists
//
InitializeListHead( &g_FreeConnectionList );
InitializeListHead( &g_OpenConnectionList );
//
// Allocate The Packet Pool
//
NdisAllocatePacketPool(
&nNdisStatus,
&g_hPacketPool,
TCPS_PACKET_POOL_SIZE,
sizeof( TCPS_PACKET_RESERVED )
);
ASSERT( NT_SUCCESS( nNdisStatus ) );
if( !NT_SUCCESS( nNdisStatus ) )
{
#if DBG
DbgPrint( "TCPS_Startup: Failed To Allocate Packet Pool\n" );
#endif
return( STATUS_INSUFFICIENT_RESOURCES );
}
g_bPacketPoolAllocated = TRUE;
//
// Allocate The Buffer Pool
//
NdisAllocateBufferPool(
&nNdisStatus,
&g_hBufferPool,
TCPS_BUFFER_POOL_SIZE
);
ASSERT( NT_SUCCESS( nNdisStatus ) );
if( !NT_SUCCESS( nNdisStatus ) )
{
#if DBG
DbgPrint( "TCPS_Startup: Failed To Allocate Buffer Pool\n" );
#endif
NdisFreePacketPool( g_hPacketPool );
g_bPacketPoolAllocated = FALSE;
g_bBufferPoolAllocated = FALSE;
return( STATUS_INSUFFICIENT_RESOURCES );
}
g_bBufferPoolAllocated = TRUE;
//
// Initialize The Local IP Address
//
KS_InitIPAddress(
&g_LocalAddress, // Pointer To A TA_IP_ADDRESS
INADDR_ANY, // Any Local Internet Address
KS_htons( IPPORT_ECHO ) // ECHO Port
);
//
// Open The Local TDI Address Object
//
nTdiStatus = STATUS_REQUEST_ABORTED;
nTdiStatus = KS_OpenTransportAddress(
TCP_DEVICE_NAME_W,
(PTRANSPORT_ADDRESS )&g_LocalAddress,
&g_KS_Address
);
ASSERT( NT_SUCCESS( nTdiStatus ) );
if ( !NT_SUCCESS( nTdiStatus ) )
{
return( nTdiStatus );
}
//
// Initialize And Link Up The Free Connections Pool
//
for( i = 0; i < MAX_CONNECTIONS ; i++ )
{
PTCPS_Connection pConnection = &g_ConnectionSpace[i];
OBJECT_ATTRIBUTES TcpObjectAttributes;
PVOID *contextAddress;
PFILE_FULL_EA_INFORMATION eaBuffer;
ULONG eaLength;
UNICODE_STRING TcpDeviceName;
IO_STATUS_BLOCK IoStatus;
//
// Zero The Connection Memory
//
NdisZeroMemory( pConnection, sizeof( TCPS_Connection ) );
InitializeListHead( &pConnection->m_ReceivedTcpPacketList );
//
// Create The Connection Endpoint
//
nTdiStatus = KS_OpenConnectionEndpoint(
TCP_DEVICE_NAME_W,
&g_KS_Address,
&pConnection->m_KS_Endpoint,
pConnection // Context
);
ASSERT( NT_SUCCESS( nTdiStatus ) );
if ( !NT_SUCCESS( nTdiStatus ) )
{
break;
}
pConnection->m_bIsConnectionObjectValid = TRUE;
InsertTailList(
&g_FreeConnectionList,
&g_ConnectionSpace[i].m_ListElement
);
}
g_bAddressOpen = TRUE;
//
// Setup Event Handlers On The Server Address Object
//
nTdiStatus = KS_SetEventHandlers(
&g_KS_Address,
pDeviceObject, // Event Context
TCPS_ConnectEventHandler, // ConnectEventHandler
TCPS_DisconnectEventHandler, // DisconnectEventHandler
NULL, // ErrorEventHandler,
#ifdef USE_RECEIVE_EVENT_HANDLER
TCPS_ReceiveEventHandler, // ReceiveEventHandler
#else
NULL, // ReceiveEventHandler
#endif
NULL, // ReceiveDatagramEventHandler
NULL // ReceiveExpeditedEventHandler
);
ASSERT( NT_SUCCESS( nTdiStatus ) );
if( !NT_SUCCESS( nTdiStatus ) )
return( nTdiStatus );
g_nTCPS_UseCount = 1;
return( STATUS_SUCCESS );
}
/////////////////////////////////////////////////////////////////////////////
//// TCPS_Shutdown
//
// Purpose
// Shutdown the ECHO server.
//
// Parameters
//
// Return Value
//
// Remarks
//
VOID TCPS_Shutdown( PDEVICE_OBJECT pDeviceObject )
{
TDI_STATUS nTdiStatus;
#if DBG
DbgPrint( "TCPS_Shutdown Entry...\n" );
#endif
if( --g_nTCPS_UseCount <= 0 )
{
PTCPS_Connection pConnection;
//
// Destroy All Connections
//
while( !IsListEmpty( &g_OpenConnectionList ) )
{
pConnection = (PTCPS_Connection )RemoveHeadList( &g_OpenConnectionList );
#if DBG
DbgPrint( "Destroying Connection; ConnectionContext: 0x%X\n",
pConnection );
#endif
if( pConnection->m_bIsConnected )
{
//
// Perform Synchronous Disconnect
//
nTdiStatus = KS_Disconnect(
&pConnection->m_KS_Endpoint,
NULL, // UserCompletionEvent
NULL, // UserCompletionRoutine
NULL, // UserCompletionContext
NULL, // pIoStatusBlock
0 // Disconnect Flags
);
}
//
// Mark As Not Connected
//
pConnection->m_bIsConnected = FALSE;
//
// Empty the ReceivedTcpPacketList
// ----------------------------
// TCPS_EchoTcpPackets will empty the list if pConnection->m_bIsConnected
// is FALSE.
//
TCPS_EchoTcpPackets( pConnection );
//
// Return Connection To Free List
//
TCPS_FreeConnection( pConnection );
}
//
// Release Connections In The Free Connection List
//
while( !IsListEmpty( &g_FreeConnectionList ) )
{
pConnection = (PTCPS_Connection )RemoveHeadList( &g_FreeConnectionList );
#if DBG
DbgPrint( "Destroying Connection; ConnectionContext: 0x%X\n",
pConnection );
#endif
//
// Close The TDI Connection Object, If Necessary
//
if( pConnection->m_bIsConnectionObjectValid )
{
KS_CloseConnectionEndpoint( &pConnection->m_KS_Endpoint );
}
pConnection->m_bIsConnectionObjectValid = FALSE;
}
//
// Close The TDI Address Object, If Necessary
//
if( g_bAddressOpen )
{
KS_CloseTransportAddress( &g_KS_Address );
}
g_bAddressOpen = FALSE;
//
// Free Packet And Buffer Pools
//
if( g_bBufferPoolAllocated )
NdisFreeBufferPool( g_hBufferPool );
g_bBufferPoolAllocated = FALSE;
if( g_bPacketPoolAllocated )
NdisFreePacketPool( g_hPacketPool );
g_bPacketPoolAllocated = FALSE;
g_nTCPS_UseCount = 0;
return;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -