讨论:Delphi下拦截2层数据侦的实现(ARP为主) ( 积分: 200 )

  • 主题发起人 主题发起人 DJ6674
  • 开始时间 开始时间
谢谢爱元元的哥哥。
我不是做商用开发,做毕业设计而已。
 
这边不好贴附件,我把以前做的小项目的NDIS驱动的代码全贴给你。希望对你毕设有帮助,这些代码大部分都是根据微软的例子,加入自己简单的拦截逻辑就可以了。
 
/*++
代码:
Copyright (c) 1997 BY Simahuapeng
Module Name:
	miniport.c
--*/

#include "precomp.h"
#include "util.h"
#include "pcaenet.h"
#include "ethertype.h"
#include "DDKLBLInc.h"
#include "cons_def.h"

#pragma hdrstop

//extern FAST_MUTEX	fw_mutex;

NDIS_STATUS
MPInitialize(
	OUT PNDIS_STATUS			OpenErrorStatus,
	OUT PUINT					SelectedMediumIndex,
	IN	PNDIS_MEDIUM			MediumArray,
	IN	UINT					MediumArraySize,
	IN	NDIS_HANDLE				MiniportAdapterHandle,
	IN	NDIS_HANDLE				WrapperConfigurationContext
	)
/*++

Routine Description:

	This is the initialize handler which gets called as a result of the BindAdapter handler
	calling NdisIMInitializeDeviceInstanceEx(). The context parameter which we pass there is
	the adapter structure which we retreive here. We also need to initialize the Power Management
	variable.
	LoadBalalncing- We keep a global list of all the passthru miniports installed and bundle
	two of them together if they have the same BundleId (read from registry)

	Arguments:

	OpenErrorStatus			Not used by us.
	SelectedMediumIndex		Place-holder for what media we are using
	MediumArray				Array of ndis media passed down to us to pick from
	MediumArraySize			Size of the array
	MiniportAdapterHandle	The handle NDIS uses to refer to us
	WrapperConfigurationContext	For use by NdisOpenConfiguration

Return Value:

	NDIS_STATUS_SUCCESS unless something goes wrong

--*/
{
	UINT	i;
	PADAPT	pAdapt;
	NDIS_STATUS						Status = NDIS_STATUS_FAILURE;


	NDIS_STATUS						BundleStatus = NDIS_STATUS_FAILURE;
	NDIS_STRING						BundleUniString;
	KIRQL							OldIrql;

	DBGPRINT("==>Passthru Initialize Miniport/n");

	//
	// Start off by retrieving the adapter context and storing the Miniport handle in it
	//
	pAdapt = NdisIMGetDeviceContext(MiniportAdapterHandle);
	pAdapt->MiniportHandle = MiniportAdapterHandle;

	//
	// Make sure the medium saved is one of the ones being offered
	//

	for (i = 0; i < MediumArraySize; i++)
	{
		if (MediumArray[i] == pAdapt->Medium)
		{
			*SelectedMediumIndex = i;
			break;
		}
	}

	if (i == MediumArraySize)
	{
		return(NDIS_STATUS_UNSUPPORTED_MEDIA);
	}


	//
	// Set the attributes now. The NDIS_ATTRIBUTE_DESERIALIZE is the key. This enables us
	// to make up-calls to NDIS w/o having to call NdisIMSwitchToMiniport/NdisIMQueueCallBack.
	// This also forces us to protect our data using spinlocks where appropriate. Also in this
	// case NDIS does not queue packets on out behalf. Since this is a very simple pass-thru
	// miniport, we do not have a need to protect anything. However in a general case there
	// will be a need to use per-adapter spin-locks for the packet queues at the very least.
	//
	NdisMSetAttributesEx(MiniportAdapterHandle,
						 pAdapt,
						 0,										// CheckForHangTimeInSeconds
						 NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT	|
							NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|
							NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
							NDIS_ATTRIBUTE_DESERIALIZE |
							NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
						 0);

	//
	// Setting up the default value for the Device State Flag as PM capable
	// initialize the PM Variable, (for both miniport and the protocol) Device is ON by default
	//
	pAdapt->MPDeviceState=NdisDeviceStateD0;
	pAdapt->PTDeviceState=NdisDeviceStateD0;

	//
	// Begin the Load Balancing and Bundle Identifier work here
	// Default case: the miniport is the primary miniport
	//
	pAdapt->isSecondary		=	FALSE;	// default - primary
	pAdapt->pPrimaryAdapt	=	pAdapt;	//default, point to self
	pAdapt->pSecondaryAdapt	=	pAdapt;	//default, point to self

	//
	// Set miniport as a secondary miniport, if need be
	//
	BundleStatus  =	MPBundleSearchAndSetSecondary (pAdapt);

	//
	// Inserting into our global Passthru pAdapt List
	//
	KeAcquireSpinLock (&amp;pAdapt->SpinLock, &amp;OldIrql);

	pAdapt->Next = pAdaptList;
	pAdaptList = pAdapt;

	KeReleaseSpinLock (&amp;pAdapt->SpinLock, OldIrql);
		
	//
	// We are done, In current implementation, Bundle Status does not affect the success of initialization
	//
	Status = NDIS_STATUS_SUCCESS;

	DBGPRINT(&quot;<== Passthru Initialize Miniport/n&quot;);

	return Status;
}


NDIS_STATUS
MPSend(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	PNDIS_PACKET			Packet,
	IN	UINT					Flags
	)
/*++

Routine Description:

	Send handler. Just re-wrap the packet and send it below. Re-wrapping is necessary since
	NDIS uses the WrapperReserved for its own use.

	LBFO- All sends will be done in the secondary miniport of the bundle.

	We are using the Secondary Miniport as the Send path. All sends should use that pAdapt structure.

Arguments:

	MiniportAdapterContext	Pointer to the adapter
	Packet					Packet to send
	Flags					Unused, passed down below

Return Value:

	Return code from NdisSend

--*/
{
	PADAPT			pAdapt = (PADAPT)MiniportAdapterContext;
	NDIS_STATUS		Status;
	PNDIS_PACKET	MyPacket;
	PRSVD			Rsvd;
	PVOID			MediaSpecificInfo = NULL;
	ULONG			MediaSpecificInfoSize = 0;

//add by qsc
	USHORT            nEtherType, nIPhdrLen, nTCPhdrLen, nICMPhdrLen;
	ULONG             nNumberOfBytesRead = 0;
	ULONG             nIPSrcAddress, nIPSrcAddrOffset;
	ULONG             nIPDstAddress, nIPDstAddrOffset;
	UCHAR		  nProtocol;
	ULONG		  nProtocolAddrOffset;
	UCHAR		  nMatch;
//end add
//add by df
	KIRQL oldirql;
	//
	//  According to our LBFO design, all sends will be performed on the secondary miniport
	//	However, the must be completed on the primary's miniport handle
	//

	ASSERT (pAdapt->pSecondaryAdapt);

	pAdapt = pAdapt->pSecondaryAdapt;


	if (IsIMDeviceStateOn (pAdapt) == FALSE)
	{
		return NDIS_STATUS_FAILURE;
	}

//-----------------------------------------------------------add by qsc
 
	//ExAcquireFastMutex(&amp;fw_mutex);	//add by df
	//attantion
	//ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
	//KeRaiseIrql(DISPATCH_LEVEL, &amp;oldirql);
	
	nMatch=UTIL_MatchRule(Packet, DT_OUT);

	//KeLowerIrql(oldirql);
	//ExReleaseFastMutex(&amp;fw_mutex); 	//add by df
	if(nMatch==DENY)
		return NDIS_STATUS_SUCCESS;

//----------------------------------------------------------------------end add


	NdisAllocatePacket(&amp;Status,
					   &amp;MyPacket,
					   pAdapt->SendPacketPoolHandle);

	if (Status == NDIS_STATUS_SUCCESS)
	{
		PNDIS_PACKET_EXTENSION	Old, New;

		Rsvd = (PRSVD)(MyPacket->ProtocolReserved);
		Rsvd->OriginalPkt = Packet;
		MyPacket->Private.Flags = Flags;

		MyPacket->Private.Head = Packet->Private.Head;
		MyPacket->Private.Tail = Packet->Private.Tail;
		NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);

		//
		// Copy the OOB Offset from the original packet to the new
		// packet.
		//
		NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
					   NDIS_OOB_DATA_FROM_PACKET(Packet),
					   sizeof(NDIS_PACKET_OOB_DATA));

		//
		// Copy the per packet info into the new packet
		// This includes ClassificationHandle, etc.
		// Make sure other stuff is not copied !!!
		//
		NdisIMCopySendPerPacketInfo(MyPacket, Packet);
		
		//
		// Copy the Media specific information
		//
		NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
											&amp;MediaSpecificInfo,
											&amp;MediaSpecificInfoSize);

		if (MediaSpecificInfo || MediaSpecificInfoSize)
		{
			NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
												MediaSpecificInfo,
												MediaSpecificInfoSize);
		}


		NdisSend(&amp;Status,
				 pAdapt->BindingHandle,
				 MyPacket);


		if (Status != NDIS_STATUS_PENDING)
		{
			NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
			NdisFreePacket(MyPacket);
		}
	}
	else
	{
		//
		// We are out of packets. Silently drop it. Alternatively we can deal with it:
		//	- By keeping separate send and receive pools
		//	- Dynamically allocate more pools as needed and free them when not needed
		//
	}

	return(Status);
}


VOID
MPSendPackets(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	PPNDIS_PACKET			PacketArray,
	IN	UINT					NumberOfPackets
	)
/*++

Routine Description:

	Batched send-handler. TBD. Either this or the Send function can be specified but not both.
	LBFO - The Send will be done on the secondary miniport of the bundle

Arguments:

	MiniportAdapterContext	Pointer to our adapter
	PacketArray				Set of packets to send
	NumberOfPackets			Self-explanatory

Return Value:

	None

--*/
{
	PADAPT			pAdapt = (PADAPT)MiniportAdapterContext;
	NDIS_STATUS		Status;
	UINT			i;
	PVOID			MediaSpecificInfo = NULL;
	UINT			MediaSpecificInfoSize = 0;

	//
	//	Route all sends to the seondary, if no secondary exists, it will point to itself
	//
	pAdapt = pAdapt->pSecondaryAdapt;

	for (i = 0; i < NumberOfPackets; i++)
	{
		PRSVD			Rsvd;
		PNDIS_PACKET	Packet, MyPacket;

		Packet = PacketArray[i];

		if (IsIMDeviceStateOn(pAdapt) == FALSE)
		{
			Status = NDIS_STATUS_FAILURE;
			break;
		}

		NdisAllocatePacket(&amp;Status,
						   &amp;MyPacket,
						   pAdapt->SendPacketPoolHandle);

		if (Status == NDIS_STATUS_SUCCESS)
		{
			PNDIS_PACKET_EXTENSION	Old, New;

			Rsvd = (PRSVD)(MyPacket->ProtocolReserved);
			Rsvd->OriginalPkt = Packet;

			MyPacket->Private.Flags = NdisGetPacketFlags(Packet);

			MyPacket->Private.Head = Packet->Private.Head;
			MyPacket->Private.Tail = Packet->Private.Tail;
			NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);

			//
			// Copy the OOB Offset from the original packet to the new
			// packet.
			//
			NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
						   NDIS_OOB_DATA_FROM_PACKET(Packet),
						   sizeof(NDIS_PACKET_OOB_DATA));
			//
			// Copy the per packet info into the new packet
			// This includes ClassificationHandle, etc.
			// Make sure other stuff is not copied !!!
			//
			NdisIMCopySendPerPacketInfo(MyPacket, Packet);

			//
			// Copy the Media specific information
			//
			NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
												&amp;MediaSpecificInfo,
												&amp;MediaSpecificInfoSize);

			if (MediaSpecificInfo || MediaSpecificInfoSize)
			{
				NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
													MediaSpecificInfo,
													MediaSpecificInfoSize);
			}

			NdisSend(&amp;Status,
					 pAdapt->BindingHandle,
					 MyPacket);

			if (Status != NDIS_STATUS_PENDING)
			{
				NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
				NdisFreePacket(MyPacket);
			}
		}

		if (Status != NDIS_STATUS_PENDING)
		{
			//
			// We are out of packets. Silently drop it. Alternatively we can deal with it:
			//	- By keeping separate send and receive pools
			//	- Dynamically allocate more pools as needed and free them when not needed
			//
			NdisMSendComplete(pAdapt->pPrimaryAdapt->MiniportHandle,
							  Packet,
							  Status);

			// LBFO - Complete with the prmary's miniport handle
			// We should use the miniport handle that was used to call this function
		}
	}
}


NDIS_STATUS
MPQueryInformation(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	NDIS_OID				Oid,
	IN	PVOID					InformationBuffer,
	IN	ULONG					InformationBufferLength,
	OUT PULONG					BytesWritten,
	OUT PULONG					BytesNeeded
		)
/*++

Routine Description:

	Miniport QueryInfo handler.
	In the Power Management scenario, OID_PNP_QUERY_POWER is not sent to the underlying miniport.
	OID_PNP_CAPABILITES is passed as a request to the miniport below.
	If the result is a success then the InformationBuffer is filled in the MPQueryPNPCapabilites.

	LBFO - For present all queries are passed on to the miniports that they were requested on.

	PM- If the MP is not ON (DeviceState > D0) return immediately  (except for query power and set power)
         If MP is ON, but the PT is not at D0, then queue the queue the request for later processing

	Requests to miniports are always serialized

Arguments:

	MiniportAdapterContext	Pointer to the adapter structure
	Oid						Oid for this query
	InformationBuffer		Buffer for information
	InformationBufferLength	Size of this buffer
	BytesWritten			Specifies how much info is written
	BytesNeeded				In case the buffer is smaller than what we need, tell them how much is needed


Return Value:

	Return code from the NdisRequest below.

--*/
{
	PADAPT	pAdapt = (PADAPT)MiniportAdapterContext;
	NDIS_STATUS	Status = NDIS_STATUS_FAILURE;

	do
	{
		//
		// Return Success for this OID
		//
		if (Oid == OID_PNP_QUERY_POWER)
		{
			Status=NDIS_STATUS_SUCCESS;
			break;
		}

		//
		// All other queries are failed, if the miniport is not at D0
		//
		if (pAdapt->MPDeviceState > NdisDeviceStateD0 || pAdapt->StandingBy == TRUE)
		{
			Status = NDIS_STATUS_FAILURE;
			break;
		}
		//
		//	We are doing all sends on the secondary, so send all requests with Send OIDs to the Secondary
		//
		if (MPIsSendOID(Oid))
		{
			pAdapt = pAdapt->pSecondaryAdapt;
			//
			// Will point to itself, if there is no secondary (see initialization)
			//
		}

		pAdapt->Request.RequestType = NdisRequestQueryInformation;
		pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;
		pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
		pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
		pAdapt->BytesNeeded = BytesNeeded;
		pAdapt->BytesReadOrWritten = BytesWritten;
		pAdapt->OutstandingRequests = TRUE;

		//
		// if the Protocol device state is OFF, then the IM driver cannot send the request below and must pend it
		//
		if (pAdapt->PTDeviceState > NdisDeviceStateD0)
		{
			pAdapt->QueuedRequest = TRUE;
			Status = NDIS_STATUS_PENDING;
			break;
		}

		//
		// default case, most requests will be passed to the miniport below
		//
		NdisRequest(&amp;Status,
					pAdapt->BindingHandle,
					&amp;pAdapt->Request);


		//
		// If the Query was a success, pass the results back to the entity that made the request
		//
		if (Status == NDIS_STATUS_SUCCESS)
		{
			*BytesWritten = pAdapt->Request.DATA.QUERY_INFORMATION.BytesWritten;
			*BytesNeeded = pAdapt->Request.DATA.QUERY_INFORMATION.BytesNeeded;
		}

		//
		// Fill the buffer with the required values if Oid == OID_PNP_CAPABILITIES
		// and the query was successful
		//
		if (Oid  == OID_PNP_CAPABILITIES  &amp;&amp; Status == NDIS_STATUS_SUCCESS)
		{
			MPQueryPNPCapbilities(pAdapt,&amp;Status);
		}

		if (Status != NDIS_STATUS_PENDING)
		{
			pAdapt->OutstandingRequests = FALSE;
		}

	} while (FALSE);

	return(Status);

}


VOID
MPQueryPNPCapbilities(
	IN OUT	PADAPT			pAdapt,
	OUT		PNDIS_STATUS	pStatus
	)
/*++

Routine Description:

	Miniport QueryInfo OID_PNP_CAPAIBILITIES:
	If the Oid == Oid_PNP_CAPABILITIES, InformationBuffer is returned with all the fields
	assigned NdisDeviceStateUnspecified in the NDIS_PM_WAKE_UP_CAPABILITIES structure

	OID_QUERY_POWER_STATE is returned with NDIS_STATUS_SUCCESS and should never be passed below.

Arguments:

	MiniportAdapterContext	Pointer to the adapter structure
	Oid						Oid for this query
	InformationBuffer		Buffer for information
	InformationBufferLength	Size of this buffer
	BytesWritten			Specifies how much info is written
	BytesNeeded				In case the buffer is smaller than what we need, tell them how much is needed

Return Value:

	Return code from the NdisRequest below.

--*/

{
	PNDIS_PNP_CAPABILITIES			pPNPCapabilities;
	PNDIS_PM_WAKE_UP_CAPABILITIES	pPMstruct;

	if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES))
	{
		pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);

		//
		// Setting up the buffer to be returned to the Protocol above the Passthru miniport
		//
		pPMstruct= &amp; pPNPCapabilities->WakeUpCapabilities;
		pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
		pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
		pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
		*pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);
		*pAdapt->BytesNeeded = 0;


		//
		// Setting our internal flags
		// Default, device is ON
		//
		pAdapt->MPDeviceState = NdisDeviceStateD0;
		pAdapt->PTDeviceState = NdisDeviceStateD0;

		*pStatus = NDIS_STATUS_SUCCESS;
	}
	else
	{
		*pAdapt->BytesNeeded= sizeof(NDIS_PNP_CAPABILITIES);
		*pStatus = NDIS_STATUS_RESOURCES;
	}
}


NDIS_STATUS
MPSetInformation(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	NDIS_OID				Oid,
	IN	PVOID					InformationBuffer,
	IN	ULONG					InformationBufferLength,
	OUT PULONG					BytesRead,
	OUT PULONG					BytesNeeded
	)
/*++

Routine Description:

	Miniport SetInfo handler.

	In the case of OID_PNP_SET_POWER, record the power state and return the OID.	
	Do not pass below
	If the device is suspended, do not block the SET_POWER_OID 
	as it is used to reactivate the Passthru miniport

	
	PM- If the MP is not ON (DeviceState > D0) return immediately  (except for 'query power' and 'set power')
         If MP is ON, but the PT is not at D0, then queue the queue the request for later processing

	Requests to miniports are always serialized


Arguments:

	MiniportAdapterContext	Pointer to the adapter structure
	Oid						Oid for this query
	InformationBuffer		Buffer for information
	InformationBufferLength	Size of this buffer
	BytesRead				Specifies how much info is read
	BytesNeeded				In case the buffer is smaller than what we need, tell them how much is needed

Return Value:

	Return code from the NdisRequest below.

--*/
{
	PADAPT		pAdapt = (PADAPT)MiniportAdapterContext;
	NDIS_STATUS	Status;

	Status = NDIS_STATUS_FAILURE;

	do
	{
		//
		// The Set Power should not be sent to the miniport below the Passthru, but is handled internally
		//
		if (Oid == OID_PNP_SET_POWER)
		{
			MPProcessSetPowerOid( &amp;Status, 
			                       pAdapt, 
			                       InformationBuffer, 
			                       InformationBufferLength, 
			                       BytesRead, 
			                       BytesNeeded);
			break;

		}

		//
		// All other Set Information requests are failed, if the miniport is not at D0 or is transitioning to
		// a device state greater than D0
		//
		if (pAdapt->MPDeviceState > NdisDeviceStateD0 || pAdapt->StandingBy == TRUE)
		{
			Status = NDIS_STATUS_FAILURE;
			break;
		}


		// Set up the Request and return the result
		pAdapt->Request.RequestType = NdisRequestSetInformation;
		pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid;
		pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
		pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
		pAdapt->BytesNeeded = BytesNeeded;
		pAdapt->BytesReadOrWritten = BytesRead;
		pAdapt->OutstandingRequests = TRUE;


		//
		// if the Protocol device state is OFF, then the IM driver cannot send the request below and must pend it
		//
		if ( pAdapt->PTDeviceState > NdisDeviceStateD0)
		{
			pAdapt->QueuedRequest = TRUE;
			Status = NDIS_STATUS_PENDING;
			break;
		}

		NdisRequest(&amp;Status,
					pAdapt->BindingHandle,
					&amp;pAdapt->Request);


		if (Status == NDIS_STATUS_SUCCESS)
		{
			*BytesRead = pAdapt->Request.DATA.SET_INFORMATION.BytesRead;
			*BytesNeeded = pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded;
		}


		if (Status != NDIS_STATUS_PENDING)
		{
			pAdapt->OutstandingRequests = FALSE;
		}

	} while (FALSE);

	return(Status);
}


VOID
MPProcessSetPowerOid(
	IN OUT PNDIS_STATUS      pNdisStatus,
	IN  PADAPT					pAdapt,
	IN	PVOID					InformationBuffer,
	IN	ULONG					InformationBufferLength,
	OUT PULONG					BytesRead,
	OUT PULONG					BytesNeeded
    )
/*++

Routine Description:
	This routine does all the procssing for a request with a SetPower Oid
    The SampleIM miniport shoud accept  the Set Power and transition to the new state

    The Set Power should not be passed to the miniport below

    If the IM miniport is going into a low power state, then there is no guarantee if it will ever
    be asked go back to D0, before getting halted. No requests should be pended or queued.

	
Arguments:
	IN OUT PNDIS_STATUS      *pNdisStatus - Status of the operation
	IN  PADAPT					pAdapt,   - The Adapter structure
	IN	PVOID					InformationBuffer, - The New DeviceState
	IN	ULONG					InformationBufferLength,
	OUT PULONG					BytesRead, - No of bytes read
	OUT PULONG					BytesNeeded -  No of bytes needed


Return Value:
    Status  - NDIS_STATUS_SUCCESS if all the wait events succeed.
    

--*/

{

	
	NDIS_DEVICE_POWER_STATE NewDeviceState;

	DBGPRINT (&quot;==>MPProcessSetPowerOid&quot;); 
	ASSERT (InformationBuffer != NULL);

	NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);

	*pNdisStatus = NDIS_STATUS_FAILURE;

	do 
	{
		//
		// Check for invalid length
		//
		if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
		{
			*pNdisStatus = NDIS_STATUS_INVALID_LENGTH;
			break;
		}

		//
		// Check for invalid device state
		//
		if ((pAdapt->MPDeviceState > NdisDeviceStateD0) &amp;&amp; (NewDeviceState != NdisDeviceStateD0))
		{
			//
			// If the miniport is in a non-D0 state, the miniport can only receive a Set Power to D0
			//
			ASSERT (!(pAdapt->MPDeviceState > NdisDeviceStateD0) &amp;&amp; (NewDeviceState != NdisDeviceStateD0));

			*pNdisStatus = NDIS_STATUS_FAILURE;
			break;
		}	

		//
		// Is the miniport transitioning from an On (D0) state to an Low Power State (>D0)
		// If so, then set the StandingBy Flag - (Block all incoming requests)
		//
		if (pAdapt->MPDeviceState == NdisDeviceStateD0 &amp;&amp; NewDeviceState > NdisDeviceStateD0)
		{
			pAdapt->StandingBy = TRUE;
		}

		//
		// If the miniport is transitioning from a low power state to ON (D0), then clear the StandingBy flag
		// All incoming requests will be pended until the physical miniport turns ON.
		//
		if (pAdapt->MPDeviceState > NdisDeviceStateD0 &amp;&amp;  NewDeviceState == NdisDeviceStateD0)
		{
			pAdapt->StandingBy = FALSE;
		}
		
		//
		// Now update the state in the pAdapt structure;
		//
		pAdapt->MPDeviceState = NewDeviceState;
		
		*pNdisStatus = NDIS_STATUS_SUCCESS;
	

	} while (FALSE);	
		
	if (*pNdisStatus == NDIS_STATUS_SUCCESS)
	{
		*BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
		*BytesNeeded = 0;
	}
	else
	{
		*BytesRead = 0;
		*BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
	}

	DBGPRINT (&quot;<==MPProcessSetPowerOid&quot;); 
}







VOID
MPReturnPacket(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	PNDIS_PACKET			Packet
	)
/*++

Routine Description:


Arguments:


Return Value:


--*/
{
	PADAPT			pAdapt = (PADAPT)MiniportAdapterContext;
	PNDIS_PACKET	MyPacket;
	PRSVD			Resvd;

	Resvd = (PRSVD)(Packet->MiniportReserved);
	MyPacket = Resvd->OriginalPkt;

	NdisFreePacket(Packet);
	NdisReturnPackets(&amp;MyPacket, 1);
}


NDIS_STATUS
MPTransferData(
	OUT PNDIS_PACKET			Packet,
	OUT PUINT					BytesTransferred,
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	NDIS_HANDLE				MiniportReceiveContext,
	IN	UINT					ByteOffset,
	IN	UINT					BytesToTransfer
	)
/*++

Routine Description:

	Miniport's transfer data handler.

Arguments:

	Packet					Destination packet
	BytesTransferred		Place-holder for how much data was copied
	MiniportAdapterContext	Pointer to the adapter structure
	MiniportReceiveContext	Context
	ByteOffset				Offset into the packet for copying data
	BytesToTransfer			How much to copy.

Return Value:

	Status of transfer

--*/
{
	PADAPT		pAdapt = (PADAPT)MiniportAdapterContext;
	NDIS_STATUS	Status;

	//
	// Return, if the device is OFF
	//

	if (IsIMDeviceStateOn(pAdapt) == FALSE)
	{
		return NDIS_STATUS_FAILURE;
	}

	//
	// All receives are to be done on the primary, will point to itself
	//
	pAdapt = pAdapt->pPrimaryAdapt;


	NdisTransferData(&amp;Status,
					 pAdapt->BindingHandle,
					 MiniportReceiveContext,
					 ByteOffset,
					 BytesToTransfer,
					 Packet,
					 BytesTransferred);

	return(Status);
}

VOID
MPHalt(
	IN	NDIS_HANDLE				MiniportAdapterContext
	)
/*++

Routine Description:

	Halt handler. All the hard-work for clean-up is done here.
	LBFO - the current instance of the driver needs to be removed from the gloabal list

Arguments:

	MiniportAdapterContext	Pointer to the Adapter

Return Value:

	None.

--*/
{
	PADAPT			pAdapt = (PADAPT)MiniportAdapterContext;
	NDIS_STATUS		Status;
	PADAPT			pCursor, *ppCursor;
	PADAPT			pPromoteAdapt = NULL;
	KIRQL			OldIrql;

	DBGPRINT (&quot;==>Passthru MPHaltMiniport/n&quot;);

	//
	// Remove the pAdapt from our global list
	//
	// Acquire the lock and keep it untill all pointers to this pAdapt have been removed
	// from the linked list
	//
	KeAcquireSpinLock (&amp;pAdapt->SpinLock, &amp;OldIrql);

	//
	// Remove the padapt from the list
	//
	for (ppCursor = &amp;pAdaptList; *ppCursor != NULL; ppCursor = &amp;(*ppCursor)->Next)
	{
		if (*ppCursor == pAdapt)
		{
			*ppCursor = pAdapt->Next;
			break;
		}
	}

	//
	//	Remove all the pointers to pAdapt from our list
	//
	for (pCursor = pAdaptList; pCursor != NULL; pCursor = pCursor->Next)
	{
		//
		// Now pointers in our global list might become invalid. Checking for Primary
		//
		if (pCursor->pPrimaryAdapt == pAdapt)
		{
			ASSERT (pCursor->isSecondary == TRUE);

			//
			// Keep a pointer to the secondary that needs to be promoted, as it is now alone
			//
			pPromoteAdapt = pCursor;
		}

		//
		// Now checking for the secondary
		//
		if (pCursor->pSecondaryAdapt == pAdapt)
		{
			ASSERT(pCursor->isSecondary == FALSE); // Assert (pCursor is Primary);

			//
			// This is all we need to change in our internal structure, the rest of the pointers are not invalid
			//
			pCursor->pSecondaryAdapt = pCursor;
		}
	}

	KeReleaseSpinLock (&amp;pAdapt->SpinLock, OldIrql);

	//
	// If there is a miniport that needs to be promoted, promote it.
	// Call API outside of spin lock
	//
	if (pPromoteAdapt != NULL)
	{
		MPPromoteSecondary(pPromoteAdapt);
	}

	//
	// If we have a valid bind, close the miniport below the protocol
	//
	if (pAdapt->BindingHandle != NULL)
	{
		//
		// Close the binding below. and wait for it to complete
		//
		NdisResetEvent(&amp;pAdapt->Event);

		NdisCloseAdapter(&amp;Status, pAdapt->BindingHandle);

		if (Status == NDIS_STATUS_PENDING)
		{
			NdisWaitEvent(&amp;pAdapt->Event, 0);
			Status = pAdapt->Status;
		}

		ASSERT (Status == NDIS_STATUS_SUCCESS);

		pAdapt->BindingHandle = NULL;
	}


	//
	// Free the resources now
	//
	NdisFreePacketPool(pAdapt->SendPacketPoolHandle);
	NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);
	NdisFreeMemory(pAdapt->BundleUniString.Buffer, MAX_BUNDLEID_LENGTH,0);


	NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);

	DBGPRINT(&quot;<==Passthru Minport Halt/n&quot;);
}


NDIS_STATUS
MPReset(
	OUT PBOOLEAN				AddressingReset,
	IN	NDIS_HANDLE				MiniportAdapterContext
	)
/*++

Routine Description:

	Reset Handler. We just don't do anything.

Arguments:

	AddressingReset			To let NDIS know whether we need help from it with our reset
	MiniportAdapterContext	Pointer to our adapter

Return Value:


--*/
{
	PADAPT	pAdapt = (PADAPT)MiniportAdapterContext;

	DBGPRINT(&quot;<== Passthru Miniport Reset/n&quot;); ;

	*AddressingReset = FALSE;

	return(NDIS_STATUS_SUCCESS);
}


//
// The functions that do the LBFO work and bundling.
// If LBFO is turned off, then the Set Scondary API is never called and there are no bundles
//
NDIS_STATUS
MPBundleSearchAndSetSecondary(
	IN	PADAPT			pAdapt
	)
/*++

Routine Description:
	Go through the list of passthru structures and and search for an instantiation with a 
	matching bundleid and call MPSetMiniportSecondary on that structure

Arguments:

	pAdapt -	Should point to the structure that belolngs to the miniport 
				whose bundle id will be used in the search

Return Value:

	NDIS_STATUS_SUCCESS if not operation failed. This value is also returned event if 
	no new bundles are formed

--*/
{
	NDIS_STATUS						Status = NDIS_STATUS_FAILURE;
	NDIS_STRING						NoBundle = NDIS_STRING_CONST (&quot;<no-bundle>&quot;);
	PADAPT							pCursor	= NULL;
	PADAPT							pPrimary = NULL;
	KIRQL							OldIrql;

	do
	{
		//
		// If bundle == '<bundle id>' then this Passthru miniport will not be a part of any bundle
		//
		if (NdisEqualUnicodeString(&amp;NoBundle, &amp;pAdapt->BundleUniString, TRUE))
		{
			Status = NDIS_STATUS_SUCCESS;
			break;
		}

		//
		// If the Bundle Identifier is not present, ie. someone entered a NULL string,
		// this miniport will not be part of a bundle 
		//

		if (pAdapt->BundleUniString.Length == 0)
		{
			Status = NDIS_STATUS_SUCCESS;
			break;
		}

		//
		// Acquire the global pAdapt List lock
		//
		KeAcquireSpinLock (&amp;pAdapt->SpinLock, &amp;OldIrql);

		//
		// Searching through the global list for a Passthru with the same BundleId
		//
		for (pCursor = pAdaptList; pCursor != NULL; pCursor = pCursor->Next)
		{
			if (pCursor == pAdapt)
			{
				//
				//	Skip to next Passthru, if the cursor is pointing to me
				//
				continue;
			}

			//
			// Do a case insenstive match, if matches, set current pAdapt as secondary
			//
			if (NdisEqualUnicodeString(&amp;pCursor->BundleUniString, &amp;pAdapt->BundleUniString, TRUE))
			{

				//
				// Making sure this is a primary of a bundle
				//
				ASSERT (pCursor->pSecondaryAdapt == pCursor &amp;&amp; pCursor->isSecondary == FALSE);

				pPrimary = pCursor;

				break;
			}
		}

		//
		//	Release the lock, and also bring down our Irql
		//
		KeReleaseSpinLock (&amp;pAdapt->SpinLock, OldIrql);

		//
		//	Call our Set Secondary function, do not call at DISPATCH_LEVEL
		//
		if (pPrimary != NULL)
		{
			Status = MPSetMiniportSecondary (pAdapt, pPrimary);

			ASSERT (Status == NDIS_STATUS_SUCCESS);
		}

		//
		//	We successsfully completed our search through the list, event if I did not find any bundles
		//
		Status = NDIS_STATUS_SUCCESS;

	} while (FALSE) ;

	return Status;
}


NDIS_STATUS
MPSetMiniportSecondary (
	IN	PADAPT		Secondary,
	IN	PADAPT		Primary
	)
/*++

Routine Description:
	Call the Ndis API to set the bundle and modify internal variables to keep track of the change


Arguments:

	Secondary Should point to the structure that points to the Secondary miniport
	Primary  Should point to the structure that points to the Primary miniport

Return Value:

	NDIS_STATUS_SUCCESS if there miniport was successfully made the secondary of the primary

--*/
{
	NDIS_STATUS	Status = NDIS_STATUS_SUCCESS;

	//
	//	ensure that the 'to be' primary is not part of another bundle
	//
	ASSERT (Primary != Secondary);
	ASSERT (Primary->isSecondary == 0);
	ASSERT (Primary->pSecondaryAdapt == Primary);

#ifdef __LBFO

	DBGPRINT (&quot;Calling NdisMSetSecondary API on the two handles/n&quot;);

	Status = NdisMSetMiniportSecondary(Secondary->MiniportHandle,
									   Primary->MiniportHandle);

	ASSERT (Status == NDIS_STATUS_SUCCESS);

	if (Status == NDIS_STATUS_SUCCESS)
	{
		//
		// Initialize the LBFO variables, to record the current state.
		//
		//
		Secondary->isSecondary = TRUE;
		Secondary->pPrimaryAdapt = Primary;
		Primary->pSecondaryAdapt = Secondary;

		//
		// Making sure that the other internal state variables have the correct value
		//
		Secondary->pSecondaryAdapt = Secondary;
		Primary->pPrimaryAdapt = Primary;
		Primary->isSecondary = FALSE;
	}

#endif

	return Status;
}


NDIS_STATUS
MPPromoteSecondary(
	IN	PADAPT		pAdapt
	)
/*++

Routine Description:

	Does the Passthru book keeping to promote a
	Passthru instantiation from a secondary to a primary miniport

Arguments:

	pAdapt - Pointer to the internal adapter structure

Return Value:

	NDIS_STATUS_SUCCESS - if success

	Otherwise the return value of the NdisMPromoteMiniport API
--*/
{
	NDIS_STATUS Status;

	DBGPRINT (&quot;==> MPPromoteMiniport/n&quot;);

	Status = NdisMPromoteMiniport(pAdapt->MiniportHandle);


	ASSERT (Status == NDIS_STATUS_SUCCESS);

	if (Status == NDIS_STATUS_SUCCESS)
	{
		pAdapt->isSecondary = FALSE;

		pAdapt->pPrimaryAdapt = pAdapt;

		pAdapt->pSecondaryAdapt = pAdapt;
	}

	DBGPRINT (&quot;<== MPPromoteMiniport/n&quot;);

	return Status;
}


BOOLEAN
MPIsSendOID (
	IN	NDIS_OID	Oid
	)
/*++

Routine Description:

		Indicates if an OID should be routed to the Send miniport. Right now, the list comprises of those OIDs which drivers
		running ethernet must support (See General Objects in the DDK). In this implementation, all OIDS are Query Oids


Arguments:

		Oid - The oid in question
Return Value:
		True  if Oid should be sent to the Send miniport
		False if Oid should be sent to the Receive miniport - default

--*/
{
	BOOLEAN fIsSend = FALSE;	//default : it is a receive  OID

	switch (Oid)
	{
		//
		// If OID needs to be sent to the Send miniport, set the boolean flag
		//
		case OID_GEN_TRANSMIT_BUFFER_SPACE :
		case OID_GEN_TRANSMIT_BLOCK_SIZE :
		case OID_GEN_MAXIMUM_TOTAL_SIZE :

		//
		// OIds used to collect transmission statistics
		//
		case OID_GEN_XMIT_OK :
		case OID_GEN_XMIT_ERROR :
		case OID_GEN_DIRECTED_BYTES_XMIT :
		case OID_GEN_DIRECTED_FRAMES_XMIT :
		case OID_GEN_MULTICAST_BYTES_XMIT :
		case OID_GEN_MULTICAST_FRAMES_XMIT :
		case OID_GEN_BROADCAST_BYTES_XMIT :
		case OID_GEN_BROADCAST_FRAMES_XMIT :
		case OID_GEN_TRANSMIT_QUEUE_LENGTH :
			fIsSend = TRUE;
			break;

		default:
			fIsSend = FALSE;
			break;
	}

	return fIsSend;
}
 
代码:
/*++
Module Name:
	protocol.c
--*/


#include &quot;precomp.h&quot;
#include &quot;util.h&quot;
#include &quot;cons_def.h&quot;

#pragma hdrstop

#define MAX_PACKET_POOL_SIZE 0x0000FFFF
#define MIN_PACKET_POOL_SIZE 0x000000FF
//extern FAST_MUTEX	fw_mutex;

VOID
PtBindAdapter(
	OUT PNDIS_STATUS			Status,
	IN  NDIS_HANDLE				BindContext,
	IN  PNDIS_STRING			DeviceName,
	IN  PVOID					SystemSpecific1,
	IN  PVOID					SystemSpecific2
	)
{
	NDIS_HANDLE						ConfigHandle = NULL;
	PNDIS_CONFIGURATION_PARAMETER	Param;
	NDIS_STRING						DeviceStr = NDIS_STRING_CONST(&quot;UpperBindings&quot;);
	PADAPT							pAdapt = NULL;
	NDIS_STATUS						Sts;
	UINT							MediumIndex;

	PNDIS_CONFIGURATION_PARAMETER	BundleParam;
	NDIS_STRING						BundleStr = NDIS_STRING_CONST(&quot;BundleId&quot;);
	NDIS_STATUS						BundleStatus;
	
	DBGPRINT(&quot;==> Passthru Protocol Initialize/n&quot;);

	do
	{
		//
		// Start off by opening the config section and reading our instance which we want
		// to export for this binding
		//
		NdisOpenProtocolConfiguration(Status,
		  							 &amp;ConfigHandle,
		  							 SystemSpecific1);
		if (*Status != NDIS_STATUS_SUCCESS)
		{
		  	break;
		}

		NdisReadConfiguration(Status,
							  &amp;Param,
		  					  ConfigHandle,
		  					  &amp;DeviceStr,
		  					  NdisParameterString);
		if (*Status != NDIS_STATUS_SUCCESS)
		{
		  	break;
		}

		//
		// Allocate memory for the Adapter structure. This represents both as the protocol-context
		// as well as the adapter structure when the miniport is initialized.
		//
		NdisAllocateMemoryWithTag(&amp;pAdapt, sizeof(ADAPT), TAG);

		if (pAdapt == NULL)
		{
			*Status = NDIS_STATUS_RESOURCES;
		  	break;
		}

		//
		// Initialize the adapter structure
		//
		NdisZeroMemory(pAdapt, sizeof(ADAPT));

		//
		// Store the String used by the registry, this will be used in reading data from the registry
		//
		NdisAllocateMemoryWithTag( &amp;(pAdapt->BundleUniString.Buffer), MAX_BUNDLEID_LENGTH ,TAG);

		if (pAdapt->BundleUniString.Buffer == NULL)
		{
		  	*Status = NDIS_STATUS_RESOURCES;
		  	break;
		}

		pAdapt->BundleUniString.MaximumLength = MAX_BUNDLEID_LENGTH ;

		NdisReadConfiguration(&amp;BundleStatus,
		  					  &amp;BundleParam,
							  ConfigHandle,
		  					  &amp;BundleStr,
		  					  NdisParameterString);

		if (BundleStatus == NDIS_STATUS_SUCCESS)
		{
		  	//
		  	// Copy the bundle identifier to our own memory
		  	//
		  	ASSERT(pAdapt->BundleUniString.MaximumLength  >= BundleParam->ParameterData.StringData.Length);

		  	pAdapt->BundleUniString.Length = BundleParam->ParameterData.StringData.Length;

		  	RtlCopyUnicodeString(&amp;pAdapt->BundleUniString, &amp;BundleParam->ParameterData.StringData);
		}
		else 
		{
			//
			//	We do not have a bundle id entry in the registry. To play safe we will enter 
			//	make the escape sequence the Bundle Id, This ensures that no bundle id's are 
			//	spuriously formed
			//

			NDIS_STRING NoBundle = NDIS_STRING_CONST (&quot;<no-bundle>&quot;);

			RtlCopyUnicodeString(&amp;pAdapt->BundleUniString, &amp;NoBundle);
		}

		//
		//	Initializing the Event and the lock
		//
		NdisInitializeEvent(&amp;pAdapt->Event);

		KeInitializeSpinLock(&amp;pAdapt->SpinLock);

		//
		// Allocate a packet pool for sends. We need this to pass sends down. We cannot use the same
		// packet descriptor that came down to our send handler
		//
		NdisAllocatePacketPoolEx(Status,
		  						 &amp;pAdapt->SendPacketPoolHandle,
		  						 MIN_PACKET_POOL_SIZE,
		  						 MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
		  						 sizeof(RSVD));

		if (*Status != NDIS_STATUS_SUCCESS)
		{
		  	break;
		}

		//
		// Allocate a packet pool for receives. We need this to indicate receives. Same consideration
		// as sends
		//
		NdisAllocatePacketPoolEx(Status,
		  						 &amp;pAdapt->RecvPacketPoolHandle,
		  						 MIN_PACKET_POOL_SIZE,
		  						 MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
		  						 sizeof(RSVD));

		if (*Status != NDIS_STATUS_SUCCESS)
		{
		  	break;
		}



		//
		// Now open the adapter below and complete the initialization
		//
		NdisOpenAdapter(Status,
		  				&amp;Sts,
		  				&amp;pAdapt->BindingHandle,
		  				&amp;MediumIndex,
		  				MediumArray,
		  				sizeof(MediumArray)/sizeof(NDIS_MEDIUM),
		  				ProtHandle,
		  				pAdapt,
		  				DeviceName,
		  				0,
		  				NULL);

		if(*Status == NDIS_STATUS_PENDING)
		{
		  	NdisWaitEvent(&amp;pAdapt->Event, 0);
		  	*Status = pAdapt->Status;
		}

		if(*Status != NDIS_STATUS_SUCCESS)
		{
		  	break;
		}

		pAdapt->Medium = MediumArray[MediumIndex];

		//
		// Now ask NDIS to initialize our miniport
		//
		NdisIMInitializeDeviceInstanceEx(DriverHandle,
  										 &amp;Param->ParameterData.StringData,
  										 pAdapt);

	

	} while(FALSE);

	if (ConfigHandle != NULL)
	{
		NdisCloseConfiguration(ConfigHandle);
	}

	if (*Status != NDIS_STATUS_SUCCESS)
	{
		if (pAdapt != NULL)
		{
			if (pAdapt->SendPacketPoolHandle != NULL)
			{
				 NdisFreePacketPool(pAdapt->SendPacketPoolHandle);
			}

			if (pAdapt->RecvPacketPoolHandle != NULL)
			{
				 NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);
			}

			NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
		}
	}


	DBGPRINT(&quot;<== Passthru Protocol Initialize/n&quot;);
}


VOID
PtOpenAdapterComplete(
	IN  NDIS_HANDLE			 ProtocolBindingContext,
	IN  NDIS_STATUS			 Status,
	IN  NDIS_STATUS			 OpenErrorStatus
	)
{
	PADAPT	  pAdapt =(PADAPT)ProtocolBindingContext;

	DBGPRINT(&quot;==> Passthru PtOpenAdapterComplete/n&quot;);
	pAdapt->Status = Status;
	NdisSetEvent(&amp;pAdapt->Event);
}


VOID
PtUnbindAdapter(
	OUT PNDIS_STATUS		Status,
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  NDIS_HANDLE			UnbindContext
	)
{
	PADAPT		 pAdapt =(PADAPT)ProtocolBindingContext;
	NDIS_HANDLE BindingHandle = pAdapt->BindingHandle;

	DBGPRINT(&quot;==> Passthru PtUnbindAdapter/n&quot;);

	if (pAdapt->QueuedRequest == TRUE)
	{
		pAdapt->QueuedRequest = FALSE;

		PtRequestComplete (pAdapt,
		                 &amp;pAdapt->Request,
		                 NDIS_STATUS_FAILURE );

	}
	//
	// Call NDIS to remove our device-instance. We do most of the work inside the HaltHandler
	//
	// The Handle will be Null if the passthru's miniport Halt Handler has been called or
	// If the IM device was never initialized
	//


	
	if(pAdapt->MiniportHandle != NULL)
	{
		*Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);

		if(*Status != NDIS_STATUS_SUCCESS)
		{
			*Status = NDIS_STATUS_FAILURE;
		}
	}
	else
	{
		//
		// We need to do some work here. 
		// Close the binding below us 
		// and release the memory allocated.
		//
		if(pAdapt->BindingHandle != NULL)
		{
			NdisResetEvent(&amp;pAdapt->Event);

			NdisCloseAdapter(Status, pAdapt->BindingHandle);

			//
			// Wait for it to complete
			//
			if(*Status == NDIS_STATUS_PENDING)
			{
				 NdisWaitEvent(&amp;pAdapt->Event, 0);
				 *Status = pAdapt->Status;
			}
		}
		else
		{
			//
			// Both Our MiniportHandle and Binding Handle  should not be NULL.
			//
			*Status = NDIS_STATUS_FAILURE;
			ASSERT(0);
		}

		//
		//	Free the memory here, if was not released earlier(by calling the HaltHandler)
		//
		NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
	}

	DBGPRINT(&quot;<==Passthru UnbindAdapter/n&quot;);
}


VOID
PtUnload(
	IN	PDRIVER_OBJECT		DriverObject
	)
{
	NDIS_STATUS Status;
	NdisDeregisterProtocol(&amp;Status, ProtHandle);
}


VOID
PtCloseAdapterComplete(
	IN	NDIS_HANDLE			ProtocolBindingContext,
	IN	NDIS_STATUS			Status
	)
{
	PADAPT	  pAdapt =(PADAPT)ProtocolBindingContext;

	pAdapt->Status = Status;
	NdisSetEvent(&amp;pAdapt->Event);
}


VOID
PtResetComplete(
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  NDIS_STATUS			Status
	)
{
	PADAPT	pAdapt =(PADAPT)ProtocolBindingContext;

	//
	// We never issue a reset, so we should not be here.
	//
	ASSERT(0);
}


VOID
PtRequestComplete(
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  PNDIS_REQUEST		NdisRequest,
	IN  NDIS_STATUS			Status
	)
{
	PADAPT		pAdapt =(PADAPT)ProtocolBindingContext;
	NDIS_OID	Oid =	pAdapt->Request.DATA.SET_INFORMATION.Oid ;

	//
	//	Change to the pAdapt for which the request originated
	//
	if(MPIsSendOID(Oid))
	{
		  pAdapt = pAdapt->pPrimaryAdapt;
		  //
		  // Will point to itself if there is no bundle(see initialization)
		  //
	}


	//
	// Since our request is not outstanding anymore
	//
	pAdapt->OutstandingRequests = FALSE;

	//
	// Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.
	//
	switch(NdisRequest->RequestType)
	{
	  case NdisRequestQueryInformation:

		  //
		  // This should not have been passsed to the miniport below us
		  //
		  ASSERT(Oid != OID_PNP_QUERY_POWER);

		  //
		  // If oid == OID_PNP_CAPABILITIES and query was successsful
		  // then fill the buffer with the required values
		  //
		  if(Oid == OID_PNP_CAPABILITIES &amp;&amp; Status == NDIS_STATUS_SUCCESS)
		  {

				MPQueryPNPCapbilities(pAdapt,&amp;Status);

		  }

		  *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;

		  *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;

		  NdisMQueryInformationComplete(pAdapt->MiniportHandle,
												  Status);
		  break;

	  case NdisRequestSetInformation:

		  ASSERT( Oid != OID_PNP_SET_POWER);

		  *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
		  *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
		  NdisMSetInformationComplete(pAdapt->MiniportHandle,
												Status);
		  break;

	  default:
		  ASSERT(0);
		  break;
	}
	
}


VOID
PtStatus(
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  NDIS_STATUS			GeneralStatus,
	IN  PVOID				StatusBuffer,
	IN  UINT				StatusBufferSize
	)
{
	PADAPT	  pAdapt =(PADAPT)ProtocolBindingContext;

	//
	// If we get a status indication before our miniport is initialized, ignore it
	// If the SampleIM is not ON, we do not pass on the status indication
	//
	if(pAdapt->MiniportHandle != NULL  &amp;&amp;
	  pAdapt->MPDeviceState == NdisDeviceStateD0 &amp;&amp;
	  pAdapt->PTDeviceState == NdisDeviceStateD0 )	
	{
		  NdisMIndicateStatus(pAdapt->MiniportHandle,
									 GeneralStatus,
									 StatusBuffer,
									 StatusBufferSize);
	}
}


VOID
PtStatusComplete(
	IN	NDIS_HANDLE			ProtocolBindingContext
	)
{
	PADAPT	  pAdapt =(PADAPT)ProtocolBindingContext;

	//
	// If we get a status indication before our miniport is initialized, ignore it
	//
	if(pAdapt->MiniportHandle != NULL  &amp;&amp;
	  pAdapt->MPDeviceState == NdisDeviceStateD0 &amp;&amp;
	  pAdapt->PTDeviceState == NdisDeviceStateD0 )	
	{
		  NdisMIndicateStatusComplete(pAdapt->MiniportHandle);
	}
}


VOID
PtSendComplete(
	IN	NDIS_HANDLE			ProtocolBindingContext,
	IN  PNDIS_PACKET		Packet,
	IN  NDIS_STATUS			Status
	)
{
	PADAPT			pAdapt =(PADAPT)ProtocolBindingContext;
	PNDIS_PACKET	Pkt;
	PRSVD			Rsvd;

	//
	// Returning the Send on the Primary, will point to itself if there is no bundle
	//
	pAdapt = pAdapt->pPrimaryAdapt;

	Rsvd =(PRSVD)(Packet->ProtocolReserved);
	Pkt = Rsvd->OriginalPkt;


	NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);

	NdisDprFreePacket(Packet);

	NdisMSendComplete(pAdapt->MiniportHandle,
							 Pkt,
							 Status);
}


VOID
PtTransferDataComplete(
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  PNDIS_PACKET		Packet,
	IN  NDIS_STATUS			Status,
	IN  UINT				BytesTransferred
	)
{
	PADAPT	  pAdapt =(PADAPT)ProtocolBindingContext;

	//
	// Returning the Send on the Primary, will point to itself if there is no LBFO
	//
	pAdapt = pAdapt->pPrimaryAdapt;

	if(pAdapt->MiniportHandle)
	{
		  NdisMTransferDataComplete(pAdapt->MiniportHandle,
											 Packet,
											 Status,
											 BytesTransferred);
	}
}


NDIS_STATUS
PtReceive(
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  NDIS_HANDLE			MacReceiveContext,
	IN  PVOID				HeaderBuffer,
	IN  UINT				HeaderBufferSize,
	IN  PVOID				LookAheadBuffer,
	IN  UINT				LookAheadBufferSize,
	IN  UINT				PacketSize
	)
/*++

Routine Description:
LBFO - need to use primary for all receives

Arguments:


Return Value:

--*/
{
	PADAPT			pAdapt =(PADAPT)ProtocolBindingContext;
	PNDIS_PACKET	MyPacket, Packet;
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;
	//add by df
	KIRQL oldirql;
	UCHAR			nMatch;
	
	if(!pAdapt->MiniportHandle)
	{
		Status = NDIS_STATUS_FAILURE;
	}
	else do
	{
		//
		// We should not be getting Receives on a Secondary, this is just specific to our  LBFO driver
		//

		if(pAdapt->isSecondary)
		{
			 DBGPRINT(&quot;PASSTHRU GETTING RECIEVES ON SECONDARY/n&quot;);
			 ASSERT(0);
		}

		//
		// If this was indicated by the miniport below as a packet, then get that packet pointer and indicate
		// it as a packet as well(with appropriate status). This way the OOB stuff is accessible to the
		// transport above us.
		//
		Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
		if(Packet != NULL)
		{
			 //
			 // Get a packet off the pool and indicate that up
			 //
			 NdisDprAllocatePacket(&amp;Status,
										  &amp;MyPacket,
										  pAdapt->RecvPacketPoolHandle);

			 if(Status == NDIS_STATUS_SUCCESS)
			 {
				  MyPacket->Private.Head = Packet->Private.Head;
				  MyPacket->Private.Tail = Packet->Private.Tail;

				  //
				  // Get the original packet(it could be the same packet as one received or a different one
				  // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
				  // correctly at the top.
				  //
				  NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
				  NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);

				  //
				  // Set Packet Flags
				  //
				  NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
				  
				//-----------------------------------------------------------add by qsc
				 
					//ExAcquireFastMutex(&amp;fw_mutex);	//add by df
					//ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
					//KeRaiseIrql(DISPATCH_LEVEL, &amp;oldirql);
					
					nMatch=UTIL_MatchRule(MyPacket, DT_IN);

					//KeLowerIrql(oldirql);
					//ExReleaseFastMutex(&amp;fw_mutex); 	//add by df

					if(nMatch==DENY)
						return NDIS_STATUS_SUCCESS;

				//----------------------------------------------------------------------end add

				  //
				  // Make sure the status is set to NDIS_STATUS_RESOURCES.
				  //
				  NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);

				  NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &amp;MyPacket, 1);

				  ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
				  NdisDprFreePacket(MyPacket);
				  break;
			 }
		}

		//
		// Fall through if the miniport below us has either not indicated a packet or we could not
		// allocate one
		//
		pAdapt->IndicateRcvComplete = TRUE;
		switch(pAdapt->Medium)
		{
		  case NdisMedium802_3:
			 NdisMEthIndicateReceive(pAdapt->MiniportHandle,
											 MacReceiveContext,
											 HeaderBuffer,
											 HeaderBufferSize,
											 LookAheadBuffer,
											 LookAheadBufferSize,
											 PacketSize);
			 break;

		  case NdisMedium802_5:
			 NdisMTrIndicateReceive(pAdapt->MiniportHandle,
											MacReceiveContext,
											HeaderBuffer,
											HeaderBufferSize,
											LookAheadBuffer,
											LookAheadBufferSize,
											PacketSize);
			 break;

		  case NdisMediumFddi:
			 NdisMFddiIndicateReceive(pAdapt->MiniportHandle,
											  MacReceiveContext,
											  HeaderBuffer,
											  HeaderBufferSize,
											  LookAheadBuffer,
											  LookAheadBufferSize,
											  PacketSize);
			 break;

		  default:
			 ASSERT(0);
			 break;
		}

	} while(FALSE);

	return Status;
}


