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

首先是同步问题,通过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向驱动层请求数据。

你可能感兴趣的:(同步)