bool CTXHeaders::Allocate() { if (m_HeadersBuffer.Allocate(PAGE_SIZE)) { auto VA = m_HeadersBuffer.GetVA(); auto PA = m_HeadersBuffer.GetPA(); ULONG prioSize = ALIGN_UP(ETH_PRIORITY_HEADER_SIZE, ULONGLONG); //Headers buffer layout: // Priority header // Virtio header // Ethernet headers m_VlanHeaderVA = VA; m_VirtioHeaderVA = RtlOffsetToPointer(m_VlanHeaderVA, prioSize); m_EthHeaderVA = RtlOffsetToPointer(m_VirtioHeaderVA, m_VirtioHdrSize); m_IPHeadersVA = RtlOffsetToPointer(m_EthHeaderVA, ETH_HEADER_SIZE); m_VirtioHeaderPA.QuadPart = PA.QuadPart + RtlPointerToOffset(VA, m_VirtioHeaderVA); m_VlanHeaderPA.QuadPart = PA.QuadPart + RtlPointerToOffset(VA, m_VlanHeaderVA); m_EthHeaderPA.QuadPart = PA.QuadPart + RtlPointerToOffset(VA, m_EthHeaderVA); m_IPHeadersPA.QuadPart = PA.QuadPart + RtlPointerToOffset(VA, m_IPHeadersVA); m_MaxEthHeadersSize = m_HeadersBuffer.GetSize() - prioSize - m_VirtioHdrSize; return true; } return false; }
/****************************************************************** Replacement of resource requirement list: adding new resource list to existing resource requirement list *******************************************************************/ static void AddNewResourceList(tRRLData *pData, PIO_RESOURCE_LIST pior) { if (pData->prrl) { ULONG len = RtlPointerToOffset(pior, &pior->Descriptors[0]); pData->currentList = (PIO_RESOURCE_LIST)RtlOffsetToPointer(pData->prrl, pData->prrl->ListSize); RtlCopyMemory(pData->currentList, pior, len); pData->currentList->Count = 0; pData->prrl->ListSize += len; pData->prrl->AlternativeLists++; pData->currentDesc = &pData->currentList->Descriptors[0]; } }
/****************************************************************** Replacement of resource requirement list: initialize the new list *******************************************************************/ static void InitializeNewResourceRequirementsList( tRRLData *pData, PIO_RESOURCE_REQUIREMENTS_LIST newList, PIO_RESOURCE_REQUIREMENTS_LIST oldList) { pData->prrl = newList; pData->currentList = NULL; pData->currentDesc = NULL; if (pData->prrl) { ULONG len = RtlPointerToOffset(pData->prrl, &pData->prrl->List[0]); RtlCopyMemory(newList, oldList, len); newList->ListSize = len; newList->AlternativeLists = 0; } }
void ParaNdis_DebugInitialize(PVOID DriverObject,PVOID RegistryPath) { NDIS_STRING usRegister, usDeregister, usPrint; PVOID pr, pd; BOOLEAN res; WPP_INIT_TRACING(DriverObject, RegistryPath); NdisAllocateSpinLock(&CrashLock); KeInitializeCallbackRecord(&CallbackRecord); ParaNdis_PrepareBugCheckData(); NdisInitUnicodeString(&usPrint, L"vDbgPrintEx"); NdisInitUnicodeString(&usRegister, L"KeRegisterBugCheckReasonCallback"); NdisInitUnicodeString(&usDeregister, L"KeDeregisterBugCheckReasonCallback"); pd = MmGetSystemRoutineAddress(&usPrint); if (pd) PrintProcedure = (vDbgPrintExType)pd; pr = MmGetSystemRoutineAddress(&usRegister); pd = MmGetSystemRoutineAddress(&usDeregister); if (pr && pd) { BugCheckRegisterCallback = (KeRegisterBugCheckReasonCallbackType)pr; BugCheckDeregisterCallback = (KeDeregisterBugCheckReasonCallbackType)pd; } res = BugCheckRegisterCallback(&CallbackRecord, ParaNdis_OnBugCheck, KbCallbackSecondaryDumpData, "NetKvm"); DPrintf(0, ("[%s] Crash callback %sregistered", __FUNCTION__, res ? "" : "NOT ")); #ifdef OVERRIDE_DEBUG_BREAK if (sizeof(PVOID) == sizeof(ULONG)) { UCHAR replace[5] = {0xe9,0,0,0,0}; ULONG replacement; NDIS_STRING usDbgBreakPointName; NdisInitUnicodeString(&usDbgBreakPointName, L"DbgBreakPoint"); pDbgBreakPoint = (PUCHAR)MmGetSystemRoutineAddress(&usDbgBreakPointName); if (pDbgBreakPoint) { DPrintf(0, ("Replacing original BP handler at %p", pDbgBreakPoint)); replacement = RtlPointerToOffset(pDbgBreakPoint + 5, AnotherDbgBreak); RtlCopyMemory(replace + 1, &replacement, sizeof(replacement)); RtlCopyMemory(DbgBreakPointChunk, pDbgBreakPoint, sizeof(DbgBreakPointChunk)); RtlCopyMemory(pDbgBreakPoint, replace, sizeof(replace)); } } #endif }
/****************************************************************** Replacement of resource requirement list: done with new resource list, verify if it contains all the required resources *******************************************************************/ static void FinalizeResourceList(tRRLData *pData) { if (pData->prrl && pData->currentList) { BOOLEAN bFound = FALSE; ULONG len = RtlPointerToOffset(pData->currentList, &pData->currentList->Descriptors[0]); UINT i; for (i = 0; i < pData->currentList->Count && !bFound; ++i) { len += sizeof(IO_RESOURCE_DESCRIPTOR); if (pData->currentList->Descriptors[i].Type == CmResourceTypeInterrupt) bFound = TRUE; } if (!bFound) { pData->prrl->AlternativeLists--; pData->prrl->ListSize -= len; } } }
/******************************************************** Allocate and fill our capabilities, dependent on registry setting Note than NDIS test of WLK1.2 and 1.3 fail (offloadmisc) if CS capability indicated and passes if only LSO indicated ********************************************************/ NDIS_STATUS CreateOffloadInfo5Internal( PARANDIS_ADAPTER *pContext, PVOID *ppInfo, PULONG pulSize, PCCHAR reason, NDIS_TASK_OFFLOAD_HEADER *pHeader) { NDIS_STATUS status = NDIS_STATUS_RESOURCES; ULONG size = sizeof(NDIS_TASK_OFFLOAD_HEADER) + sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_IP_CHECKSUM) + sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND); *ppInfo = ParaNdis_AllocateMemory(pContext, size); if (*ppInfo) { ULONG flags = 0; NDIS_TASK_TCP_IP_CHECKSUM cs; NDIS_TASK_TCP_LARGE_SEND lso; flags |= GetTcpIpCheckSumCapabilities(pContext, &cs) ? 2 : 0; flags |= GetLargeSendCapabilities(pContext, &lso) ? 1 : 0; if (flags) { NDIS_TASK_OFFLOAD_HEADER *ph; NDIS_TASK_OFFLOAD *pto; UINT i = 0; ULONG *pOffset; PVOID base; *pulSize = size; NdisZeroMemory(*ppInfo, size); ph = (NDIS_TASK_OFFLOAD_HEADER *)*ppInfo; *ph = *pHeader; pto = (NDIS_TASK_OFFLOAD *)(ph + 1); base = ph; pOffset = &ph->OffsetFirstTask; ph->OffsetFirstTask = 0; do { if (flags & (1 << i)) { flags &= ~(1 << i); pto->Version = NDIS_TASK_OFFLOAD_VERSION; pto->Size = sizeof(*pto); *pOffset = RtlPointerToOffset(base, pto); base = pto; pOffset = &pto->OffsetNextTask; switch(i) { case 1: { NDIS_TASK_TCP_IP_CHECKSUM *pcs = (NDIS_TASK_TCP_IP_CHECKSUM *)pto->TaskBuffer; pto->Task = TcpIpChecksumNdisTask; pto->TaskBufferLength = sizeof(*pcs); NdisMoveMemory(pcs, &cs, sizeof(cs)); pto = (NDIS_TASK_OFFLOAD *)(pcs + 1); break; } case 0: { NDIS_TASK_TCP_LARGE_SEND *pls = (NDIS_TASK_TCP_LARGE_SEND *)pto->TaskBuffer; pto->Task = TcpLargeSendNdisTask; pto->TaskBufferLength = sizeof(*pls); NdisMoveMemory(pls, &lso, sizeof(lso)); pto = (NDIS_TASK_OFFLOAD *)(pls + 1); break; } default: break; } } ++i; } while (flags); status = ParseOffload(pContext, ph, size, FALSE, reason, FALSE); } else { NdisFreeMemory(*ppInfo, 0, 0); *ppInfo = NULL; status = NDIS_STATUS_NOT_SUPPORTED; } } return status; }
static NDIS_STATUS ParseOffloadTask( PARANDIS_ADAPTER *pContext, BOOLEAN bApply, /* for 'set'*/ NDIS_TASK_OFFLOAD *pto, ULONG offset, ULONG maxSize) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; NDIS_TASK_TCP_IP_CHECKSUM *pcs = NULL; NDIS_TASK_TCP_LARGE_SEND *pls = NULL; NDIS_TASK_IPSEC *pips = NULL; LPCSTR sName = NULL; ULONG TaskBufferSize = 0, tailOffset = 0; switch(pto->Task) { case TcpIpChecksumNdisTask: pcs = (NDIS_TASK_TCP_IP_CHECKSUM *)pto->TaskBuffer; TaskBufferSize = sizeof(*pcs); sName = "TcpIpChecksumNdisTask"; break; case TcpLargeSendNdisTask: pls = (NDIS_TASK_TCP_LARGE_SEND *)pto->TaskBuffer; TaskBufferSize = sizeof(*pls); sName = "TcpLargeSendNdisTask"; break; case IpSecNdisTask: pips = (NDIS_TASK_IPSEC *)pto->TaskBuffer; TaskBufferSize = sizeof(*pips); sName = "IpSecNdisTask"; break; default: break; } tailOffset = offset + RtlPointerToOffset(pto, &pto->TaskBuffer) + TaskBufferSize; if (!TaskBufferSize) { DPrintf(0, ("[%s], unknown offload task %d", __FUNCTION__, pto->Task)); } else if (tailOffset > maxSize) { DPrintf(0, ("[%s], can not parse %s at offset %d, tail at %d", __FUNCTION__, sName, offset, tailOffset)); status = NDIS_STATUS_BUFFER_TOO_SHORT; } else if (TaskBufferSize > pto->TaskBufferLength) { DPrintf(0, ("[%s], invalid size of %s", __FUNCTION__, sName)); status = NDIS_STATUS_BUFFER_TOO_SHORT; } else if (pcs) { DPrintf(0, ("[%s], parsing %s", __FUNCTION__, sName)); DPrintf(0, ("Rx4: checksum IP(%d),TCP(%d),UDP(%d), options IP(%d),TCP(%d)", pcs->V4Receive.IpChecksum, pcs->V4Receive.TcpChecksum, pcs->V4Receive.UdpChecksum, pcs->V4Receive.IpOptionsSupported, pcs->V4Receive.TcpOptionsSupported )); DPrintf(0, ("Tx4: checksum IP(%d),TCP(%d),UDP(%d), options IP(%d),TCP(%d)", pcs->V4Transmit.IpChecksum, pcs->V4Transmit.TcpChecksum, pcs->V4Transmit.UdpChecksum, pcs->V4Transmit.IpOptionsSupported, pcs->V4Transmit.TcpOptionsSupported )); if (bApply) { if (IsValidPcs(pContext, pcs)) { tOffloadSettingsFlags *pf = &pContext->Offload.flags; pf->fTxIPChecksum = !!pcs->V4Transmit.IpChecksum; pf->fTxTCPChecksum = !!pcs->V4Transmit.TcpChecksum; pf->fTxUDPChecksum = !!pcs->V4Transmit.UdpChecksum; pf->fTxTCPOptions = !!pcs->V4Transmit.TcpOptionsSupported; pf->fTxIPOptions = !!pcs->V4Transmit.IpOptionsSupported; pf->fRxIPChecksum = !!pcs->V4Receive.IpChecksum; pf->fRxIPOptions = !!pcs->V4Receive.IpOptionsSupported; pf->fRxTCPChecksum = !!pcs->V4Receive.TcpChecksum; pf->fRxTCPOptions = !!pcs->V4Receive.TcpOptionsSupported; pf->fRxUDPChecksum = !!pcs->V4Receive.UdpChecksum; } else status = STATUS_NOT_SUPPORTED; } } else if (pls) { DPrintf(0, ("[%s], parsing %s version %d", __FUNCTION__, sName, pls->Version)); DPrintf(0, ("options IP(%d),TCP(%d),MaxOffload %d, MinSegments %d", pls->IpOptions, pls->TcpOptions, pls->MaxOffLoadSize, pls->MinSegmentCount)); if (bApply) { if (IsValidPls(pContext, pls)) { tOffloadSettingsFlags *pf = &pContext->Offload.flags; pf->fTxLsoIP = !!pls->IpOptions; pf->fTxLsoTCP = !!pls->TcpOptions; pf->fTxLso = 1; } else status = STATUS_NOT_SUPPORTED; } } else if (pips) { DPrintf(0, ("[%s], parsing %s", __FUNCTION__, sName)); } 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; }
NTSTATUS RtlMakeSelfRelativeSD( IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, IN OUT PULONG BufferLength ) /*++ Routine Description: Makes a copy of a security descriptor. The produced copy will be in self-relative form. The security descriptor to be copied may be in either absolute or self-relative form. Arguments: SecurityDescriptor - Pointer to a security descriptor. This descriptor will not be modified. SelfRelativeSecurityDescriptor - Pointer to a buffer that will contain the returned self-relative security descriptor. BufferLength - Supplies the length of the buffer. If the supplied buffer is not large enough to hold the self-relative security descriptor, an error will be returned, and this field will return the minimum size required. Return Value: STATUS_BUFFER_TOO_SMALL - The supplied buffer was too small to contain the resultant security descriptor. --*/ { ULONG NewDaclSize; ULONG NewSaclSize; ULONG NewOwnerSize; ULONG NewGroupSize; ULONG AllocationSize; PSID NewOwner; PSID NewGroup; PACL NewDacl; PACL NewSacl; PCHAR Field; PCHAR Base; // // Convert security descriptors to new data type so we don't // have to cast all over the place. // PISECURITY_DESCRIPTOR_RELATIVE IResultantDescriptor = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSecurityDescriptor; PISECURITY_DESCRIPTOR IPassedSecurityDescriptor = (PISECURITY_DESCRIPTOR)SecurityDescriptor; RtlpQuerySecurityDescriptor( IPassedSecurityDescriptor, &NewOwner, &NewOwnerSize, &NewGroup, &NewGroupSize, &NewDacl, &NewDaclSize, &NewSacl, &NewSaclSize ); RTL_PAGED_CODE(); AllocationSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + NewOwnerSize + NewGroupSize + NewDaclSize + NewSaclSize ; if (AllocationSize > *BufferLength) { *BufferLength = AllocationSize; return( STATUS_BUFFER_TOO_SMALL ); } RtlZeroMemory( IResultantDescriptor, AllocationSize ); RtlCopyMemory( IResultantDescriptor, IPassedSecurityDescriptor, FIELD_OFFSET( SECURITY_DESCRIPTOR_RELATIVE, Owner )); Base = (PCHAR)(IResultantDescriptor); Field = Base + (ULONG)sizeof(SECURITY_DESCRIPTOR_RELATIVE); if (NewSaclSize > 0) { RtlCopyMemory( Field, NewSacl, NewSaclSize ); IResultantDescriptor->Sacl = RtlPointerToOffset(Base,Field); Field += NewSaclSize; } else { IResultantDescriptor->Sacl = 0; } if (NewDaclSize > 0) { RtlCopyMemory( Field, NewDacl, NewDaclSize ); IResultantDescriptor->Dacl = RtlPointerToOffset(Base,Field); Field += NewDaclSize; } else { IResultantDescriptor->Dacl = 0; } if (NewOwnerSize > 0) { RtlCopyMemory( Field, NewOwner, NewOwnerSize ); IResultantDescriptor->Owner = RtlPointerToOffset(Base,Field); Field += NewOwnerSize; } if (NewGroupSize > 0) { RtlCopyMemory( Field, NewGroup, NewGroupSize ); IResultantDescriptor->Group = RtlPointerToOffset(Base,Field); } RtlpSetControlBits( IResultantDescriptor, SE_SELF_RELATIVE ); return( STATUS_SUCCESS ); }
STATIC PAGEABLE VOID messagetable_SerializingCallback( _In_ PCMESSAGE_TABLE_ENTRY ptEntry, _In_opt_ PCMESSAGE_TABLE_ENTRY ptPreviousEntry, _In_ PVOID pvContext, _Out_ PBOOLEAN pbContinueEnumeration ) { PSERIALIZING_CALLBACK_CONTEXT ptContext = (PSERIALIZING_CALLBACK_CONTEXT)pvContext; PMESSAGE_RESOURCE_BLOCK ptCurrentBlock = NULL; PMESSAGE_RESOURCE_ENTRY ptCurrentEntry = NULL; PAGED_CODE(); #ifndef DBG UNREFERENCED_PARAMETER(pbContinueEnumeration); #endif // !DBG ASSERT(NULL != ptEntry); ASSERT(NULL != pvContext); ASSERT(NULL != pbContinueEnumeration); ASSERT(*pbContinueEnumeration); // Obtain a pointer to the current block header ptCurrentBlock = &(ptContext->ptMessageData->atBlocks[ptContext->nCurrentBlock]); // If there is a new block, set it up if ((NULL == ptPreviousEntry) || (1 != ptEntry->nEntryId - ptPreviousEntry->nEntryId)) { // // New block! // // Safe to increment the counter because we already // ASSERTed the block count inside messagetable_CountingCallback. ++(ptContext->nCurrentBlock); ++ptCurrentBlock; ptCurrentBlock->nLowId = ptEntry->nEntryId; ptCurrentBlock->cbOffsetToEntries = RtlPointerToOffset(ptContext->ptMessageData, ptContext->pcCurrentStringPosition); } // Update the last ID for the current block ptCurrentBlock->nHighId = ptEntry->nEntryId; // Copy ptCurrentEntry = (PMESSAGE_RESOURCE_ENTRY)(ptContext->pcCurrentStringPosition); ptCurrentEntry->cbLength = messagetable_SizeofSerializedEntry(ptEntry); if (ptEntry->bUnicode) { ptCurrentEntry->fFlags = 1; RtlMoveMemory(ptCurrentEntry->acText, ptEntry->tData.tUnicode.Buffer, ptEntry->tData.tUnicode.Length); } else { ptCurrentEntry->fFlags = 0; RtlMoveMemory(ptCurrentEntry->acText, ptEntry->tData.tAnsi.Buffer, ptEntry->tData.tAnsi.Length); } ptContext->pcCurrentStringPosition += ptCurrentEntry->cbLength; }
/****************************************************************** 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; }