驱动程序怎样和应用程序通信?

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;  
    
}  

附件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;  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值