cdutzz
驱动牛犊
驱动牛犊
  • 注册日期2002-01-18
  • 最后登录2002-01-28
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:3374回复:5

驱动程序和用户程序怎么通讯??

楼主#
更多 发布于:2002-01-27 10:22
我想作个ndis fliter,在截获packet之后怎么通知用户程序,交给用户程序处理呀??

最新喜欢:

zb_xizb_xi
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2002-01-27 16:05
你可以看一下2000 ddk里的packet,XP ddk里的ndisuio.
如果想在9x系列实现,可以看一下98ddk里的packet.

我也是驱动网的一个新手,但可以说是驱动程序的老手了,做过win 9x/2000, CE, linux, Mac的driver,以前并不知道贵网站,这周碰到了一个问题,贴了一张贴子,也没人回答,查了查以前的纪录,发现很多问题提了以后,也没有下文,不知道试国内的driver的编程水平偏低呢,还是高手不屑于回答一些问题呢,如果是前一种,我们还是要加紧努力,如果是后一种,希望高手们能向国外的同行学习,能够为提携后进多做一些工作。为提高国内驱动程序员的整体水平做一些努力。
一家之言,又冒犯之处,还请海涵。
KungFu
驱动大牛
驱动大牛
  • 注册日期2001-09-27
  • 最后登录2008-04-08
  • 粉丝0
  • 关注0
  • 积分221分
  • 威望24点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-02-04 10:52
虽然我的帖子不少,可是是个新手,我也希望高手们给知道一下,哪怕是给个思路就可以。
我不写驱动好多年
rayyang2000
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2012-09-13
  • 粉丝3
  • 关注0
  • 积分1036分
  • 威望925点
  • 贡献值3点
  • 好评度823点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-02-04 11:15
To zhaock:
不知道你这样的方案是否可以做到像zonealarm一样,在有一个未知的请求的时候,可以先停止packet的发送,等到app收到用户的选择并且告诉driver以后,再放行?
我是在9x下做的,用blockonid和waitsemaphore,但有时候会死机。
天天coding-debugging中----超稀饭memory dump file ======================================================== [b]Windows Device Driver Development and Consulting Service[/b] [color=blue][url]http://www.ybwork.com[/url][/color] ========================================================
HuYuguang
论坛版主
论坛版主
  • 注册日期2001-04-25
  • 最后登录2013-04-29
  • 粉丝3
  • 关注1
  • 积分92分
  • 威望11点
  • 贡献值0点
  • 好评度9点
  • 原创分1分
  • 专家分0分
地下室#
发布于:2002-02-04 11:23
虽然我的帖子不少,可是是个新手,我也希望高手们给知道一下,哪怕是给个思路就可以。



这个问题其实可以直接去参看packet.sys。里面对于irp
处理非常详细。


关于一般的驱动程序如何通知应用程序。前几天我刚刚
回了一个海南朋友的信,在这里再贴一遍。

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\\n\"));

    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 \\n\"));

    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\\n\"));

    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\\n\"));

    //
    // 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\\n\"));

}
*/

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!!!\\n\");
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!\\n\");
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;
}

不再回忆从前,我已经生活在幸福当中。
zhaock
驱动太牛
驱动太牛
  • 注册日期2002-01-26
  • 最后登录2018-06-02
  • 粉丝3
  • 关注2
  • 积分73328分
  • 威望362317点
  • 贡献值1点
  • 好评度226点
  • 原创分0分
  • 专家分0分
  • 社区居民
5楼#
发布于:2002-02-04 15:48
To zhaock:
不知道你这样的方案是否可以做到像zonealarm一样,在有一个未知的请求的时候,可以先停止packet的发送,等到app收到用户的选择并且告诉driver以后,再放行?
我是在9x下做的,用blockonid和waitsemaphore,但有时候会死机。

你说的可不可以详细一点? 你在98上写的是和passthru类似的驱动吗?还是采用的hook技术。应该可以自己维护一个队列,对于上层来的packet先放到队列里,等app告诉driver后,在发送。
游客

返回顶部