阅读:4353回复:2
关于应用程序和驱动程序的通信问题一问
在从下层驱动程序中传送一个消息到应用程序,
如果在应用程序创建一个事件,然后怎样在下层 的驱动程序中创建和应用程序相同的事件,并且 在驱动程序中激发该事件而在上层的应用程序中 通过WAITFORSINGLEOBJECT()函数响应相应的操 作?希望给为高手指点迷津,提供相应的例子。 谢了! |
|
最新喜欢:duyuan...
|
沙发#
发布于:2001-04-24 14:41
This is stated in the DriverWorks' help doc. And here also has many articles about this. Pls search it.
|
|
|
板凳#
发布于:2001-04-24 14:48
Crteate an event in app:
ULONG length; HANDLE hDriver=NULL,hEvent=NULL; hEvent = Createevent(NULL, TRUE, FALSE, NULL); if(hEvent==NULL){//...} hDriver = CreateFile("\\\\.\\xxxxx",GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hDriver==NULL){//..} //.... Send the event to driver: if(!DeviceIoControl(hDriver,IOCTL_SEND_EVENT,&hEvent, sizeof(HANDLE),NULL,0,&length,NULL)){//....} //... Wait for the event triggered(by the driver): WaitForSingleObject(hEvent, INFINITE); //... dispatch IRP_MJ_DEVICE_CONTROL: PIO_STACK_LOCATION irpStack; PVOID ioBuffer; ULONG ioctl; ioBuffer = Irp->AssociatedIrp.SystemBuffer; irpStack = IoGetCurrentIrpStackLocation(Irp); ioctl = irpStack->Parameters.DeviceIoControl.IoControlCode; switch(ioctl){ case IOCTL_SEND_EVENT: ObReferenceObjectByHandle((HANDLE)(*ioBuffer), 0x0002, NULL, UserMode, (PVOID *)(&(deviceExt->Event)), NULL); KeClearEvent(deviceExt->Event); } //trigger the event; KeSetEvent(deviceExt->Event, 2, FALSE); 在app建立聊事件(event),在下层就不用再建立事件。当然,如果在下层建立了命名事件,在上层只需打开此命名事件,然后等待事件就可以了(WaitForSingleObject)。 但是,m$ 不推荐这么干。 给你一个ddk的例子: //sys /*++ Copyright (c) 1996 Microsoft Corporation Module Name: Event.c Abstract: This sample demonstrates one way that a Windows NT kernel-mode driver can share and explicitly signal an Event Object with a Win32 application. This sample uses the following method: The application creates an event object using CreateEvent(). The app passes the event handle to the driver in a private IOCTL. The driver is running in the app's thread context during the IOCTL so there is a valid user-mode handle at that time. The driver dereferences the user-mode handle into system space & saves the new system handle for later use. The driver signals the event via KeSetEvent() at IRQL <= DISPATCH_LEVEL. The driver MUST delete any driver references to the event object at Unload time. An alternative method would be to create a named event in the driver via IoCreateNotificationEvent and then open the event in user mode. This API however is new to Windows NT 4.0 so you can not use this method in your NT 3.5x drivers. Note that this sample's event can be signalled (almost) at will from within the driver. A different event signal can be set when the driver is setup to do asynchronous I/O, and it is opened with FILE_FLAG_OVERLAPPED, and an event handle is passed down in an OVERLAPPED struct from the app's Read, Write, or DeviceIoControl. This different event signal is set by the I/O Manager when the driver calls IoCompleteRequest on a pending Irp. This type of Irp completion signal is not the purpose of this sample, hence the lack of Irp queing. Author: Jeff Midkiff 23-Jul-96 Enviroment: Kernel Mode Only Revision History: Jeff Midkiff 19-Apr-99 Fixed RequestorMode access control & event type to ObReferenceObjectByHandle. Fixed reference count. --*/ // // INCLUDES // #include "ntddk.h" #include "event.h" // // DEFINES // #define USER_NAME L"\\DosDevices\\EVENT" #define SYSTEM_NAME L"\\Device\\EVENT" // // DATA // typedef struct _DEVICE_EXTENSION { KDPC Dpc; KTIMER Timer; HANDLE hEvent; ULONG References; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; // // PROTOS // NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS Unload( IN PDRIVER_OBJECT DriverObject ); NTSTATUS Dispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID CustomTimerDPC( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ); NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: This routine gets called by the system to initialize the driver. Arguments: DriverObject - the system supplied driver object. RegistryPath - the system supplied registry path for this driver. Return Value: NTSTATUS --*/ { PDEVICE_OBJECT pDeviceObject; PDEVICE_EXTENSION pDeviceExtension; UNICODE_STRING usSystemName; UNICODE_STRING usUserName; NTSTATUS status; KdPrint(("Event!DriverEntry - IN\n")); // // create the device object // RtlInitUnicodeString( &usSystemName, SYSTEM_NAME ); status = IoCreateDevice( DriverObject, // DriverObject sizeof( DEVICE_EXTENSION ), // DeviceExtensionSize &usSystemName, // DeviceName FILE_DEVICE_UNKNOWN, // DeviceType 0, // DeviceCharacteristics FALSE, // Exclusive &pDeviceObject // DeviceObject ); if ( !NT_SUCCESS(status) ) { KdPrint(("\tIoCreateDevice returned 0x%x\n", status)); return( status ); } // // Set up dispatch entry points for the driver. // DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Dispatch; DriverObject->DriverUnload = Unload; // // Create a symbolic link into user mode for the driver. // RtlInitUnicodeString( &usUserName, USER_NAME ); status = IoCreateSymbolicLink( &usUserName, &usSystemName ); if ( !NT_SUCCESS(status) ) { IoDeleteDevice( pDeviceObject ); KdPrint(("\tIoCreateSymbolicLink returned 0x%x\n", status)); return( status ); } // // establish user-buffer access method // pDeviceObject->Flags |= DO_BUFFERED_IO; // // setup the device extension // pDeviceExtension = pDeviceObject->DeviceExtension; KeInitializeDpc( &pDeviceExtension->Dpc, // Dpc CustomTimerDPC, // DeferredRoutine pDeviceObject // DeferredContext ); KeInitializeTimer( &pDeviceExtension->Timer // Timer ); pDeviceExtension->hEvent = NULL; pDeviceExtension->References = 0L; KdPrint(("Event!DriverEntry - OUT\n")); return( status ); } NTSTATUS Unload( IN PDRIVER_OBJECT DriverObject ) /*++ Routine Description: This routine gets called to remove the driver from the system. Arguments: DriverObject - the system supplied driver object. Return Value: NTSTATUS --*/ { PDEVICE_OBJECT pDeviceObject = DriverObject->DeviceObject; PDEVICE_EXTENSION pDeviceExtension = pDeviceObject->DeviceExtension; UNICODE_STRING usUserName; KdPrint(("Event!Unload\n")); // Delete the user-mode symbolic link. RtlInitUnicodeString( &usUserName, USER_NAME ); IoDeleteSymbolicLink( &usUserName ); // Delete the DeviceObject IoDeleteDevice( pDeviceObject ); return( STATUS_SUCCESS ); } NTSTATUS Dispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This device control dispatcher handles IOCTLs. Arguments: DeviceObject - Context for the activity. Irp - The device control argument block. Return Value: NTSTATUS --*/ { PDEVICE_EXTENSION pDeviceExtension; PIO_STACK_LOCATION pIrpStack; PSET_EVENT pSetEvent; ULONG ulInformation = 0L; NTSTATUS status = STATUS_NOT_IMPLEMENTED; KdPrint(("Event!Dispatch - IN\n")); pDeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; pIrpStack = IoGetCurrentIrpStackLocation( Irp ); switch( pIrpStack->MajorFunction ) { case IRP_MJ_CREATE: KdPrint(("\tIRP_MJ_CREATE\n")); status = STATUS_SUCCESS; break; case IRP_MJ_CLOSE: KdPrint(("\tIRP_MJ_CLOSE\n")); KeCancelTimer( &pDeviceExtension->Timer ); // // dereference the event object or it will NEVER go away until reboot // if ( pDeviceExtension->hEvent ) { while (pDeviceExtension->References) { ObDereferenceObject( pDeviceExtension->hEvent ); pDeviceExtension->References--; } } status = STATUS_SUCCESS; break; case IRP_MJ_DEVICE_CONTROL: switch( pIrpStack->Parameters.DeviceIoControl.IoControlCode ) { case IOCTL_SET_EVENT: KdPrint(("\tIOCTL_SET_EVENT\n")); if ( pIrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_SETEVENT ) { // Parameters are invalid KdPrint(("\tSTATUS_INVALID_PARAMETER\n")); status = STATUS_INVALID_PARAMETER; } else { pSetEvent = (PSET_EVENT)Irp->AssociatedIrp.SystemBuffer; KdPrint(("\tuser-mode HANDLE = 0x%x\n", pSetEvent->hEvent )); status = ObReferenceObjectByHandle( pSetEvent->hEvent, SYNCHRONIZE, *ExEventObjectType, Irp->RequestorMode, &pDeviceExtension->hEvent, NULL ); if ( !NT_SUCCESS(status) ) { KdPrint(("\tUnable to reference User-Mode Event object, Error = 0x%x\n", status)); } else { KdPrint(("\tkernel-mode HANDLE = 0x%x\n", pDeviceExtension->hEvent )); // Warning: you should watch for wrap here pDeviceExtension->References++; // // Start the timer to run the CustomTimerDPC in DueTime seconds to // simulate an interrupt (which would queue a DPC). // The user's event object is signaled in the DPC. // // ensure relative time for this sample if ( pSetEvent->DueTime.QuadPart > 0 ) pSetEvent->DueTime.QuadPart = -(pSetEvent->DueTime.QuadPart); KdPrint(("\tDueTime = %d\n", pSetEvent->DueTime.QuadPart )); KeSetTimer( &pDeviceExtension->Timer, // Timer pSetEvent->DueTime, // DueTime &pDeviceExtension->Dpc // Dpc ); status = STATUS_SUCCESS; } } break; default: // should never hit this ASSERT(0); status = STATUS_NOT_IMPLEMENTED; break; } // switch IoControlCode break; default: // should never hit this ASSERT(0); status = STATUS_NOT_IMPLEMENTED; break; } // switch MajorFunction // // complete the Irp // Irp->IoStatus.Status = status; Irp->IoStatus.Information = ulInformation; IoCompleteRequest( Irp, IO_NO_INCREMENT ); KdPrint(("Event!Dispatch - OUT\n")); return status; } VOID CustomTimerDPC( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) /*++ Routine Description: This is the DPC associated with this drivers Timer object setup in DriverEntry. Arguments: Dpc - our DPC object associated with our Timer DeferredContext - Context for the DPC that we setup in DriverEntry SystemArgument1 - SystemArgument2 - Return Value: Nothing. --*/ { PDEVICE_OBJECT pDeviceObject = DeferredContext; PDEVICE_EXTENSION pDeviceExtension = pDeviceObject->DeviceExtension; KdPrint(("Event!CustomTimerDPC - IN\n")); // // Signal the Event created in user-mode // // Note: // Do not call KeSetEvent from your ISR; // you must call it at IRQL <= DISPATCH_LEVEL. // Your ISR should queue a DPC and the DPC can // then call KeSetEvent on the ISR's behalf. // KeSetEvent((PKEVENT)pDeviceExtension->hEvent,// Event 0, // Increment FALSE // Wait ); // there is no Irp to complete here KdPrint(("Event!CustomTimerDPC - OUT\n")); return; } // EOF //header(event.h) /*++ Copyright (c) 1996 Microsoft Corporation Module Name: Event.h Abstract: Author: Jeff Midkiff 23-Jul-96 Enviroment: Revision History: --*/ #ifndef __EVENT__ #define __EVENT__ #include "devioctl.h" typedef struct _SET_EVENT { HANDLE hEvent; LARGE_INTEGER DueTime; // requested DueTime in 100-nanosecond units } SET_EVENT, *PSET_EVENT; #define SIZEOF_SETEVENT sizeof(SET_EVENT) #define IOCTL_SET_EVENT \ CTL_CODE( FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS ) #endif // __EVENT__ //app /*++ Copyright (c) 1996 Microsoft Corporation Module Name: EventTest.c Abstract: Simple console test app demonstrating how a Win32 app can share an event object with a kernel-mode driver. For more information on using Event Objects at the application level see the Win32 SDK. Author: Jeff Midkiff 23-Jul-96 Enviroment: User Mode Revision History: --*/ // // INCLUDES // #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <winioctl.h> #include <winbase.h> #include <conio.h> #include "event.h" // // MAIN // void __cdecl main( int argc, char ** argv ) { BOOL bStatus; HANDLE hDevice; ULONG ulReturnedLength; SET_EVENT setEvent; FLOAT fDelay; LPVOID lpMessageBuffer; if ( (argc < 2) || (argv[1] == NULL) ) { printf("event <delay>\n"); printf("\twhere <delay> = time to delay the event signal in seconds.\n"); exit(0); } sscanf( argv[1], "%f", &fDelay ); // // open the device // hDevice = CreateFile( "\\\\.\\EVENT", // lpFileName GENERIC_READ | GENERIC_WRITE, // dwDesiredAccess FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode NULL, // lpSecurityAttributes OPEN_EXISTING, // dwCreationDistribution 0, // dwFlagsAndAttributes NULL // hTemplateFile ); if (hDevice == INVALID_HANDLE_VALUE) { printf("CreateFile error = %d\n", GetLastError() ); exit(0); } // // set the event signal delay // setEvent.DueTime.QuadPart = -((LONGLONG)(fDelay * 10.0E6));// use relative time for this sample // // test the driver for bad event handles // setEvent.hEvent = NULL; bStatus = DeviceIoControl( hDevice, // Handle to device IOCTL_SET_EVENT, // IO Control code &setEvent, // Input Buffer to driver. SIZEOF_SETEVENT, // Length of input buffer in bytes. NULL, // Output Buffer from driver. 0, // Length of output buffer in bytes. &ulReturnedLength, // Bytes placed in buffer. NULL // synchronous call ); if ( !bStatus ) { printf("Bad handle TEST returned code %d.\n\n", GetLastError() ); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPSTR)&lpMessageBuffer,0,NULL); printf("The Err is %s\n",lpMessageBuffer); LocalFree(lpMessageBuffer); } else { printf("we should never get here\n"); exit(0); } // // // setEvent.hEvent = CreateEvent( NULL, // lpEventAttributes TRUE, // bManualReset FALSE, // bInitialState #ifdef DBG "TEST_EVENT" // use WinObj to view named events for DBG #else NULL // lpName #endif ); if ( !setEvent.hEvent ) { printf("CreateEvent error = %d\n", GetLastError() ); } else { printf("Event HANDLE = 0x%x\n", setEvent.hEvent ); printf("Press any key to exit.\n"); while( !_kbhit() ) { bStatus = DeviceIoControl( hDevice, // Handle to device IOCTL_SET_EVENT, // IO Control code &setEvent, // Input Buffer to driver. SIZEOF_SETEVENT, // Length of input buffer in bytes. NULL, // Output Buffer from driver. 0, // Length of output buffer in bytes. &ulReturnedLength, // Bytes placed in buffer. NULL // synchronous call ); if ( !bStatus ) { printf("Ioctl failed with code %d\n", GetLastError() ); break; } else { printf("Waiting for Event...\n"); WaitForSingleObject(setEvent.hEvent, INFINITE ); printf("Event signalled.\n\n"); ResetEvent( setEvent.hEvent); //printf("Event reset.\n"); } } } // // close the driver // if ( !CloseHandle(hDevice) ) { printf("Failed to close device.\n"); } exit(0); } // EOF |
|