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

📄 protocol.cpp

📁 pppoe client
💻 CPP
字号:

//********************************************************************
//	日期:	2004/08/11 - 11:8:2004   0:40
//	名前:	tiamo
//	描述:	protocol
//*********************************************************************

#include "stdafx.h"

NDIS_MEDIUM MediumArray[1] = {NdisMedium802_3};

BOOLEAN g_bIsTimeToBind = FALSE;

// open complete
VOID protocolOpenAdapterComplete(PBIND_CONTEXT pBindContext,NDIS_STATUS status,NDIS_STATUS openErrorStatus)
{
	pBindContext->m_ulFlags |= BIND_CONTEXT_LOWER_ADAPTER_OPENED;

	pBindContext->m_statusCallback = status;
	NdisSetEvent(&pBindContext->m_evCallback);
}

// close complete
VOID protocolCloseAdapterComplete(PBIND_CONTEXT pBindContext,NDIS_STATUS status)
{
	pBindContext->m_ulFlags |= BIND_CONTEXT_LOWER_ADAPTER_CLOSED;

	pBindContext->m_statusCallback = status;
	NdisSetEvent(&pBindContext->m_evCallback);
}

// send complete
VOID protocolSendComplete(PBIND_CONTEXT pBindContext,PNDIS_PACKET pPacket,NDIS_STATUS status)
{
	PPPPOE_PACKET pPPPOEPacket = reinterpret_cast<PPROTOCOL_RESERVED>(pPacket->ProtocolReserved)->m_pPPPOEPacket;

	pPPPOEPacket->m_status = status;

	DereferencePacket(pPPPOEPacket);

	DereferenceBind(pPPPOEPacket->m_pBindContext);
}

// transfer data complete
VOID protocolTransferDataComplete(PBIND_CONTEXT pBindContext,PNDIS_PACKET pPacket,NDIS_STATUS status,UINT uByteTransferred)
{
	PPPPOE_PACKET pPPPOEPacket = reinterpret_cast<PPROTOCOL_RESERVED>(pPacket->ProtocolReserved)->m_pPPPOEPacket;
	if(status != NDIS_STATUS_SUCCESS)
	{
		DereferencePacket(pPPPOEPacket);
		return;
	}

	// reversed data,so convert it
	if(pPPPOEPacket->m_ulFlags & PPPOE_PACKET_BUFFER_REVERSED)
	{
		LONG const TEMP_BUFFER_SIZE = 100;

		UCHAR temp[TEMP_BUFFER_SIZE];
		UCHAR ucHead[PPPOE_MIN_ETH_FRAME_SIZE];
		LONG lCurrentOffset = uByteTransferred;
		LONG lCopyLen = TEMP_BUFFER_SIZE;

		// copy to temp buffer first
		NdisMoveMemory(ucHead,pPPPOEPacket->m_pucFrame + PPPOE_MAX_FRAME_SIZE,PPPOE_MIN_ETH_FRAME_SIZE);

		while(lCurrentOffset)
		{
			lCurrentOffset -= lCopyLen;
			if(lCurrentOffset < 0)
			{
				lCopyLen += lCurrentOffset;
				lCurrentOffset = 0;
			}

			// copy to temp buffer first
			NdisMoveMemory(temp,pPPPOEPacket->m_pucFrame + lCurrentOffset,lCopyLen);

			// copy back
			NdisMoveMemory(pPPPOEPacket->m_pucFrame + lCurrentOffset + PPPOE_MIN_ETH_FRAME_SIZE,temp,lCopyLen);
		}

		NdisMoveMemory(pPPPOEPacket->m_pucFrame,ucHead,PPPOE_MIN_ETH_FRAME_SIZE);

		pPPPOEPacket->m_ulFlags &= ~PPPOE_PACKET_BUFFER_REVERSED;
	}
	
	// insert to the list
	NdisInterlockedInsertTailList(&pBindContext->m_ltRecvPacket,&pPPPOEPacket->m_ltPackets,&pBindContext->m_lockSelf);
}

