深度剖析WinPcap之(八)――打开与关闭适配器(26)(完)

/* #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之(八)章节全部结束。

 

你可能感兴趣的:(职场,休闲,winpcap)