驱动层和应用层的同步通信

首先是同步问题,通过Ring3创建事件,并将该事件传递给Ring0,同时Ring3创建监控线程,等待Ring0发起事件。

                                           监控到事件(通知)

Ring0(监控)----------------------------------------------------------------> Ring3  

应用层得到事件通知后,向驱动层发起数据获取请求。由Ring3主动发起,Ring0被动接受。

                                          询问(CTL_CODE)

Ring3     ---------------------------------------------------------------- >     Ring0  

                                        回答(通过OUT参数)

Ring3     <----------------------------------------------------------------       Ring0  

 

具体实现:

应用层:

HANDLE hDevice = CreateFile("\\\\.\\PRMonitor",
                                GENERIC_READ|GENERIC_WRITE,
                                0,
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_SYSTEM,
                                NULL);   //打开设备
    if(hDevice==INVALID_HANDLE_VALUE)
    {
        printf("Failed to obtain device with error code: %d\n",GetLastError());
        getchar();
        return;
    }

    
    DWORD dwOutput;
    char* OutputBuffer[256];
    HANDLE m_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);  //创建事件
    DeviceIoControl(hDevice,IOCTL_STARTHOOK,&m_hEvent,sizeof(HANDLE),NULL,0,&dwOutput,NULL); //发事件给ring0
    
    printf("IoControl code sent\n");
    while(true)
    {

        WaitForSingleObject(m_hEvent,INFINITE);  //等待ring0事件通知
        DeviceIoControl(hDevice,IOCTL_GETINFO,NULL,0,&OutputBuffer,256,&dwOutput,NULL);  //获取数据
        printf("%s\n",OutputBuffer);
        ResetEvent(m_hEvent);  //重置事件
    }
 
驱动层:

PRKEVENT gpEventObject;
POBJECT_HANDLE_INFORMATION objHandleInfo;

 
NTSTATUS DevDispatch(PDEVICE_OBJECT  DeviceObject,PIRP  Irp)
{
    PVOID pInBuffer;
    ULONG pInbufferSize;
    PVOID pOutBuffer;
    ULONG pOutbufferSize;
    NTSTATUS status;
    PIO_STACK_LOCATION ps = IoGetCurrentIrpStackLocation(Irp);
            
    switch(ps->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_STARTHOOK:  //传送事件
        if(!bProcMon)
        {
            ……
            pInBuffer = Irp->AssociatedIrp.SystemBuffer;
            pInbufferSize = ps->Parameters.DeviceIoControl.InputBufferLength;
            if(pInBuffer == NULL || pInbufferSize < sizeof(HANDLE))
            {
                KdPrint(("Set Event Error\n"));
                status = STATUS_INVALID_BUFFER_SIZE;
                break;
            }
            hEvent = *(HANDLE*)pInBuffer;

            status = ObReferenceObjectByHandle(hEvent,
                GENERIC_ALL,
                NULL,
                KernelMode,
                &gpEventObject,
                &objHandleInfo);
            KdPrint(("gpEventObject: %x\n",gpEventObject));
            
            
        }
        
        break;

    case IOCTL_GETINFO:    //传送数据
        pOutBuffer = Irp->AssociatedIrp.SystemBuffer;
        pOutbufferSize = ps->Parameters.DeviceIoControl.OutputBufferLength;
        RtlCopyMemory(pOutBuffer,output,sizeof(output));
        
        Irp->IoStatus.Information = pOutbufferSize; 
        
        break;
    }
    //////////////////////////////////////////////////////////////////////////
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp,IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}
 
在需要通知应用层事件的地方(比如监控到某一事件时)加上这一句
KeSetEvent(gpEventObject,0,FALSE);  
这时应用层程序就会通过DeviceIoControl向驱动层请求数据。
 
 
 
 
posted on 2009-04-17 15:16  dflower  阅读(1987)  评论(0编辑  收藏  举报