📄 buffer.c
字号:
/*
* 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 + -