// request complete
VOID protocolRequestComplete(PBIND_CONTEXT pBindContext,PNDIS_REQUEST pRequest,NDIS_STATUS status)
{
	__try
	{
		if(pRequest->RequestType == NdisRequestQueryInformation)
		{
			switch(pRequest->DATA.QUERY_INFORMATION.Oid)
			{
			case OID_802_3_CURRENT_ADDRESS:
				pBindContext->m_ulFlags |= BIND_CONTEXT_MAC_ADDRESS_GOT;
				break;

			case OID_GEN_LINK_SPEED:
				pBindContext->m_ulFlags |= BIND_CONTEXT_LINK_SPPED_GOT;
				break;

			case OID_GEN_MAXIMUM_FRAME_SIZE:
				pBindContext->m_ulFlags |= BIND_CONTEXT_MAX_FRAME_SIZE_GOT;
				break;
			
			default:
				__leave;
				break;
			}
		}
		else
		{
			if(pRequest->DATA.SET_INFORMATION.Oid != OID_GEN_CURRENT_PACKET_FILTER)
				__leave;

			if(status == NDIS_STATUS_SUCCESS)
			{
				if(pBindContext->m_ulFlags & BIND_CONTEXT_PACKET_FILTER_SET)
					pBindContext->m_ulFlags &= ~BIND_CONTEXT_PACKET_FILTER_SET;
				else
					pBindContext->m_ulFlags |= BIND_CONTEXT_PACKET_FILTER_SET;
			}
		}

		NdisSetEvent(&pBindContext->m_evCallback);
		pBindContext->m_statusCallback = status;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
	}
}

// receive complete
VOID protocolReceiveComplete(PBIND_CONTEXT pBindContext)
{
	NdisAcquireSpinLock(&pBindContext->m_lockSelf);

	if(!pBindContext->m_bProcessingRecvPacket)
	{
		pBindContext->m_bProcessingRecvPacket = TRUE;

		while(!IsListEmpty(&pBindContext->m_ltRecvPacket))
		{
			PLIST_ENTRY pEntry = RemoveHeadList(&pBindContext->m_ltRecvPacket);
			NdisReleaseSpinLock(&pBindContext->m_lockSelf);

			// get packet
			PPPPOE_PACKET pPacket = CONTAINING_RECORD(pEntry,PPPOE_PACKET,m_ltPackets);
		
			// initialize packet member value
			if(InitializePPPOEPacketForRecved(pPacket))
			{
				// process it
				ProcessRecvPacket(pBindContext,pPacket);
			}

			// dereference it
			DereferencePacket(pPacket);

			NdisAcquireSpinLock(&pBindContext->m_lockSelf);
		}		
		
		pBindContext->m_bProcessingRecvPacket = FALSE;
	}

	NdisReleaseSpinLock(&pBindContext->m_lockSelf);
}

// status complete
VOID protocolStatusComplete(PBIND_CONTEXT pBindContext)
{
	return;
}

// status
VOID protocolStatus(PBIND_CONTEXT pBindContext,NDIS_STATUS generalStatus,PVOID pStatusBuffer,UINT uStatusBufferSize)
{
	if(generalStatus == NDIS_STATUS_MEDIA_DISCONNECT)
	{
		NotifyBindingRemoval(pBindContext);
	}
}

// receive
NDIS_STATUS protocolReceive(PBIND_CONTEXT pBindContext,NDIS_HANDLE MacReceiveContext,PVOID pHeaderBuffer,UINT uHeaderBufferSize,
							PVOID pLookAheadBuffer,UINT uLookaheadBufferSize,UINT uPacketSize)
{
	// always accept the packect
	NDIS_STATUS status = NDIS_STATUS_NOT_ACCEPTED;

	// check pppoe frame
	if(!FastCheckIsPPPOEFrame(static_cast<PPPPOE_FRAME>(pHeaderBuffer),uHeaderBufferSize))
		return NDIS_STATUS_NOT_ACCEPTED;

	// check buffer size
	if( uHeaderBufferSize + uPacketSize > PPPOE_MAX_ETH_FRAME_SIZE || 
		uHeaderBufferSize < PPPOE_MIN_ETH_FRAME_SIZE)
		return NDIS_STATUS_NOT_ACCEPTED;

	// create a pppoe packet
	PPPPOE_PACKET pPPPOEPacket = GetSimplePPPOEPacket();

	if(!pPPPOEPacket)
		return NDIS_STATUS_NOT_ACCEPTED;

	// check full buffer received
	if(uLookaheadBufferSize < uPacketSize)
	{
		// move head buffer to the end first
		NdisMoveMemory(pPPPOEPacket->m_pucFrame + PPPOE_MAX_FRAME_SIZE,pHeaderBuffer,uHeaderBufferSize);

		NdisTransferData(&status,pBindContext->m_pOpenBlock,MacReceiveContext,0,uPacketSize,
						 pPPPOEPacket->m_pNdisPacket,&uPacketSize);

		pPPPOEPacket->m_ulFlags |= PPPOE_PACKET_BUFFER_REVERSED;
	}
	else
	{
		// copy head buffer
		NdisMoveMemory(pPPPOEPacket->m_pFrame,pHeaderBuffer,uHeaderBufferSize);

		// copy lookahead buffer
		NdisMoveMemory(pPPPOEPacket->m_pucFrame + uHeaderBufferSize,pLookAheadBuffer,uLookaheadBufferSize);

		status = NDIS_STATUS_SUCCESS;
	}

	if(status != NDIS_STATUS_PENDING)
		protocolTransferDataComplete(pBindContext,pPPPOEPacket->m_pNdisPacket,status,uPacketSize);

	return status;
}

// receive packet
INT protocolReceivePacket(PBIND_CONTEXT pBindContext,PNDIS_PACKET pPacket)
{
	BOOLEAN bNeedCallReturn = FALSE;
	PPPPOE_PACKET pPPPOEPacket = NdisPacket2PPPOEPacket(pBindContext,pPacket,&bNeedCallReturn);

	if(!pPPPOEPacket)
		return 0;

	NdisInterlockedInsertTailList(&pBindContext->m_ltRecvPacket,&pPPPOEPacket->m_ltPackets,&pBindContext->m_lockSelf);

	return bNeedCallReturn;
}

// bind adapter
VOID protocolBindAdapter(PNDIS_STATUS pStatus,NDIS_HANDLE hBindContext,PNDIS_STRING pDeviceName,PVOID pSys1,PVOID pSys2)
{
	DbgEnterFunction();
	
	PBIND_CONTEXT pBind = NULL;
	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
	NDIS_STATUS openErrorStatus;
	__try
	{
		NdisAcquireSpinLock(&g_lockBind);
		if(!g_bIsTimeToBind)
		{
			*pStatus = status = NDIS_STATUS_FAILURE;
			NdisReleaseSpinLock(&g_lockBind);
			__leave;
		}

		NdisReleaseSpinLock(&g_lockBind);

		// create bind
		pBind = CreateBind();

		// open lower miniport
		NDIS_MEDIUM mediumArray[1] ={NdisMedium802_3};
		UINT selMedium;

		NdisOpenAdapter(&status,&openErrorStatus,&pBind->m_pOpenBlock,&selMedium,mediumArray,
						sizeof(mediumArray)/sizeof(NDIS_MEDIUM),g_hProtocolHandle,pBind,pDeviceName,0,NULL);

		if(status != NDIS_STATUS_PENDING)
		{
			protocolOpenAdapterComplete(pBind,status,openErrorStatus);
		}

		NdisWaitEvent(&pBind->m_evCallback,0);
		NdisResetEvent(&pBind->m_evCallback);
		status = pBind->m_statusCallback;

		if(status != NDIS_STATUS_SUCCESS || mediumArray[selMedium] != NdisMedium802_3)
			ExRaiseStatus(status);

		// query lower miniport for current address
		QueryLowerMiniportForCurrentAddress(pBind);

		// query lower miniport for current address
		QueryLowerMiniportForLinkSpeed(pBind);

		// query lower miniport for max frame size
		QueryLowerMiniportForMaxFrameSize(pBind);

		// set packet filter
		if(g_bSetFilterAtBind)
			SetLowerMiniportPacketFilter(pBind,TRUE);

		// add bind to list
		NdisInterlockedInsertHeadList(&g_ltBinds,&pBind->m_ltBinds,&g_lockBind);

		pBind->m_ulBindState = BIND_LOWER_MINIPORT_OPENED;

		pBind->m_ulFlags |= BIND_CONTEXT_BINDED;

		status = NDIS_STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		if(pBind)
		{
			if(pBind->m_pOpenBlock)
			{
				NdisCloseAdapter(&openErrorStatus,pBind->m_pOpenBlock);

				if(openErrorStatus == NDIS_STATUS_PENDING)
				{
					NdisWaitEvent(&pBind->m_evCallback,0);
					NdisResetEvent(&pBind->m_evCallback);
				}
			}

			FreeBind(pBind);
		}
	}

	*pStatus = status;

	DbgLeaveFunctionWithStatus(status);
}

// unbind
VOID protocolUnbindAdapter(OUT PNDIS_STATUS pStatus,PBIND_CONTEXT pBindContext,NDIS_HANDLE hUnbindContext)
{
	DbgEnterFunction();
	
	NdisAcquireSpinLock(&pBindContext->m_lockSelf);

	if(pBindContext->m_ulBindState == BIND_LOWER_MINIPORT_CLOSING)
	{
		NdisReleaseSpinLock(&pBindContext->m_lockSelf);

		NdisMSleep(10000);

		NdisAcquireSpinLock(&pBindContext->m_lockSelf);
	}

	pBindContext->m_ulBindState = BIND_ROMOVING;

	NdisReleaseSpinLock(&pBindContext->m_lockSelf);

	NotifyBindingRemoval(pBindContext);

	NdisAcquireSpinLock(&g_lockBind);

	RemoveEntryList(&pBindContext->m_ltBinds);

	NdisReleaseSpinLock(&g_lockBind);

	DereferenceBind(pBindContext);

	NdisWaitEvent(&pBindContext->m_evRemove,0);

	while(pBindContext->m_lPacketNeedReturn > 0)
		NdisMSleep(10000);

	NdisCloseAdapter(pStatus,pBindContext->m_pOpenBlock);

	if(*pStatus != NDIS_STATUS_PENDING)
	{
		protocolCloseAdapterComplete(pBindContext,*pStatus);
	}

	NdisWaitEvent(&pBindContext->m_evCallback,0);

	NdisResetEvent(&pBindContext->m_evCallback);

	pBindContext->m_ulBindState = BIND_FREEING;

	FreeBind(pBindContext);

	*pStatus = NDIS_STATUS_SUCCESS;

	DbgLeaveFunctionWithStatus(*pStatus);
}

// unload
VOID protocolUnload()
{
}

// pnp event
NDIS_STATUS protocolPnPEvent(PBIND_CONTEXT pBindContext,PNET_PNP_EVENT pNetPnPEvent)
{
	if(pNetPnPEvent->NetEvent == NetEventSetPower)
	{
		NdisAcquireSpinLock(&pBindContext->m_lockSelf);

		NDIS_DEVICE_POWER_STATE newState = *static_cast<PNDIS_DEVICE_POWER_STATE>(pNetPnPEvent->Buffer);

		if(newState != NdisDeviceStateD0)
		{
			BOOLEAN bNeedClose = FALSE;
			if(pBindContext->m_ulBindState == BIND_LOWER_MINIPORT_OPENED)
			{
				pBindContext->m_ulBindState = BIND_LOWER_MINIPORT_CLOSING;
				bNeedClose = TRUE;
			}

			NdisReleaseSpinLock(&pBindContext->m_lockSelf);

			if(bNeedClose)
				NotifyBindingRemoval(pBindContext);
			
			NdisAcquireSpinLock(&pBindContext->m_lockSelf);

			while(pBindContext->m_lRefCount > 1)
			{
				NdisReleaseSpinLock(&pBindContext->m_lockSelf);

				NdisMSleep(10000);
			}

			pBindContext->m_ulBindState = BIND_LOWER_MINIPORT_CLOSED;

			NdisReleaseSpinLock(&pBindContext->m_lockSelf);
		}
		else
		{
			if(pBindContext->m_ulBindState == BIND_LOWER_MINIPORT_CLOSED)
				pBindContext->m_ulBindState = BIND_LOWER_MINIPORT_OPENED;
			
			NdisReleaseSpinLock(&pBindContext->m_lockSelf);
		}
	}

	return NDIS_STATUS_SUCCESS;
}

⌨️ 快捷键说明

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