FindNDISNode(IN NDIS_HANDLE ProtocolBindingContext)
{
KIRQL oldIrql;
PLIST_ENTRY thisEntry, listHead;
PNDIS_PROTOCOL_HOOK pNode;
KeAcquireSpinLock(&spinLock, &oldIrql);
listHead=&DoubleHead;
thisEntry=listHead->Flink;
while(1)
{
pNode=CONTAINING_RECORD(thisEntry,NDIS_PROTOCOL_HOOK,ListEntry);
if(pNode->ProtocolBindingContext=ProtocolBindingContext)
return pNode;
else{
thisEntry = thisEntry->Flink;
}
}
KeReleaseSpinLock(&spinLock, oldIrql);
}
NDIS_HANDLE
RegisterUfNDISProtocol(void)
{
NTSTATUS Status = STATUS_SUCCESS;
NDIS_HANDLE hUfProtocol = NULL;
NDIS_PROTOCOL_CHARACTERISTICS UfProtocol;
NDIS_STRING ProtocolName;
NdisZeroMemory(&UfProtocol,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
UfProtocol.MajorNdisVersion = 0x04;
UfProtocol.MinorNdisVersion = 0x0;
NdisInitUnicodeString(&ProtocolName,L"UfProtocol");
UfProtocol.Name = ProtocolName;
UfProtocol.ReceiveHandler = FwNDISProtocolReceive;
NdisRegisterProtocol(&Status,&hUfProtocol,&UfProtocol,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if(Status == STATUS_SUCCESS) return hUfProtocol;
else return NULL;
}
VOID DeregisterUfNDISProtocol(NDIS_HANDLE hUfProtocol)
{
NTSTATUS Status;
NdisDeregisterProtocol(&Status,hUfProtocol);
}
NTSTATUS
HookExistingNDISProtocols(void)
{
PULONG ProtocolPtr;
NDIS_HANDLE hUfProtocol = NULL;
PNDIS_OPEN_BLOCK OpenBlockPtr = NULL;
PNDIS_PROTOCOL_HOOK pNode;
KIRQL oldIrql;
hUfProtocol= RegisterUfNDISProtocol();
if(hUfProtocol == NULL) return STATUS_UNSUCCESSFUL;
ProtocolPtr=(PULONG)hUfProtocol;
ProtocolPtr=(PULONG)((PUCHAR)ProtocolPtr+sizeof(REFERENCE)+8);
ProtocolPtr=(PULONG)(*ProtocolPtr);
while(ProtocolPtr != NULL) {
OpenBlockPtr = (PNDIS_OPEN_BLOCK)(*ProtocolPtr);
if(OpenBlockPtr != NULL) {
pNode =(PNDIS_PROTOCOL_HOOK)ExAllocatePoolWithTag(PagedPool, sizeof(NDIS_PROTOCOL_HOOK),'FU');
if(pNode != NULL) {
pNode->ProtocolBindingContext=OpenBlockPtr->ProtocolBindingContext;
pNode->OpenBlockPtr=OpenBlockPtr;
pNode->RealSendHandler=OpenBlockPtr->SendHandler;
//How about WanSendHandler?
pNode->RealReceiveHandler=OpenBlockPtr->ReceiveHandler;
pNode->RealReceivePacketHandler=OpenBlockPtr-> ReceivePacketHandler ; pNode->RealSendPacketsHandler=OpenBlockPtr->SendPacketsHandler;
pNode->RealTransferDataCompleteHandler=OpenBlockPtr->TransferDataCompleteHandler;
KeAcquireSpinLock(&spinLock, &oldIrql);
InsertTailList(&DoubleHead, &pNode->ListEntry);
KeReleaseSpinLock(&spinLock, oldIrql);
OpenBlockPtr->ReceivePacketHandler=NewReceivePacketHandler;
OpenBlockPtr->TransferDataCompleteHandler=NewTransferDataCompleteHandler ;
OpenBlockPtr->ReceiveHandler=NewReceiveHandler;
}
}
ProtocolPtr = (PULONG)((PUCHAR)ProtocolPtr + sizeof(REFERENCE) + 8);
ProtocolPtr = (PULONG)(*ProtocolPtr);
}
DeregisterUfNDISProtocol(hUfProtocol);
return STATUS_SUCCESS;
}
NTSTATUS
ReleaseExistingNDISProtocols(void)
{
PNDIS_PROTOCOL_HOOK pNode= NULL;
PNDIS_OPEN_BLOCK OpenBlockPtr = NULL;
KIRQL oldIrql;
PLIST_ENTRY thisEntry;
KeAcquireSpinLock(&spinLock, &oldIrql);
if (!IsListEmpty(&DoubleHead)){
thisEntry=RemoveHeadList(&DoubleHead);
PNDIS_PROTOCOL_HOOK pNode=CONTAINING_RECORD (thisEntry,NDIS_PROTOCOL_HOOK,ListEntry);
if(pNode != NULL) {
OpenBlockPtr=pNode->OpenBlockPtr;
if(OpenBlockPtr != NULL) {
OpenBlockPtr->ReceivePacketHandler=pNode->RealReceivePacketHandler;
OpenBlockPtr->ReceiveHandler=pNode->RealReceiveHandler;
OpenBlockPtr->TransferDataCompleteHandler=pNode->RealTransferDataCompleteHandler;
}
ExFreePoolWithTag(pNode,'FU');
}
}
KeReleaseSpinLock(&spinLock, oldIrql);
return STATUS_SUCCESS;
}
NDIS_STATUS
NewReceiveHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookaheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize)
{
NDIS_STATUS status;
PNDIS_PACKET packet=NULL;
PNDIS_BUFFER hdr_buffer=NULL, data_buffer=NULL;
PVOID buf=NULL;
ULONG bytes;
BOOLEAN result=FALSE;
PNDIS_PROTOCOL_HOOK pNode=NULL;
NDIS_HANDLE BindingHandle;
pNode =(PNDIS_PROTOCOL_HOOK)FindNDISNode(ProtocolBindingContext);
BindingHandle=(NDIS_HANDLE)(pNode->OpenBlockPtr);
if(PacketSize <= LookAheadBufferSize)
{
NdisAllocateBuffer(&status, &hdr_buffer, g_buffer_pool, HeaderBuffer, HeaderBufferSize);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("NewReceiveHandler:NdisAllocateBuffer Failed/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisAllocateBuffer(&status, &data_buffer, g_buffer_pool, LookaheadBuffer, LookaheadBufferSize);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("NewReceiveHandler:NdisAllocateBuffer Failed/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisAllocatePacket(&status, &packet, g_packet_pool);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("NewReceiveHandler:NdisAllocatePacket Failed/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisChainBufferAtFront(packet, data_buffer);
NdisChainBufferAtFront(packet, hdr_buffer);
result = FilterPacket(packet);
} else {
Status =NdisAllocateMemoryWithTag(&buf,HeaderBufferSize + PacketSize,'FU');
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("NewReceiveHandler:NdisAllocateMemoryWithTag Failed/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
if(buf == NULL)
{
DbgPrint("NewReceiveHandler:buf==NULL/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisZeroMemory(buf, HeaderBufferSize +PacketSize);
NdisMoveMemory(buf, HeaderBuffer, HeaderBufferSize);
NdisAllocateBuffer(&status, &hdr_buffer, g_buffer_pool, buf, HeaderBufferSize);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("NewReceiveHandler:NdisAllocateBuffer Failed/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisAllocateBuffer(&status, &data_buffer, g_buffer_pool, (char *)buf + HeaderBufferSize, PacketSize);
if(Status !=NDIS_STATUS_SUCCESS)
{
DbgPrint("NewReceiveHandler:NdisAllocateBuffer Failed/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisAllocatePacket(&status, &packet, g_packet_pool);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("NewReceiveHandler:NdisAllocatePacket Failed/n");
return(NDIS_STATUS_NOT_ACCEPTED);
}
NdisChainBufferAtFront(packet, data_buffer);
PROTOCOL_RESERVED(packet)->buffer = hdr_buffer;
NdisTransferData(&Status,
BindingHandle,
MacReceiveContext,
0,
PacketSize,
packet,
&bytes);
if (status == NDIS_STATUS_SUCCESS){
NdisChainBufferAtFront(packet, hdr_buffer);
result = FilterPacket(packet);
} else if (status == NDIS_STATUS_PENDING) {
result = FALSE; // wait for NdisTransferDataComplete to be called
status = NDIS_STATUS_SUCCESS;
buf = NULL;
hdr_buffer = NULL;
data_buffer = NULL;
packet = NULL;
} else
result = FALSE; // drop the packet
}
if (result) {
if (buf == NULL) {
status=pNode->RealReceiveHandler (ProtocolBindingContext,(NDIS_HANDLE)LookaheadBuffer, HeaderBuffer, HeaderBufferSize,
LookaheadBuffer, LookaheadBufferSize, PacketSize);
} else {
status = pNode->RealReceiveHandler (ProtocolBindingContext,
(NDIS_HANDLE)((char *)buf + HeaderBufferSize), HeaderBuffer, HeaderBufferSize,
(char *)buf + HeaderBufferSize, PacketSize, PacketSize);
}
}
if (buf != NULL)
NdisFreeMemory(buf,HeaderBufferSize + PacketSize,0 );
if (hdr_buffer != NULL)
NdisFreeBuffer(hdr_buffer);
if (data_buffer != NULL)
NdisFreeBuffer(data_buffer);
if (packet != NULL)
NdisFreePacket(packet);
return status;
}
VOID
NewTransferDataCompleteHandler (
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred
)
{
PNDIS_BUFFER hdr_buffer, data_buffer;
PVOID buf;
ULONG data_size, hdr_size
BOOLEAN result=FALSE;
PNDIS_PROTOCOL_HOOK pNode=NULL;
NDIS_STATUS status;
pNode = (PNDIS_PROTOCOL_HOOK)FindNDISNode(ProtocolBindingContext);
NdisQueryPacket(Packet, NULL, NULL, &data_buffer, NULL);
hdr_buffer=PROTOCOL_RESERVED(Packet)->buffer;
NdisChainBufferAtFront(Packet, hdr_buffer);
buf=MmGetSystemAddressForMdl(hdr_buffer);
NdisQueryBuffer(hdr_buffer, NULL, &hdr_size);
NdisQueryBuffer(data_buffer, NULL, &data_size);
result = FilterPacket(packet);
if (result) {
pNode->RealReceiveHandler(ProtocolBindingContext,
(NDIS_HANDLE)((char *)buf + hdr_size), buf, hdr_size,
(char *)buf + hdr_size, data_size, data_size);
}
NdisFreeMemory(buf,HeaderBufferSize + PacketSize,0 );
NdisFreeBuffer(hdr_buffer);
NdisFreeBuffer(data_buffer);
NdisFreePacket(Packet);
}
INT
NewReceivePacketHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
)
{
BOOLEAN result=FALSE;
PNDIS_PROTOCOL_HOOK pNode;
pNode=(PNDIS_PROTOCOL_HOOK)FindNDISNode(ProtocolBindingContext);
result=FilterPacket(packet);
if (result) {
return pNode->RealReceivePacketHandler(ProtocolBindingContext, Packet);
}else{
return 0;
}
}
VOID
NewNdisOpenAdapter(
OUT PNDIS_STATUS Status,
OUT PNDIS_STATUS OpenErrorStatus,
OUT PNDIS_HANDLE NdisBindingHandle,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE NdisProtocolHandle,
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_STRING AdapterName,
IN UINT OpenOptions,
IN PSTRING AddressingInformation OPTIONAL)
{
PNDIS_PROTOCOL_HOOK pNode=NULL;
PNDIS_OPEN_BLOCK OpenBlockPtr=NULL;
PNDIS_HANDLE pNdisBindingHandle;
KIRQL oldIrql;
pNdisBindingHandle=NdisBindingHandle;
((NDISOPENADAPTER)(g_OriginalNdisOpenAdapter))(Status, OpenErrorStatus, NdisBindingHandle,SelectedMediumIndex, MediumArray, MediumArraySize,NdisProtocolHandle, ProtocolBindingContext, AdapterName, OpenOptions,AddressingInformation);
OpenBlockPtr=(PNDIS_OPEN_BLOCK)(*pNdisBindingHandle);
if(OpenBlockPtr != NULL) {
pNode = (PNDIS_PROTOCOL_HOOK)ExAllocatePoolWithTag(PagedPool, sizeof(NDIS_PROTOCOL_HOOK),'FU');
if(pNode !=NULL) {
pNode->ProtocolBindingContext=OpenBlockPtr->ProtocolBindingContext;
pNode->OpenBlockPtr=OpenBlockPtr;
pNode->RealReceivePacketHandler=OpenBlockPtr->ReceivePacketHandler;
pNode->RealTransferDataCompleteHandler=OpenBlockPtr->TransferDataCompleteHandler;
pNode->RealReceiveHandler=OpenBlockPtr->ReceiveHandler;
KeAcquireSpinLock(&spinLock, &oldIrql);
InsertTailList(&DoubleHead, &pNode->ListEntry);
KeReleaseSpinLock(&spinLock, oldIrql);
OpenBlockPtr->ReceivePacketHandler=NewReceivePacketHandler;
OpenBlockPtr->TransferDataCompleteHandler=NewTransferDataCompleteHandler ; OpenBlockPtr->ReceiveHandler=NewReceiveHandler;
}
}
}