📄 minihook.c
字号:
/*——————————————————————————————————————
文件:miniport.c
工程:xpassthru
概述:演示NDIS中间驱动程序输出封包结构信息
版权所有(c) 2001-2002 X 工作室
http://www.xfilt.com
xstudio@xfilt.com
*/
#include "prexsim.h"
#pragma hdrstop
NDIS_STATUS
MPRegisterAsMiniport(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NDIS_STATUS Status;
NDIS_MINIPORT_CHARACTERISTICS MiniportStruct;
NdisZeroMemory(&MiniportStruct, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
MiniportStruct.MajorNdisVersion = 4;
MiniportStruct.MinorNdisVersion = 0;
MiniportStruct.Reserved = 0;
MiniportStruct.HaltHandler = MPHalt;
MiniportStruct.InitializeHandler = MPInitialize;
MiniportStruct.QueryInformationHandler = MPQueryInformation;
MiniportStruct.SetInformationHandler = MPSetInformation;
MiniportStruct.ResetHandler = MPReset;
MiniportStruct.TransferDataHandler = MPTransferData;
MiniportStruct.ReconfigureHandler = NULL;
MiniportStruct.DisableInterruptHandler = NULL;
MiniportStruct.EnableInterruptHandler = NULL;
MiniportStruct.HandleInterruptHandler = NULL;
MiniportStruct.ISRHandler = NULL;
MiniportStruct.AllocateCompleteHandler = NULL;
MiniportStruct.CheckForHangHandler = NULL;
MiniportStruct.SendHandler = MPSend;
MiniportStruct.ReturnPacketHandler = MPReturnPacket;
//————————————————————————————————————
// 尽管Send或者SendPackets函数指针应该指定,但是如果SendPackets指针被
// 指定则SendHandler函数将被忽略,所以只需保留一个。
//
MiniportStruct.SendPacketsHandler = MPSendPackets;
Status = NdisIMRegisterLayeredMiniport(
WrapperHandle, &MiniportStruct, sizeof(MiniportStruct), &DriverHandle);
DbgPrint("<== NdisIMRegisterLayeredMiniport,the return code is %u.\n", Status);
return Status;
}
/*——————————————————————————————————————
Miniport设备的初始化函数,初始化状态值,并加入全局列表已备调用
详情请参阅DDK帮助文档关于MiniportInitialize函数的解释
*/
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
)
{
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");
//————————————————————————————————————
// 首先通过MiniportAdapterHandle句柄得到adapter结构并保存MiniportHandle
//
pAdapt = NdisIMGetDeviceContext(MiniportAdapterHandle);
pAdapt->MiniportHandle = MiniportAdapterHandle;
//————————————————————————————————————
// 通过循环语句验证Medium的合法性,并设置当前选择的Medium索引值。
//
for (i = 0; i < MediumArraySize; i++)
{
if (MediumArray[i] == pAdapt->Medium)
{
*SelectedMediumIndex = i;
break;
}
}
if (i == MediumArraySize)
return(NDIS_STATUS_UNSUPPORTED_MEDIA);
//————————————————————————————————————
// 设置MiniportAdapter的属性
//
NdisMSetAttributesEx(MiniportAdapterHandle,
pAdapt,
0, // 检查时允许挂起的时间,单位为秒。
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
NDIS_ATTRIBUTE_DESERIALIZE |
NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
0);
//————————————————————————————————————
// 设置Miniport和Protocol设备的状态为NdisDeviceStateD0
// NdisDeviceStateD0表示设备电源管理准备就绪已经激活,默认值为ON。
//
pAdapt->MPDeviceState = NdisDeviceStateD0;
pAdapt->PTDeviceState = NdisDeviceStateD0;
//————————————————————————————————————
// 开始加载列表并绑定标识,设置为默认选项,miniport作为主miniport
//
pAdapt->isSecondary = FALSE; // 默认为主不是副
pAdapt->pPrimaryAdapt = pAdapt; // 默认主adapter为自己
pAdapt->pSecondaryAdapt = pAdapt; // 默认副adapter也为自己
//————————————————————————————————————
// 调用自定义函数MPBundleSearchAndSetSecondary设置下一个adapter
//
BundleStatus = MPBundleSearchAndSetSecondary (pAdapt);
//————————————————————————————————————
// 将本身加入到全局的Adapter列表,在操作全局变量时,为了使多进程间同步
// 使用KeAcquireSpinLock和KeReleaseSpinLock进行加锁和解锁。
//
KeAcquireSpinLock (&pAdapt->SpinLock, &OldIrql);
pAdapt->Next = pAdaptList;
pAdaptList = pAdapt;
KeReleaseSpinLock (&pAdapt->SpinLock, OldIrql);
//————————————————————————————————————
// 当前中间驱动程序初始化完成,设置返回的状态值。
//
Status = NDIS_STATUS_SUCCESS;
DBGPRINT("<== Passthru Initialize Miniport\n");
return Status;
}
/*——————————————————————————————————————
查询驱动或者网卡的性能和状态。详情请参阅DDK文档关于
MiniportQueryInformation的说明。
*/
NDIS_STATUS
MPQueryInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded
)
{
//————————————————————————————————————
// 调用自定义函数MPQueryOrSetInformation查询驱动或者网卡的性能和状态。
//
return MPQueryOrSetInformation(
TRUE,
MiniportAdapterContext,
Oid,
InformationBuffer,
InformationBufferLength,
BytesWritten,
BytesNeeded
);
}
/*——————————————————————————————————————
设置驱动或者网卡的性能和状态。详情请参阅DDK文档关于
MiniportSetInformation的说明。
*/
NDIS_STATUS
MPSetInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
{
//————————————————————————————————————
// 调用自定义函数MPQueryOrSetInformation设置驱动或者网卡的性能和状态。
//
return MPQueryOrSetInformation(
FALSE,
MiniportAdapterContext,
Oid,
InformationBuffer,
InformationBufferLength,
BytesRead,
BytesNeeded
);
}
/*——————————————————————————————————————
查询或者设置驱动或者网卡的性能和状态。
*/
NDIS_STATUS
MPQueryOrSetInformation(
IN BOOLEAN IsQuery,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWrittenOrRead,
OUT PULONG BytesNeeded
)
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
DBGPRINT("==>Passthru Miniport MPQueryInformation\n");
//————————————————————————————————————
// 这个循环语句并不是真正的循环执行,因为碰到它的条件语句while(FALSE)
// 循环就会结束,这样做的目的是碰到break语句可以直接跳出循环继续执行,
// 从而可以忽略break语句之后循环语句之内语句的执行。
//
do
{
if(IsQuery)
{
//————————————————————————————————
// 这个OID是OID_PNP_QUERY_POWER,返回成功。
//
if (Oid == OID_PNP_QUERY_POWER)
{
Status = NDIS_STATUS_SUCCESS;
break;
}
}
else
{
//————————————————————————————————
// 这个OID是OID_PNP_SET_POWER,调用自定义函数
// MPProcessSetPowerOid 设置是否阻断或者允许引入的请求。
//
if (Oid == OID_PNP_SET_POWER)
{
MPProcessSetPowerOid( &Status, pAdapt, InformationBuffer
, InformationBufferLength, BytesWrittenOrRead, BytesNeeded);
break;
}
}
//——————————————————————————————————
// 如果miniport的状态不是NdisDeviceStateD0,表示没有准备就绪返回失败。
//
if (pAdapt->MPDeviceState
> NdisDeviceStateD0 || pAdapt->StandingBy == TRUE)
{
Status = NDIS_STATUS_FAILURE;
break;
}
//——————————————————————————————————
// 根据Oid调用自定义函数MPIsSendOID判断是否为发送状态,如果是发送
// 状态,将pAdapt指针设置为下一个adapter的指针。
//
if (IsQuery && MPIsSendOID(Oid))pAdapt = pAdapt->pSecondaryAdapt;
//——————————————————————————————————
// 设置adapter的结构数据。
//
if(IsQuery)
{
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;
}
else
{
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 = BytesWrittenOrRead;
pAdapt->OutstandingRequests = TRUE;
//——————————————————————————————————
// 如果Protocol设备没有准备就绪则请求不能向下转发,只能设置成Pending
// 状态,表示未转发。
//
if (pAdapt->PTDeviceState > NdisDeviceStateD0)
{
pAdapt->QueuedRequest = TRUE;
Status = NDIS_STATUS_PENDING;
break;
}
//——————————————————————————————————
// 默认处理通常直接调用系统函数NdisRequest将请求向Miniport下层转发。
//
NdisRequest(&Status, pAdapt->BindingHandle, &pAdapt->Request);
//——————————————————————————————————
// 如果转发返回成功,则将结果返回到发出请求的调用者。
//
if (Status == NDIS_STATUS_SUCCESS)
{
if(IsQuery)
{
*BytesWrittenOrRead
= pAdapt->Request.DATA.QUERY_INFORMATION.BytesWritten;
*BytesNeeded
= pAdapt->Request.DATA.QUERY_INFORMATION.BytesNeeded;
}
else
{
*BytesWrittenOrRead
= pAdapt->Request.DATA.SET_INFORMATION.BytesRead;
*BytesNeeded
= pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded;
}
}
//——————————————————————————————————
// 如果Oid == OID_PNP_CAPABILITIES并且NdisRequest查询成功,调用自定义
// 函数MPQueryPNPCapbilities填充adapter结构中必须的数值。
//
if (IsQuery && Oid == OID_PNP_CAPABILITIES
&& Status == NDIS_STATUS_SUCCESS)
MPQueryPNPCapbilities(pAdapt, &Status);
//——————————————————————————————————
// 如果状态不是NDIS_STATUS_PENDING,设置OutstandingRequests为FALSE
//
if (Status != NDIS_STATUS_PENDING)
pAdapt->OutstandingRequests = FALSE;
} while (FALSE);
return(Status);
}
/*——————————————————————————————————————
填充adapter结构中pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer
和其它一些状态值。
*/
VOID
MPQueryPNPCapbilities(
IN OUT PADAPT pAdapt,
OUT PNDIS_STATUS pStatus
)
{
PNDIS_PNP_CAPABILITIES pPNPCapabilities;
PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
DBGPRINT("==>Passthru Miniport MPQueryPNPCapbilities\n");
if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength
>= sizeof(NDIS_PNP_CAPABILITIES))
{
//——————————————————————————————————
// 先将InformationBuffer强制转换成PNDIS_PNP_CAPABILITIES类型,然后
// 将指针赋值到pPMstruct,通过pPMstruct设置InformationBuffer的数据。
//
pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)
(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);
pPMstruct= & pPNPCapabilities->WakeUpCapabilities;
pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
//——————————————————————————————————
// 设置pAdapt结构的数值和设备状态
//
*pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);
*pAdapt->BytesNeeded = 0;
pAdapt->MPDeviceState = NdisDeviceStateD0;
pAdapt->PTDeviceState = NdisDeviceStateD0;
*pStatus = NDIS_STATUS_SUCCESS;
}
else
{
*pAdapt->BytesNeeded= sizeof(NDIS_PNP_CAPABILITIES);
*pStatus = NDIS_STATUS_RESOURCES;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -