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;
}
Пример #9
0
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 );

}
Пример #10
0
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;
}