/*
#define
BIOCSETBUFFERSIZE 9592
该IOCTL命令码用来设置内核缓冲区大小。
该IOCTL用来设置一个NPF实例的循环缓冲区的大小,当接收到一个BIOCSETBUFFERSIZE命令时,驱动程序释放老的缓冲区,分配一个新的缓冲区,并在OPEN_INSTANCE结构体中复位与该缓冲区相关的所有参数。
当前缓冲的所有数据包都被丢弃。
*/
case BIOCSETBUFFERSIZE:
/*
验证输入参数的合法性*/
if(IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG))
{
SET_FAILURE_BUFFER_SMALL();
break;
}
//
获得所需分配缓冲区的字节数
dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
if (dim / g_NCpu < sizeof(struct PacketHeader))
{
dim = 0;
}
else
{
tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
if (tpointer == NULL)
{
//
没有内存
SET_FAILURE_NOMEM();
break;
}
}
/*
获得所有缓冲区的锁*/
for (i = 0; i < g_NCpu ; i++)
{
#pragma prefast(suppress:8103,
"There's no Spinlock leak here, as it's released some lines below.")
NdisAcquireSpinLock(&Open->CpuData[i].BufferLock);
}
/*
如果有旧的缓冲区,就释放掉*/
if (Open->CpuData[0].Buffer != NULL)
{
ExFreePool(Open->CpuData[0].Buffer);
}
/*
在OPEN_INSTANCE结构体中复位相关的所有参数*/
for (i = 0 ; i < g_NCpu ; i++)
{
if (dim > 0)
Open->CpuData[i].Buffer=
(PUCHAR)tpointer + (dim/g_NCpu)*i;
else
Open->CpuData[i].Buffer = NULL;
Open->CpuData[i].Free = dim/g_NCpu;
Open->CpuData[i].P = 0;
Open->CpuData[i].C = 0;
Open->CpuData[i].Accepted = 0;
Open->CpuData[i].Dropped = 0;
Open->CpuData[i].Received = 0;
}
Open->ReaderSN=0;
Open->WriterSN=0;
Open->Size = dim/g_NCpu;
/*
释放所有缓冲区的锁*/
i = g_NCpu;
do
{
i--;
#pragma prefast(suppress:8107,
"There's no Spinlock leak here, as it's acquired some lines above.")
NdisReleaseSpinLock(&Open->CpuData[i].BufferLock);
}while(i != 0);
SET_RESULT_SUCCESS(0);
break;
/*
#define
BIOCSETEVENTHANDLE 7920
该IOCTL命令码用来把用户(packet.dll)所分配的读事件句柄传递给内核层。
参数:HANDLE
参数为size为句柄的大小sizeof(HANDLE)。*/
case BIOCSETEVENTHANDLE:
/*
验证输入参数的合法性*/
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
sizeof (hUserEvent))
{
SET_FAILURE_INVALID_REQUEST();
break;
}
hUserEvent = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
/*
对hUserEvent进行访问授权确认,如果访问被授权,就返回该对象体对应的指针pKernelEvent。*/
Status = ObReferenceObjectByHandle(hUserEvent,
EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode,
(PVOID*) &pKernelEvent, NULL);
if (!NT_SUCCESS(Status))
{
// Status = ??? already set
Information = 0;
break;
}
/*
如果&Open->ReadEvent等于NULL,就把Open->ReadEvent赋为pKernelEvent,否则Open->ReadEvent值不改变。*/
if (InterlockedCompareExchangePointer(&Open->ReadEvent,
pKernelEvent, NULL) != NULL)
{
//
释放
pKernelEvent
ObDereferenceObject(pKernelEvent);
SET_FAILURE_INVALID_REQUEST();
break;
}
//
把
ReadEvent
复位为非激活状态
KeResetEvent(Open->ReadEvent);
SET_RESULT_SUCCESS(0);
break;
…
说明:
深度剖析WinPcap之(八)章节全部结束。