深度剖析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之(八)章節全部結束。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章