IP过滤-驱动和应用程序通信

    前段时间写一个IP过滤的驱动,以前没有接触过驱动,Google一把,网上有很多例子,不过都不能满足自己的需求,所以就参考大家的资料自己研究一下。呵呵。程序用了三层:第一层就是驱动来负责过滤数据包并把拦截的结果返回给应用程序。第二层VC动态链接库来负责加载卸载驱动,和驱动通信。并提供接口给第三层调用。第三层C#Winform,调用VC动态链接库提供的接口,间接和驱动通信,并显示驱动返回结果。

    用到最多的就是DeviceIoControl这个函数,可以通过这个函数向驱动程序发送消息,还可以从驱动程序获取消息,下面让我们来看一下这个函数的结构吧:
BOOL DeviceIoControl(
HANDLE hDevice, //创建的驱动设备句柄
DWORD dwIoControlCode, //应用程序调用驱动程序的控制命令
LPVOID lpInBuffer, //应用程序传递给驱动程序的数据缓冲区地址
DWORD nInBufferSize, //应用程序传递给驱动程序的数据缓冲区大小,字节数
LPVOID lpOutBuffer, //驱动程序返回给应用程序的数据缓冲区地址
DWORD nOutBufferSize, //驱动程序返回给应用程序的数据缓冲区大小,字节数
LPDWORD lpBytesReturned, //驱动程序实际返回给应用程序的数据字节数地址
LPOVERLAPPED lpOverlapped//重叠操作结构 一般设为NULL
);
向驱动发消息:
DWORD WriteIo(DWORD code, PVOID buffer, DWORD count)
{
if(driverHandle == NULL)
return DRV_ERROR_INVALID_HANDLE;

DWORD bytesReturned;
      BOOL returnCode = DeviceIoControl(driverHandle,
        code,
        buffer,
        count,
       NULL,
        0,
       &bytesReturned,
        NULL);
if(!returnCode) return DRV_ERROR_IO; return DRV_SUCCESS;
}
    

从驱动获取消息:

DWORD  ReadIo(DWORD code, PVOID buffer, DWORD count)
{
if(driverHandle == NULL)
return DRV_ERROR_INVALID_HANDLE;

DWORD bytesReturned;
BOOL retCode = DeviceIoControl(driverHandle,
  code,
  NULL,
  0,
  buffer,
  count,
  &bytesReturned,
  NULL);

if(!retCode)
return DRV_ERROR_IO;

return DRV_SUCCESS;
}

有了这两个函数我们就可以向驱动发消息和从驱动获取数据了。我们可以通过Writeto 把要添加或删除的Ip过滤规则发给驱动程序。下一步我们要做的就是当驱动拦截到添加的IP过滤规则后怎么通知应用程序。这里用到了CreateEvent,然后把这个m_hCommEvent 通过Writeto 通知给驱动,
BOOL   CreateFilterEvent(DWORD code)
        m_hCommEvent= CreateEvent(NULL, false, false, NULL);
if(driverHandle == NULL)
{
MessageBox(NULL,TEXT("driverHandle is null"),NULL,MB_OK); 
//return FALSE;
       DWORD dwReturn;
//download event object to device driver
BOOL retCode = DeviceIoControl(driverHandle, 
code, 
       &m_hCommEvent,
sizeof(m_hCommEvent), 
NULL, 
0, 
&dwReturn, 
NULL);
if(retCode)
{
  return TRUE;
}
else
{
return FALSE;
}
}
然后通过CreateThread创建一下线程来接受驱动的消息,
在线程函数里写:
 while(threadFlag)
{  
if(m_hCommEvent)
{
            WaitForSingleObject(m_hCommEvent,INFINITE);  
            //收到驱动的通知
           //从驱动取数据
           //通知C#窗体
           ResetEvent(m_hCommEvent);
        }
}
驱动里做一下处理:
                               HANDLE hEvent =*(PHANDLE)ioBuffer;
NTSTATUS status = ObReferenceObjectByHandle(
hEvent,
GENERIC_ALL,
NULL,
KernelMode,
&gpEventObject,
&objHandleInfo);
if(!NT_SUCCESS(status))
      { 
   if(gpEventObject)
{
 ObDereferenceObject(gpEventObject);
}
if(hEvent)
                                       {

}
              Irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
}
if(status != STATUS_SUCCESS)
{
DbgPrint("ObReferenceObjectByHandle failed! status = %x\n", status);
Irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
break;
}
当驱动拦截到过滤的IP数据包的时候:
                                                if(gpEventObject)
       { 
                                                    //一个变量赋值等应用程序收到通知的时候来去这个数据
             KeSetEvent(gpEventObject, 0,FALSE);//by Fs.song
      }

只是程序记录。
posted @ 2009-08-13 12:09  Ctrliman  阅读(1383)  评论(0编辑  收藏  举报