⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minihook.c

📁 Windows防火墙与网络封包截获技术源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*——————————————————————————————————————
	文件: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 + -