VOID
PtReceiveComplete(
	IN	NDIS_HANDLE		ProtocolBindingContext
	)
/*++

Routine Description:

	Called by the adapter below us when it is done indicating a batch of received buffers.

Arguments:

	ProtocolBindingContext	Pointer to our adapter structure.

Return Value:

	None

--*/
{
	PADAPT		pAdapt =(PADAPT)ProtocolBindingContext;

	//
	// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
	//
	if(pAdapt->isSecondary)
	{
		  DBGPRINT(&quot;PASSTHRU GETTING RECEIVES ON SECONDARY/n&quot;);
		  ASSERT(0);
	}

	if((pAdapt->MiniportHandle != NULL) &amp;&amp; pAdapt->IndicateRcvComplete)
	{
		switch(pAdapt->Medium)
		{
		  case NdisMedium802_3:
			NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);
			break;

		  case NdisMedium802_5:
			NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);
			break;

		  case NdisMediumFddi:
			NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);
			break;

		  default:
			ASSERT(0);
			break;
		}
	}
	pAdapt->IndicateRcvComplete = FALSE;
}


INT
PtReceivePacket(
	IN	NDIS_HANDLE			ProtocolBindingContext,
	IN	PNDIS_PACKET		Packet
	)
/*++

Routine Description:

	ReceivePacket handler. Called up by the miniport below when it supports NDIS 4.0 style receives.
	Re-package the packet and hand it back to NDIS for protocols above us. The re-package part is
	important since NDIS uses the WrapperReserved part of the packet for its own book-keeping. Also
	the re-packaging works differently when packets flow-up or down. In the up-path(here) the protocol
	reserved is owned by the protocol above. We need to use the miniport reserved here.

Arguments:

	ProtocolBindingContext	Pointer to our adapter structure.
	Packet - Pointer to the packet

Return Value:

	== 0 -> We are done with the packet
	!= 0 -> We will keep the packet and call NdisReturnPackets() this many times when done.
--*/
{
	PADAPT			pAdapt =(PADAPT)ProtocolBindingContext;
	NDIS_STATUS	Status;
	PNDIS_PACKET	MyPacket;
	PRSVD			Resvd;
	UCHAR			nMatch;

	//add by df
	KIRQL oldirql;
	
	if(!pAdapt->MiniportHandle)
	{
		  return 0;
	}

	//
	// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
	//
	if(pAdapt->isSecondary)
	{
		  DBGPRINT(&quot;PASSTHRU GETTING RECEIVES ON SECONDARY/n&quot;);
		  ASSERT(0);
	}




//-----------------------------------------------------------add by qsc
 
	//ExAcquireFastMutex(&amp;fw_mutex);	//add by df
	//ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
	//KeRaiseIrql(DISPATCH_LEVEL, &amp;oldirql);
	
	nMatch=UTIL_MatchRule(Packet, DT_IN);

	//KeLowerIrql(oldirql);
	//ExReleaseFastMutex(&amp;fw_mutex); 	//add by df

	if(nMatch==DENY)
		return NDIS_STATUS_SUCCESS;

//----------------------------------------------------------------------end add


	//
	// Get a packet off the pool and indicate that up
	//
	NdisDprAllocatePacket(&amp;Status,
						   &amp;MyPacket,
						   pAdapt->RecvPacketPoolHandle);

	if(Status == NDIS_STATUS_SUCCESS)
	{
		Resvd =(PRSVD)(MyPacket->MiniportReserved);
		Resvd->OriginalPkt = Packet;

		MyPacket->Private.Head = Packet->Private.Head;
		MyPacket->Private.Tail = Packet->Private.Tail;

		//
		// Get the original packet(it could be the same packet as one received or a different one
		// based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
		// correctly at the top.
		//
		NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));

		//
		// Set Packet Flags
		//
		NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

		Status = NDIS_GET_PACKET_STATUS(Packet);

		NDIS_SET_PACKET_STATUS(MyPacket, Status);
		NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));

		NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &amp;MyPacket, 1);

		if(Status == NDIS_STATUS_RESOURCES)
		{
		  NdisDprFreePacket(MyPacket);
		}

		return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
	}
	else
	{
		  //
		  // We are out of packets. Silently drop it. Alternatively we can deal with it:
		  //	- By keeping separate send and receive pools
		  //	- Dynamically allocate more pools as needed and free them when not needed
		  //
		  return(0);
	}
}




NDIS_STATUS
PtPNPHandler(
	IN	NDIS_HANDLE		ProtocolBindingContext,
	IN	PNET_PNP_EVENT	pNetPnPEvent
	)

/*++
Routine Description:

	This is the Protocol PNP handlers. All PNP Related OIDS(requests) are routed to this function
	If the Power of the SetPower PNP Event is received, then the new power state is copied to
	the internal state of the Passthru driver. Need to complete all sends and requests before
	returning from this	function.

Arguments:

	ProtocolBindingContext	Pointer to our adapter structure.
	pNetPnPEvent Pointer to a Net_PnP_Event

Return Value:

	NDIS_STATUS_SUCCESS: as we do not do much here

--*/
{
	PADAPT			pAdapt  =(PADAPT)ProtocolBindingContext;
	NDIS_STATUS	Status  = NDIS_STATUS_SUCCESS;

	DBGPRINT (&quot;PtPnPHandler&quot;);

	//
	// This will happen when all entities in the system need to be notified
	//

	switch(pNetPnPEvent->NetEvent)
	{
	 case  NetEventSetPower :
	    Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);
	    break;

	 case NetEventReconfigure :
	    Status  = PtPnPNetEventReconfigure(pAdapt, (PCWSTR)pNetPnPEvent->Buffer);
	    break;

	 default :
	    Status  = NDIS_STATUS_SUCCESS;
	    break;
	}

	return Status;
}

NDIS_STATUS
PtPnPNetEventReconfigure(
	IN	PADAPT			pAdapt,
	IN	PCWSTR			pBundleString
	)
{
	NDIS_STATUS	BundleStatus = NDIS_STATUS_SUCCESS;
	NDIS_STRING NewBundleUniString;
	

	if(pAdapt == NULL)
	{
		NdisReEnumerateProtocolBindings (ProtHandle);		
		return BundleStatus;
	}

	if (pBundleString == NULL)
	{
		return BundleStatus;
	}

	NdisInitUnicodeString( &amp;NewBundleUniString, pBundleString);


	do
	{
	   //
	   // If the bundle Identifier was not changed, do not do anything
	   //
	   if(NdisEqualUnicodeString(&amp;NewBundleUniString, &amp;pAdapt->BundleUniString, TRUE))
	   {
	  	   break;
	   }

	   //
	   // We have a new bundle id , copy it and do the necessary bundling work
	   //
	   RtlCopyUnicodeString(&amp;pAdapt->BundleUniString , &amp;NewBundleUniString);

	   //
	   //  If we are part of a bundle and our bundle id was changed, either the primary or the secondary
	   //  will get promoted
	   //  If we are the secondary of a bundle promote ourselves
	   //
	   if(pAdapt->isSecondary)
	   {
			PADAPT pPrimaryAdapt = pAdapt->pPrimaryAdapt;

			BundleStatus = MPPromoteSecondary(pAdapt);

			if(BundleStatus != NDIS_STATUS_SUCCESS)
			{
				 ASSERT(0);
				 break;
			}

			//
			// resetting all the internal variables of the primary Adapter structure
			//
			pPrimaryAdapt->pPrimaryAdapt = pPrimaryAdapt;
			pPrimaryAdapt->pSecondaryAdapt = pPrimaryAdapt;
			pPrimaryAdapt->isSecondary = FALSE;
	   }
	   else
	   {
			//
			// The BundleId has changed. If we are the primary of a bundle,
			// then we need to promote the secondary
			//
			if(pAdapt->pSecondaryAdapt != pAdapt)
			{
				BundleStatus = MPPromoteSecondary(pAdapt->pSecondaryAdapt);
				if(BundleStatus != NDIS_STATUS_SUCCESS)
				{
				     ASSERT(0);
				     break;
				}

				//
				// resetting all our internal variables
				//
				pAdapt->pSecondaryAdapt  = pAdapt;
				pAdapt->pPrimaryAdapt = pAdapt;
				pAdapt->isSecondary = FALSE ;
			}
	   }

	   //
	   //	Now we need to see if the new bundle ID makes the Passthru part of another bundle
	   //	If so. then set the current pAdapt as the secondary
	   //
	   BundleStatus = MPBundleSearchAndSetSecondary(pAdapt);

	} while(FALSE) ;

	DBGPRINT(&quot;<==PtPNPNetEventReconfigure/n&quot;);

	return BundleStatus;
}





NDIS_STATUS
PtPnPNetEventSetPower(
	IN	PADAPT			pAdapt,
	IN  PNET_PNP_EVENT	pNetPnPEvent
	)
/*++
Routine Description:

	Sets the PowerState to the required level. Waits for all outstanding Sends and requests to complete

Arguments:

	pAdapt			-	Pointer to the adpater structure
	pNetPnpEvent	-	The Net Pnp Event. this contains the new device state

Return Value:

	NDIS_STATUS_SUCCESS: If the device successfully changed its power state


--*/
{
	PNDIS_DEVICE_POWER_STATE	pDeviceState  =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
	NDIS_DEVICE_POWER_STATE		PrevDeviceState = pAdapt->PTDeviceState;  
	NDIS_STATUS					Status ;
	

	//
	// Set the Internal Device State, this blocks all new sends or receives
	//
	pAdapt->PTDeviceState = *pDeviceState;

	//
	// if we are being sent to standby, block for outstanding requests and sends
	//
	if(*pDeviceState > NdisDeviceStateD0)
	{
	   //
	   // If the physical miniport is going to standby, fail all incoming requests
	   //
	   if (PrevDeviceState == NdisDeviceStateD0)
	   {
           pAdapt->StandingBy = TRUE;
	   }

	   while(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) != 0)
	   {
	  	   //
	  	   // sleep till outstanding sends complete
	  	   //
	  	   NdisMSleep(10);
	   }

	   while(pAdapt->OutstandingRequests == TRUE)
	   {
	  	   //
	  	   // sleep till outstanding requests complete
	  	   //
	  	   NdisMSleep(10);
	   }

	   ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);
	   ASSERT(pAdapt->OutstandingRequests == FALSE);
	}
	else
	{
		//
		// The protocol is being turned on. A pending request must be completed
		//
		if (pAdapt->QueuedRequest == TRUE)
		{

			pAdapt->QueuedRequest = FALSE;

			NdisRequest(&amp;Status,
			           pAdapt->BindingHandle,
			           &amp;pAdapt->Request);

			//
			// The underlying miniport completed the request synchronously, the IM
			// needs to complete the request which it had pended earlier
			//

			if (Status != NDIS_STATUS_PENDING)
			{
				PtRequestComplete(pAdapt,
			    	            &amp;pAdapt->Request,
			        	        Status);
			}

		}

		//
		// If the physical miniport is powering up (from Low power state to D0), 
		// clear the flag
		//
		if (PrevDeviceState > NdisDeviceStateD0)
		{
			pAdapt->StandingBy = FALSE;
		}


	}

	Status = NDIS_STATUS_SUCCESS;

	return Status;
}
 
代码:
#include &quot;precomp.h&quot;
#include &quot;fw_rule.h&quot;
#include &quot;util.h&quot;
#include &quot;DDKLBLInc.h&quot;
#include &quot;cons_def.h&quot;
#include &quot;fw_interface.h&quot;

#include &quot;driver.h&quot;

#define DEVICE_NAME	L&quot;//Device//DOGFW&quot;
#define DOSDEVICE_NAME L&quot;//DosDevices//DOGFW&quot;

#pragma hdrstop

#pragma NDIS_INIT_FUNCTION(DriverEntry)

NDIS_PHYSICAL_ADDRESS	HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
NDIS_HANDLE				ProtHandle = NULL;
NDIS_HANDLE				DriverHandle = NULL;
NDIS_MEDIUM				MediumArray[3] =
{
	NdisMedium802_3,	// Ethernet
	NdisMedium802_5,	// Token-ring
	NdisMediumFddi		// Fddi
};

PADAPT					pAdaptList=NULL;
PDEVICE_OBJECT			g_DeviceObject = NULL;
NDIS_HANDLE				g_NdisDeviceHandle = NULL;

struct Fw_Rules			g_Rules;
struct Statistics		g_stat;
struct ip 				g_IPHeader,		*g_pIPHeader=NULL;
struct tcphdr			g_TCPHeader,	*g_pTCPHeader=NULL;
struct udphdr			g_UDPHeader,	*g_pUDPHeader=NULL;
struct icmp				g_ICMPHeader,	*g_pICMPHeader=NULL;

struct All_Alarms 		g_AllAlarm[MAX_CALL_NUM];
struct All_Logs			g_AllLog[MAX_CALL_NUM];

PFILE_OBJECT 			g_alarmfop=NULL;
PDEVICE_EXTENSION 		g_alarmpdx=NULL;
PFILE_OBJECT 			g_logfop=NULL;
PDEVICE_EXTENSION 		g_logpdx=NULL;

//FAST_MUTEX  fw_mutex;

extern USHORT	lcall_num,acall_num;

NTSTATUS
DefaultDispatch(
				IN PDEVICE_OBJECT DeviceObject,
				IN PIRP Irp
				)
{
	PIO_STACK_LOCATION	IrpStack;
	ULONG	ControlCode;
	ULONG	InputLength, OutputLength;

	IrpStack=IoGetCurrentIrpStackLocation(Irp);
	ControlCode=IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputLength=IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputLength=IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	Irp->IoStatus.Status=STATUS_SUCCESS;
	Irp->IoStatus.Information=0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}


NTSTATUS
DeviceIoDispatch(
				 IN PDEVICE_OBJECT DeviceObject,
				 IN PIRP Irp
				 )
{
	PIO_STACK_LOCATION	IrpStack;
	ULONG	ControlCode;
	ULONG	InputLength, OutputLength;
	
	//add by df
	struct All_Rules		*pallrules=NULL;
	struct Proto_Restrict	*pprotocol=NULL;
	struct Time_Restrict	*pschedule=NULL;

	struct All_Alarms		*pallalarm=NULL;
	struct All_Logs			*palllog=NULL;
	struct Statistics		*pstat=NULL;
	
	PVOID					chkbuf=NULL;
	ULONG					info=0;
	NTSTATUS				status;
	
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

	IrpStack	=IoGetCurrentIrpStackLocation(Irp);
	ControlCode	=IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputLength	=IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputLength=IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
/*
	KdPrint((&quot;ControlCode=%d InputLength=%d OutputLength=%d&quot;,
		      ControlCode,
			  InputLength,
			  InputLength));
*/
	switch(ControlCode)
	{
	case IOCTL_DOGFW_CTL_FW_STATUS:				//char *fw_status
		//KdPrint((&quot;IOCTL_DOGFW_CTL_FW_STATUS Begin&quot;));
		//ExAcquireFastMutex(&amp;fw_mutex);
		if (InputLength < sizeof(char))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		g_Rules.global.fw_status=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
		info=sizeof(char);
		status=STATUS_SUCCESS;
		//KdPrint((&quot;IOCTL_DOGFW_CTL_FW_STATUS end&quot;));
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_CTL_LOG:					//char *log_enable
		//ExAcquireFastMutex(&amp;fw_mutex);
		if (InputLength < sizeof(char))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		g_Rules.global.log_enable=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
		info=sizeof(char);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_CTL_WARN:					//char *warn_enable
		//ExAcquireFastMutex(&amp;fw_mutex);
		if (InputLength < sizeof(char))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		g_Rules.global.warn_enable=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
		info=sizeof(char);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_CTL_SCHEDULE:				//struct Time_Restrict *schedule
		//ExAcquireFastMutex(&amp;fw_mutex);
		if (InputLength < sizeof(struct Time_Restrict))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		pschedule=(struct Time_Restrict *)Irp->AssociatedIrp.SystemBuffer;
		g_Rules.global.schedule.enable		=pschedule->time_enable;
		g_Rules.global.schedule.start_time	=pschedule->start_time;
		g_Rules.global.schedule.end_time	=pschedule->end_time;
		info=sizeof(struct Time_Restrict);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_CTL_FWMODE:				//char *fw_mode
		//ExAcquireFastMutex(&amp;fw_mutex);
		if (InputLength < sizeof(char))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		g_Rules.global.fw_mode=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
		info=sizeof(char);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_CTL_PROTOCOL:				//struct Proto_Restrict *protocol
		//ExAcquireFastMutex(&amp;fw_mutex);
		if (InputLength < sizeof(struct Proto_Restrict))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}
		pprotocol=(struct Proto_Restrict *)Irp->AssociatedIrp.SystemBuffer;
		g_Rules.tcp.enable			=pprotocol->tcp_enable;
		g_Rules.udp.enable			=pprotocol->udp_enable;
		g_Rules.icmp.enable			=pprotocol->icmp_enable;
		g_Rules.ip.enable			=pprotocol->restip_enable;
		info=sizeof(struct Proto_Restrict);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_CTL_CHKDATA:				
		chkbuf=(PVOID)Irp->AssociatedIrp.SystemBuffer;
		UTIL_AddKeyword(chkbuf,InputLength,1);
		info=InputLength;
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_CTL_URLDATA:				
		chkbuf=(PVOID)Irp->AssociatedIrp.SystemBuffer;
		UTIL_AddKeyword(chkbuf,InputLength,0);
		info=InputLength;
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_CTL_TCPURLDATA:				
		chkbuf=(PVOID)Irp->AssociatedIrp.SystemBuffer;
		UTIL_AddKeyword(chkbuf,InputLength,2);
		info=InputLength;
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_CTL_DELCHKDATA:
		UTIL_DelKeyword();
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_CTL_DELURLDATA:
		UTIL_DelURLWord();
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_CTL_DELTCPURLDATA:
		UTIL_DelTCPURLWord();
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_CTL_FLUXCTRL:				//struct Flux_Control *flux
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_RULE_ADD:
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_RULE_DEL:
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_RULE_CHANGE:
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_RULE_ADDALL:				//struct All_Rules *all_rule
		//KdPrint((&quot;IOCTL_DOGFW_RULE_ADDALL Begin&quot;)); 
		//ExAcquireFastMutex(&amp;fw_mutex);
		if (InputLength < sizeof(struct All_Rules))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}

		pallrules=(struct All_Rules *)Irp->AssociatedIrp.SystemBuffer;
		if (pallrules->rules_num>MAX_RULE_NUM)
		{
			status=STATUS_UNSUCCESSFUL;			//number of rules are too much
			break;
		}
		//if g_rules not NULL, delete all
		UTIL_DelAllrules();
		UTIL_AddAllrules(pallrules);
		info=sizeof(struct All_Rules);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);

		//KdPrint((&quot;IOCTL_DOGFW_RULE_ADDALL end&quot;)); 
		break;

	case IOCTL_DOGFW_RULE_DELALL:				//none
		//KdPrint((&quot;IOCTL_DOGFW_RULE_DELALL Begin&quot;));  
		//ExAcquireFastMutex(&amp;fw_mutex);
		UTIL_DelAllrules();
		status=STATUS_SUCCESS;

		//KdPrint((&quot;IOCTL_DOGFW_RULE_DELALL End&quot;)); 
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_RULE_READ:
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_STAT_READ:					//see in test app sample
		//ExAcquireFastMutex(&amp;fw_mutex);
		pstat=(struct Statistics *)Irp->AssociatedIrp.SystemBuffer;
		memcpy((void *)pstat,(void *)&amp;g_stat,sizeof(struct Statistics));
		info=sizeof(struct Statistics);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_LOG_READ:
		//ExAcquireFastMutex(&amp;fw_mutex);
		palllog=(struct All_Logs *)Irp->AssociatedIrp.SystemBuffer;
		if (lcall_num==0)
			memcpy((void *)palllog,(void *)&amp;g_AllLog[2],sizeof(struct All_Logs));
		else
			memcpy((void *)palllog,(void *)&amp;g_AllLog[lcall_num-1],sizeof(struct All_Logs));
		info=sizeof(struct All_Logs);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_DOGFW_ALARM_READ:
		//ExAcquireFastMutex(&amp;fw_mutex);
		pallalarm=(struct All_Alarms *)Irp->AssociatedIrp.SystemBuffer;
		if (acall_num==0)
			memcpy((void *)pallalarm,(void *)&amp;g_AllAlarm[2],sizeof(struct All_Alarms));
		else
			memcpy((void *)pallalarm,(void *)&amp;g_AllAlarm[acall_num-1],sizeof(struct All_Alarms));
		info=sizeof(struct All_Alarms);
		status=STATUS_SUCCESS;
		//ExReleaseFastMutex(&amp;fw_mutex);
		break;

	case IOCTL_REGISTER_ALARM_EVENT:				// code == 0x8012
		{					
			//ExAcquireFastMutex(&amp;fw_mutex);
			if (InputLength < sizeof(HANDLE))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			if (!RegisterEvent(pdx, IrpStack->FileObject, *(PHANDLE) Irp->AssociatedIrp.SystemBuffer, UserMode, E_ALARM))
			{
				status = STATUS_UNSUCCESSFUL;
				break;
			}
			info=sizeof(HANDLE);
			status=STATUS_SUCCESS;
			//ExReleaseFastMutex(&amp;fw_mutex);
			break;
		}						

	case IOCTL_REGISTER_LOG_EVENT:					// code == 0x8013
		{						
			//ExAcquireFastMutex(&amp;fw_mutex);
			if (InputLength < sizeof(HANDLE))
			{
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			if (!RegisterEvent(pdx, IrpStack->FileObject, *(PHANDLE) Irp->AssociatedIrp.SystemBuffer, UserMode, E_LOG))
			{
				status = STATUS_UNSUCCESSFUL;
				break;
			}
			info=sizeof(HANDLE);
			status=STATUS_SUCCESS;
			//ExReleaseFastMutex(&amp;fw_mutex);
			break;
		}						

	case IOCTL_DOGFW_LOG_CALLBACK:					//see in test app sample
		status=STATUS_SUCCESS;
		break;

	case IOCTL_DOGFW_ALARM_CALLBACK:				//see in test app sample
	default:
		status=STATUS_SUCCESS;
		break;
	}

	CompleteRequest(Irp,status,info);
	return status;
}


NTSTATUS
DriverEntry(
			IN	PDRIVER_OBJECT		DriverObject,
			IN	PUNICODE_STRING		RegistryPath
			)
{
	NDIS_STATUS						Status;
	NDIS_PROTOCOL_CHARACTERISTICS	PChars;
	NDIS_MINIPORT_CHARACTERISTICS	MChars;
	PNDIS_CONFIGURATION_PARAMETER	Param;
	NDIS_STRING						Name;
	NDIS_HANDLE						WrapperHandle;
	PDRIVER_DISPATCH				MajorFunc[IRP_MJ_MAXIMUM_FUNCTION+1];
	UNICODE_STRING					DeviceName, DosDeviceName;
	PDEVICE_EXTENSION 				pdx;
	int i;

	DbgPrint((&quot;DriverEntry------------------------------------/n&quot;));

	RtlInitUnicodeString(&amp;DeviceName, DEVICE_NAME);
	RtlInitUnicodeString(&amp;DosDeviceName, DOSDEVICE_NAME);
	//ExInitializeFastMutex(&amp;fw_mutex);

	//
	// Register the miniport with NDIS. Note that it is the miniport
	// which was started as a driver and not the protocol. Also the miniport
	// must be registered prior to the protocol since the protocol's BindAdapter
	// handler can be initiated anytime and when it is, it must be ready to
	// start driver instances.
	//
	NdisMInitializeWrapper(&amp;WrapperHandle, DriverObject, RegistryPath, NULL);

	NdisZeroMemory(&amp;MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));

	MChars.MajorNdisVersion = 4;
	MChars.MinorNdisVersion = 0;

	MChars.InitializeHandler = MPInitialize;
	MChars.QueryInformationHandler = MPQueryInformation;
	MChars.SetInformationHandler = MPSetInformation;
	MChars.ResetHandler = MPReset;
	MChars.TransferDataHandler = MPTransferData;
	MChars.HaltHandler = MPHalt;

	//
	// We will disable the check for hang timeout so we do not
	// need a check for hang handler!
	//
	MChars.CheckForHangHandler = NULL;
	MChars.SendHandler = MPSend;
	MChars.ReturnPacketHandler = MPReturnPacket;

	//
	// Either the Send or the SendPackets handler should be specified.
	// If SendPackets handler is specified, SendHandler is ignored
	//
	// MChars.SendPacketsHandler = MPSendPackets;

	Status = NdisIMRegisterLayeredMiniport(WrapperHandle,
		&amp;MChars,
		sizeof(MChars),
		&amp;DriverHandle);
	ASSERT(Status == NDIS_STATUS_SUCCESS);

	NdisMRegisterUnloadHandler(WrapperHandle, PtUnload);

	//
	// Now register the protocol.
	//
	NdisZeroMemory(&amp;PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
	PChars.MajorNdisVersion = 4;
	PChars.MinorNdisVersion = 0;

	//
	// Make sure the protocol-name matches the service-name under which this protocol is installed.
	// This is needed to ensure that NDIS can correctly determine the binding and call us to bind
	// to miniports below.
	//
	NdisInitUnicodeString(&amp;Name, L&quot;SFilter&quot;);	// Protocol name
	PChars.Name = Name;
	PChars.OpenAdapterCompleteHandler	= PtOpenAdapterComplete;
	PChars.CloseAdapterCompleteHandler	= PtCloseAdapterComplete;
	PChars.SendCompleteHandler			= PtSendComplete;
	PChars.TransferDataCompleteHandler	= PtTransferDataComplete;

	PChars.ResetCompleteHandler			= PtResetComplete;
	PChars.RequestCompleteHandler		= PtRequestComplete;
	PChars.ReceiveHandler				= PtReceive;
	PChars.ReceiveCompleteHandler		= PtReceiveComplete;
	PChars.StatusHandler				= PtStatus;
	PChars.StatusCompleteHandler		= PtStatusComplete;
	PChars.BindAdapterHandler			= PtBindAdapter;
	PChars.UnbindAdapterHandler			= PtUnbindAdapter;
	PChars.UnloadHandler				= NULL;
	PChars.ReceivePacketHandler			= PtReceivePacket;
	PChars.PnPEventHandler				= PtPNPHandler;

	NdisRegisterProtocol(&amp;Status,
		&amp;ProtHandle,
		&amp;PChars,
		sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

	ASSERT(Status == NDIS_STATUS_SUCCESS);

	NdisIMAssociateMiniport(DriverHandle, ProtHandle);

	for(i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
		MajorFunc[i]=DefaultDispatch;

	MajorFunc[IRP_MJ_CREATE] = DispatchCreate;
	MajorFunc[IRP_MJ_CLOSE] = DispatchClose;
	MajorFunc[IRP_MJ_DEVICE_CONTROL]=DeviceIoDispatch;

	NdisMRegisterDevice(
		WrapperHandle,
		&amp;DeviceName,
		&amp;DosDeviceName,
		MajorFunc,
		&amp;g_DeviceObject,
		&amp;g_NdisDeviceHandle
		);

	pdx = (PDEVICE_EXTENSION) g_DeviceObject->DeviceExtension;
	pdx->DeviceObject=g_DeviceObject;
	InitializeListHead(&amp;pdx->hlist);
	KeInitializeSpinLock(&amp;pdx->lockHandles);
	//IoInitializeRemoveLock(&amp;pdx->RemoveLock, 0, 0, 0);
	g_DeviceObject->Flags&amp;= ~DO_DEVICE_INITIALIZING;	//hear of ....

	RtlFillMemory(&amp;g_Rules,sizeof(g_Rules),0);
	RtlFillMemory(&amp;g_stat,sizeof(g_stat),0);

	g_pIPHeader					=&amp;g_IPHeader;
	g_pTCPHeader				=&amp;g_TCPHeader;
	g_pUDPHeader				=&amp;g_UDPHeader;
	g_pICMPHeader				=&amp;g_ICMPHeader;
	g_Rules.global.pkeylist		=NULL;
	g_Rules.global.fw_status	=FWS_ALLOWALL;
	g_Rules.icmp.enable			=1;
	g_Rules.tcp.enable			=1;
	g_Rules.udp.enable			=1;
	g_Rules.ip.enable			=1;

	return(Status);
}
 
这个是比较核心的拦截模块,呵呵,直接用国外的代码,估计搞delphi的接触C比较少,加上了中文注释。
代码:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES

#define MODULE_NAME &quot;UTIL&quot;
#include &quot;precomp.h&quot;
#include &quot;DDKLBLInc.h&quot;
#include &quot;cons_def.h&quot;
#include &quot;fw_rule.h&quot;
#include &quot;PCAENET.H&quot;
#include &quot;fw_interface.h&quot;
#include &quot;driver.h&quot;
#include <math.h>
#include <stdlib.h>

extern struct Fw_Rules 		g_Rules;
extern struct Statistics	g_stat;
extern struct ip 			*g_pIPHeader;
extern struct tcphdr		*g_pTCPHeader;
extern struct udphdr		*g_pUDPHeader;
extern struct icmp			*g_pICMPHeader;

extern struct All_Alarms	g_AllAlarm[MAX_CALL_NUM];
extern struct All_Logs		g_AllLog[MAX_CALL_NUM];

extern PFILE_OBJECT 		g_alarmfop;
extern PDEVICE_EXTENSION 	g_alarmpdx;
extern PFILE_OBJECT 		g_logfop;
extern PDEVICE_EXTENSION 	g_logpdx;

USHORT  alarm_num=0,log_num=0,acall_num=0,lcall_num=0;
//
// Force undef of VTOOLSD For Windows 98 DDK Build
// -----------------------------------------------
// See comments in PCAIPLCE.H.
//
#ifdef NO_VTOOLSD
#undef VTOOLSD
#endif

#ifndef VTOOLSD // For Windows 98 DDK Build
//#include <vmm.h>
//#pragma VxD_LOCKED_DATA_SEG
//#pragma VxD_LOCKED_CODE_SEG

//#define isprint(c) (((c) >= 0x20) &amp;&amp; ((c) < 0x80))
#endif

void*  UTIL_AllocateMemory(unsigned int size)
{
	PVOID ptr=NULL;
	ptr=ExAllocatePool(NonPagedPool , size);
	
	return ptr;
}

void  UTIL_FreeMemory(void* p)
{
	if (p)
		ExFreePool(p);
}

/////////////////////////////////////////////////////////////////////////////
//// UTIL_ReadOnPacket
//
// Purpose
// Logical read on the packet data in a NDIS_PACKET.
//
// Parameters
//
// Return Value
//
// Remarks
// The purpose of this function is to provide a convienient mechanism to
// read packet data from an NDIS_PACKET that may have multiple chained
// NDIS_BUFFERs.
//


VOID
UTIL_ReadOnPacket(
				  PNDIS_PACKET Packet,
				  PUCHAR lpBuffer,
				  ULONG nNumberOfBytesToRead,
				  ULONG nOffset,                // Byte Offset, Starting With MAC Header
				  PULONG lpNumberOfBytesRead
				  )
{
	PNDIS_BUFFER    CurrentBuffer;
	UINT            nBufferCount, TotalPacketLength;
	PUCHAR          VirtualAddress;
	UINT            CurrentLength, CurrentOffset;
	UINT            AmountToMove;
	
	*lpNumberOfBytesRead = 0;
	if (!nNumberOfBytesToRead)
		return;
	
	//
	// Query Packet
	//
	NdisQueryPacket(
		(PNDIS_PACKET )Packet,
		(PUINT )NULL,           // Physical Buffer Count
		(PUINT )&amp;nBufferCount,  // Buffer Count
		&amp;CurrentBuffer,         // First Buffer
		&amp;TotalPacketLength      // TotalPacketLength
		);
	
	//
	// Query The First Buffer
	//
	NdisQueryBuffer(
		CurrentBuffer,
		&amp;VirtualAddress,
		&amp;CurrentLength
		);
	
	CurrentOffset = 0;
	
	while( nOffset || nNumberOfBytesToRead )
	{
		while( !CurrentLength )
		{
			NdisGetNextBuffer(
				CurrentBuffer,
				&amp;CurrentBuffer
				);
			
			// If we've reached the end of the packet.  We return with what
			// we've done so far (which must be shorter than requested).
			if (!CurrentBuffer)
				return;
			
			NdisQueryBuffer(
				CurrentBuffer,
				&amp;VirtualAddress,
				&amp;CurrentLength
				);
			
			CurrentOffset = 0;
		}
		
		if( nOffset )
		{
			// Compute how much data to move from this fragment
			if( CurrentLength > nOffset )
				CurrentOffset = nOffset;
			else
				CurrentOffset = CurrentLength;
			
			nOffset -= CurrentOffset;
			CurrentLength -= CurrentOffset;
		}
		
		if( nOffset )
		{
			CurrentLength = 0;
			continue;
		}
		
		if( !CurrentLength )
		{
			continue;
		}
		
		// Compute how much data to move from this fragment
		if (CurrentLength > nNumberOfBytesToRead)
			AmountToMove = nNumberOfBytesToRead;
		else
			AmountToMove = CurrentLength;
		
		// Copy the data.
		NdisMoveMemory(
			lpBuffer,
			&amp;VirtualAddress[ CurrentOffset ],
			AmountToMove
			);
		
		// Update destination pointer
		lpBuffer += AmountToMove;
		
		// Update counters
		*lpNumberOfBytesRead +=AmountToMove;
		nNumberOfBytesToRead -=AmountToMove;
		CurrentLength = 0;
	}
}

/////////////////////////////////////////////////////////////////////////////
//// UTIL_htonl
//
// Purpose
// Converts a ULONG from host to network byte order.
//
// Parameters
//
// Return Value
//
// Remarks
// ATTENTION!!! Must revise for non-Intel (Alpha) hosts.
//
// Why isn't this function named simply &quot;htonl&quot;? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//

ULONG UTIL_htonl( ULONG hostlong )
{
	PUCHAR pBuffer;
	ULONG	nResult;
	UCHAR	c, *pResult;
	
	pBuffer = (PUCHAR )&amp;hostlong;
	
	if( !pBuffer )
	{
		return( 0L );
	}
	
	pResult = (UCHAR * )&amp;nResult;
	
	c = ((UCHAR * )pBuffer)[ 0 ];
	((UCHAR * )pResult)[ 0 ] = ((UCHAR * )pBuffer)[ 3 ];
	((UCHAR * )pResult)[ 3 ] = c;
	
	c = ((UCHAR * )pBuffer)[ 1 ];
	((UCHAR * )pResult)[ 1 ] = ((UCHAR * )pBuffer)[ 2 ];
	((UCHAR * )pResult)[ 2 ] = c;
	
	return( nResult );
}


/////////////////////////////////////////////////////////////////////////////
//// UTIL_htons
//
// Purpose
// Converts a USHORT from host to network byte order.
//
// Parameters
//
// Return Value
//
// Remarks
// ATTENTION!!! Must revise for non-Intel (Alpha) hosts.
//
// Why isn't this function named simply &quot;htons&quot;? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//

USHORT UTIL_htons( USHORT hostshort )
{
	PUCHAR	pBuffer;
	USHORT	nResult;
	
	nResult = 0;
	pBuffer = (PUCHAR )&amp;hostshort;
	
	nResult = ( (pBuffer[ 0 ] << 8) &amp; 0xFF00 )
		| ( pBuffer[ 1 ] &amp; 0x00FF );
	
	return( nResult );
}

/////////////////////////////////////////////////////////////////////////////
//// UTIL_ntohl
//
// Purpose
// Converts a ULONG from network to host byte order.
//
// Parameters
//
// Return Value
//
// Remarks
//
// Why isn't this function named simply &quot;ntohl&quot;? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//

ULONG UTIL_ntohl( ULONG netlong )
{
	return( UTIL_htonl( netlong ) );
}

/////////////////////////////////////////////////////////////////////////////
//// UTIL_ntohs
//
// Purpose
// Converts a USHORT from network to host byte order.
//
// Parameters
//
// Return Value
//
// Remarks
//
// Why isn't this function named simply &quot;ntohs&quot;? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//

USHORT UTIL_ntohs( USHORT netshort )
{
	return( UTIL_htons( netshort ) );
}


/////////////////////////////////////////////////////////////////////////////
//// in_cksum
//
// Purpose
// Standard Internet Protocol checksum routine.
//
// Parameters
//
// Return Value
//
// Remarks
// ICMP, IGMP, UDP and TCP all use the same checksum algorithm
//

USHORT in_cksum( PUCHAR pStartingByte, int nByteCount )
{
	register ULONG sum = 0;
	register PUSHORT addr = (PUSHORT )pStartingByte;
	
	//
	// Add 16-bit Words
	//
	while (nByteCount > 1)
	{
		//
		// This Is The Inner Loop
		//
		sum += *(addr++);
		nByteCount -= 2;
	}
	
	//
	// Add leftover byte, if any
	//
	if (nByteCount > 0)
#if BIG_ENDIAN
		sum += (*(PUCHAR )addr) << 8;
#else
	sum += *(PUCHAR )addr;
#endif
	
	//
	// Fold 32-bit sum to 16-bit
	//
	while (sum >> 16)
		sum = (sum &amp; 0xffff) + (sum >> 16);
	
	//
	// Return one's compliment of final sum.
	//
	return (USHORT) ~sum;
}


/////////////////////////////////////////////////////////////////
//  
//函数UTIL_CountPacket
//
//参数
//方向、动作
//
//返回值
//无
//
//
//备注
//统计在in、out方向上允许或禁止的包。in(0)、out(1)、allow(0)
//deny(1)

void UTIL_CountPacket (USHORT ptype,char direct,char action,int packsize)
{
/*
if 方向为in {
if 动作为允许  统计结构累计
if 动作为禁止  统计结构累计
}
if 方向为out {
if 动作为允许  统计结构累计
if 动作为禁止  统计结构累计
}
	*/
	if (direct==DT_IN)
	{
		if (action==ALLOW)
		{
			switch (ptype)
			{
			case PT_TCP:
				g_stat.ip.tcp.allow_in_bytes+=packsize;
				g_stat.ip.tcp.allow_in_pkts++;
				break;
			case PT_UDP:
				g_stat.ip.udp.allow_in_bytes+=packsize;
				g_stat.ip.udp.allow_in_pkts++;
				break;
			case PT_ICMP:
				g_stat.ip.icmp.allow_in_bytes+=packsize;
				g_stat.ip.icmp.allow_in_pkts++;
				break;
			case PT_RESTIP:
				g_stat.ip.restip.allow_in_bytes+=packsize;
				g_stat.ip.restip.allow_in_pkts++;
				break;
			default:
				g_stat.notip.other_stat.allow_in_bytes+=packsize;
				g_stat.notip.other_stat.allow_in_pkts++;
			}
		}
		if (action==DENY)
		{
			switch (ptype)
			{
			case PT_TCP:
				g_stat.ip.tcp.deny_in_bytes+=packsize;
				g_stat.ip.tcp.deny_in_pkts++;
				break;
			case PT_UDP:
				g_stat.ip.udp.deny_in_bytes+=packsize;
				g_stat.ip.udp.deny_in_pkts++;
				break;
			case PT_ICMP:
				g_stat.ip.icmp.deny_in_bytes+=packsize;
				g_stat.ip.icmp.deny_in_pkts++;
				break;
			case PT_RESTIP:
				g_stat.ip.restip.deny_in_bytes+=packsize;
				g_stat.ip.restip.deny_in_pkts++;
				break;
			default:
				g_stat.notip.other_stat.deny_in_bytes+=packsize;
				g_stat.notip.other_stat.deny_in_pkts++;
			}
		}
	}
	if (direct==DT_OUT)
	{
		if (action==ALLOW)
		{
			switch (ptype)
			{
			case PT_TCP:
				g_stat.ip.tcp.allow_out_bytes+=packsize;
				g_stat.ip.tcp.allow_out_pkts++;
				break;
			case PT_UDP:
				g_stat.ip.udp.allow_out_bytes+=packsize;
				g_stat.ip.udp.allow_out_pkts++;
				break;
			case PT_ICMP:
				g_stat.ip.icmp.allow_out_bytes+=packsize;
				g_stat.ip.icmp.allow_out_pkts++;
				break;
			case PT_RESTIP:
				g_stat.ip.restip.allow_out_bytes+=packsize;
				g_stat.ip.restip.allow_out_pkts++;
				break;
			default:
				g_stat.notip.other_stat.allow_out_bytes+=packsize;
				g_stat.notip.other_stat.allow_out_pkts++;
			}
		}
		if (action==DENY)
		{
			switch (ptype)
			{
			case PT_TCP:
				g_stat.ip.tcp.deny_out_bytes+=packsize;
				g_stat.ip.tcp.deny_out_pkts++;
				break;
			case PT_UDP:
				g_stat.ip.udp.deny_out_bytes+=packsize;
				g_stat.ip.udp.deny_out_pkts++;
				break;
			case PT_ICMP:
				g_stat.ip.icmp.deny_out_bytes+=packsize;
				g_stat.ip.icmp.deny_out_pkts++;
				break;
			case PT_RESTIP:
				g_stat.ip.restip.deny_out_bytes+=packsize;
				g_stat.ip.restip.deny_out_pkts++;
				break;
			default:
				g_stat.notip.other_stat.deny_out_bytes+=packsize;
				g_stat.notip.other_stat.deny_out_pkts++;
			}
		}
	}
	
}

/////////////////////////////////////////////////////////////////
//  
//函数UTIL_WriteLog
//
//参数
//USHORT ID,struct ip cur_ip
//
//返回值
//无
//
//
//备注
//在IOCTL中加入SETLOGADDRESS,传入回调函数地址,并得到当前线程号。
//在此函数中调用 _VWIN32_QueueUserApc() 调用应用程序函数。


void UTIL_TcpWriteLog(
					  struct Fw_Rule_Node *pTcpRule,
					  struct ip *piphdr,
					  struct tcphdr *ptcphdr
					  )
{
	g_AllLog[lcall_num].logs[log_num].ID=pTcpRule->ID;
	g_AllLog[lcall_num].log_num=log_num+1;
	g_AllLog[lcall_num].protocol=PT_TCP;
	memcpy((void *)&amp;g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	memcpy((void *)&amp;g_AllLog[lcall_num].logs[log_num].log_trans_pkt.tcp_pkt,(void *)ptcphdr,sizeof(struct tcphdr));
	if ((log_num+1)>=MAX_LOG_NUM)
	{
		if (g_logfop &amp;&amp; g_logpdx)
			SignalEvent(g_logpdx,g_logfop);
		log_num=0;
		lcall_num++;
		if (lcall_num>=MAX_CALL_NUM)
			lcall_num=0;
	}
	else
	{
		log_num++;
	}
}

/////////////////////////////////////////////////////////////////
//  
//函数UTIL_Alarm
//
//参数
//USHORT ID,struct ip cur_ip
//
//返回值
//无
//
//
//备注
//在IOCTL中加入SETALARMADDRESS,传入回调函数地址,并得到当前线程号。
//在此函数中调用 _VWIN32_QueueUserApc() 调用应用程序函数。

void UTIL_TcpAlarm(
				   struct Fw_Rule_Node *pTcpRule,
				   struct ip *piphdr,
				   struct tcphdr *ptcphdr
				   )
{
	g_AllAlarm[acall_num].Alarms[alarm_num].ID=pTcpRule->ID;
	g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_TCP;
	g_AllAlarm[acall_num].alarm_num=alarm_num+1;
	memcpy((void *)&amp;g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	memcpy((void *)&amp;g_AllAlarm[acall_num].Alarms[alarm_num].alarm_trans_pkt.tcp_pkt,(void *)ptcphdr,sizeof(struct tcphdr));
	if ((alarm_num+1)>=MAX_ALARM_NUM)
	{
		if (g_alarmfop &amp;&amp; g_alarmpdx)
			SignalEvent(g_alarmpdx,g_alarmfop);
		alarm_num=0;
		acall_num++;
		if (acall_num>=MAX_CALL_NUM)
			acall_num=0;
	}
	else
	{
		alarm_num++;
	}
}


void UTIL_UdpWriteLog(
					  struct Fw_Rule_Node *pUdpRule,
					  struct ip *piphdr,
					  struct udphdr *pudphdr
					  )
{
	g_AllLog[lcall_num].logs[log_num].ID=pUdpRule->ID;
	g_AllLog[lcall_num].log_num=log_num+1;
	g_AllLog[lcall_num].protocol=PT_UDP;
	memcpy((void *)&amp;g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	memcpy((void *)&amp;g_AllLog[lcall_num].logs[log_num].log_trans_pkt.udp_pkt,(void *)pudphdr,sizeof(struct udphdr));
	if ((log_num+1)>=MAX_LOG_NUM)
	{
		if (g_logfop &amp;&amp; g_logpdx)
			SignalEvent(g_logpdx,g_logfop);
		log_num=0;
		lcall_num++;
		if (lcall_num>=MAX_CALL_NUM)
			lcall_num=0;
	}
	else
	{
		log_num++;
	}
}

void UTIL_UdpAlarm(
				   struct Fw_Rule_Node *pUdpRule,
				   struct ip *piphdr,
				   struct udphdr *pudphdr
				   )
{
	g_AllAlarm[acall_num].Alarms[alarm_num].ID=pUdpRule->ID;
	g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_UDP;
	g_AllAlarm[acall_num].alarm_num=alarm_num+1;
	memcpy((void *)&amp;g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	memcpy((void *)&amp;g_AllAlarm[acall_num].Alarms[alarm_num].alarm_trans_pkt.udp_pkt,(void *)pudphdr,sizeof(struct udphdr));
	if ((alarm_num+1)>=MAX_ALARM_NUM)
	{
		if (g_alarmfop &amp;&amp; g_alarmpdx)
			SignalEvent(g_alarmpdx,g_alarmfop);
		alarm_num=0;
		acall_num++;
		if (acall_num>=MAX_CALL_NUM)
			acall_num=0;
	}
	else
	{
		alarm_num++;
	}
}

void UTIL_IcmpWriteLog(
					   struct Fw_Rule_Node *pIcmpRule,
					   struct ip *piphdr,
					   struct icmp *picmphdr
					   )
{
	g_AllLog[lcall_num].logs[log_num].ID=pIcmpRule->ID;
	g_AllLog[lcall_num].log_num=log_num+1;
	g_AllLog[lcall_num].protocol=PT_ICMP;
	memcpy((void *)&amp;g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	memcpy((void *)&amp;g_AllLog[lcall_num].logs[log_num].log_trans_pkt.icmp_pkt,(void *)picmphdr,sizeof(struct icmp));
	if ((log_num+1)>=MAX_LOG_NUM)
	{
		if (g_logfop &amp;&amp; g_logpdx)
			SignalEvent(g_logpdx,g_logfop);
		log_num=0;
		lcall_num++;
		if (lcall_num>=MAX_CALL_NUM)
			lcall_num=0;
	}
	else
	{
		log_num++;
	}
}

void UTIL_IcmpAlarm(
					struct Fw_Rule_Node *pIcmpRule,
					struct ip *piphdr,
					struct icmp *picmphdr
					)
{
	g_AllAlarm[acall_num].Alarms[alarm_num].ID=pIcmpRule->ID;
	g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_ICMP;
	g_AllAlarm[acall_num].alarm_num=alarm_num+1;
	memcpy((void *)&amp;g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	memcpy((void *)&amp;g_AllAlarm[acall_num].Alarms[alarm_num].alarm_trans_pkt.icmp_pkt,(void *)picmphdr,sizeof(struct icmp));
	if ((alarm_num+1)>=MAX_ALARM_NUM)
	{
		if (g_alarmfop &amp;&amp; g_alarmpdx)
			SignalEvent(g_alarmpdx,g_alarmfop);
		alarm_num=0;
		acall_num++;
		if (acall_num>=MAX_CALL_NUM)
			acall_num=0;
	}
	else
	{
		alarm_num++;
	}
}

void UTIL_RestipWriteLog(
						 struct Fw_Rule_Node *pRestipRule,
						 struct ip *piphdr
						 )
{
	g_AllLog[lcall_num].logs[log_num].ID=pRestipRule->ID;
	g_AllLog[lcall_num].log_num=log_num+1;
	g_AllLog[lcall_num].protocol=PT_RESTIP;
	memcpy((void *)&amp;g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	if ((log_num+1)>=MAX_LOG_NUM)
	{
		if (g_logfop &amp;&amp; g_logpdx)
			SignalEvent(g_logpdx,g_logfop);
		log_num=0;
		lcall_num++;
		if (lcall_num>=MAX_CALL_NUM)
			lcall_num=0;
	}
	else
	{
		log_num++;
	}
}

void UTIL_RestipAlarm(
					  struct Fw_Rule_Node *pRestipRule,
					  struct ip *piphdr
					  )
{
	g_AllAlarm[acall_num].Alarms[alarm_num].ID=pRestipRule->ID;
	g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_RESTIP;
	g_AllAlarm[acall_num].alarm_num=alarm_num+1;
	memcpy((void *)&amp;g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
	if ((alarm_num+1)>=MAX_ALARM_NUM)
	{
		if (g_alarmfop &amp;&amp; g_alarmpdx)
			SignalEvent(g_alarmpdx,g_alarmfop);
		alarm_num=0;
		acall_num++;
		if (acall_num>=MAX_CALL_NUM)
			acall_num=0;
	}
	else
	{
		alarm_num++;
	}
}

/////////////////////////////////////////////////////////////////
//  
//函数UTIL_SizeupPort
//
//参数
//USHORT cur_port,char p_operator,USHORT port1,USHORT port2
//
//返回值
//TRUE,FALSE
//
//
//备注
//cur_port是否满足规则中对端口的要求

BOOLEAN UTIL_SizeupPort(
						USHORT cur_port,
						char p_operator,
						USHORT port1,
						USHORT port2
						)
{
	// 对端口没有特殊要求,即默认任何端口都符合
	if (port1==0 &amp;&amp; port2==0)
		return TRUE;
	
	switch (p_operator)
	{
	case OP_GT:
		return (cur_port>port1);
	case OP_LT:
		return (cur_port<port1);
	case OP_EQ:
		return (cur_port==port1);
	case OP_NE:
		return (cur_port != port1);
	case OP_BW:
		return (cur_port>port1 &amp;&amp; cur_port<port2);
	}
	return FALSE;
}

//////////////////////////////////////////////////////
//
//函数UTIL_GetCurrentTime()
//
//参数
//无
//
//返回值
//从当天零点到调用函数时的秒数
//
//
int	UTIL_GetCurrentTime(void)
{
	LARGE_INTEGER  current;
	ULONGLONG	cursec=0;
	ULONG	sec=0;
	KeQuerySystemTime(&amp;current);
	cursec=current.QuadPart/10000000;
	sec=(int)(cursec%86400);
	return (sec+3600*8);
}

/*-------------------------------------------------------------------

  数据检查相关函数
  
--------------------------------------------------------------------*/

//kmp算法中求next
void UTIL_getnext(char *p,int len_p,short *next)//p为子串,len_p为子串长度
{
	short i=0,j=-1;
	next[0]=-1;
	
	while (i<=len_p-1)
	{
		while(j>=0 &amp;&amp; p[i]!=p[j])
		{
			j=next[j];
			
		}
		i++;j++;next[i]=j;
	}
}

//kmp 算法
BOOLEAN UTIL_kmp(
				 char	*data,
				 int	datasize,
				 char	*keyword,
				 int	keysize,
				 short	*next
				 )
{
	int i=0,j=0;
	while(i<=datasize-1&amp;&amp;j<=keysize-1)
	{
		while(j>=0 &amp;&amp; data[i]!=keyword[j])
		{
			j=next[j];
		}
		i++;j++;
	}
	if (j==keysize) return TRUE;
	else return FALSE;
}

///////////////////////////////////////////////
//查找符合端口节点的函数
//
//参数
//
//返回值
//
//备注
struct	KeyList  *UTIL_FindPortNode(USHORT port,int bkey)
{
	struct KeyList	*plistnode;
	
	if(bkey==1)
		plistnode=g_Rules.global.pkeylist;
	else if(bkey == 0)
		plistnode=g_Rules.global.pURLList;
	else
		plistnode=g_Rules.global.pTCPURLList;

	while (plistnode)
	{
		if (port<plistnode->port)
		{
			plistnode=plistnode->next;
			continue;
		}
		if (plistnode->port==port)
			return plistnode;
		if(port>plistnode->port)
			break;		
	}
	return NULL;
}

///////////////////////////////////////////////
//插入关键字节点的函数
//
//参数
//
//返回值
//
//备注
void UTIL_InsertKeyNode(struct  KeyList *pnode,UINT id,char *key,ULONG keylen)
{
	struct Keyword	*keynode,*newkey;
	
	newkey=(struct Keyword *)UTIL_AllocateMemory(sizeof(struct Keyword));
	newkey->id=id;
	newkey->keyword=key;
	newkey->len=keylen;
	newkey->overlap=(short *)UTIL_AllocateMemory((keylen+1)*sizeof(short));
	UTIL_getnext(newkey->keyword,newkey->len ,newkey->overlap);
	newkey->next=NULL;
	keynode=pnode->pkeyword;
	while(keynode->next)
	{
		keynode=keynode->next;
	}
	keynode->next=newkey;
	return;
}

///////////////////////////////////////////////
//找到符合端口的插入函数
//
//参数
//
//返回值
//
//备注
void UTIL_FindRightPlace(struct KeyList **prenode,USHORT port,int bkey)
{
	struct KeyList	*pnode,*ppre,*pnext;
	
	if(bkey==1)
		pnode=g_Rules.global.pkeylist;
	else if(bkey == 0)
		pnode=g_Rules.global.pURLList;
	else
		pnode=g_Rules.global.pTCPURLList;
	if (pnode==NULL || port<pnode->port)
	{
		*prenode=NULL;
		return;
	}
	else
	{
		ppre=pnode;
		pnext=ppre->next;
		while (pnext)
		{
			if (port > ppre->port &amp;&amp; port < pnext->port ) 	// I find it
			{
				*prenode=ppre;
				return;
			}
			ppre=pnext;
			pnext=ppre->next;			
		}
		//pnext==null
		*prenode=ppre;
		return;
	}
}
///////////////////////////////////////////////
//插入新的端口节点到端口链表末尾的函数
//
//参数
//
//返回值
//
//备注
void UTIL_InsertNewPortNode(struct KeyList *pprenode,
							struct KeyList *pnewnode,
							int bkey
							)
{
	if (pprenode==NULL)
	{
		if(bkey==1)
		{
			pnewnode->next=g_Rules.global.pkeylist;
			g_Rules.global.pkeylist=pnewnode;
		}
		else if(bkey == 0)
		{
			pnewnode->next=g_Rules.global.pURLList;
			g_Rules.global.pURLList=pnewnode;
		}
		else
		{
			pnewnode->next=g_Rules.global.pTCPURLList;
			g_Rules.global.pTCPURLList=pnewnode;
		}		
	}
	else
	{
		pnewnode->next=pprenode->next;
		pprenode->next=pnewnode;
	}	
}

///////////////////////////////////////////////
//插入端口节点函数
//
//参数
//
//返回值
//
//备注
void UTIL_UpdatePortNode(struct	Interface_Keyword *pkeyhead,
						 char 	*key,
						 ULONG	keylen,
						 int	bkey
						 )
{
	struct  KeyList *pnode;
	struct KeyList	*prenode,*nextnode,*pnewport;
	struct Keyword	*pnewkey;
	
	if (pnode=UTIL_FindPortNode(pkeyhead->port,bkey))
	{
		UTIL_InsertKeyNode(pnode,pkeyhead->id,key,keylen);
	}
	else
	{
		pnewkey=(struct Keyword *)UTIL_AllocateMemory(sizeof(struct Keyword));
		pnewport=(struct KeyList *)UTIL_AllocateMemory(sizeof(struct KeyList));
		pnewkey->id=pkeyhead->id;
		pnewkey->keyword=key;
		pnewkey->len=keylen;
		pnewkey->overlap=(short *)UTIL_AllocateMemory((keylen+1)*sizeof(short));
		UTIL_getnext(pnewkey->keyword,pnewkey->len ,pnewkey->overlap);
		pnewkey->next=NULL;
		pnewport->port=pkeyhead->port;
		pnewport->pkeyword=pnewkey;
		
		UTIL_FindRightPlace(&amp;prenode,pnewport->port,bkey);
		
		UTIL_InsertNewPortNode(prenode,pnewport,bkey);
	}
}

///////////////////////////////////////////////
//关键字增加函数
//
//参数
//
//返回值
//
//备注
void UTIL_AddKeyword(PVOID keyword,ULONG buflen,int bkey)
{
	struct	Interface_Keyword *pkeyhead;
	char 	*key;
	ULONG 	keylen;
	PVOID 	keybuf;
	
	keybuf=UTIL_AllocateMemory(buflen);
	memcpy(keybuf,keyword,buflen);
	pkeyhead=(struct Interface_Keyword *)keybuf;
	key=(char *)keybuf+sizeof(struct Interface_Keyword);
	keylen=buflen-sizeof(struct Interface_Keyword);
	UTIL_UpdatePortNode(pkeyhead,key,keylen,bkey);
}

///////////////////////////////////////////////
//关键字删除函数
//
//参数
//
//返回值
//
//备注

void UTIL_DelKeyword(void)
{
	struct KeyList *ptr_current=NULL;
	struct KeyList *ptr_next=NULL;
	
	if (g_Rules.global.pkeylist!=NULL)
	{
		ptr_current=g_Rules.global.pkeylist;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.global.pkeylist=NULL;
	}
	return;
}

///////////////////////////////////////////////
//URL删除函数
//
//参数
//
//返回值
//
//备注
void UTIL_DelURLWord(void)
{
	struct KeyList *ptr_current=NULL;
	struct KeyList *ptr_next=NULL;
	
	if (g_Rules.global.pURLList!=NULL)
	{
		ptr_current=g_Rules.global.pURLList;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.global.pURLList=NULL;
	}
	return;
}

//删除TCP
void UTIL_DelTCPURLWord(void)
{
	struct KeyList *ptr_current=NULL;
	struct KeyList *ptr_next=NULL;
	
	if (g_Rules.global.pTCPURLList!=NULL)
	{
		ptr_current=g_Rules.global.pTCPURLList;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.global.pTCPURLList=NULL;
	}
	return;
}

///////////////////////////////////////////////
//数据检查函数
//
//参数
//data 	被检查的数据
//datasize 	mean as name
//nSport	源端口
//nDport	目标端口
//
//返回值
//true 	------被检查的数据中包含关键字
//false	------被检查的数据中不包含关键字
//
//备注
//检查包中的数据是否包含关键字
BOOLEAN UTIL_ExamineData(
						 char	*data,
						 int		datasize,
						 USHORT	nSport,
						 USHORT	nDport
						 )
{
	
	struct	Keyword	 *nextkey;
	struct 	KeyList	 *nextkeylist;
	BOOLEAN			 bDataContain;
	
	//if 要检查数据包内容 并且 端口符合
	if (g_Rules.global.pkeylist) 
	{
		//调用数据检查函数UTIL_kmp(.....)
		nextkeylist=g_Rules.global.pkeylist;
		while (nextkeylist &amp;&amp; (nextkeylist->port==nSport || nextkeylist->port==nDport))
		{
			nextkey=nextkeylist->pkeyword;
			while(nextkey)
			{
				bDataContain=UTIL_kmp(
					data,
					datasize,
					nextkey->keyword,
					nextkey->len,
					nextkey->overlap
					);
				
				//if 包含关键字 	返回  TRUE
				if (bDataContain)
				{
					return (TRUE);
				}
				nextkey=nextkey->next;
			}
			nextkeylist=nextkeylist->next;
		}
		//无关键字匹配
		return FALSE;
	}
	
	return FALSE;
}
//
BOOLEAN UTIL_ExamineURL(ULONG ip_dst, ULONG ip_src)
{
	struct	Keyword	 *nextkey;
	struct 	KeyList	 *nextkeylist;
	BOOLEAN			 bDataContain;
	ULONG			 lval;
	
	//if 要检查数据包内容 并且 端口符合
	if (g_Rules.global.pURLList) 
	{
		//调用数据检查函数UTIL_kmp(.....)
		nextkeylist=g_Rules.global.pURLList;
		while (nextkeylist)
		{
			nextkey=nextkeylist->pkeyword;
			while(nextkey)
			{
				lval = atol(nextkey->keyword);
				if (lval == ip_dst || lval == ip_src)
					return TRUE;
				nextkey=nextkey->next;
			}
			nextkeylist=nextkeylist->next;
		}
		//无关键字匹配
		return FALSE;
	}
	return FALSE;
}

//根据IP地址拦截
BOOLEAN UTIL_ExamineTCPURL(ULONG ip_dst, ULONG ip_src)
{
	struct	Keyword	 *nextkey;
	struct 	KeyList	 *nextkeylist;
	BOOLEAN			 bDataContain;
	ULONG			 lval;
	
	//if 要检查数据包内容 并且 端口符合
	if (g_Rules.global.pTCPURLList) 
	{
		//调用数据检查函数UTIL_kmp(.....)
		nextkeylist=g_Rules.global.pTCPURLList;
		while (nextkeylist)
		{
			nextkey=nextkeylist->pkeyword;
			while(nextkey)
			{
				lval = atol(nextkey->keyword);
				if (lval == ip_dst || lval == ip_src)
					return TRUE;
				nextkey=nextkey->next;
			}
			nextkeylist=nextkeylist->next;
		}
		//无关键字匹配
		return FALSE;
	}
	return FALSE;
}

/////////////////////////////////////////////////////////////////
//  
//函数UTIL_AddAllrules
//
//参数
//all_rules
//
//返回值
//是,否成功
//
//
//备注
//增加所有规则

BOOLEAN UTIL_AddAllrules(struct All_Rules *pallrules)
{
	int i;
	struct Fw_Rule_Node		*ptcprule,*pt_in,*pt_out;
	struct Fw_Rule_Node	    *pudprule,*pu_in,*pu_out;
	struct Fw_Rule_Node		*picmprule,*pi_in,*pi_out;
	struct Fw_Rule_Node		*prestiprule,*pr_in,*pr_out;
	
    //KdPrint((&quot;UTIL_AddAllrules&quot;));

	for(i=0;i<pallrules->rules_num;i++)
	{
		switch (pallrules->Rules[i].proto)
		{
		case PT_TCP:
			if (pallrules->Rules[i].direct &amp; DT_IN)
			{
				ptcprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				ptcprule->action			=pallrules->Rules[i].action;
				ptcprule->s_port[0]			=pallrules->Rules[i].s_port[0];
				ptcprule->s_port[1]			=pallrules->Rules[i].s_port[1];
				ptcprule->d_port[0]			=pallrules->Rules[i].d_port[0];
				ptcprule->d_port[1]			=pallrules->Rules[i].d_port[1];
				ptcprule->sp_operator		=pallrules->Rules[i].sp_operator;
				ptcprule->dp_operator		=pallrules->Rules[i].dp_operator;
				ptcprule->direct			=pallrules->Rules[i].direct;
				ptcprule->ID				=pallrules->Rules[i].id;
				ptcprule->warn_enable		=pallrules->Rules[i].warn_enable;
				ptcprule->log_enable		=pallrules->Rules[i].log_enable;
				ptcprule->ip				=pallrules->Rules[i].ip;
				ptcprule->mask				=pallrules->Rules[i].mask;
				ptcprule->schedule.enable	=pallrules->Rules[i].time.time_enable;
				ptcprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				ptcprule->schedule.end_time	=pallrules->Rules[i].time.end_time;
				ptcprule->tcpflag			=pallrules->Rules[i].tcpflag;
				ptcprule->next				=NULL;
				
				if (g_Rules.tcp.pin==NULL) //头节点
				{
					g_Rules.tcp.pin=ptcprule;
					pt_in=ptcprule;
				}
				else
				{
					pt_in->next=ptcprule;
					pt_in=ptcprule;
				}
/*
				KdPrint((&quot;in action=%u s_port=%d d_port=%d&quot;,
					      ptcprule->action,
					      ptcprule->s_port[0],
						  ptcprule->d_port[0]));
*/				
			}
			if(pallrules->Rules[i].direct &amp; DT_OUT)
			{
				ptcprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				ptcprule->action			=pallrules->Rules[i].action;
				ptcprule->s_port[0]			=pallrules->Rules[i].s_port[0];
				ptcprule->s_port[1]			=pallrules->Rules[i].s_port[1];
				ptcprule->d_port[0]			=pallrules->Rules[i].d_port[0];
				ptcprule->d_port[1]			=pallrules->Rules[i].d_port[1];
				ptcprule->sp_operator		=pallrules->Rules[i].sp_operator;
				ptcprule->dp_operator		=pallrules->Rules[i].dp_operator;
				ptcprule->direct			=pallrules->Rules[i].direct;
				ptcprule->ID				=pallrules->Rules[i].id;
				ptcprule->warn_enable		=pallrules->Rules[i].warn_enable;
				ptcprule->log_enable		=pallrules->Rules[i].log_enable;
				ptcprule->ip				=pallrules->Rules[i].ip;
				ptcprule->mask				=pallrules->Rules[i].mask;
				ptcprule->schedule.enable	=pallrules->Rules[i].time.time_enable;
				ptcprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				ptcprule->schedule.end_time	=pallrules->Rules[i].time.end_time;
				ptcprule->tcpflag			=pallrules->Rules[i].tcpflag;
				ptcprule->next=NULL;
/*				
				KdPrint((&quot;action=%u s_port=%d d_port=%d&quot;,
					      ptcprule->action,
					      ptcprule->s_port[0],
						  ptcprule->d_port[0]));
*/
				if (g_Rules.tcp.pout==NULL) //头节点
				{
					g_Rules.tcp.pout=ptcprule;
					pt_out=ptcprule;
				}
				else
				{
					pt_out->next=ptcprule;
					pt_out=ptcprule;
				}
			}
			break;
			
		case PT_UDP:
			if (pallrules->Rules[i].direct&amp;DT_IN)
			{
				pudprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				pudprule->action			=pallrules->Rules[i].action;
				pudprule->s_port[0]			=pallrules->Rules[i].s_port[0];
				pudprule->s_port[1]			=pallrules->Rules[i].s_port[1];
				pudprule->d_port[0]			=pallrules->Rules[i].d_port[0];
				pudprule->d_port[1]			=pallrules->Rules[i].d_port[1];
				pudprule->sp_operator		=pallrules->Rules[i].sp_operator;
				pudprule->dp_operator		=pallrules->Rules[i].dp_operator;
				pudprule->direct			=pallrules->Rules[i].direct;
				pudprule->ID				=pallrules->Rules[i].id;
				pudprule->warn_enable		=pallrules->Rules[i].warn_enable;
				pudprule->log_enable		=pallrules->Rules[i].log_enable;
				pudprule->ip				=pallrules->Rules[i].ip;
				pudprule->mask				=pallrules->Rules[i].mask;
				pudprule->schedule.enable	=pallrules->Rules[i].time.time_enable;
				pudprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				pudprule->schedule.end_time	=pallrules->Rules[i].time.end_time;
				pudprule->next				=NULL;
				
				if (g_Rules.udp.pin==NULL) //头节点
				{
					g_Rules.udp.pin=pudprule;
					pu_in=pudprule;
				}
				else
				{
					pu_in->next=pudprule;
					pu_in=pudprule;
				}
			}
			if (pallrules->Rules[i].direct&amp;DT_OUT)
			{
				pudprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				pudprule->action			=pallrules->Rules[i].action;
				pudprule->s_port[0]			=pallrules->Rules[i].s_port[0];
				pudprule->s_port[1]			=pallrules->Rules[i].s_port[1];
				pudprule->d_port[0]			=pallrules->Rules[i].d_port[0];
				pudprule->d_port[1]			=pallrules->Rules[i].d_port[1];
				pudprule->sp_operator		=pallrules->Rules[i].sp_operator;
				pudprule->dp_operator		=pallrules->Rules[i].dp_operator;
				pudprule->direct			=pallrules->Rules[i].direct;
				pudprule->ID				=pallrules->Rules[i].id;
				pudprule->warn_enable		=pallrules->Rules[i].warn_enable;
				pudprule->log_enable		=pallrules->Rules[i].log_enable;
				pudprule->ip				=pallrules->Rules[i].ip;
				pudprule->mask				=pallrules->Rules[i].mask;
				pudprule->schedule.enable	=pallrules->Rules[i].time.time_enable;
				pudprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				pudprule->schedule.end_time	=pallrules->Rules[i].time.end_time;
				pudprule->next				=NULL;
				
				if (g_Rules.udp.pout==NULL) //头节点
				{
					g_Rules.udp.pout=pudprule;
					pu_out=pudprule;
				}
				else
				{
					pu_out->next=pudprule;
					pu_out=pudprule;
				}
			}
			break;
			
		case PT_ICMP:
			if (pallrules->Rules[i].direct&amp;DT_IN)
			{
				picmprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				picmprule->action			=pallrules->Rules[i].action;
				picmprule->direct			=pallrules->Rules[i].direct;
				picmprule->ID				=pallrules->Rules[i].id;
				picmprule->warn_enable		=pallrules->Rules[i].warn_enable;
				picmprule->log_enable		=pallrules->Rules[i].log_enable;
				picmprule->ip				=pallrules->Rules[i].ip;
				picmprule->mask				=pallrules->Rules[i].mask;
				picmprule->schedule.enable	=pallrules->Rules[i].time.time_enable;
				picmprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				picmprule->schedule.end_time=pallrules->Rules[i].time.end_time;
				picmprule->next				=NULL;
				
				if (g_Rules.icmp.pin==NULL) //头节点
				{
					g_Rules.icmp.pin=picmprule;
					pi_in=picmprule;
				}
				else
				{
					pi_in->next=picmprule;
					pi_in=picmprule;
				}
			}
			if (pallrules->Rules[i].direct&amp;DT_OUT)
			{
				picmprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				picmprule->action			=pallrules->Rules[i].action;
				picmprule->direct			=pallrules->Rules[i].direct;
				picmprule->ID				=pallrules->Rules[i].id;
				picmprule->warn_enable		=pallrules->Rules[i].warn_enable;
				picmprule->log_enable		=pallrules->Rules[i].log_enable;
				picmprule->ip				=pallrules->Rules[i].ip;
				picmprule->mask				=pallrules->Rules[i].mask;
				picmprule->schedule.enable	=pallrules->Rules[i].time.time_enable;
				picmprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				picmprule->schedule.end_time=pallrules->Rules[i].time.end_time;
				picmprule->next				=NULL;

				if (g_Rules.icmp.pout==NULL) //头节点
				{
					g_Rules.icmp.pout=picmprule;
					pi_out=picmprule;
				}
				else
				{
					pi_out->next=picmprule;
					pi_out=picmprule;
				}
			}
			break;
			
		case	PT_RESTIP:
			if (pallrules->Rules[i].direct &amp; DT_IN)
			{
				prestiprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				prestiprule->action			=pallrules->Rules[i].action;
				prestiprule->direct			=pallrules->Rules[i].direct;
				prestiprule->ID				=pallrules->Rules[i].id;
				prestiprule->warn_enable	=pallrules->Rules[i].warn_enable;
				prestiprule->log_enable		=pallrules->Rules[i].log_enable;
				prestiprule->ip				=pallrules->Rules[i].ip;
				prestiprule->mask			=pallrules->Rules[i].mask;
				prestiprule->schedule.enable=pallrules->Rules[i].time.time_enable;
				prestiprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				prestiprule->schedule.end_time=pallrules->Rules[i].time.end_time;
				prestiprule->next			=NULL;
				
				if (g_Rules.ip.pin==NULL) //头节点
				{
					g_Rules.ip.pin=prestiprule;
					pr_in=prestiprule;
				}
				else
				{
					pr_in->next=prestiprule;
					pr_in=prestiprule;
				}
			}
			if(pallrules->Rules[i].direct &amp; DT_OUT)
			{
				prestiprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
				prestiprule->action			=pallrules->Rules[i].action;
				prestiprule->direct			=pallrules->Rules[i].direct;
				prestiprule->ID				=pallrules->Rules[i].id;
				prestiprule->warn_enable	=pallrules->Rules[i].warn_enable;
				prestiprule->log_enable		=pallrules->Rules[i].log_enable;
				prestiprule->ip				=pallrules->Rules[i].ip;
				prestiprule->mask			=pallrules->Rules[i].mask;
				prestiprule->schedule.enable=pallrules->Rules[i].time.time_enable;
				prestiprule->schedule.start_time=pallrules->Rules[i].time.start_time;
				prestiprule->schedule.end_time=pallrules->Rules[i].time.end_time;
				prestiprule->next			=NULL;

				if (g_Rules.ip.pout==NULL) //头节点
				{
					g_Rules.ip.pout=prestiprule;
					pr_out=prestiprule;
				}
				else
				{
					pr_out->next=prestiprule;
					pr_out=prestiprule;
				}
			}
			break;
			
		default:
			//return FALSE;		//skip not define protocol
			break;
			
			
		}   // end of switch (protocol)
		
	}   //end of for
	return TRUE;
}

/////////////////////////////////////////////////////////////////
//  
//函数UTIL_DelAllrules
//
//参数
//无
//
//返回值
//是,否成功
//
//
//备注
//删除所有规则

BOOLEAN UTIL_DelAllrules(void)
{
	
	struct Fw_Rule_Node		*ptr_current=NULL;
	struct Fw_Rule_Node		*ptr_next=NULL;
	
	//KdPrint((&quot;UTIL_DelAllrules&quot;));

	//tcp in chain
	if (g_Rules.tcp.pin!=NULL)
	{
		ptr_current=g_Rules.tcp.pin;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.tcp.pin=NULL;
	}
	//tcp out chain
	if (g_Rules.tcp.pout!=NULL)
	{
		ptr_current=g_Rules.tcp.pout;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.tcp.pout=NULL;
	}
	
	//udp in chain
	if (g_Rules.udp.pin!=NULL)
	{
		ptr_current=g_Rules.udp.pin;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.udp.pin=NULL;
	}
	//udp out chain
	if (g_Rules.udp.pout!=NULL)
	{
		ptr_current=g_Rules.udp.pout;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.udp.pout=NULL;
	}
	
	//icmp in chain
	if (g_Rules.icmp.pin!=NULL)
	{
		ptr_current=g_Rules.icmp.pin;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.icmp.pin=NULL;
	}
	//icmp out chain
	if (g_Rules.icmp.pout!=NULL)
	{
		ptr_current=g_Rules.icmp.pout;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.icmp.pout=NULL;
	}
	//restip in chain
	if (g_Rules.ip.pin!=NULL)
	{
		ptr_current=g_Rules.ip.pin;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.ip.pin=NULL;
	}
	//restip out chain
	if (g_Rules.ip.pout!=NULL)
	{
		ptr_current=g_Rules.ip.pout;
		ptr_next=ptr_current->next;
		while (ptr_current!=NULL)
		{
			UTIL_FreeMemory((void *)ptr_current);
			ptr_current=ptr_next;
			if (ptr_current!=NULL)
				ptr_next=ptr_current->next;
		}
		g_Rules.ip.pout=NULL;
	}
	return TRUE;
	
}

UCHAR	UTIL_MatchTcpRule(struct ip *pIpHeader, struct tcphdr *pTcpHeader, UCHAR Direct)
{
	UCHAR		nAction=NOT_MATCH;
	USHORT		nSrcPort, nDstPort;
	ULONG		nSrcIP, nDstIP;
	struct Fw_Rule	*pTcpRule=NULL;
	struct Fw_Rule_Node	*ptr=NULL;
	
	//KdPrint((&quot;UTIL_MatchTcpRule&quot;));

	pTcpRule=&amp;g_Rules.tcp;
	if(!pTcpRule->enable) return DENY;	//不允许TCP协议通过 
	
	if(Direct==DT_OUT)
	{
		nSrcIP=(ULONG)pIpHeader->ip_src.s_addr;
		nDstIP=(ULONG)pIpHeader->ip_dst.s_addr;
		nSrcPort=UTIL_ntohs(pTcpHeader->th_sport);
		nDstPort=UTIL_ntohs(pTcpHeader->th_dport);
		ptr=pTcpRule->pout;
	}
	else
	{
		nSrcIP=pIpHeader->ip_dst.s_addr;
		nDstIP=pIpHeader->ip_src.s_addr;
		nSrcPort=UTIL_ntohs(pTcpHeader->th_dport);
		nDstPort=UTIL_ntohs(pTcpHeader->th_sport);
		ptr=pTcpRule->pin;
	}
	
	//KdPrint((&quot;UTIL_MatchTcpRule ...&quot;));

	for(; ptr!=NULL; ptr=ptr->next)
	{
		if(ptr->schedule.enable)
		{
			int cur_time=UTIL_GetCurrentTime(); 
			//	if 当前时间不在时间表范围内返回 PASS
			if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
			{
				ptr=ptr->next;   //取下一个节点
				continue;
			}
		}

		if(UTIL_SizeupPort(nSrcPort, ptr->sp_operator, ptr->s_port[0], ptr->s_port[1]) &amp;&amp;
		   UTIL_SizeupPort(nDstPort, ptr->dp_operator, ptr->d_port[0], ptr->d_port[1]) &amp;&amp;
		   ((ptr->ip==(nDstIP &amp; ptr->mask))||(ptr->ip==0)))
		{
			//tcpflag add by df
			if (ptr->tcpflag==0||ptr->tcpflag==pTcpHeader->th_flags) 
			{
				nAction=ptr->action;
				break;
			}
		}
	}

	UTIL_CountPacket(PT_TCP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
	if (nAction!=NOT_MATCH)
	{
		if (g_Rules.global.warn_enable &amp;&amp; ptr->warn_enable &amp;&amp; g_alarmfop &amp;&amp;g_alarmpdx)
			UTIL_TcpAlarm(ptr, pIpHeader, pTcpHeader);
		if (g_Rules.global.log_enable &amp;&amp; ptr->log_enable &amp;&amp; g_logfop &amp;&amp; g_logpdx)
			UTIL_TcpWriteLog(ptr, pIpHeader,pTcpHeader );
	}
	return nAction;
}


UCHAR	UTIL_MatchUdpRule(struct ip *pIpHeader, struct udphdr *pUdpHeader, UCHAR Direct)
{
	UCHAR		nAction=NOT_MATCH;
	USHORT		nSrcPort, nDstPort;
	ULONG		nSrcIP, nDstIP;
	struct Fw_Rule_Node	*ptr=NULL;
	
	if(!g_Rules.udp.enable) return DENY;	//不允许UDP协议通过 
	
	if(Direct==DT_OUT)
	{
		nSrcIP=pIpHeader->ip_src.s_addr;
		nDstIP=pIpHeader->ip_dst.s_addr;
		nSrcPort=UTIL_ntohs(pUdpHeader->uh_sport);
		nDstPort=UTIL_ntohs(pUdpHeader->uh_dport);
		ptr=g_Rules.udp.pout;
	}
	else
	{
		nSrcIP=pIpHeader->ip_dst.s_addr;
		nDstIP=pIpHeader->ip_src.s_addr;
		nSrcPort=UTIL_ntohs(pUdpHeader->uh_dport);
		nDstPort=UTIL_ntohs(pUdpHeader->uh_sport);
		ptr=g_Rules.udp.pin;
	}
	
	for(; ptr!=NULL; ptr=ptr->next)
	{
		if(ptr->schedule.enable)
		{
			int cur_time=UTIL_GetCurrentTime(); 
			//	if 当前时间不在时间表范围内
			//		返回 PASS
			if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
			{
				ptr=ptr->next;   //取下一个节点
				continue;
			}
			
		}
		
		if(UTIL_SizeupPort(nSrcPort, ptr->sp_operator, ptr->s_port[0], ptr->s_port[1]) &amp;&amp;
			UTIL_SizeupPort(nDstPort, ptr->dp_operator, ptr->d_port[0], ptr->d_port[1]) &amp;&amp;
			((ptr->ip==(nDstIP &amp; ptr->mask))||(ptr->ip==0)))
		{
			nAction=ptr->action;
			break;
		}
	}
	
	UTIL_CountPacket(PT_UDP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
	if (nAction!=NOT_MATCH)
	{
		if (g_Rules.global.warn_enable &amp;&amp; ptr->warn_enable  &amp;&amp; g_alarmfop &amp;&amp;g_alarmpdx)
			UTIL_UdpAlarm(ptr, pIpHeader, pUdpHeader);
		if (g_Rules.global.log_enable &amp;&amp; ptr->log_enable &amp;&amp; g_logfop &amp;&amp; g_logpdx)
			UTIL_UdpWriteLog(ptr, pIpHeader, pUdpHeader);
	}
	return nAction;
}


UCHAR	UTIL_MatchIcmpRule(struct ip *pIpHeader, struct icmp *pIcmpHeader, UCHAR Direct)
{
	UCHAR		nAction=NOT_MATCH;
	ULONG		nSrcIP, nDstIP;
	struct Fw_Rule_Node	*ptr=NULL;
	
	if(!g_Rules.icmp.enable) return DENY;	//不允许ICMP协议通过 
	
	if(Direct==DT_OUT)
	{
		nSrcIP=pIpHeader->ip_src.s_addr;
		nDstIP=pIpHeader->ip_dst.s_addr;
		ptr=g_Rules.icmp.pout;
	}
	else
	{
		nSrcIP=pIpHeader->ip_dst.s_addr;
		nDstIP=pIpHeader->ip_src.s_addr;
		ptr=g_Rules.icmp.pin;
	}
	
	for(; ptr!=NULL; ptr=ptr->next)
	{
		if(ptr->schedule.enable)
		{
			int cur_time=UTIL_GetCurrentTime(); 
			//	if 当前时间不在时间表范围内
			//		返回 PASS
			if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
			{
				ptr=ptr->next;   //取下一个节点
				continue;
			}
			
		}
		
		if((ptr->ip==(nDstIP &amp; ptr->mask))||(ptr->ip==0))
		{
			nAction=ptr->action;
			break;
		}
	}

	UTIL_CountPacket(PT_ICMP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
	if (nAction!=NOT_MATCH)
	{
		if (g_Rules.global.warn_enable &amp;&amp; ptr->warn_enable &amp;&amp; g_alarmfop &amp;&amp;g_alarmpdx)
			UTIL_IcmpAlarm(ptr, pIpHeader, pIcmpHeader);
		if (g_Rules.global.log_enable &amp;&amp; ptr->log_enable &amp;&amp; g_logfop &amp;&amp; g_logpdx)
			UTIL_IcmpWriteLog(ptr, pIpHeader, pIcmpHeader);
	}
	return nAction;
}


UCHAR	UTIL_MatchIpRule(struct ip *pIpHeader, UCHAR Direct)
{
	UCHAR		nAction=NOT_MATCH;
	ULONG		nSrcIP, nDstIP;
	struct Fw_Rule_Node	*ptr=NULL;

	if(!g_Rules.ip.enable) return DENY;	//不允许ICMP协议通过 

	if(Direct==DT_OUT)
	{
		nSrcIP=pIpHeader->ip_src.s_addr;
		nDstIP=pIpHeader->ip_dst.s_addr;
		ptr=g_Rules.ip.pout;
	}
	else
	{
		nSrcIP=pIpHeader->ip_dst.s_addr;
		nDstIP=pIpHeader->ip_src.s_addr;
		ptr=g_Rules.ip.pin;
	}

	for(; ptr!=NULL; ptr=ptr->next)
	{
		if(ptr->schedule.enable)
		{
			int cur_time=UTIL_GetCurrentTime(); 

			//	if 当前时间不在时间表范围内返回 PASS
			if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
			{
				ptr=ptr->next;   //取下一个节点
				continue;
			}

		}

		if((ptr->ip==(nDstIP &amp; ptr->mask))||(ptr->ip==0))
		{
			nAction=ptr->action;
			break;
		}
	}
	UTIL_CountPacket(PT_RESTIP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
	if (nAction!=NOT_MATCH)
	{
		if (g_Rules.global.warn_enable &amp;&amp; ptr->warn_enable &amp;&amp; g_alarmfop &amp;&amp;g_alarmpdx)
			UTIL_RestipAlarm(ptr, pIpHeader);
		if (g_Rules.global.log_enable &amp;&amp; ptr->log_enable &amp;&amp; g_logfop &amp;&amp; g_logpdx)
			UTIL_RestipWriteLog(ptr, pIpHeader);
	}
	return nAction;
}

UCHAR UTIL_MatchNotIpRule(PNDIS_PACKET Packet, USHORT nEtherType, UCHAR Direct)
{
	return ALLOW;
}

UCHAR UTIL_MatchRule(PNDIS_PACKET Packet, UCHAR Direct)
{
	ULONG		nNumberOfBytesRead = 0; 
	UCHAR		nProtocol;
	USHORT		nEtherType, nIPhdrLen, nIPOffset;
	UCHAR		nAction;
	ULONG 		datetime=0;
	ULONG		datasize;
	PUCHAR		ppktdata=NULL;
	BOOLEAN		bisinclude;

	//如果防火墙状态为切断所有则返回
	if(g_Rules.global.fw_status==FWS_DENYALL)
	{
		//KdPrint((&quot;FWS_DENYALL&quot;));
		return DENY;
	}

	if(g_Rules.global.fw_status==FWS_ALLOWALL) 
	{
		//KdPrint((&quot;FWS_ALLOWALL&quot;));
		return ALLOW;
	}

	//KdPrint((&quot;UTIL_MatchRule&quot;));

	datetime=UTIL_GetCurrentTime();
	if (g_Rules.global.schedule.enable)
	{
		//取得当前时间
		int cur_time=UTIL_GetCurrentTime(); 

		//	if 当前时间不在时间表范围内 返回 PASS
		if (cur_time<g_Rules.global.schedule.start_time||
			cur_time>g_Rules.global.schedule.end_time)
		{
			return ALLOW;					
		}
	}

	UTIL_ReadOnPacket(
		Packet,
		(PUCHAR )&amp;nEtherType,
		sizeof( USHORT ),
		MEtherType,             // See PCAEnet.h
		&amp;nNumberOfBytesRead
		);

	//if 读出不正确,直接PASS
	if(!nNumberOfBytesRead) return ALLOW;

	nEtherType = UTIL_htons( nEtherType );	//将包类型转换为网络顺序
	if( nEtherType == ETHERTYPE_IP )		//if 包类型是IP包
	{
		//read ip header
		UTIL_ReadOnPacket(
			Packet,
			(PUCHAR )g_pIPHeader,
			sizeof(*g_pIPHeader),
			MHdrSize,		     // ATTENTION!!! Media-Dependent!!!
			&amp;nNumberOfBytesRead
			);	

		//IP头不完整,丢弃
		if(nNumberOfBytesRead<sizeof(struct ip)) return DENY;

		//分片非第一片允许通过
		nIPOffset=UTIL_ntohs(g_pIPHeader->ip_off);
		if(((nIPOffset&amp;IP_DF)==0) &amp;&amp; ((nIPOffset&amp;0x1FFF)!=0)) return ALLOW;

		nIPhdrLen=g_pIPHeader->ip_hl*4;
		nProtocol=g_pIPHeader->ip_p;

		// 按照协议,分别进行审计
		switch(nProtocol)
		{
		case IPPROTO_TCP:
			if(UTIL_ExamineTCPURL(g_pIPHeader->ip_dst.s_addr,g_pIPHeader->ip_src.s_addr))
			{
				nAction=DENY;
			}
			else
			{					
				UTIL_ReadOnPacket(
					Packet,
					(PUCHAR)g_pTCPHeader,
					sizeof(*g_pTCPHeader),
					MHdrSize + nIPhdrLen,
					&amp;nNumberOfBytesRead
					);

				//TCP头不完整,不允许通过
				if(nNumberOfBytesRead<sizeof(struct tcphdr)) return DENY;	

				//fetch pkt data
				datasize=Packet->Private.TotalLength-MHdrSize-nIPhdrLen-sizeof(struct tcphdr);
				ppktdata=UTIL_AllocateMemory(datasize);						
				UTIL_ReadOnPacket(
					Packet,
					ppktdata,
					datasize,
					MHdrSize + nIPhdrLen+sizeof(struct tcphdr),
					&amp;nNumberOfBytesRead
					);

				nAction=UTIL_MatchTcpRule(g_pIPHeader, g_pTCPHeader, Direct);

				//examine data
				if (nAction==ALLOW)
				{
					//if contain keyword ,drop
					bisinclude=UTIL_ExamineData(ppktdata,datasize,UTIL_ntohs(g_pTCPHeader->th_sport),UTIL_ntohs(g_pTCPHeader->th_dport));
					if (bisinclude)
						nAction=DENY;
				}
			}
			break;

		case IPPROTO_UDP:
			if(UTIL_ExamineURL(g_pIPHeader->ip_dst.s_addr,g_pIPHeader->ip_src.s_addr))
				nAction=DENY;
			else{
				UTIL_ReadOnPacket(
					Packet,
					(PUCHAR)g_pUDPHeader,
					sizeof(*g_pUDPHeader),
					MHdrSize + nIPhdrLen,
					&amp;nNumberOfBytesRead
					);
				if(nNumberOfBytesRead<sizeof(struct udphdr)) return DENY;	//UDP头不完整,不允许通过 
				nAction=UTIL_MatchUdpRule(g_pIPHeader, g_pUDPHeader, Direct);
			}
			break;

		case IPPROTO_ICMP:
			UTIL_ReadOnPacket(
				Packet,
				(PUCHAR)g_pICMPHeader,
				sizeof(*g_pICMPHeader),
				MHdrSize + nIPhdrLen,
				&amp;nNumberOfBytesRead
				);
			if(nNumberOfBytesRead<4) return DENY;	//ICMP头不完整,不允许通过 
			nAction=UTIL_MatchIcmpRule(g_pIPHeader, g_pICMPHeader, Direct);
			break;

		default:
			nAction=UTIL_MatchIpRule(g_pIPHeader, Direct);
			break;
		}

		if(nAction==NOT_MATCH)
		{
			if(g_Rules.global.fw_mode==RM_ALLOW) 
			{
				switch(nProtocol)
				{
				case IPPROTO_TCP:
					bisinclude=UTIL_ExamineData(ppktdata,datasize,UTIL_ntohs(g_pTCPHeader->th_sport),UTIL_ntohs(g_pTCPHeader->th_dport));
					if (bisinclude)	
						nAction=DENY;
					else
						nAction=ALLOW;
					break;
				case IPPROTO_UDP:
					nAction=ALLOW;
					break;
				case IPPROTO_ICMP:
					nAction=ALLOW;
					break;
				default:
					nAction=ALLOW;
					break;
				}
			}
			else 
			{
				nAction=DENY;
			}
		}

		if (ppktdata)
		{
			UTIL_FreeMemory((void *)ppktdata);
		}

		return nAction;
	}
	else
	{
		nAction=UTIL_MatchNotIpRule(Packet, nEtherType, Direct);
		if(nAction==NOT_MATCH)
		{
			if(g_Rules.global.fw_mode==RM_ALLOW) 
			{
				return ALLOW;
			}
			else
			{
				return DENY;
			}
		}
		return nAction;
	}
}
 
接受答案了.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部