📄 prothook.c
字号:
/*——————————————————————————————————————
文件:protocol.c
工程:xpassthru
概述:演示NDIS中间驱动程序输出封包结构信息
版权所有(c) 2001-2002 X 工作室
http://www.xfilt.com
xstudio@xfilt.com
*/
#include "prexsim.h"
#pragma hdrstop
#define MAX_PACKET_POOL_SIZE 0x0000FFFF
#define MIN_PACKET_POOL_SIZE 0x000000FF
NDIS_STATUS
PtRegisterAsProtocol(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NDIS_STATUS Status;
NDIS_PROTOCOL_CHARACTERISTICS ProtocolStruct;
NDIS_STRING Name;
NdisZeroMemory(&ProtocolStruct, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
ProtocolStruct.MajorNdisVersion = 4;
ProtocolStruct.MinorNdisVersion = 0;
NdisInitUnicodeString(&Name, L"xfilter"); // Protocol名称
ProtocolStruct.Name = Name;
ProtocolStruct.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
ProtocolStruct.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
ProtocolStruct.SendCompleteHandler = PtSendComplete;
ProtocolStruct.TransferDataCompleteHandler = PtTransferDataComplete;
ProtocolStruct.ResetCompleteHandler = PtResetComplete;
ProtocolStruct.RequestCompleteHandler = PtRequestComplete;
ProtocolStruct.ReceiveHandler = PtReceive;
ProtocolStruct.ReceiveCompleteHandler = PtReceiveComplete;
ProtocolStruct.StatusHandler = PtStatus;
ProtocolStruct.StatusCompleteHandler = PtStatusComplete;
ProtocolStruct.BindAdapterHandler = PtBindAdapter;
ProtocolStruct.UnbindAdapterHandler = PtUnbindAdapter;
ProtocolStruct.UnloadHandler = NULL;
ProtocolStruct.ReceivePacketHandler = PtReceivePacket;
ProtocolStruct.PnPEventHandler = PtPNPHandler;
NdisRegisterProtocol(&Status, &ProtHandle
, &ProtocolStruct, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
DBGPRINT("<== NdisRegisterProtocol.\n");
return Status;
}
/*——————————————————————————————————————
被NDIS调用将Protocol驱动绑定到下层的miniport设备。详情请参阅DDK文档关于
ProtocolBindAdapter函数的解释。
*/
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("UpperBindings");
PADAPT pAdapt = NULL;
NDIS_STATUS Sts;
UINT MediumIndex;
PNDIS_CONFIGURATION_PARAMETER BundleParam;
NDIS_STRING BundleStr = NDIS_STRING_CONST("BundleId");
NDIS_STATUS BundleStatus;
DBGPRINT("==> Passthru Protocol Initialize PtBindAdapter\n");
do
{
//——————————————————————————————————
// 打开Protocol配置得到句柄ConfigHandle
//
NdisOpenProtocolConfiguration(Status, &ConfigHandle, SystemSpecific1);
if (*Status != NDIS_STATUS_SUCCESS) break;
//——————————————————————————————————
// 利用句柄ConfigHandle读出配置参数到Param结构
//
NdisReadConfiguration(Status, &Param
, ConfigHandle, &DeviceStr, NdisParameterString);
if (*Status != NDIS_STATUS_SUCCESS) break;
//——————————————————————————————————
// 为Adapter结构分配内存
//
NdisAllocateMemoryWithTag(&pAdapt, sizeof(ADAPT), TAG);
if (pAdapt == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
//——————————————————————————————————
// 初始化Adapter结构数据为0
//
NdisZeroMemory(pAdapt, sizeof(ADAPT));
//——————————————————————————————————
// 初始化pAdapt->BundleUniString.Buffer,这个缓冲区将用来保存从注册
// 表读出来的数据。
//
NdisAllocateMemoryWithTag(
&(pAdapt->BundleUniString.Buffer), MAX_BUNDLEID_LENGTH ,TAG);
if (pAdapt->BundleUniString.Buffer == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
pAdapt->BundleUniString.MaximumLength = MAX_BUNDLEID_LENGTH ;
NdisReadConfiguration(&BundleStatus
, &BundleParam, ConfigHandle, &BundleStr, NdisParameterString);
if (BundleStatus == NDIS_STATUS_SUCCESS)
{
//————————————————————————————————
// 复制绑定标识到自己初始化的缓冲区pAdapt->BundleUniString
//
ASSERT(pAdapt->BundleUniString.MaximumLength
>= BundleParam->ParameterData.StringData.Length);
pAdapt->BundleUniString.Length
= BundleParam->ParameterData.StringData.Length;
RtlCopyUnicodeString(
&pAdapt->BundleUniString, &BundleParam->ParameterData.StringData);
}
else
{
//————————————————————————————————
// 没有在注册表里找到绑定ID,设定BundleUniString为"<no-bundle>"
//
NDIS_STRING NoBundle = NDIS_STRING_CONST ("<no-bundle>");
RtlCopyUnicodeString(&pAdapt->BundleUniString, &NoBundle);
}
//——————————————————————————————————
// 初始化Event并加同步锁
//
NdisInitializeEvent(&pAdapt->Event);
KeInitializeSpinLock(&pAdapt->SpinLock);
//——————————————————————————————————
// 为发送封包分配内存缓冲池
//
NdisAllocatePacketPoolEx(Status,
&pAdapt->SendPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
sizeof(RSVD));
if (*Status != NDIS_STATUS_SUCCESS) break;
//——————————————————————————————————
// 为接收封包分配内存缓冲池
//
NdisAllocatePacketPoolEx(Status,
&pAdapt->RecvPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
sizeof(RSVD));
if (*Status != NDIS_STATUS_SUCCESS) break;
//——————————————————————————————————
// 打开底层adapter设备并且完成初始化
//
NdisOpenAdapter(Status, &Sts, &pAdapt->BindingHandle, &MediumIndex,
MediumArray, sizeof(MediumArray)/sizeof(NDIS_MEDIUM), ProtHandle,
pAdapt, DeviceName, 0, NULL);
if(*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
if(*Status != NDIS_STATUS_SUCCESS) break;
pAdapt->Medium = MediumArray[MediumIndex];
//——————————————————————————————————
// 告诉NDIS初始化我们的miniport设备
//
NdisIMInitializeDeviceInstanceEx(
DriverHandle, &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("<== Passthru Protocol Initialize\n");
}
/*——————————————————————————————————————
在PtBindAdapter里调用NdisOpenAdapter完成绑定后执行,用来解除阻塞状态。
详情请参阅DDK文档关于ProtocolOpenAdapterComplete函数的解释。
*/
VOID
PtOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
pAdapt->Status = Status;
DBGPRINT("==> Passthru PtOpenAdapterComplete\n");
NdisSetEvent(&pAdapt->Event);
}
/*——————————————————————————————————————
当我需要解除与底层adapter设备的绑定时由NDIS调用,这个函数使用miniport的
HaltHandler共享功能函数,这段代码应该保证NdisCloseAdapter和NdisFreeMemory
这两个函数只能被调用一次。
*/
VOID
PtUnbindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
)
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
NDIS_HANDLE BindingHandle = pAdapt->BindingHandle;
DBGPRINT("==> Passthru PtUnbindAdapter\n");
if (pAdapt->QueuedRequest == TRUE)
{
pAdapt->QueuedRequest = FALSE;
PtRequestComplete (pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE );
}
//————————————————————————————————————
// 调用NDIS移除设备句柄,通常我们需要在HaltHandler做许多工作。
//
// 如果passthru的miniport的halt handler已经被调用或者如果中间设备根本没有
// 初始化,这个句柄将为NULL。
//
if(pAdapt->MiniportHandle != NULL)
{
*Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);
if(*Status != NDIS_STATUS_SUCCESS) *Status = NDIS_STATUS_FAILURE;
}
else
{
//——————————————————————————————————
// 关闭底层绑定并且释放内存
//
if(pAdapt->BindingHandle != NULL)
{
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(Status, pAdapt->BindingHandle);
//————————————————————————————————
// 等待结束
//
if(*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
}
else
{
//————————————————————————————————
// Miniport句柄和绑定句柄不应该为NULL,为NULL则设置错误状态。
//
*Status = NDIS_STATUS_FAILURE;
ASSERT(0);
}
//——————————————————————————————————
// 在这里释放内存
//
NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
}
DBGPRINT("<==Passthru UnbindAdapter\n");
}
/*——————————————————————————————————————
这是一个可选函数,在这里调用NdisDeregisterProtocol释放执行
NdisRegisterProtocol注册protocol时使用的资源.
*/
VOID
PtUnload(
IN PDRIVER_OBJECT DriverObject
)
{
NDIS_STATUS Status;
NdisDeregisterProtocol(&Status, ProtHandle);
DBGPRINT("<== Passthru Protocol PtUnload\n");
}
/*——————————————————————————————————————
关闭adapter完成后的处理函数
*/
VOID
PtCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -