VOID LoadDynamicFunction() { NDIS_STRING CancelSendPackets,GetPoolFromPacket,IMGetCurrentPacketStack,IMNotifyPnPEvent; PVOID pNdisBaseAddress = NULL; PsGetVersion(&gSfOsMajorVersion,&gSfOsMinorVersion,NULL,NULL); // 为了兼容没有SP补丁的Windows 2000 系统, // 我们使用 自定义的函数取代 NdisGetRoutineAddress函数功能 if( IS_NDIS51() ) { RtlInitUnicodeString(&CancelSendPackets,L"NdisCancelSendPackets"); MyNdisCancelSendPackets = (NDISCANCELSENDPACKETS)NdisGetRoutineAddress(&CancelSendPackets); RtlInitUnicodeString(&GetPoolFromPacket,L"NdisGetPoolFromPacket"); MyNdisGetPoolFromPacket = (NDISGETPOOLFROMPACKET)NdisGetRoutineAddress(&GetPoolFromPacket); RtlInitUnicodeString(&IMGetCurrentPacketStack,L"NdisIMGetCurrentPacketStack"); MyNdisIMGetCurrentPacketStack = (NDISIMGETCURRENTPACKETSTACK)NdisGetRoutineAddress(&IMGetCurrentPacketStack); RtlInitUnicodeString(&IMNotifyPnPEvent,L"NdisIMNotifyPnPEvent"); MyNdisIMNotifyPnPEvent = (NDISIMNOTIFYPNPEVENT)NdisGetRoutineAddress(&IMNotifyPnPEvent); } }
/** This implementation picks the NDIS 6.2 Read/Write lock structures & API on OS versions where NDIS support those and would pick the older API on NDIS 6.0. Since the new API are not available on NDIS 6.0 OS, it does not link the new API into the binary, instead it dynamically loads the API address & uses them. This way the same binary can run on both NDIS 6.0 & 6.2 OSes, using the correct API for that OS. */ NDIS_STATUS MpDetermineRWLockType() { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG ndisVersion; NDIS_STRING allocateRoutineName; NDIS_STRING freeRoutineName; NDIS_STRING acquireReadRoutineName; NDIS_STRING acquireWriteRoutineName; NDIS_STRING releaseRoutineName; do { NdisZeroMemory(&GlobalRWLockHandlers, sizeof(MP_RW_LOCK_HANDLERS)); // Start with pre NDIS 6.2 using the old API. If this is NDIS 6.2+ and // we cannot find address of new API, we will fail GlobalRWLockHandlers.AllocateHandler = MpAllocateOldRWLock; GlobalRWLockHandlers.FreeHandler = MpFreeOldRWLock; GlobalRWLockHandlers.AcquireReadHandler = MpAcquireOldRWLockForRead; GlobalRWLockHandlers.AcquireWriteHandler = MpAcquireOldRWLockForWrite; GlobalRWLockHandlers.ReleaseHandler = MpReleaseOldRWLock; ndisVersion = NdisGetVersion(); if (ndisVersion > MP_NDIS_VERSION_NEEDS_COMPATIBILITY) { // NDIS 6.2 or above. Use the new API // Load the address of the new NDisRead/Write lock API NdisInitUnicodeString(&allocateRoutineName, L"NdisAllocateRWLock"); NdisInitUnicodeString(&freeRoutineName, L"NdisFreeRWLock"); NdisInitUnicodeString(&acquireReadRoutineName, L"NdisAcquireRWLockRead"); NdisInitUnicodeString(&acquireWriteRoutineName, L"NdisAcquireRWLockWrite"); NdisInitUnicodeString(&releaseRoutineName, L"NdisReleaseRWLock"); *((PVOID *)&MpNdisAllocateRWLock) = NdisGetRoutineAddress(&allocateRoutineName); if (MpNdisAllocateRWLock == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisAllocateRWLock\n")); break; } *((PVOID *)&MpNdisFreeRWLock) = NdisGetRoutineAddress(&freeRoutineName); if (MpNdisFreeRWLock == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisFreeRWLock\n")); break; } *((PVOID *)&MpNdisAcquireRWLockRead) = NdisGetRoutineAddress(&acquireReadRoutineName); if (MpNdisAcquireRWLockRead == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisAcquireRWLockRead\n")); break; } *((PVOID *)&MpNdisAcquireRWLockWrite) = NdisGetRoutineAddress(&acquireWriteRoutineName); if (MpNdisAcquireRWLockWrite == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisAcquireRWLockWrite\n")); break; } *((PVOID *)&MpNdisReleaseRWLock) = NdisGetRoutineAddress(&releaseRoutineName); if (MpNdisReleaseRWLock == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to find address of NdisReleaseRWLock\n")); break; } // Set our pointers GlobalRWLockHandlers.AllocateHandler = MpAllocateNewRWLock; GlobalRWLockHandlers.FreeHandler = MpFreeNewRWLock; GlobalRWLockHandlers.AcquireReadHandler = MpAcquireNewRWLockForRead; GlobalRWLockHandlers.AcquireWriteHandler = MpAcquireNewRWLockForWrite; GlobalRWLockHandlers.ReleaseHandler = MpReleaseNewRWLock; } }while (FALSE); return ndisStatus; }