阅读:1550回复:10
送分!DDD编写的WDM驱动如何使用事件对象实现与应用程序的通信?
无
|
|
沙发#
发布于:2003-09-28 22:31
更正!不是DDD是DDK!
\"DDK编写的WDM驱动如何使用事件对象实现与应用程序的通信\" |
|
板凳#
发布于:2003-09-29 10:56
找一下,论坛里原来有一篇文章的。
|
|
|
地板#
发布于:2003-09-29 11:00
我原来保存过,这里帖出来。
不过不敢掠他人之美,记得是authru2000帖出来的。 1、先由应用程序创建一个事件,然后通过DEVICEIOCONTOL将该事件的句柄传给驱动,最后再创建一个辅助线程来查询该事件。 如DS中的例子所写: // testintr.cpp - application for interrupt demo driver //============================================================================= // // Compuware Corporation // NuMega Lab // 9 Townsend West // Nashua, NH 03060 USA // // Copyright (c) 1998 Compuware Corporation. All Rights Reserved. // Unpublished - rights reserved under the Copyright laws of the // United States. // //============================================================================= #include <stdio.h> #include <stdlib.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #include <winioctl.h> #include \"common.h\" // This is a simple console app that exercises the interrupt demo // driver. // // The test app waits for the driver to notify it that there is // interrupt data to read. The driver notifies the app by setting // an event whose handle the app passes to the driver at startup. // The app simply emits the interrupt data (a count and a timestamp) // to the console. TIMESTAMP tsbuf[FIFOSIZE]; HANDLE h, hEvent; ///////////////////////////////////////////////////////////////// // ServiceThread // // This thread is awakened by the driver to tell the app to come // and get the interrupt records // DWORD WINAPI ServiceThread(PVOID hEvent) { ULONG nItems, nBytesRead; PTIMESTAMP pts; while (TRUE) { WaitForSingleObject(hEvent, INFINITE); printf(\"New event:\\n\"); if (!DeviceIoControl( h, IOCTL_GET_TIMESTAMP_DATA, NULL, 0, tsbuf, sizeof(tsbuf), &nBytesRead, NULL) ) { printf(\"DeviceIoControl failed %x\\n\", GetLastError()); exit(1); } nItems = nBytesRead/sizeof(TIMESTAMP); for (pts = tsbuf; nItems; nItems--, pts++) printf(\"Interrupt time %08x (High=%08x) count %x\\n\", pts->ts_time, pts->ts_interrupt_count); } return 0; } ///////////////////////////////////////////////////////////////// // // Main // void __cdecl main(int ac, char* av[]) { DWORD Tid; ULONG error; ULONG nRet; // Open the device h = CreateFile(\"\\\\\\\\.\\\\IntrDemo0\", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (h == INVALID_HANDLE_VALUE) { error=GetLastError(); fprintf(stderr, \"Cannot open device, error %d (0x%x)\\n\", error, error); exit(1); } // Create an event for notification hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (! DeviceIoControl( h, IOCTL_SET_NOTIFICATION_EVENT, &hEvent, sizeof(hEvent), NULL, 0, &nRet, NULL ) ) { printf(\"Ioctl failed: %x\\n\", GetLastError()); exit(1); } // Create the thread that waits for the event CreateThread(0, 0x1000, ServiceThread, (PVOID)hEvent, 0, &Tid); printf(\"press return to exit . . .\\n\"); // Look for a key to terminate while (TRUE) if (_getche() == 0xd) break; CloseHandle(hEvent); CloseHandle(h); } 2、在驱动中这样处理: ////////////////////////////////////////////////////////////////// // DeviceControl // // The test app uses a DeviceIoControl call for two purposes: // // 1. It passes an event handle to the driver. The driver sets // the event when there is something for the app to do, i.e., // when an interrupt occurs, and the app fetches the data. // // 2. It fetches the timestamp data for the interrupts. // NTSTATUS InterruptDemoDevice:eviceControl(KIrp I) { T << I; I.Information() = 0; switch (I.IoctlCode()) {//注意这里 case IOCTL_SET_NOTIFICATION_EVENT: { HANDLE hEvent = *(HANDLE*)I.IoctlBuffer(); if (m_pEvent) delete m_pEvent; m_pEvent = new (NonPagedPool) KEvent(hEvent, OBJECT_TYPE_ALL_ACCESS); return I.Complete(STATUS_SUCCESS); } case IOCTL_GET_TIMESTAMP_DATA: if (SynchronizeInterrupt(&m_Interrupt, LinkTo(ReadTimeFifo), PIRP(I)) ) return I.Complete(STATUS_SUCCESS); else return I.Complete(STATUS_UNSUCCESSFUL); break; default: T << \"Bad Request: \" << I.IoctlCode() << \"\\n\"; return I.Complete(STATUS_INVALID_PARAMETER); } } ////////////////////////////////////////////////////////////////// // Isr // // This is the interrupt service routine. Since we always return // FALSE (to indicate that we did not service the interrupt), there // is no interaction with the hardware required. The system will // call the actual floppy interrupt handler. This routine justs // counts the interrupt (m_InterruptCount), grabs a timestamp, // and requests queues the DPC object. // BOOLEAN InterruptDemoDevice::Isr(void) { T << \"In the ISR\\n\"; TIMESTAMP ts; ts.ts_interrupt_count = ++m_InterruptCount; KeQueryTickCount(&ts.ts_time); m_TimeStampFifo.Write(&ts, 1); m_Dpc.Request(); return FALSE; } ////////////////////////////////////////////////////////////////// // Dpc // // This the callback associated with the device\'s DPC object. The // ISR queues the dpc object, resulting in a call to this routine. // It invokes the synch crit section member function TestAndClearNotifyApp, // which determines if it is necessary to notify the app of the // interrupt. The idea is that we only notify the app when there // is no outstanding interrupt to which the app has not responded. // VOID InterruptDemoDevice:pc(PVOID Arg1, PVOID Arg2) { BOOLEAN Notify; BOOLEAN SynchStatus; if (m_pEvent) { SynchStatus = SynchronizeInterrupt( &m_Interrupt, LinkTo(TestAndClearNotifyApp), &Notify ); if (SynchStatus) { T << \"DPC, App notify=\" << ULONG(Notify) << \"\\n\"; if (Notify) //注意这里 m_pEvent->Set(); } else T << \"Dpc error synchronizing\\n\"; } } set前最好先判断一下该事件是否有效,如下所示: if(IntEvent!= NULL) IntEvent->Set(IO_NO_INCREMENT,FALSE); |
|
|
地下室#
发布于:2003-09-29 16:35
App事件对象是可以传入Drvier的,也就是说App和Driver可以共享你的事件
|
|
|
5楼#
发布于:2003-09-29 17:30
我看都没看就给你分了!看清题目!是用DDK来做,不是用DS,DS的我早就搞定了!
|
|
6楼#
发布于:2003-09-29 19:41
我原来保存过,这里帖出来。 我想你记错了,肯定不是我。我没有用DS写驱动的。 ;) BTW,如果authru2000说的是我的话。。。 :D |
|
7楼#
发布于:2003-10-04 05:48
Use DDK, DS. I don\'t understand why this gives pointers
|
|
8楼#
发布于:2003-10-04 17:30
我已经搞定了,麻烦大家了!
|
|
9楼#
发布于:2003-10-28 10:15
请问APP事件是怎样传入DRIVER的?
|
|
|
10楼#
发布于:2003-10-28 11:05
搞定了也告诉大家,是如何解决的??
|
|
|