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

📄 buffer.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS NDIS library
 * FILE:        ndis/buffer.c
 * PURPOSE:     Buffer management routines
 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
 * REVISIONS:
 *   CSH 01/08-2000 Created
 */

#include <ndissys.h>


__inline ULONG SkipToOffset(
    IN PNDIS_BUFFER Buffer,
    IN UINT Offset,
    IN OUT PUCHAR *Data,
    IN OUT PUINT Size)
/*
 * FUNCTION: Skips Offset bytes into a buffer chain
 * ARGUMENTS:
 *     Buffer = Pointer to NDIS buffer
 *     Offset = Number of bytes to skip
 *     Data   = Address of a pointer that on return will contain the
 *              address of the offset in the buffer
 *     Size   = Address of a pointer that on return will contain the
 *              size of the destination buffer
 * RETURNS:
 *     Offset into buffer, -1 if buffer chain was smaller than Offset bytes
 * NOTES:
 *     Buffer may be NULL
 */
{
    for (;;) {

        if (!Buffer)
            return 0xFFFFFFFF;

        NdisQueryBuffer(Buffer, (PVOID)Data, Size);

        if (Offset < *Size) {
            *Data  = (PUCHAR) ((ULONG_PTR) *Data + Offset);
            *Size -= Offset;
            break;
        }

        Offset -= *Size;

        NdisGetNextBuffer(Buffer, &Buffer);
    }

    return Offset;
}

UINT CopyBufferToBufferChain(
    PNDIS_BUFFER DstBuffer,
    UINT DstOffset,
    PUCHAR SrcData,
    UINT Length)
/*
 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
 * ARGUMENTS:
 *     DstBuffer = Pointer to destination NDIS buffer
 *     DstOffset = Destination start offset
 *     SrcData   = Pointer to source buffer
 *     Length    = Number of bytes to copy
 * RETURNS:
 *     Number of bytes copied to destination buffer
 * NOTES:
 *     The number of bytes copied may be limited by the destination
 *     buffer size
 */
{
    UINT BytesCopied, BytesToCopy, DstSize;
    PUCHAR DstData;

    NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X)  DstOffset (0x%X)  SrcData (0x%X)  Length (%d)\n", DstBuffer, DstOffset, SrcData, Length));

    /* Skip DstOffset bytes in the destination buffer chain */
    if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF)
        return 0;

    /* Start copying the data */
    BytesCopied = 0;
    for (;;) {
        BytesToCopy = MIN(DstSize, Length);

        RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
        BytesCopied += BytesToCopy;
        SrcData      = (PUCHAR) ((ULONG_PTR) SrcData + BytesToCopy);

        Length -= BytesToCopy;
        if (Length == 0)
            break;

        DstSize -= BytesToCopy;
        if (DstSize == 0) {
            /* No more bytes in desination buffer. Proceed to
               the next buffer in the destination buffer chain */
            NdisGetNextBuffer(DstBuffer, &DstBuffer);
            if (!DstBuffer)
                break;

            NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
        }
    }

    return BytesCopied;
}


UINT CopyBufferChainToBuffer(
    PUCHAR DstData,
    PNDIS_BUFFER SrcBuffer,
    UINT SrcOffset,
    UINT Length)
