概述
1、内核通知应用层方法:
a、如果是vxd,使用shell_postmessage是最简单的方法,但是只能传递两个DWORD。walter oney的
那本关于vxd的书中有更详细的描述,该书的中文版可以在侯俊杰的网站上下载。还有一本关于vxd得好书,
《windows vxd与设备驱动权威指南》,孙喜明译,作者名字太怪,我记不住,但是个msj上的牛人。这本
书翻译的不错,孙喜明是98/99活跃在tsinghua bbs上的vxd高手。
b、如果是sys,思路如下:首先在driver中IoCreateDevice,然后让应用层创建一个线程,调用deviceioctl,
异步调用,然后等待事件。驱动程序到了需要通知应用层的时候,iocompleteirp,应用层的那个事件就
变成有信号的,然后就可以得到通知的数据。你可以参考我的代码(附件1,附件2)。该方法同样适用于
vxd,但是由于vxd没有系统队列的概念,因此你需要使用自定义队列管理应用层请求。稍稍费劲,可以参考
98ddk/src/net/ndis/vpacket目录下的实现。
附件1、
请注意看notifyevent函数。
当驱动程序需要通知应用层的时候,调用notifyevent函数。
/*
++
Copyright (c) 2001
Module Name:
devctrl.c
Abstract:
Author:
Environment:
Revision History:
-- */
#include " ioctl.h "
NTSTATUS
IM_CTRL_Open(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/* ++
Routine Description:
This is the dispatch routine for create/open and close requests.
These requests complete successfully.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
-- */
{
NTSTATUS status = STATUS_SUCCESS;
DBGPRINT(( " OpenAdapter " ));
Irp -> IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
IM_CTRL_Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/* ++
Routine Description:
This is the dispatch routine for create/open and close requests.
These requests complete successfully.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
-- */
{
NTSTATUS status = STATUS_SUCCESS;
DBGPRINT(( " CloseAdapter " ));
Irp -> IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
IM_CTRL_Cleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/* ++
Routine Description:
This is the dispatch routine for cleanup requests.
This routine is called whenever a handle to the device
is closed.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
-- */
{
NTSTATUS status = STATUS_SUCCESS;
DBGPRINT(( " Packet: Cleanup " ));
Irp -> IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
/*
VOID
IM_CTRL_Unload(
IN PDRIVER_OBJECT DriverObject
)
{
UNICODE_STRING win32DeviceName;
DBGPRINT(("Unload Enter "));
//
// First delete the Control deviceobject and the corresponding
// symbolicLink
//
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
if(Globals.ControlDeviceObject)
IoDeleteDevice(Globals.ControlDeviceObject);
DBGPRINT(("Unload Exit "));
}
*/
NTSTATUS
IM_CTRL_IoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
ULONG RequireLength = 0 ;
PADAPT pAdapt;
UINT AdapterNum;
PDEVICE_EXTENSION pDevExt;
KIRQL OldIRQL;
pDevExt = DeviceObject -> DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
ioControlCode = irpStack -> Parameters.DeviceIoControl.IoControlCode;
ioBuffer = Irp -> AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack -> Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack -> Parameters.DeviceIoControl.OutputBufferLength;
Status = NDIS_STATUS_SUCCESS;
KeAcquireSpinLock( & ImdGlobals.SpinLock, & OldIRQL);
switch (ioControlCode)
{
case GET_EVENT_MSG:
if (outputBufferLength < sizeof (EVENTMSG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break ;
}
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject,Irp,NULL,CancelIrp);
Status = STATUS_PENDING;
KeReleaseSpinLock( & ImdGlobals.SpinLock,OldIRQL);
return Status;
case SET_OPTION :
// ............ more case
default :
Status = STATUS_INVALID_PARAMETER;
break ;
}
KeReleaseSpinLock( & ImdGlobals.SpinLock,OldIRQL);
Irp -> IoStatus.Status = Status;
Irp -> IoStatus.Information = outputBufferLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
VOID
CancelIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
if (Irp == DeviceObject -> CurrentIrp)
{
IoReleaseCancelSpinLock(Irp -> CancelIrql);
IoStartNextPacket(DeviceObject,TRUE);
}
else
{
KeRemoveEntryDeviceQueue(
& DeviceObject -> DeviceQueue,
& Irp -> Tail.Overlay.DeviceQueueEntry
);
IoReleaseCancelSpinLock(Irp -> CancelIrql);
}
Irp -> IoStatus.Status = STATUS_CANCELLED;
Irp -> IoStatus.Information;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return ;
}
VOID
StartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
return ;
}
BOOLEAN
NotifyEvent(
IN PEVENTMSG EventMsg
)
{
PDEVICE_OBJECT DeviceObject = ImdGlobals.ControlDeviceObject ;
PIRP Irp ;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
KIRQL CancelIrql;
Irp = DeviceObject -> CurrentIrp;
if ( ! Irp) return FALSE;
IoAcquireCancelSpinLock( & CancelIrql);
if (Irp -> Cancel)
{
IoReleaseCancelSpinLock(CancelIrql);
return FALSE;
}
IoSetCancelRoutine(Irp,NULL);
IoReleaseCancelSpinLock(CancelIrql);
irpStack = IoGetCurrentIrpStackLocation(Irp);
ioBuffer = Irp -> AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack -> Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack -> Parameters.DeviceIoControl.OutputBufferLength;
if (outputBufferLength < sizeof (EVENTMSG))
{
outputBufferLength = 0 ;
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
RtlCopyMemory(ioBuffer,EventMsg, sizeof (EVENTMSG));
outputBufferLength = sizeof (EVENTMSG);
}
Irp -> IoStatus.Status = Status;
Irp -> IoStatus.Information = outputBufferLength;
IoStartNextPacket(DeviceObject,TRUE);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return TRUE;
}
Copyright (c) 2001
Module Name:
devctrl.c
Abstract:
Author:
Environment:
Revision History:
-- */
#include " ioctl.h "
NTSTATUS
IM_CTRL_Open(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/* ++
Routine Description:
This is the dispatch routine for create/open and close requests.
These requests complete successfully.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
-- */
{
NTSTATUS status = STATUS_SUCCESS;
DBGPRINT(( " OpenAdapter " ));
Irp -> IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
IM_CTRL_Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/* ++
Routine Description:
This is the dispatch routine for create/open and close requests.
These requests complete successfully.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
-- */
{
NTSTATUS status = STATUS_SUCCESS;
DBGPRINT(( " CloseAdapter " ));
Irp -> IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
IM_CTRL_Cleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/* ++
Routine Description:
This is the dispatch routine for cleanup requests.
This routine is called whenever a handle to the device
is closed.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
-- */
{
NTSTATUS status = STATUS_SUCCESS;
DBGPRINT(( " Packet: Cleanup " ));
Irp -> IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
/*
VOID
IM_CTRL_Unload(
IN PDRIVER_OBJECT DriverObject
)
{
UNICODE_STRING win32DeviceName;
DBGPRINT(("Unload Enter "));
//
// First delete the Control deviceobject and the corresponding
// symbolicLink
//
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
if(Globals.ControlDeviceObject)
IoDeleteDevice(Globals.ControlDeviceObject);
DBGPRINT(("Unload Exit "));
}
*/
NTSTATUS
IM_CTRL_IoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
ULONG RequireLength = 0 ;
PADAPT pAdapt;
UINT AdapterNum;
PDEVICE_EXTENSION pDevExt;
KIRQL OldIRQL;
pDevExt = DeviceObject -> DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
ioControlCode = irpStack -> Parameters.DeviceIoControl.IoControlCode;
ioBuffer = Irp -> AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack -> Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack -> Parameters.DeviceIoControl.OutputBufferLength;
Status = NDIS_STATUS_SUCCESS;
KeAcquireSpinLock( & ImdGlobals.SpinLock, & OldIRQL);
switch (ioControlCode)
{
case GET_EVENT_MSG:
if (outputBufferLength < sizeof (EVENTMSG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break ;
}
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject,Irp,NULL,CancelIrp);
Status = STATUS_PENDING;
KeReleaseSpinLock( & ImdGlobals.SpinLock,OldIRQL);
return Status;
case SET_OPTION :
// ............ more case
default :
Status = STATUS_INVALID_PARAMETER;
break ;
}
KeReleaseSpinLock( & ImdGlobals.SpinLock,OldIRQL);
Irp -> IoStatus.Status = Status;
Irp -> IoStatus.Information = outputBufferLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
VOID
CancelIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
if (Irp == DeviceObject -> CurrentIrp)
{
IoReleaseCancelSpinLock(Irp -> CancelIrql);
IoStartNextPacket(DeviceObject,TRUE);
}
else
{
KeRemoveEntryDeviceQueue(
& DeviceObject -> DeviceQueue,
& Irp -> Tail.Overlay.DeviceQueueEntry
);
IoReleaseCancelSpinLock(Irp -> CancelIrql);
}
Irp -> IoStatus.Status = STATUS_CANCELLED;
Irp -> IoStatus.Information;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return ;
}
VOID
StartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
return ;
}
BOOLEAN
NotifyEvent(
IN PEVENTMSG EventMsg
)
{
PDEVICE_OBJECT DeviceObject = ImdGlobals.ControlDeviceObject ;
PIRP Irp ;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
KIRQL CancelIrql;
Irp = DeviceObject -> CurrentIrp;
if ( ! Irp) return FALSE;
IoAcquireCancelSpinLock( & CancelIrql);
if (Irp -> Cancel)
{
IoReleaseCancelSpinLock(CancelIrql);
return FALSE;
}
IoSetCancelRoutine(Irp,NULL);
IoReleaseCancelSpinLock(CancelIrql);
irpStack = IoGetCurrentIrpStackLocation(Irp);
ioBuffer = Irp -> AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack -> Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack -> Parameters.DeviceIoControl.OutputBufferLength;
if (outputBufferLength < sizeof (EVENTMSG))
{
outputBufferLength = 0 ;
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
RtlCopyMemory(ioBuffer,EventMsg, sizeof (EVENTMSG));
outputBufferLength = sizeof (EVENTMSG);
}
Irp -> IoStatus.Status = Status;
Irp -> IoStatus.Information = outputBufferLength;
IoStartNextPacket(DeviceObject,TRUE);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return TRUE;
}
附件2、
你需要仔细看的函数是GetEventMsg。
#include
"
stdafx.h
"
#include " winioctl.h "
#include " define.h "
typedef struct _ANSY_IMD_EVENT_MSG
{
OVERLAPPED OverLapped;
UCHAR Buffer[ sizeof (IMDEVENTMSG)];
} ANSY_IMDEVENTMSG, * PANSY_IMDEVENTMSG;
//
// hEventStop must be created by such code:
// hEventStop = CreateEvent(
// 0,
// TRUE,
// FALSE,
// NULL
// );
// when caller want the GetEventMsg exit the block,
// just SetEvent(hEventStop);
BOOL
GetEventMsg(
IN HANDLE hDev,
IN HANDLE hEventStop,
OUT PIMDEVENTMSG EventMsg
)
{
BOOL bRet;
static ANSY_IMDEVENTMSG Packet[ 32 ];
static HANDLE hEvent[ 32 + 1 ];
static bool s_bFirstCall = TRUE;
DWORD cb;
HANDLE hEventNew;
int i,j,k;
if (s_bFirstCall) // if first call ,let's call 32 times readfile first
{
for (i = 0 ;i < 32 ;i ++ )
{
Packet.OverLapped.Offset = 0 ;
Packet.OverLapped.OffsetHigh = 0 ;
Packet.OverLapped.hEvent = CreateEvent(
0 ,
TRUE,
FALSE,
NULL
); // manual reset,initial=false
hEvent = Packet.OverLapped.hEvent;
bRet = DeviceIoControl(
hDev,
GET_EVENT_MSG,
NULL,
0 ,
Packet.Buffer,
sizeof (IMDEVENTMSG),
& cb,
& Packet.OverLapped
);
}
hEvent[ 32 ] = hEventStop;
s_bFirstCall = false ;
}
i = WaitForMultipleObjects( // which read return?
33 ,
hEvent,
false , // wait untill one hevent signal
INFINITE // wait forever
);
if (i == WAIT_FAILED) return false ;
if (i == 32 )
{
ASSERT(hEvent == hEventStop);
return true ; // hEventStop raise
}
for (j = 0 ;j < 32 ;j ++ )
{
if (Packet[j].OverLapped.hEvent == hEvent) break ; // which read return?
}
k = j;
cb = 0 ;
bRet = GetOverlappedResult(
hDev,
& Packet[k].OverLapped,
& cb,
false
);
if ( ! bRet)
{
printf( " GetOverlappedResult failed!!! " );
return false ;
}
ASSERT(cb == sizeof (IMDEVENTMSG));
memcpy(( void * )EventMsg,( void * )Packet[k].Buffer,cb);
CloseHandle(Packet[k].OverLapped.hEvent);
for (j = i;j < 32 ;i ++ ) hEvent = hEvent[ ++ j];
hEventNew = CreateEvent( 0 , TRUE, 0 , NULL);
if ( ! hEventNew)
{
printf( " Can not create event! " );
return false ;
}
Packet[k].OverLapped.hEvent = hEventNew;
memset(Packet[k].Buffer, 0 , sizeof (IMDEVENTMSG));
hEvent[ 31 ] = hEventNew;
// k返回了,就再读K一次
bRet = DeviceIoControl(
hDev,
GET_EVENT_MSG,
NULL,
0 ,
Packet[k].Buffer,
sizeof (IMDEVENTMSG),
& cb,
& Packet[k].OverLapped
);
return bRet;
}
#include " winioctl.h "
#include " define.h "
typedef struct _ANSY_IMD_EVENT_MSG
{
OVERLAPPED OverLapped;
UCHAR Buffer[ sizeof (IMDEVENTMSG)];
} ANSY_IMDEVENTMSG, * PANSY_IMDEVENTMSG;
//
// hEventStop must be created by such code:
// hEventStop = CreateEvent(
// 0,
// TRUE,
// FALSE,
// NULL
// );
// when caller want the GetEventMsg exit the block,
// just SetEvent(hEventStop);
BOOL
GetEventMsg(
IN HANDLE hDev,
IN HANDLE hEventStop,
OUT PIMDEVENTMSG EventMsg
)
{
BOOL bRet;
static ANSY_IMDEVENTMSG Packet[ 32 ];
static HANDLE hEvent[ 32 + 1 ];
static bool s_bFirstCall = TRUE;
DWORD cb;
HANDLE hEventNew;
int i,j,k;
if (s_bFirstCall) // if first call ,let's call 32 times readfile first
{
for (i = 0 ;i < 32 ;i ++ )
{
Packet.OverLapped.Offset = 0 ;
Packet.OverLapped.OffsetHigh = 0 ;
Packet.OverLapped.hEvent = CreateEvent(
0 ,
TRUE,
FALSE,
NULL
); // manual reset,initial=false
hEvent = Packet.OverLapped.hEvent;
bRet = DeviceIoControl(
hDev,
GET_EVENT_MSG,
NULL,
0 ,
Packet.Buffer,
sizeof (IMDEVENTMSG),
& cb,
& Packet.OverLapped
);
}
hEvent[ 32 ] = hEventStop;
s_bFirstCall = false ;
}
i = WaitForMultipleObjects( // which read return?
33 ,
hEvent,
false , // wait untill one hevent signal
INFINITE // wait forever
);
if (i == WAIT_FAILED) return false ;
if (i == 32 )
{
ASSERT(hEvent == hEventStop);
return true ; // hEventStop raise
}
for (j = 0 ;j < 32 ;j ++ )
{
if (Packet[j].OverLapped.hEvent == hEvent) break ; // which read return?
}
k = j;
cb = 0 ;
bRet = GetOverlappedResult(
hDev,
& Packet[k].OverLapped,
& cb,
false
);
if ( ! bRet)
{
printf( " GetOverlappedResult failed!!! " );
return false ;
}
ASSERT(cb == sizeof (IMDEVENTMSG));
memcpy(( void * )EventMsg,( void * )Packet[k].Buffer,cb);
CloseHandle(Packet[k].OverLapped.hEvent);
for (j = i;j < 32 ;i ++ ) hEvent = hEvent[ ++ j];
hEventNew = CreateEvent( 0 , TRUE, 0 , NULL);
if ( ! hEventNew)
{
printf( " Can not create event! " );
return false ;
}
Packet[k].OverLapped.hEvent = hEventNew;
memset(Packet[k].Buffer, 0 , sizeof (IMDEVENTMSG));
hEvent[ 31 ] = hEventNew;
// k返回了,就再读K一次
bRet = DeviceIoControl(
hDev,
GET_EVENT_MSG,
NULL,
0 ,
Packet[k].Buffer,
sizeof (IMDEVENTMSG),
& cb,
& Packet[k].OverLapped
);
return bRet;
}
最后
以上就是可耐芹菜为你收集整理的驱动程序怎样和应用程序通信?的全部内容,希望文章能够帮你解决驱动程序怎样和应用程序通信?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复