Windows 驱动之间的通信
来源:互联网 发布:购物车的数据库设计 编辑:程序博客网 时间:2024/06/05 09:44
本文主要介绍windows NT驱动之间利用CTL_CODE如何通信。一般来讲,用户态的应用程序通过调用CreateFile和DeviceIOControl就可以和内核态驱动之间进行通信,如果是内核态的一个驱动程序想和另外一个驱动程序进行类似操作又如何实现呢,接下来会做详细的说明。
主要的思路是首先得到另外一个驱动的handle,再构建一个IRP,赋予必要的参数,再把这个IRP发送给另外一个驱动,等待另外一个驱动处理完毕后获取返回的数据。具体代码如下:
PIRP SMBIrp;
PIO_STACK_LOCATION irpStack;
RtlInitUnicodeString(&usDeviceToFilter, L"/Device/AdvSMBus");
status = IoGetDeviceObjectPointer(&usDeviceToFilter,FILE_WRITE_DATA,&SMBusObject,&g_LM87Data.SmbHc);
if( !NT_SUCCESS(status) )
...{
KdPrint(("LM87: Can't get SMBus host! "));
}
SMBIrp = IoAllocateIrp (g_LM87Data.SmbHc->StackSize, FALSE);
if(!SMBIrp)
...{
KdPrint(("LM87: Allocate irp failed! "));
}
irpStack = IoGetNextIrpStackLocation(SMBIrp);
g_LM87Data.SMBusHostData.Address = LM87_SMBUS_ADDRESS;
g_LM87Data.SMBusHostData.Offset = LM87_INTER_TEMP_REGISTER;
g_LM87Data.SMBusHostData.Data = 0x0;
irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SMBUS_READ_BYTE;
irpStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(SMBUS_HOST);
irpStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(SMBUS_HOST);
SMBIrp->AssociatedIrp.SystemBuffer = &g_LM87Data.SMBusHostData;
IoSetCompletionRoutine (SMBIrp, LM87RequestComplete, &g_LM87Data.SyncEvent, TRUE, TRUE, TRUE);
IoCallDriver (g_LM87Data.SmbHc, SMBIrp);
KeWaitForSingleObject(&g_LM87Data.SyncEvent, Executive, KernelMode, FALSE, NULL);
KdPrint(("LM87: query result is [%X] ",g_LM87Data.SMBusHostData.Data));
result[1] = g_LM87Data.SMBusHostData.Data * 10; //compatible with DiagAnywhere
IoFreeIrp(SMBIrp);
PIO_STACK_LOCATION irpStack;
RtlInitUnicodeString(&usDeviceToFilter, L"/Device/AdvSMBus");
status = IoGetDeviceObjectPointer(&usDeviceToFilter,FILE_WRITE_DATA,&SMBusObject,&g_LM87Data.SmbHc);
if( !NT_SUCCESS(status) )
...{
KdPrint(("LM87: Can't get SMBus host! "));
}
SMBIrp = IoAllocateIrp (g_LM87Data.SmbHc->StackSize, FALSE);
if(!SMBIrp)
...{
KdPrint(("LM87: Allocate irp failed! "));
}
irpStack = IoGetNextIrpStackLocation(SMBIrp);
g_LM87Data.SMBusHostData.Address = LM87_SMBUS_ADDRESS;
g_LM87Data.SMBusHostData.Offset = LM87_INTER_TEMP_REGISTER;
g_LM87Data.SMBusHostData.Data = 0x0;
irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SMBUS_READ_BYTE;
irpStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(SMBUS_HOST);
irpStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(SMBUS_HOST);
SMBIrp->AssociatedIrp.SystemBuffer = &g_LM87Data.SMBusHostData;
IoSetCompletionRoutine (SMBIrp, LM87RequestComplete, &g_LM87Data.SyncEvent, TRUE, TRUE, TRUE);
IoCallDriver (g_LM87Data.SmbHc, SMBIrp);
KeWaitForSingleObject(&g_LM87Data.SyncEvent, Executive, KernelMode, FALSE, NULL);
KdPrint(("LM87: query result is [%X] ",g_LM87Data.SMBusHostData.Data));
result[1] = g_LM87Data.SMBusHostData.Data * 10; //compatible with DiagAnywhere
IoFreeIrp(SMBIrp);
在上面的这段代码中,我们先用IoGetDeviceObjectPointer得到另外一个驱动的handle,然后利用IoAllocateIrp生成一个IRP,在赋完必要的参数之后通过IoCallDriver发送给另外一个驱动,这里需要注意的是在IoCallDriver之前有IoSetCompletionRoution的调用,当另外一个驱动处理完这个IRP之后进入它所设定的Roution之中,通过一个Event我们就知道IRP已经处理完毕,我们可以获取相要的数据了。
NTSTATUS
LM87RequestComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
...{
PKEVENT Event;
Event = (PKEVENT) Context;
KeSetEvent (Event, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
LM87RequestComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
...{
PKEVENT Event;
Event = (PKEVENT) Context;
KeSetEvent (Event, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
这样就实现了在内核态的一个驱动程序和另外一个驱动程序的通信。另外还有一种实现的方式是通过WorKItem和IoBuildDeviceIoControlRequest来实现,这里就不做详细的介绍了。
- Windows 驱动之间的通信
- Windows 驱动与驱动之间的通信
- Windows CE下bootloader和驱动之间的通信
- Windows多线程之间的通信
- linux内核两个驱动之间的通信
- linux内核两个驱动之间的通信
- linux内核两个驱动之间的通信
- WINDOWS下,窗口之间的通信
- windows和linux服务器之间的通信
- Windows Form 线程之间通信
- 在windows下,进程之间通信的几种方式?
- Windows主机和Virtualbox+Debian之间的串口通信
- Windows主机和Virtualbox+Debian之间的串口通信
- 线程之间的通信(主要windows下message)
- 用socket实现Linux和Windows之间的通信
- 两台windows之间MQ中间消息件的通信
- Windows驱动和应用程序通信
- vlan之间的通信
- SQL 流程控制命令
- 面试题4
- SQL 变量
- 面试题5
- 注释符、运算符与通配符
- Windows 驱动之间的通信
- 面试题6
- J2ME Porting 到ARM LINUX探讨
- 数据类型
- STL标准模板库
- Transact-SQL 语言概述
- cp命令(复制)
- SQL 语言
- AST 使用笔记