📄 rndis.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
rndis.c
Abstract:
This module understands RNDIS messages..
Functions:
--*/
#include <windows.h>
#include <ndis.h>
#include <halether.h>
#undef ZONE_INIT
#undef ZONE_WARNING
#include <string.h>
#include <rndismini.h>
#include "mddpriv.h"
#include "rneutil.h"
#include "rndis.h"
#define __THIS_FILE__ TEXT("rndis.cpp")
#ifdef CELOGMSG
#undef CELOGMSG
#endif
#define CELOGMSG(Cond, Printf_exp) ((void)0)//DEBUGCELOGMSG(Cond, Printf_exp)
#define CELOGDUMPDATA(Cond, ID, Data, Len) ((void)0)//DEBUGCELOG(Cond, ID, Data, Len)
#define ZONE_RNDIS DEBUGZONE(1)
#define ZONE_DATA DEBUGZONE(5)
#define ZONE_ERROR DEBUGZONE(15)
#define DEBUG_SINGLE_CHAR 1
#include <celog.h>
////////////////////////////////////////////////////////////////////////////////
// For convenience..
//
#define GET_PTR_TO_RNDIS_DATA_BUFF(_Message) \
((PVOID) ((PUCHAR)(_Message) + _Message->DataOffset))
#define RESERVED_FROM_RECV_PACKET(_Packet) \
((PRCV_RNDIS_PACKET *)((_Packet)->MiniportReserved))
#define NDIS_PACKET_MINIPORTRESERVED(_Packet) \
((_Packet)->MiniportReserved)
#define MIN(x,y) ((x > y) ? y : x)
DWORD OEMEthGetSecs(void);
////////////////////////////////////////////////////////////////////////////////
// Externs..
//
//extern NPAGED_LOOKASIDE_LIST DataWrapperLookAsideList;
////////////////////////////////////////////////////////////////////////////////
// Global variable for RNDIS MDD..
//
RNDIS_MDD RndisMdd;
//NPAGED_LOOKASIDE_LIST RcvRndisPacketLookAsideList;
//NDIS_HANDLE NdisPacketPool;
//NDIS_HANDLE NdisBufferPool;
//HANDLE g_TxEvent;
// RNDIS Message Buffer
static BufferDescript MsgBufferDesc;
static BYTE MsgBuffer[MAX_PACKET_SIZE+4*(sizeof(DATA_WRAPPER)+sizeof(DWORD))];
// Ethernet Frame
#define MAX_ETH_BLOCK 1520
static BufferDescript EthBufferDesc;
static BYTE EthBuffer[(MAX_ETH_BLOCK+sizeof(DWORD))*10];
////////////////////////////////////////////////////////////////////////////////
// RndisStartRNDISMINI1()
//
// Routine Description:
//
// Thread that instantiate the virtual adapter instance.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//void
//RndisStartRNDISMINI1(void)
//{
// VMiniInstantiateMiniport(TRUE);
//
//} // RndisStartRNDISMINI1()
////////////////////////////////////////////////////////////////////////////////
// RndisForceReturnCEVminiPackets()
//
// Routine Description:
//
// Force return all packets we queued in listVMiniNdisPackets.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
// Note:
//
// ** WARNING ** This function should only be called in the INTERRUPT
// context!!!
//
/*
void
RndisForceReturnCEVminiPackets(void)
{
PLIST_ENTRY pLink;
PNDIS_PACKET pNdisPacket;
EnterCriticalSection(&RndisMdd.lockVMiniNdisPackets);
while (!IsListEmpty(&(RndisMdd.listVMiniNdisPackets)))
{
ASSERT(RndisMdd.dwTotalVMiniPendings);
pLink = RemoveHeadList(&(RndisMdd.listVMiniNdisPackets));
RndisMdd.dwTotalVMiniPendings--;
pNdisPacket = CONTAINING_RECORD(
pLink,
NDIS_PACKET,
MiniportReserved);
//
// Return the NdisPacket to VMini now..
// Can't be in CS since VMiniIndicatePacketDone() will use NDIS CS
// and NDIS may be calling RndisSendPacket() hence a deadlock!
//
LeaveCriticalSection(&RndisMdd.lockVMiniNdisPackets);
VMiniIndicatePacketDone(
pNdisPacket);
EnterCriticalSection(&RndisMdd.lockVMiniNdisPackets);
}
LeaveCriticalSection(&RndisMdd.lockVMiniNdisPackets);
} // RndisForceReturnCEVminiPackets()
*/
////////////////////////////////////////////////////////////////////////////////
// RndisRestart()
//
// Routine Description:
//
// DeInitialize RNDISMINI1 and get us back to RNDIS_UNINITIALIZED state
// ready for new connection..
//
// Arguments:
//
// bResetPDD :: TRUE if we need to reset the PDD, FALSE otherwise.
//
// Return Value:
//
// None.
//
// Note:
//
// ** WARNING ** This function should only be called in the INTERRUPT
// context!!!
//
void
RndisRestart(BOOL bResetPDD)
{
CELOGMSG (ZONE_INIT, (TEXT("RNDISMINI --- RESTART ---\r\n")));
EdbgOutputDebugString("RNDISMINI --- RESET ---\r\n");
RndisMdd.dwDeviceState = RNDIS_UNINITIALIZED;
//
// 1. Deinitialize RNDISMINI1 which in its ShutDownHandler() will get
// us to return all its pending TX packets.
//
// 2. Hard Reset PDD.
// This should cause PDD to return all pending RNDIS messages that
// it may be half sending, and reset its hw to ready a future
// new connection.
//
//
// Tear down CE Miniport driver RNDISMINI1
//
// VMiniInstantiateMiniport(FALSE);
if (bResetPDD)
{
//
// HardReset the hardware here..
// Somehow we need to wait a while till host is not looking to do this.
// Otherwise host will fail to unload cleanly the rndis host
// driver (???)
//
// Sleep(500);
DWORD dwStartSec=OEMEthGetSecs();
while (dwStartSec==OEMEthGetSecs()); // Wait 1 second.
RndisMdd.PddCharacteristics.SetHandler(
REQ_ID_HARD_RESET,
NULL,
0x00);
// PDD_Set(
// REQ_ID_HARD_RESET,
// NULL,
// 0x00);
}
// else
// RndisMdd.PddCharacteristics.SetHandler(
// REQ_ID_SOFT_RESET,
// NULL,
// 0x00);
// PDD_Set(
// REQ_ID_SOFT_RESET,
// NULL,
// 0x00);
// Reset to internal flag
RndisMdd.dwCurrentPacketFilter=0;
//InBuffer.dwDataSize==0;
//BufferReset();
} // RndisRestart()
////////////////////////////////////////////////////////////////////////////////
// RndisPrepareRndisPacket()
//
// Routine Description:
//
// This function forms a linke DATA_WRAPPER and queue that to pListEntry.
//
// Arguments:
//
// pNdisPacket :: The NdisPacket that contains user data.
// pListEntry :: Where we link the DATA_WRAPPER containing RNDIS_PACKET
// data header and the NdisBuffer from NdisPacket.
// The newly formed DATA_WRAPPER will be linked at the
// end of this list.
// pdwTotalLen :: Total Length of the collection of RNDIS_PACKETs so far..
//
// Return Value:
//
// SUCCESS, ERROR_NO_MEM, ERROR_MAX_REACHED
//
#define SUCCESS 0x00000000
#define ERROR_MAX_REACHED 0x00000002
DWORD
RndisPrepareRndisPacket(
PBYTE pDataBuffer,
DWORD dwDataLen,
PRNDIS_MESSAGE pRndisMessage,
DWORD dwTotalMessageBufferSize)
{
DWORD dwCurrentPacketLength;
// DWORD dwTotalDataLength;
// PRNDIS_MESSAGE pRndisMessage;
PRNDIS_PACKET pRndisPacket;
// PNDIS_BUFFER pNdisBuffer;
CELOGMSG (ZONE_RNDIS,
(TEXT("RNdis:: PrePareRndisPacket (%d Bytes)\r\n"),dwDataLen));
if (pRndisMessage) {
dwCurrentPacketLength =
RNDIS_MESSAGE_SIZE (RNDIS_PACKET) +
dwDataLen;
//
// Pad it to multiple of 8 bytes (required by RNDIS host).
//
dwCurrentPacketLength += (8 - (dwCurrentPacketLength % 8));
if (dwCurrentPacketLength > dwTotalMessageBufferSize)
{
EdbgOutputDebugString("RNdis:: Too much outgoing, bailing out!\r\n");
CELOGMSG (ZONE_RNDIS,(TEXT("RNdis:: Max[%d] SoFar[%d] CurentPacket[%d]\r\n"),
dwTotalMessageBufferSize,
0,
dwCurrentPacketLength));
return ERROR_MAX_REACHED;
}
//
// Okay, it fits.. make it..
//
// Fill up the RNDIS_PACKET header
//
pRndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
pRndisMessage->MessageLength = dwCurrentPacketLength;
pRndisPacket = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pRndisMessage);
pRndisPacket->DataOffset = sizeof(RNDIS_PACKET);
pRndisPacket->DataLength = dwDataLen;
pRndisPacket->OOBDataOffset = 0x00;
pRndisPacket->OOBDataLength = 0x00;
pRndisPacket->NumOOBDataElements = 0x00;
pRndisPacket->PerPacketInfoOffset = 0x00;
pRndisPacket->PerPacketInfoLength = 0x00;
pRndisPacket->VcHandle = 0x00;
pRndisPacket->Reserved = 0x00;
//
// Now, handle the NDIS_BUFFERs
//
memcpy(pRndisPacket+1,pDataBuffer,dwDataLen);
//
// Outta here with flying color..
// Here is the new offset..
//
};
return SUCCESS;
} // RndisPrepareRndisPacket()
// Rndis SendPacket flag
BOOL bRndisSendPacketEmpty=TRUE;
BOOL PDD_IsPacketSend(void)
{
return bRndisSendPacketEmpty;
}
void
MddSendRndisPacketComplete(PDATA_WRAPPER pDataWrapper)
{
bRndisSendPacketEmpty=TRUE;
} // MddSendRndisPacketComplete()
////////////////////////////////////////////////////////////////////////////////
// RndisSendPacket()
//
// Routine Description:
//
// When VMini has packet to indicate up to the Rndis host..
// If we are not already sending, then start the PDD to send otherwise
// queue this NdisPacket.
//
// Arguments:
//
// pNdisPacket :: The Ndis packet.
//
// Return Value:
//
// TRUE if we want to keep the packet, FALSE otherwise.
//
#define RNDIS_MESSAGE_HEAD_SIZE (sizeof(RNDIS_MESSAGE) - sizeof(RNDIS_MESSAGE_CONTAINER))
UINT16 RndisEDbgSendFrame(BYTE * pData, DWORD dwLength)
{
DWORD dwTotalLen = 0x00;
DWORD dwWaitMSec=0;
BOOL bSuccess = FALSE;
static BYTE bTempBuffer[MAX_PACKET_SIZE];
PRNDIS_MESSAGE pRndisMessage=(PRNDIS_MESSAGE)bTempBuffer;
DWORD dwTotalMessageBufferSize=MAX_PACKET_SIZE- RNDIS_MESSAGE_HEAD_SIZE;
DWORD dwStartSec=OEMEthGetSecs();
CELOGMSG (ZONE_DATA,(TEXT("Rndis::RndisEDbgSendFrame(dwLength=%d)\r\n"),dwLength));
while (RndisMdd.dwCurrentPacketFilter == 0 && OEMEthGetSecs()- dwStartSec <2)
//PDD_ISR();
RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);
if (RndisMdd.dwCurrentPacketFilter == 0)
{
CELOGMSG (ZONE_DATA,(TEXT("Rndis::RndisSendPacket() to host:: Reject! filter == 0\r\n")));
return 1;
}
if (RndisPrepareRndisPacket(pData,dwLength,pRndisMessage,dwTotalMessageBufferSize)
==SUCCESS) {
static DATA_WRAPPER DataWrapper;
dwStartSec=OEMEthGetSecs();
DataWrapper.Link.Flink= DataWrapper.Link.Blink=NULL;
DataWrapper.pucData=bTempBuffer;
DataWrapper.dwDataSize=pRndisMessage->MessageLength + RNDIS_MESSAGE_HEAD_SIZE;
bRndisSendPacketEmpty=FALSE;
do
{
//
// PDD is idling, kick start the sending process..
//
// if (PDD_SendRndisPacket(&DataWrapper)) {
RndisMdd.PddCharacteristics.SendRndisPacketHandler(&DataWrapper);
bSuccess = TRUE;
// }
// PDD_ISR();
RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);
}while (!bSuccess && (OEMEthGetSecs()-dwStartSec<2));
if (bSuccess) { // Loop until success.
while (!PDD_IsPacketSend())
// PDD_ISR();
RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);
}
}
// PDD_ISR();
RndisMdd.PddCharacteristics.ISRHandler(&dwWaitMSec);
// EdbgOutputDebugString("Rndis::RndisEDbgSendFrame return (%d) Byte (%d)\r\n",bSuccess,dwLength);
return (bSuccess?0:1);
} // RndisSendPacket()
void
MddSendRndisMessageComplete(PDATA_WRAPPER pDataWrapper)
{
if (FreeBuffer(&MsgBufferDesc, pDataWrapper)==FALSE) {
EdbgOutputDebugString("ASSERT! Rndis::MddSendRndisMessageComplete return FALSE\r\n");
}
} // MddSendRndisMessageComplete();
////////////////////////////////////////////////////////////////////////////////
// RndisSendRndisMessage()
//
// Routine Description:
//
// This function creates RNDIS message and send it out.
//
// Arguments:
//
// None.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -