阅读:3425回复:5
驱动程序和用户程序怎么通讯??
我想作个ndis fliter,在截获packet之后怎么通知用户程序,交给用户程序处理呀??
|
|
最新喜欢:zb_xi |
沙发#
发布于:2002-01-27 16:05
你可以看一下2000 ddk里的packet,XP ddk里的ndisuio.
如果想在9x系列实现,可以看一下98ddk里的packet. 我也是驱动网的一个新手,但可以说是驱动程序的老手了,做过win 9x/2000, CE, linux, Mac的driver,以前并不知道贵网站,这周碰到了一个问题,贴了一张贴子,也没人回答,查了查以前的纪录,发现很多问题提了以后,也没有下文,不知道试国内的driver的编程水平偏低呢,还是高手不屑于回答一些问题呢,如果是前一种,我们还是要加紧努力,如果是后一种,希望高手们能向国外的同行学习,能够为提携后进多做一些工作。为提高国内驱动程序员的整体水平做一些努力。 一家之言,又冒犯之处,还请海涵。 |
|
板凳#
发布于:2002-02-04 10:52
虽然我的帖子不少,可是是个新手,我也希望高手们给知道一下,哪怕是给个思路就可以。
|
|
|
地板#
发布于:2002-02-04 11:15
To zhaock:
不知道你这样的方案是否可以做到像zonealarm一样,在有一个未知的请求的时候,可以先停止packet的发送,等到app收到用户的选择并且告诉driver以后,再放行? 我是在9x下做的,用blockonid和waitsemaphore,但有时候会死机。 |
|
|
地下室#
发布于: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; } |
|
|
5楼#
发布于:2002-02-04 15:48
To zhaock: 你说的可不可以详细一点? 你在98上写的是和passthru类似的驱动吗?还是采用的hook技术。应该可以自己维护一个队列,对于上层来的packet先放到队列里,等app告诉driver后,在发送。 |
|