VOID* OvsAllocateMemoryWithTag(size_t size, ULONG tag) { OVS_VERIFY_IRQL_LE(DISPATCH_LEVEL); return NdisAllocateMemoryWithTagPriority(gOvsExtDriverHandle, (UINT32)size, tag, NormalPoolPriority); }
VOID * OvsAllocateMemory(size_t size) { OVS_VERIFY_IRQL_LE(DISPATCH_LEVEL); return NdisAllocateMemoryWithTagPriority(gOvsExtDriverHandle, (UINT32)size, OVS_MEMORY_TAG, NormalPoolPriority); }
/********************************************************** Implements general-purpose memory allocation routine Parameters: ULONG ulRequiredSize: block size Return value: PVOID allocated memory block NULL on error ***********************************************************/ PVOID ParaNdis_AllocateMemoryRaw(NDIS_HANDLE MiniportHandle, ULONG ulRequiredSize) { return NdisAllocateMemoryWithTagPriority( MiniportHandle, ulRequiredSize, PARANDIS_MEMORY_TAG, NormalPoolPriority); }
PVOID VenetAlloc(ULONG size) { PVOID p; p = NdisAllocateMemoryWithTagPriority(mp_handle, size, VNET, HighPoolPriority); if (p) NdisZeroMemory(p, size); return p; }
_Ret_maybenull_ _Result_nullonfailure_ NON_PAGEABLE_FUNCTION void* AX25Adapter::operator new(_In_ size_t size, _In_ NDIS_HANDLE driverHandle) noexcept { // Check the size of the allocation makes sense if (size != sizeof(AX25Adapter)) { // Invalid size - refuse to handle the request TraceEvents(TRACE_LEVEL_ERROR, TRACE_ADAPTER, "Failed to allocate space for AX25Adapter: invalid size %d (expected %d)", static_cast<int>(size), static_cast<int>(sizeof(AX25Adapter))); return nullptr; } // Verify the driver handle was passed in if (driverHandle == nullptr) { // invalid driver handle - refuse to try to pass this on to NDIS TraceEvents(TRACE_LEVEL_ERROR, TRACE_ADAPTER, "Failed to allocate space for AX25Adapter: driverHandle is nullptr"); return nullptr; } // Allocate the memory static_assert(sizeof(AX25Adapter) <= MAXUINT, "static_cast below is invalid for very large objects"); void* result = NdisAllocateMemoryWithTagPriority(driverHandle, static_cast<UINT>(size), AX25_ADAPTER_TAG, NormalPoolPriority); // Log if there was an error if (result == nullptr) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_ADAPTER, "Failed to allocate space for AX25Adapter: NdisAllocateMemoryWithTagPriority returned nullptr"); } else { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_ADAPTER, "Allocated new AX25Adapter at %p", result); } return result; }
static BOOLEAN AllocateCPUMappingArray(NDIS_HANDLE NdisHandle, PPARANDIS_SCALING_SETTINGS RSSScalingSettings) { ULONG i; ULONG CPUNumber = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS); PCHAR NewCPUMappingArray = (PCHAR) NdisAllocateMemoryWithTagPriority( NdisHandle, sizeof(CCHAR) * CPUNumber, PARANDIS_MEMORY_TAG, NormalPoolPriority); if(!NewCPUMappingArray) return FALSE; RSSScalingSettings->CPUIndexMapping = NewCPUMappingArray; RSSScalingSettings->CPUIndexMappingSize = CPUNumber; for(i = 0; i < CPUNumber; i++) { RSSScalingSettings->CPUIndexMapping[i] = PARANDIS_RECEIVE_QUEUE_UNCLASSIFIED; } return TRUE; }
PVOID filterAuditAllocMem( NDIS_HANDLE NdisHandle, ULONG Size, ULONG FileNumber, ULONG LineNumber ) { PVOID pBuffer; PFILTERD_ALLOCATION pAllocInfo; if (!filterdInitDone) { NdisAllocateSpinLock(&(filterdMemoryLock)); filterdInitDone = TRUE; } // // Integer overflow check // if ((Size + sizeof(FILTERD_ALLOCATION)) < Size) { DEBUGP(DL_VERY_LOUD+50, ("filterAuditAllocMem: Integer overflow error file %d, line %d, Size %d \n", FileNumber, LineNumber, Size)); pBuffer = NULL; } else { pAllocInfo = NdisAllocateMemoryWithTagPriority( NdisHandle, Size+sizeof(FILTERD_ALLOCATION), (ULONG)'gdTF', LowPoolPriority ); if (pAllocInfo == (PFILTERD_ALLOCATION)NULL) { DEBUGP(DL_VERY_LOUD+50, ("filterAuditAllocMem: file %d, line %d, Size %d failed!\n", FileNumber, LineNumber, Size)); pBuffer = NULL; } else { pBuffer = (PVOID)&(pAllocInfo->UserData); NdisFillMemory(pBuffer, Size, 0xaf); pAllocInfo->Signature = FILTERD_MEMORY_SIGNATURE; pAllocInfo->FileNumber = FileNumber; pAllocInfo->LineNumber = LineNumber; pAllocInfo->Size = Size; pAllocInfo->OwnerHandle = NdisHandle; pAllocInfo->Next = (PFILTERD_ALLOCATION)NULL; NdisAcquireSpinLock(&(filterdMemoryLock)); pAllocInfo->Prev = filterdMemoryTail; if (filterdMemoryTail == (PFILTERD_ALLOCATION)NULL) { // // empty list // filterdMemoryHead = filterdMemoryTail = pAllocInfo; } else { filterdMemoryTail->Next = pAllocInfo; } filterdMemoryTail = pAllocInfo; filterdAllocCount++; NdisReleaseSpinLock(&(filterdMemoryLock)); } } DEBUGP(DL_VERY_LOUD+100, ("filterAuditAllocMem: file %c%c%c%c, line %d, %d bytes, OwerHandle %p, Memory 0x%p\n", (CHAR)(FileNumber & 0xff), (CHAR)((FileNumber >> 8) & 0xff), (CHAR)((FileNumber >> 16) & 0xff), (CHAR)((FileNumber >> 24) & 0xff), LineNumber, Size, NdisHandle, pBuffer)); return (pBuffer); }
// Figure out the actual size of NDIS_QOS_PARAMETERS if it were to accommodate // NumClassificationElements classification elements. Note that the first // element must be aligned at the end of the parent NDIS_QOS_PARAMETERS // structure. // ParamSize = sizeof(NDIS_QOS_PARAMETERS); FirstElementOffset = ALIGN_UP(ParamSize, NDIS_QOS_CLASSIFICATION_ELEMENT); ParamSize = FirstElementOffset + NumClassificationElements * sizeof(NDIS_QOS_CLASSIFICATION_ELEMENT); // // Allocate the NDIS_QOS_PARAMETERS structure. // Parameters = NdisAllocateMemoryWithTagPriority( NdisDriverHandle, ParamSize, NIC_TAG_QOS_PARAMS, NormalPoolPriority); if (Parameters == NULL) { DEBUGP(MP_ERROR, "Failed to allocate NDIS_QOS_PARAMETERS.\n"); return NULL; } // // Initialize the structure. // NdisZeroMemory(Parameters, ParamSize); Parameters->Header.Type = NDIS_OBJECT_TYPE_QOS_PARAMETERS; Parameters->Header.Revision = NDIS_QOS_PARAMETERS_REVISION_1;
NDIS_STATUS FilterDoInternalRequest( IN PNETGW_ADAPT FilterModuleContext, IN NDIS_REQUEST_TYPE RequestType, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, IN ULONG OutputBufferLength ) { PNETGW_ADAPT pAdapter = (PNETGW_ADAPT)FilterModuleContext; PFILTER_REQUEST_CONTEXT pContext; PINTERNAL_OID_REQUEST pInternalRequest; PNDIS_OID_REQUEST pNdisRequest = NULL; NDIS_STATUS Status; UNREFERENCED_PARAMETER(OutputBufferLength); pInternalRequest = (PINTERNAL_OID_REQUEST)NdisAllocateMemoryWithTagPriority( pAdapter->FilterHandle, sizeof(INTERNAL_OID_REQUEST), FILTER_TAG, NormalPoolPriority); if (pInternalRequest == NULL) return NDIS_STATUS_RESOURCES; NdisZeroMemory(pInternalRequest, sizeof(*pInternalRequest)); pNdisRequest = &pInternalRequest->NdisReq; pNdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; pNdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; pNdisRequest->Header.Size = sizeof(NDIS_OID_REQUEST); pNdisRequest->RequestType = RequestType; pInternalRequest->bLocal = TRUE; pInternalRequest->pReq = pNdisRequest; pInternalRequest->pOrigReq = NULL; pContext = (PFILTER_REQUEST_CONTEXT)(&pNdisRequest->SourceReserved[0]); *pContext = (NDIS_OID_REQUEST*)pInternalRequest; pNdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; pNdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; pNdisRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1; pNdisRequest->RequestHandle = pAdapter->FilterHandle; pNdisRequest->SupportedRevision = NDIS_OID_REQUEST_REVISION_1; switch (RequestType) { case NdisRequestQueryInformation: pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid; pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; break; case NdisRequestSetInformation: pNdisRequest->DATA.SET_INFORMATION.Oid = Oid; pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength; break; default: ASSERT(FALSE); break; } pNdisRequest->RequestId = (PVOID)FILTER_REQUEST_ID; Status = NdisFOidRequest(pAdapter->FilterHandle, pNdisRequest); if (Status != NDIS_STATUS_PENDING) FilterOidRequestComplete(pAdapter, pNdisRequest, Status); return Status; }
/****************************************************************** Replacement of resource requirement list, when needed: The procedure traverses over all the resource lists in existing resource requirement list (we receive it in IRP information field). When the driver is not built to work with MSI resources, we must remove them from the resource requirement list, otherwise the driver will fail to initialize Typically MSI interrupts are labeled as preferred ones, when line interrupts are labeled as alternative resources. Removing message interrupts, remove also "alternative" label from line interrupts. *******************************************************************/ static PIO_RESOURCE_REQUIREMENTS_LIST ParseFilterResourceIrp( IN NDIS_HANDLE MiniportAddDeviceContext, PIO_RESOURCE_REQUIREMENTS_LIST prrl, BOOLEAN bRemoveMSIResources) { tRRLData newRRLData; ULONG nRemoved = 0; PIO_RESOURCE_REQUIREMENTS_LIST newPrrl = NULL; DPrintf(resourceFilterLevel, ("[%s]%s\n", __FUNCTION__, bRemoveMSIResources ? "(Remove MSI resources...)" : "")); if (MiniportAddDeviceContext && prrl) newPrrl = (PIO_RESOURCE_REQUIREMENTS_LIST)NdisAllocateMemoryWithTagPriority( MiniportAddDeviceContext, prrl->ListSize, PARANDIS_MEMORY_TAG, NormalPoolPriority); InitializeNewResourceRequirementsList(&newRRLData, newPrrl, prrl); if (prrl) { ULONG n, offset; PVOID p = &prrl->List[0]; DPrintf(resourceFilterLevel, ("[%s] %d bytes, %d lists\n", __FUNCTION__, prrl->ListSize, prrl->AlternativeLists)); offset = RtlPointerToOffset(prrl, p); for (n = 0; n < prrl->AlternativeLists && offset < prrl->ListSize; ++n) { ULONG nDesc; IO_RESOURCE_LIST *pior = (IO_RESOURCE_LIST *)p; if ((offset + sizeof(*pior)) < prrl->ListSize) { IO_RESOURCE_DESCRIPTOR *pd = &pior->Descriptors[0]; DPrintf(resourceFilterLevel, ("[%s]+%d %d:%d descriptors follow\n", __FUNCTION__, offset, n, pior->Count)); offset += RtlPointerToOffset(p, pd); AddNewResourceList(&newRRLData, pior); for (nDesc = 0; nDesc < pior->Count; ++nDesc) { BOOLEAN bRemove = FALSE; if ((offset + sizeof(*pd)) <= prrl->ListSize) { DPrintf(resourceFilterLevel, ("[%s]+%d %d: type %d, flags %X, option %X\n", __FUNCTION__, offset, nDesc, pd->Type, pd->Flags, pd->Option)); if (pd->Type == CmResourceTypeInterrupt) { if (pd->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) { bRemove = bRemoveMSIResources; } else { // reset IO_RESOURCE_ALTERNATIVE attribute on Line Interrupt, // if we remove MSI vectors, otherwise Windows will not allocate it for the device if (bRemoveMSIResources && (pd->Option & IO_RESOURCE_ALTERNATIVE)) { pd->Option &= ~IO_RESOURCE_ALTERNATIVE; } } } if (!bRemove) AddNewResourceDescriptor(&newRRLData, pd); else nRemoved++; } offset += sizeof(*pd); pd = (IO_RESOURCE_DESCRIPTOR *)RtlOffsetToPointer(prrl, offset); } FinalizeResourceList(&newRRLData); p = pd; } } } if (bRemoveMSIResources && nRemoved) { DPrintf(0, ("[%s] %d resources removed\n", __FUNCTION__, nRemoved)); } return newPrrl; }
/********************************************************** Required NDIS handler Initialize adapter context, prepare it for operation, set in PAUSED STATE Return value: SUCCESS or kind of error ***********************************************************/ static NDIS_STATUS ParaNdis6_Initialize( NDIS_HANDLE miniportAdapterHandle, NDIS_HANDLE miniportDriverContext, PNDIS_MINIPORT_INIT_PARAMETERS miniportInitParameters) { NDIS_MINIPORT_ADAPTER_ATTRIBUTES miniportAttributes; NDIS_STATUS status = NDIS_STATUS_SUCCESS; BOOLEAN bNoPauseOnSuspend = FALSE; PARANDIS_ADAPTER *pContext; UNREFERENCED_PARAMETER(miniportDriverContext); DEBUG_ENTRY(0); #pragma warning( suppress: 28197) /* allocate context structure */ pContext = (PARANDIS_ADAPTER *) NdisAllocateMemoryWithTagPriority( miniportAdapterHandle, sizeof(PARANDIS_ADAPTER), PARANDIS_MEMORY_TAG, NormalPoolPriority); /* This call is for Static Driver Verifier only - has no real functionality*/ __sdv_save_adapter_context(pContext); if (!pContext) { DPrintf(0, ("[%s] ERROR: Memory allocation failed!\n", __FUNCTION__)); status = NDIS_STATUS_RESOURCES; } if (status == NDIS_STATUS_SUCCESS) { /* set mandatory fields which Common use */ NdisZeroMemory(pContext, sizeof(PARANDIS_ADAPTER)); pContext->ulUniqueID = NdisInterlockedIncrement(&gID); pContext->DriverHandle = DriverHandle; pContext->MiniportHandle = miniportAdapterHandle; } if (status == NDIS_STATUS_SUCCESS) { NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes)); miniportAttributes.RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; miniportAttributes.RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; miniportAttributes.RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; miniportAttributes.RegistrationAttributes.MiniportAdapterContext = pContext; miniportAttributes.RegistrationAttributes.AttributeFlags = // actual for USB // NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER; #ifndef NO_VISTA_POWER_MANAGEMENT miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND; #endif #if NDIS_SUPPORT_NDIS630 miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND; bNoPauseOnSuspend = TRUE; #endif miniportAttributes.RegistrationAttributes.CheckForHangTimeInSeconds = 4; miniportAttributes.RegistrationAttributes.InterfaceType = NdisInterfacePci; status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 1 failed (%X)!\n", __FUNCTION__, status)); } } if (status == NDIS_STATUS_SUCCESS) { /* prepare statistics struct for further reports */ pContext->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; pContext->Statistics.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1; pContext->Statistics.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1; /* let Common do all the rest */ status = ParaNdis_InitializeContext(pContext, miniportInitParameters->AllocatedResources); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: ParaNdis6_InitializeContext failed (%X)!\n", __FUNCTION__, status)); } pContext->bNoPauseOnSuspend = bNoPauseOnSuspend; } if (status == NDIS_STATUS_SUCCESS) { ULONG i; NDIS_PNP_CAPABILITIES power60Caps; #if NDIS_SUPPORT_NDIS620 NDIS_PM_CAPABILITIES power620Caps; #endif #ifdef NO_VISTA_POWER_MANAGEMENT pPowerCaps = NULL; #endif ParaNdis_FillPowerCapabilities(&power60Caps); NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes)); miniportAttributes.GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; #if NDIS_SUPPORT_NDIS620 miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2; miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2; miniportAttributes.GeneralAttributes.PowerManagementCapabilitiesEx = &power620Caps; ParaNdis6_Fill620PowerCapabilities(&power620Caps); #else miniportAttributes.GeneralAttributes.PowerManagementCapabilities = &power60Caps; #endif miniportAttributes.GeneralAttributes.MediaType = NdisMedium802_3; miniportAttributes.GeneralAttributes.PhysicalMediumType = NdisPhysicalMedium802_3; miniportAttributes.GeneralAttributes.MtuSize = pContext->MaxPacketSize.nMaxDataSize; miniportAttributes.GeneralAttributes.LookaheadSize = pContext->MaxPacketSize.nMaxFullSizeOS; miniportAttributes.GeneralAttributes.MaxXmitLinkSpeed = miniportAttributes.GeneralAttributes.MaxRcvLinkSpeed = PARANDIS_FORMAL_LINK_SPEED; miniportAttributes.GeneralAttributes.MediaConnectState = pContext->bConnected ? MediaConnectStateConnected : MediaConnectStateDisconnected; miniportAttributes.GeneralAttributes.XmitLinkSpeed = miniportAttributes.GeneralAttributes.RcvLinkSpeed = pContext->bConnected ? PARANDIS_FORMAL_LINK_SPEED : NDIS_LINK_SPEED_UNKNOWN; miniportAttributes.GeneralAttributes.MediaDuplexState = MediaDuplexStateFull; miniportAttributes.GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | /* NIC has no internal loopback support */ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | /* Must be set since using NdisMIndicateReceivePacket */ NDIS_MAC_OPTION_NO_LOOPBACK; /* NIC has no internal loopback support */ if (IsPrioritySupported(pContext)) miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021P_PRIORITY; if (IsVlanSupported(pContext)) miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021Q_VLAN; miniportAttributes.GeneralAttributes.SupportedPacketFilters = PARANDIS_PACKET_FILTERS; miniportAttributes.GeneralAttributes.MaxMulticastListSize = PARANDIS_MULTICAST_LIST_SIZE; miniportAttributes.GeneralAttributes.MacAddressLength = ETH_LENGTH_OF_ADDRESS; #if PARANDIS_SUPPORT_RSS if(pContext->bRSSOffloadSupported) { miniportAttributes.GeneralAttributes.RecvScaleCapabilities = ParaNdis6_RSSCreateConfiguration( &pContext->RSSParameters, &pContext->RSSCapabilities, pContext->RSSMaxQueuesNumber); pContext->bRSSInitialized = TRUE; } #endif for(i = 0; i < ARRAYSIZE(pContext->ReceiveQueues); i++) { NdisAllocateSpinLock(&pContext->ReceiveQueues[i].Lock); InitializeListHead(&pContext->ReceiveQueues[i].BuffersList); pContext->ReceiveQueues[i].BatchReceiveArray = ParaNdis_AllocateMemory(pContext, sizeof(*pContext->ReceiveQueues[i].BatchReceiveArray)*pContext->NetMaxReceiveBuffers); if(!pContext->ReceiveQueues[i].BatchReceiveArray) { pContext->ReceiveQueues[i].BatchReceiveArray = &pContext->ReceiveQueues[i].BatchReceiveEmergencyItem; pContext->ReceiveQueues[i].BatchReceiveArraySize = 1; } else { pContext->ReceiveQueues[i].BatchReceiveArraySize = pContext->NetMaxReceiveBuffers; } } pContext->ReceiveQueuesInitialized = TRUE; miniportAttributes.GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; miniportAttributes.GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; miniportAttributes.GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; miniportAttributes.GeneralAttributes.IfConnectorPresent = TRUE; miniportAttributes.GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.PermanentMacAddress, pContext->PermanentMacAddress); ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.CurrentMacAddress, pContext->CurrentMacAddress); ParaNdis6_GetSupportedOid(&miniportAttributes.GeneralAttributes); /* update also SupportedStatistics in ready to use statistics block */ pContext->Statistics.SupportedStatistics = ParaNdis6_GetSupportedStatisticsFlags(); status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 2 failed (%X)!\n", __FUNCTION__, status)); } } if (pContext && status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING) { // no need to cleanup NdisFreeMemory(pContext, 0, 0); pContext = NULL; } if (pContext && status == NDIS_STATUS_SUCCESS) { status = ParaNdis_FinishInitialization(pContext); if (status != NDIS_STATUS_SUCCESS) { ParaNdis_CleanupContext(pContext); NdisFreeMemory(pContext, 0, 0); pContext = NULL; } } if (pContext && status == NDIS_STATUS_SUCCESS) { if (NDIS_STATUS_SUCCESS == ParaNdis6_GetRegistrationOffloadInfo(pContext, &miniportAttributes.OffloadAttributes)) status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes); if (status != NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 3 failed (%X)!\n", __FUNCTION__, status)); } } if (pContext && status == NDIS_STATUS_SUCCESS) { ParaNdis_DebugRegisterMiniport(pContext, TRUE); } DEBUG_EXIT_STATUS(status ? 0 : 2, status); return status; }
VOID IndicateReceivePacket( __in PTAP_ADAPTER_CONTEXT Adapter, __in PUCHAR packetData, __in const unsigned int packetLength ) { PUCHAR injectBuffer; // // Handle miniport Pause // --------------------- // NDIS 6 miniports implement a temporary "Pause" state normally followed // by the Restart. While in the Pause state it is forbidden for the miniport // to indicate receive NBLs. // // That is: The device interface may be "up", but the NDIS miniport send/receive // interface may be temporarily "down". // // BUGBUG!!! In the initial implementation of the NDIS 6 TapOas inject path // the code below will simply ignore inject packets passed to the driver while // the miniport is in the Paused state. // // The correct implementation is to go ahead and build the NBLs corresponding // to the inject packet - but queue them. When Restart is entered the // queued NBLs would be dequeued and indicated to the host. // if(tapAdapterSendAndReceiveReady(Adapter) != NDIS_STATUS_SUCCESS) { DEBUGP (("[%s] Lying send in IndicateReceivePacket while adapter paused\n", MINIPORT_INSTANCE_ID (Adapter))); return; } // Allocate flat buffer for packet data. injectBuffer = (PUCHAR )NdisAllocateMemoryWithTagPriority( Adapter->MiniportAdapterHandle, packetLength, TAP_RX_INJECT_BUFFER_TAG, NormalPoolPriority ); if( injectBuffer) { PMDL mdl; // Copy packet data to flat buffer. NdisMoveMemory (injectBuffer, packetData, packetLength); // Allocate MDL for flat buffer. mdl = NdisAllocateMdl( Adapter->MiniportAdapterHandle, injectBuffer, packetLength ); if( mdl ) { PNET_BUFFER_LIST netBufferList; mdl->Next = NULL; // No next MDL // Allocate the NBL and NB. Link MDL chain to NB. netBufferList = NdisAllocateNetBufferAndNetBufferList( Adapter->ReceiveNblPool, 0, // ContextSize 0, // ContextBackFill mdl, // MDL chain 0, packetLength ); if(netBufferList != NULL) { ULONG receiveFlags = 0; LONG nblCount; NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL if(KeGetCurrentIrql() == DISPATCH_LEVEL) { receiveFlags |= NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL; } // Set flag indicating that this is an injected packet TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList); TAP_RX_NBL_FLAG_SET(netBufferList,TAP_RX_NBL_FLAGS_IS_INJECTED); netBufferList->MiniportReserved[0] = NULL; netBufferList->MiniportReserved[1] = NULL; // Increment in-flight receive NBL count. nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount); ASSERT(nblCount > 0 ); netBufferList->SourceHandle = Adapter->MiniportAdapterHandle; // // Indicate the packet // ------------------- // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length // contains the complete packet including Ethernet header and payload. // NdisMIndicateReceiveNetBufferLists( Adapter->MiniportAdapterHandle, netBufferList, NDIS_DEFAULT_PORT_NUMBER, 1, // NumberOfNetBufferLists receiveFlags ); return; } else { DEBUGP (("[%s] NdisAllocateNetBufferAndNetBufferList failed in IndicateReceivePacket\n", MINIPORT_INSTANCE_ID (Adapter))); NOTE_ERROR (); NdisFreeMdl(mdl); NdisFreeMemory(injectBuffer,0,0); } } else { DEBUGP (("[%s] NdisAllocateMdl failed in IndicateReceivePacket\n", MINIPORT_INSTANCE_ID (Adapter))); NOTE_ERROR (); NdisFreeMemory(injectBuffer,0,0); } } else { DEBUGP (("[%s] NdisAllocateMemoryWithTagPriority failed in IndicateReceivePacket\n", MINIPORT_INSTANCE_ID (Adapter))); NOTE_ERROR (); } }
// Returns with reference count initialized to one. PTAP_ADAPTER_CONTEXT tapAdapterContextAllocate(__in NDIS_HANDLE MiniportAdapterHandle) { PTAP_ADAPTER_CONTEXT adapter = NULL; adapter = (PTAP_ADAPTER_CONTEXT)NdisAllocateMemoryWithTagPriority( GlobalData.NdisDriverHandle, sizeof(TAP_ADAPTER_CONTEXT), TAP_ADAPTER_TAG, NormalPoolPriority); if (adapter) { NET_BUFFER_LIST_POOL_PARAMETERS nblPoolParameters = {0}; NdisZeroMemory(adapter, sizeof(TAP_ADAPTER_CONTEXT)); adapter->MiniportAdapterHandle = MiniportAdapterHandle; // Initialize cancel-safe IRP queue tapIrpCsqInitialize(&adapter->PendingReadIrpQueue); // Initialize TAP send packet queue. tapPacketQueueInitialize(&adapter->SendPacketQueue); // Allocate the adapter lock. NdisAllocateSpinLock(&adapter->AdapterLock); // NBL pool for making TAP receive indications. NdisZeroMemory(&nblPoolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS)); // Initialize event used to determine when all receive NBLs have been returned. NdisInitializeEvent(&adapter->ReceiveNblInFlightCountZeroEvent); nblPoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nblPoolParameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; nblPoolParameters.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; nblPoolParameters.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT; nblPoolParameters.ContextSize = 0; // nblPoolParameters.ContextSize = sizeof(RX_NETBUFLIST_RSVD); nblPoolParameters.fAllocateNetBuffer = TRUE; nblPoolParameters.PoolTag = TAP_RX_NBL_TAG; #pragma warning(suppress : 28197) adapter->ReceiveNblPool = NdisAllocateNetBufferListPool(adapter->MiniportAdapterHandle, &nblPoolParameters); if (adapter->ReceiveNblPool == NULL) { DEBUGP(("[TAP] Couldn't allocate adapter receive NBL pool\n")); NdisFreeMemory(adapter, 0, 0); } // Add initial reference. Normally removed in AdapterHalt. adapter->RefCount = 1; // Safe for multiple removes. NdisInitializeListHead(&adapter->AdapterListLink); // // The miniport adapter is initially powered up // adapter->CurrentPowerState = NdisDeviceStateD0; } return adapter; }
/** * This is a debug only function that performs memory management operations for us. * Memory allocated using this function is tracked, flagged when leaked, and caught for * overflows and underflows. * \warning Do not use this function directly. Using MP_ALLOCATE_MEMORY ensures that * this function gets called for debug version of the driver. Retail builds will use Ndis API * for allocation of memory * * \param Size The size in bytes of memory to allocate * \param FileName The full path of file where this function is invoked from * \param LineNumber The line number in the file where this method was called from * \param Flags Flags for special memory insturctions. Currently unused. * \return Pointer to the allocated memory or NULL in case of a failure * \sa MpFreeMemory, MP_ALLOCATE_MEMORY, MP_FREE_MEMORY, NdisAllocateMemoryWithTagPriority, MpFreeAllocatedBlocks */ PVOID MpAllocateMemory ( NDIS_HANDLE AllocateHandle, ULONG Size, ULONG Tag, EX_POOL_PRIORITY Priority, __nullterminated PCHAR FileName, ULONG LineNumber, ULONG Flags ) { PVOID memory = NULL; // // If the memory manager has not been initialized, do so now // if (!GlobalMemoryManagerInitialized) { // // NOTE: If two thread allocate the very first allocation simultaneously // it could cause double initialization of the memory manager. This is a // highly unlikely scenario and will occur in debug versions only. // NdisAllocateSpinLock(&GlobalMemoryLock); InitializeListHead(&GlobalMemoryList); GlobalMemoryManagerInitialized = TRUE; } // // Allocate the required memory chunk plus header and trailer bytes // memory = NdisAllocateMemoryWithTagPriority( AllocateHandle, Size + sizeof(MP_MEMORY_BLOCK) + sizeof(ULONG), Tag, Priority ); if (memory != NULL) { // // Memory allocation succeeded. Add information about the allocated // block in the list that tracks all allocations. // PMP_MEMORY_BLOCK memoryBlockHeader; // Fill in the memory header and trailer memoryBlockHeader = (PMP_MEMORY_BLOCK) memory; memoryBlockHeader->File = FileName; memoryBlockHeader->Line = LineNumber; memoryBlockHeader->Length = Size; memoryBlockHeader->Flags = Flags; memoryBlockHeader->HeaderPattern = MP_HEADER_PATTERN; *((PULONG) (((PUCHAR)(memory))+Size + sizeof(MP_MEMORY_BLOCK))) = MP_TRAILER_PATTERN; // Jump ahead by memory header so pointer returned to caller points at the right place memory = ((PUCHAR)memory) + sizeof (MP_MEMORY_BLOCK); // Store a reference to this block in the list NdisAcquireSpinLock (&GlobalMemoryLock); InsertHeadList (&GlobalMemoryList, &memoryBlockHeader->ListEntry); NdisReleaseSpinLock (&GlobalMemoryLock); } return memory; }
NDIS_STATUS NDISLWF_AttachHandler( NDIS_HANDLE NdisFilterHandle, NDIS_HANDLE FilterDriverContext, PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters ) { PNDISLWF_CONTEXT FilterContext; NDIS_STATUS NdisStatus; NDIS_FILTER_ATTRIBUTES FilterAttributes; DPF(("%s!%s [%x.%x] (FilterHandle=%p DriverContext=%p AttachParameters=%p)\n", __MODULE__, __FUNCTION__, PsGetCurrentProcessId(), PsGetCurrentThreadId(), NdisFilterHandle, FilterDriverContext, AttachParameters )); // Allocate an instance of the NDISLWF_CONTEXT structure // Use the pool tag CMfc (NdisAllocateMemoryWithTagPriority()) and store // the context in FilterContext if ( ( FilterContext = NdisAllocateMemoryWithTagPriority ( NdisFilterHandle, sizeof(NDISLWF_CONTEXT), 'cfMC', //CodeMachineFilterContext NormalPoolPriority ) ) == NULL ) { NdisStatus = NDIS_STATUS_RESOURCES; DPF(("%s!%s NdisAllocateMemoryWithTagPriority() FAIL\n", __MODULE__, __FUNCTION__)); goto Exit; } NdisZeroMemory(FilterContext, sizeof(NDISLWF_CONTEXT)); FilterContext->FilterHandle = NdisFilterHandle; FilterContext->MiniportIfIndex = AttachParameters->BaseMiniportIfIndex; // Initialize the FilterAttribute structure NdisZeroMemory(&FilterAttributes, sizeof(NDIS_FILTER_ATTRIBUTES)); FilterAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1; FilterAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES); FilterAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES; FilterAttributes.Flags = 0; // Register the filter attributes in FilterAttributes with NDIS // and register the FilterContext allocated above as the FilterModuleContext // (NdisFSetAttributes()) NdisStatus = NdisFSetAttributes( NdisFilterHandle, FilterContext, &FilterAttributes); if (NdisStatus != NDIS_STATUS_SUCCESS) { DPF(("%s!%s NdisFSetAttributes() FAIL=%08x\n", __MODULE__, __FUNCTION__, NdisStatus)); goto Exit; } return NdisStatus; Exit : if ( FilterContext ) { // Free the filter context in FilterContext (NdisFreeMemory()) NdisFreeMemory ( FilterContext, sizeof(NDISLWF_CONTEXT), 0 ); } return NdisStatus; } // NDISLWF_AttachHandler()
/****************************************************************** Replacement of resource requirement list, when needed: The procedure traverses over all the resource lists in existing resource requirement list (we receive it in IRP information field). When the driver is not built to work with MSI resources, we must remove them from the resource requirement list, otherwise the driver will fail to initialize Typically MSI interrupts are labeled as preferred ones, when line interrupts are labeled as alternative resources. Removing message interrupts, remove also "alternative" label from line interrupts. *******************************************************************/ static PIO_RESOURCE_REQUIREMENTS_LIST ParseFilterResourceIrp( IN NDIS_HANDLE MiniportAddDeviceContext, PIO_RESOURCE_REQUIREMENTS_LIST prrl, BOOLEAN bRemoveMSIResources) { tRRLData newRRLData; ULONG nRemoved = 0; UINT nInterrupts = 0; PIO_RESOURCE_REQUIREMENTS_LIST newPrrl = NULL; ULONG QueueNumber; #if NDIS_SUPPORT_NDIS620 QueueNumber = NdisGroupActiveProcessorCount(ALL_PROCESSOR_GROUPS) + 1; #elif NDIS_SUPPORT_NDIS6 QueueNumber = NdisSystemProcessorCount(); #else QueueNumber = 0; /* Don't create MSI resource descriptors*/ #endif if (QueueNumber > 2048) QueueNumber = 2048; DPrintf(resourceFilterLevel, ("[%s]%s\n", __FUNCTION__, bRemoveMSIResources ? "(Remove MSI resources...)" : "")); newPrrl = (PIO_RESOURCE_REQUIREMENTS_LIST)NdisAllocateMemoryWithTagPriority( MiniportAddDeviceContext, prrl->ListSize + (bRemoveMSIResources ? 0 : QueueNumber * sizeof(IO_RESOURCE_DESCRIPTOR)), PARANDIS_MEMORY_TAG, NormalPoolPriority); InitializeNewResourceRequirementsList(&newRRLData, newPrrl, prrl); if (prrl) { ULONG n, offset; PVOID p = &prrl->List[0]; DPrintf(resourceFilterLevel, ("[%s] %d bytes, %d lists\n", __FUNCTION__, prrl->ListSize, prrl->AlternativeLists)); offset = RtlPointerToOffset(prrl, p); for (n = 0; n < prrl->AlternativeLists && offset < prrl->ListSize; ++n) { ULONG nDesc; IO_RESOURCE_LIST *pior = (IO_RESOURCE_LIST *)p; if ((offset + sizeof(*pior)) < prrl->ListSize) { IO_RESOURCE_DESCRIPTOR *pd = &pior->Descriptors[0]; DPrintf(resourceFilterLevel, ("[%s]+%d %d:%d descriptors follow\n", __FUNCTION__, offset, n, pior->Count)); offset += RtlPointerToOffset(p, pd); AddNewResourceList(&newRRLData, pior); for (nDesc = 0; nDesc < pior->Count; ++nDesc) { BOOLEAN bRemove = FALSE; if ((offset + sizeof(*pd)) <= prrl->ListSize) { #ifdef DBG DPrintf(resourceFilterLevel, ("[%s]+%d %d: type %d/%s, flags %X, option %X\n", __FUNCTION__, offset, nDesc, pd->Type, CM_RESOURCE_TYPE2String(pd->Type), pd->Flags, pd->Option)); #else DPrintf(resourceFilterLevel, ("[%s]+%d %d: type %d, flags %X, option %X\n", __FUNCTION__, offset, nDesc, pd->Type, pd->Flags, pd->Option)); #endif if (pd->Type == CmResourceTypeInterrupt) { nInterrupts++; DPrintf(0, ("[%s] min/max = %lx/%lx Option = 0x%lx, ShareDisposition = %u \n", __FUNCTION__, pd->u.Interrupt.MinimumVector, pd->u.Interrupt.MaximumVector, pd->Option, pd->ShareDisposition)); if (pd->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) { bRemove = bRemoveMSIResources; } else { // reset IO_RESOURCE_ALTERNATIVE attribute on Line Interrupt, // if we remove MSI vectors, otherwise Windows will not allocate it for the device if (bRemoveMSIResources && (pd->Option & IO_RESOURCE_ALTERNATIVE)) { pd->Option &= ~IO_RESOURCE_ALTERNATIVE; } } } if (!bRemove) AddNewResourceDescriptor(&newRRLData, pd); else nRemoved++; } offset += sizeof(*pd); pd = (IO_RESOURCE_DESCRIPTOR *)RtlOffsetToPointer(prrl, offset); } if (!bRemoveMSIResources) { while (nInterrupts < QueueNumber) { IO_RESOURCE_DESCRIPTOR ior; ior.Type = CmResourceTypeInterrupt; ior.Flags = CM_RESOURCE_INTERRUPT_LATCHED | CM_RESOURCE_INTERRUPT_MESSAGE | CM_RESOURCE_INTERRUPT_POLICY_INCLUDED; ior.Option = 0; ior.ShareDisposition = CmResourceShareDeviceExclusive; ior.u.Interrupt.MinimumVector = ior.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN; ior.u.Interrupt.AffinityPolicy = IrqPolicyMachineDefault; ior.u.Interrupt.PriorityPolicy = IrqPriorityNormal; AddNewResourceDescriptor(&newRRLData, &ior); nInterrupts++; } } FinalizeResourceList(&newRRLData); p = pd; } } } if (!bRemoveMSIResources) { SetupInterrruptAffinity(newPrrl); } if (bRemoveMSIResources && nRemoved) { DPrintf(0, ("[%s] %d resources removed\n", __FUNCTION__, nRemoved)); } return newPrrl; }