/*
 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
 * ARGUMENTS:
 *     DstData   = Pointer to destination buffer
 *     SrcBuffer = Pointer to source NDIS buffer
 *     SrcOffset = Source start offset
 *     Length    = Number of bytes to copy
 * RETURNS:
 *     Number of bytes copied to destination buffer
 * NOTES:
 *     The number of bytes copied may be limited by the source
 *     buffer size
 */
{
    UINT BytesCopied, BytesToCopy, SrcSize;
    PUCHAR SrcData;

    NDIS_DbgPrint(MAX_TRACE, ("DstData 0x%X  SrcBuffer 0x%X  SrcOffset 0x%X  Length %d\n",DstData,SrcBuffer, SrcOffset, Length));

    /* Skip SrcOffset bytes in the source buffer chain */
    if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
        return 0;

    /* Start copying the data */
    BytesCopied = 0;
    for (;;) {
        BytesToCopy = MIN(SrcSize, Length);

        NDIS_DbgPrint(MAX_TRACE, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData));

        RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
        BytesCopied += BytesToCopy;
        DstData      = (PUCHAR)((ULONG_PTR) DstData + BytesToCopy);

        Length -= BytesToCopy;
        if (Length == 0)
            break;

        SrcSize -= BytesToCopy;
        if (SrcSize == 0) {
            /* No more bytes in source buffer. Proceed to
               the next buffer in the source buffer chain */
            NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
            if (!SrcBuffer)
                break;

            NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
        }
    }

    return BytesCopied;
}


UINT CopyPacketToBuffer(
    PUCHAR DstData,
    PNDIS_PACKET SrcPacket,
    UINT SrcOffset,
    UINT Length)
/*
 * FUNCTION: Copies data from an NDIS packet to a buffer
 * ARGUMENTS:
 *     DstData   = Pointer to destination buffer
 *     SrcPacket = Pointer to source NDIS packet
 *     SrcOffset = Source start offset
 *     Length    = Number of bytes to copy
 * RETURNS:
 *     Number of bytes copied to destination buffer
 * NOTES:
 *     The number of bytes copied may be limited by the source
 *     buffer size
 */
{
    PNDIS_BUFFER FirstBuffer;
    PVOID Address;
    UINT FirstLength;
    UINT TotalLength;

    NDIS_DbgPrint(MAX_TRACE, ("DstData (0x%X)  SrcPacket (0x%X)  SrcOffset (0x%X)  Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));

    NdisGetFirstBufferFromPacket(SrcPacket,
                                 &FirstBuffer,
                                 &Address,
                                 &FirstLength,
                                 &TotalLength);

    return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
}


UINT CopyPacketToBufferChain(
    PNDIS_BUFFER DstBuffer,
    UINT DstOffset,
    PNDIS_PACKET SrcPacket,
    UINT SrcOffset,
    UINT Length)
/*
 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
 * ARGUMENTS:
 *     DstBuffer = Pointer to destination NDIS buffer
 *     DstOffset = Destination start offset
 *     SrcPacket = Pointer to source NDIS packet
 *     SrcOffset = Source start offset
 *     Length    = Number of bytes to copy
 * RETURNS:
 *     Number of bytes copied to destination buffer
 * NOTES:
 *     The number of bytes copied may be limited by the source and
 *     destination buffer sizes
 */
{
    PNDIS_BUFFER SrcBuffer;
    PUCHAR DstData, SrcData;
    UINT DstSize, SrcSize;
    UINT Count, Total;

    NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X)  DstOffset (0x%X)  SrcPacket (0x%X)  SrcOffset (0x%X)  Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length));

    /* Skip DstOffset bytes in the destination buffer chain */
    NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
    if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF)
        return 0;
    /* Skip SrcOffset bytes in the source packet */
    NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total);
    if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
        return 0;
    /* Copy the data */
    for (Total = 0;;) {
        /* Find out how many bytes we can copy at one time */
        if (Length < SrcSize)
            Count = Length;
        else
            Count = SrcSize;
        if (DstSize < Count)
            Count = DstSize;

        RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);

        Total  += Count;
        Length -= Count;
        if (Length == 0)
            break;

        DstSize -= Count;
        if (DstSize == 0) {
            /* No more bytes in destination buffer. Proceed to
               the next buffer in the destination buffer chain */
            NdisGetNextBuffer(DstBuffer, &DstBuffer);
            if (!DstBuffer)
                break;

            NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
        }

        SrcSize -= Count;
        if (SrcSize == 0) {
            /* No more bytes in source buffer. Proceed to
               the next buffer in the source buffer chain */
            NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
            if (!SrcBuffer)
                break;

            NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
        }
    }

    return Total;
}


/*
 * @implemented
 */
#undef NdisAdjustBufferLength
VOID
EXPORT
NdisAdjustBufferLength(
    IN PNDIS_BUFFER Buffer,
    IN UINT         Length)
/*
 * FUNCTION: Modifies the length of an NDIS buffer
 * ARGUMENTS:
 *     Buffer = Pointer to NDIS buffer descriptor
 *     Length = New size of buffer
 */
{
    Buffer->ByteCount = Length;
}


/*
 * @implemented
 */
#undef NDIS_BUFFER_TO_SPAN_PAGES
ULONG
EXPORT
NDIS_BUFFER_TO_SPAN_PAGES(
    IN  PNDIS_BUFFER    Buffer)
/*
 * FUNCTION: Determines how many physical pages a buffer is made of
 * ARGUMENTS:
 *     Buffer = Pointer to NDIS buffer descriptor
 */
{
    if (MmGetMdlByteCount(Buffer) == 0)
        return 1;

    return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
            MmGetMdlVirtualAddress(Buffer),
            MmGetMdlByteCount(Buffer));
}


/*
 * @implemented
 */
VOID
EXPORT
NdisAllocateBuffer(
    OUT PNDIS_STATUS    Status,
    OUT PNDIS_BUFFER    * Buffer,
    IN  NDIS_HANDLE     PoolHandle,
    IN  PVOID           VirtualAddress,
    IN  UINT            Length)
/*
 * FUNCTION: Allocates an NDIS buffer descriptor
 * ARGUMENTS:
 *     Status         = Address of buffer for status
 *     Buffer         = Address of buffer for NDIS buffer descriptor
 *     PoolHandle     = Handle returned by NdisAllocateBufferPool
 *     VirtualAddress = Pointer to virtual address of data buffer
 *     Length         = Number of bytes in data buffer
 */
{
    ASSERT(VirtualAddress != NULL);
    ASSERT(Length > 0);
    
    *Buffer = IoAllocateMdl(VirtualAddress, Length, FALSE, FALSE, NULL);
    if (*Buffer != NULL) {
        MmBuildMdlForNonPagedPool(*Buffer);
        (*Buffer)->Next = NULL;
        *Status = NDIS_STATUS_SUCCESS;
    } else {
        *Status = NDIS_STATUS_FAILURE;
    }
}


/*
 * @implemented
 */
VOID
EXPORT
NdisAllocateBufferPool(
    OUT PNDIS_STATUS    Status,
    OUT PNDIS_HANDLE    PoolHandle,
    IN  UINT            NumberOfDescriptors)
/*
 * FUNCTION: Allocates storage for an NDIS buffer pool
 * ARGUMENTS:
 *     Status              = Address of buffer for status
 *     PoolHandle          = Address of buffer for pool handle
 *     NumberOfDescriptors = Size of buffer pool in number of descriptors
 */
{
    *Status = NDIS_STATUS_SUCCESS;
    *PoolHandle = 0;
}


/*
 * @implemented
 */
VOID
EXPORT
NdisAllocatePacket(
    OUT PNDIS_STATUS    Status,
    OUT PNDIS_PACKET    * Packet,
    IN  NDIS_HANDLE     PoolHandle)
/*
 * FUNCTION: Allocates an NDIS packet descriptor
 * ARGUMENTS:
 *     Status     = Address of buffer for status
 *     Packet     = Address of buffer for packet descriptor
 *     PoolHandle = Handle returned by NdisAllocatePacketPool
 */
{
    KIRQL OldIrql;
    PNDIS_PACKET Temp;
    PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;

    NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X)  Packet (0x%X)  PoolHandle (0x%X).\n",
        Status, Packet, PoolHandle));

    if (Pool == NULL)
    {
        *Status = NDIS_STATUS_FAILURE;
        return;
    }

    KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql);

    if (Pool->FreeList) {
        Temp           = Pool->FreeList;
        Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;

        KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);

        RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
        Temp->Private.Pool = Pool;

        *Packet = Temp;
        *Status = NDIS_STATUS_SUCCESS;
    } else {
        *Status = NDIS_STATUS_RESOURCES;
        KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
    }
}


/*
 * @implemented
 */
VOID
EXPORT
NdisAllocatePacketPool(
    OUT PNDIS_STATUS    Status,
    OUT PNDIS_HANDLE    PoolHandle,
    IN  UINT            NumberOfDescriptors,
    IN  UINT            ProtocolReservedLength)
/*
 * FUNCTION: Allocates storage for an NDIS packet pool
 * ARGUMENTS:
 *     Status                 = Address of buffer for status
 *     PoolHandle             = Address of buffer for pool handle
 *     NumberOfDescriptors    = Size of packet pool in number of descriptors
 *     ProtocolReservedLength = Size of protocol reserved area in bytes
 */
{
    NdisAllocatePacketPoolEx(
        Status,
        PoolHandle,
        NumberOfDescriptors,
        0,
        ProtocolReservedLength);
}


/*
 * @unimplemented
 */
VOID
EXPORT
NdisAllocatePacketPoolEx(
    OUT PNDIS_STATUS    Status,
    OUT PNDIS_HANDLE    PoolHandle,
    IN  UINT            NumberOfDescriptors,
    IN  UINT            NumberOfOverflowDescriptors,
    IN  UINT            ProtocolReservedLength)
/*
 * FUNCTION:
 * ARGUMENTS:
 * NOTES:
 *    NDIS 5.0
 */
{
    PNDISI_PACKET_POOL Pool;
    UINT Size, Length, i;
    PNDIS_PACKET Packet, NextPacket;

    NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X)  PoolHandle (0x%X)  "
        "NumberOfDescriptors (%d)  ProtocolReservedLength (%d).\n",
        Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength));

    if (NumberOfDescriptors > 0xffff)
    {
        *Status = NDIS_STATUS_RESOURCES;
    }
    else
    {
        NumberOfDescriptors += NumberOfOverflowDescriptors;
        if (NumberOfDescriptors > 0xffff)
        {
            NumberOfDescriptors = 0xffff;
        }

        Length = sizeof(NDIS_PACKET) + ProtocolReservedLength;
        Size   = sizeof(NDISI_PACKET_POOL) + Length * NumberOfDescriptors;

        Pool   = ExAllocatePool(NonPagedPool, Size);
        if (Pool) 
        {
            KeInitializeSpinLock(&Pool->SpinLock.SpinLock);
            Pool->PacketLength = Length;

            if (NumberOfDescriptors > 0) 
            {
                Packet         = (PNDIS_PACKET)&Pool->Buffer;
                Pool->FreeList = Packet;

                NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
                for (i = 1; i < NumberOfDescriptors; i++) 
                {
                    Packet->Private.Head = (PNDIS_BUFFER)NextPacket;
                    Packet               = NextPacket;
                    NextPacket           = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
                }
                Packet->Private.Head = NULL;
            } 
            else
                Pool->FreeList = NULL;

            *Status     = NDIS_STATUS_SUCCESS;
            *PoolHandle = (PNDIS_HANDLE)Pool;
        } else
            *Status = NDIS_STATUS_RESOURCES;
    }
}


/*
 * @implemented
 */
#undef NdisBufferLength
ULONG
EXPORT
NdisBufferLength(
    IN  PNDIS_BUFFER    Buffer)
/*
 * FUNCTION: Modifies the length of an NDIS buffer
 * ARGUMENTS:
 *     Buffer = Pointer to NDIS buffer descriptor
 *     Length = New size of buffer
 * NOTES:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -