johnliu
驱动小牛
驱动小牛
  • 注册日期2004-08-06
  • 最后登录2005-03-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1162回复:2

如何在驱动和app之间同步

楼主#
更多 发布于:2004-12-12 18:57
如何使用事件在驱动和APP之间同步?
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-12-12 18:58
Figure 1    Using Asynchronous Capabilities
Async.c

/*
   Async.c - 1999 James M. Finnegan - Microsoft Systems Journal
 
   This module sends various requests the associated kernel-mode driver to
   instruct the driver to trigger KM to user-mode notification mechanisms.
 */
 #include <windows.h>
 #include <winioctl.h>
 
 #define FILE_DEVICE_UNKNOWN             0x00000022
 #define IOCTL_UNKNOWN_BASE              FILE_DEVICE_UNKNOWN
 
 #define IOCTL_NOTIFY_KERNEL_EVENT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800,  
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 #define IOCTL_NOTIFY_USER_EVENT   CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0801,
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 #define IOCTL_NOTIFY_EMPTY_IRP    CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0802,
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 #define IOCTL_NOTIFY_REGISTER_APC CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803,
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 
 #define IOCTL_NOTIFY_REGISTER_APC_WITH_KM_ALERTING \
     CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0804, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 
 
 extern HANDLE hDriver;
 
 
 BOOL WINAPI KernelModeEvent(DWORD t)
 {
     HANDLE KnotifyEvent;
     DWORD dwBytesReturned;
     BOOL  bReturnCode = FALSE;
     OVERLAPPED ov={0};
 
 
     // Create an event handle for async notification
     // from our driver
     ov.hEvent = CreateEvent(NULL,  // Default security
                             TRUE,  // Manual reset
                             FALSE, // non-signaled state
                             NULL); // No name
 
     // Tell the driver to signal its event...
     bReturnCode = DeviceIoControl(hDriver,
                                   IOCTL_NOTIFY_KERNEL_EVENT,
                                   0, 0,
                                   0, 0,
                                   &dwBytesReturned,
                                   &ov);
        
     // Wait here for the event handle to be set, indicating
     // that the IOCTL processing is complete.
     bReturnCode = GetOverlappedResult(hDriver, &ov,
                                       &dwBytesReturned, TRUE);
 
     CloseHandle(ov.hEvent);
 
     // Get a handle to the named kernel event and wait on it!
     KnotifyEvent = OpenEvent(SYNCHRONIZE, FALSE, "KnotifyEvent");
     WaitForSingleObject(KnotifyEvent, INFINITE);
        
     MessageBox(NULL,"Kernel-mode event has been signaled!","Unotify",MB_OK);
 
     return 0;
 }
 
 
 BOOL WINAPI UserModeEvent(DWORD t)
 {
     HANDLE UserModeEvent;
     DWORD dwBytesReturned;
     BOOL  bReturnCode = FALSE;
     OVERLAPPED ov={0};
 
 
     // Create an event handle that the KM driver can signal
     UserModeEvent = CreateEvent(NULL,  // Default security
                                 TRUE,  // Manual reset
                                 FALSE, // non-signaled state
                                 NULL); // No name
 
     // Create an event handle for async notification
     // from our driver
     ov.hEvent = CreateEvent(NULL,  // Default security
                             TRUE,  // Manual reset
                             FALSE, // non-signaled state
                             NULL); // No name
 
     // Tell the driver to signal its event...
     bReturnCode = DeviceIoControl(hDriver,
                                   IOCTL_NOTIFY_USER_EVENT,
                                   &UserModeEvent, sizeof(HANDLE),
                                   0, 0,
                                   &dwBytesReturned,
                                   &ov);
        
     // Wait here for the event handle to be set, indicating
     // that the IOCTL processing is complete.
     bReturnCode = GetOverlappedResult(hDriver, &ov,
                                       &dwBytesReturned, TRUE);
 
     CloseHandle(ov.hEvent);
 
    
     WaitForSingleObject(UserModeEvent, INFINITE);
 
     MessageBox(NULL,"User-mode event has been signaled!","Unotify",MB_OK);
 
     CloseHandle(UserModeEvent);
    
     return 0;
 }
 
 
 BOOL WINAPI EmptyIRP(DWORD t)
 {
     DWORD dwBytesReturned;
     BOOL  bReturnCode = FALSE;
     OVERLAPPED ov={0};
 
 
     // Create an event handle for async notification
     // from our driver
     ov.hEvent = CreateEvent(NULL,  // Default security
                             TRUE,  // Manual reset
                             FALSE, // non-signaled state
                             NULL); // No name
 
     // Issue an empty IRP to the driver.  The driver will mark it pending till
     // it's ready to complete it
     bReturnCode = DeviceIoControl(hDriver,
                                   IOCTL_NOTIFY_EMPTY_IRP,
                                   0, 0,
                                   0, 0,
                                   &dwBytesReturned,
                                   &ov);
        
     // Wait here for the event handle to be set, indicating
     // that the IOCTL processing is complete.
     bReturnCode = GetOverlappedResult(hDriver, &ov,
                                       &dwBytesReturned, TRUE);
 
     CloseHandle(ov.hEvent);
 
     MessageBox(NULL,"Empty IRP has been completed!","Unotify",MB_OK);
 
     return 0;
 }
 
 
 void ApcCallback(PVOID NormalContext, PVOID SystemArgument1,
                  PVOID SystemArgument2)
 {
     char Message[80];
 
 
     wsprintf(Message,"APC Callback!\n P1 == %lx\n P2 == %lx\n P3 == %lx",
              NormalContext, SystemArgument1, SystemArgument2);
     MessageBox(NULL, Message, "Unotify", MB_OK);
 }
 
 void ApcDispatch()
 {
     DWORD dwBytesReturned;
     BOOL  bReturnCode = FALSE;
     OVERLAPPED ov={0};
 
     DWORD pfnApc = (DWORD)&ApcCallback;
 
     // Create an event handle for async notification
     // from our driver
     ov.hEvent = CreateEvent(NULL,  // Default security
                             TRUE,  // Manual reset
                             FALSE, // non-signaled state
                             NULL); // No name
    
     // Tell the driver to signal its event...
     bReturnCode = DeviceIoControl(hDriver,
                                   IOCTL_NOTIFY_REGISTER_APC,
                                   &pfnApc, sizeof(DWORD),
                                   0, 0,
                                   &dwBytesReturned,
                                   &ov);
        
     // Wait here for the event handle to be set, indicating
     // that the IOCTL processing is complete.
     bReturnCode = GetOverlappedResult(hDriver, &ov,
                                       &dwBytesReturned, TRUE);
 
     CloseHandle(ov.hEvent);
    
     MessageBox(NULL,"APC Dispatched!","Unotify",MB_OK);
 
     // Force the thread into being alertable...
     SleepEx(INFINITE, TRUE);
 }
 
 void ApcDispatchWithKMAlertHack()
 {
     DWORD dwBytesReturned;
     BOOL  bReturnCode = FALSE;
     OVERLAPPED ov={0};
 
     DWORD pfnApc = (DWORD)&ApcCallback;
 
 
     // Create an event handle for async notification
     // from our driver
     ov.hEvent = CreateEvent(NULL,  // Default security
                             TRUE,  // Manual reset
                             FALSE, // non-signaled state
                             NULL); // No name
    
     // Tell the driver to signal its event...
     bReturnCode = DeviceIoControl(hDriver,
                                   IOCTL_NOTIFY_REGISTER_APC_WITH_KM_ALERTING,
                                   &pfnApc, sizeof(DWORD),
                                   0, 0,
                                   &dwBytesReturned,
                                   &ov);
        
     // Wait here for the event handle to be set, indicating
     // that the IOCTL processing is complete.
     bReturnCode = GetOverlappedResult(hDriver, &ov,
                                       &dwBytesReturned, TRUE);
 
     CloseHandle(ov.hEvent);
    
     MessageBox(NULL,"APC Dispatched!  Look, no user-mode alert!","Unotify",MB_OK);
 }
DynamIc.c
/*
     Dynamic.c - 1998, 1999 James M. Finnegan - Microsoft Systems Journal
  
     This module implements the functionality to dynamically load and
     unload Windows NT drivers via the Service Control Manager.
 */
 #include <windows.h>
 
 BOOL InstallAndStartDriver(SC_HANDLE hSCManager, LPCTSTR DriverName,
                            LPCTSTR ServiceExe)
 {
     SC_HANDLE  hService;
     BOOL       bReturn;
 
     // Create the driver entry in the SC Manager.
     hService = CreateService(hSCManager,            // SCManager database
                              DriverName,            // name of service
                              DriverName,            // name to display
                              SERVICE_ALL_ACCESS,    // desired access
                              SERVICE_KERNEL_DRIVER, // service type
                              SERVICE_DEMAND_START,  // start type
                              SERVICE_ERROR_NORMAL,  // error control type
                              ServiceExe,            // service's binary
                              NULL,                  // no load ordering group
                              NULL,                  // no tag identifier
                              NULL,                  // no dependencies
                              NULL,                  // LocalSystem account
                              NULL                   // no password
                              );
 
     // This may fail because the service entry already exists.  However,
     // we've tried to load it earlier, so something clearly is wrong if
     // we can't create it!
     if(!hService)
         return FALSE;
 
     // Start the driver!
     bReturn = StartService(hService, 0, NULL);
 
     // Dispose of the handle...
     CloseServiceHandle(hService);
 
     // Return whatever the driver start returned...
     return bReturn;
 }
 
 BOOL LoadDynamicNTDriver()
 {
     SC_HANDLE   hSCManager;
     char        currentDirectory[128];
     BOOL        bReturn;
 
 
     // Open Service Control Manager on the local machine...
     hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 
     // Assume driver is in the same directory as the DLL.  Hence, create
     // a fully qualified pathname for the SCM to add to the registry.
     GetCurrentDirectory(128, currentDirectory);
     lstrcat(currentDirectory,"\\Knotify.sys");
    
     // Install drive in the registry and start it...
     bReturn = InstallAndStartDriver(hSCManager, "Knotify", currentDirectory);
 
     // Close the Service Control Manager...
     CloseServiceHandle(hSCManager);
 
     return bReturn;
 }
 
 ////////////////////////////////////////////////////////////////////////////
 //  Unload routines
 ////////////////////////////////////////////////////////////////////////////
 
 BOOL UnloadDynamicNTDriver()
 {
     SC_HANDLE       hSCManager;
     SC_HANDLE       hService;
     SERVICE_STATUS  serviceStatus;
     BOOL            bReturn;
 
 
    // Open Service Control Manager on the local machine...
     hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 
     // Open the Service Control Manager for our driver service...
     hService = OpenService(hSCManager, "Knotify", SERVICE_ALL_ACCESS);
 
     // Stop the driver.  Will return TRUE on success...
     bReturn = ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus);
 
     // Delete the driver from the registry...
     if(bReturn == TRUE)
         bReturn = DeleteService(hService);
 
     // Close the SC Manager
     CloseServiceHandle(hService);
 
     // Close Service Control Manager
     CloseServiceHandle(hSCManager);
 
     return bReturn;
 }
 
 
 HANDLE LoadDriver(OSVERSIONINFO *os, BOOL *fNTDynaLoaded)
 {
     HANDLE hDevice;
 
     // Default to FALSE on informing the caller if we've dynamically
     // loaded the Windows NT driver via the SCM.
     *fNTDynaLoaded = FALSE;
 
     // If we're under Windows NT...
     if(os->dwPlatformId == VER_PLATFORM_WIN32_NT)
     {
         // Try opening the device driver (in case it's static).  
         // We'll deal with a failure in a moment...
         hDevice = CreateFile("\\\\.\\Knotify",
                              GENERIC_READ | GENERIC_WRITE,
                              FILE_SHARE_READ | FILE_SHARE_WRITE,
                              0,                     // Default security
                              OPEN_EXISTING,
                              FILE_FLAG_OVERLAPPED,  // Perform asynchronous I/O
                              0);                    // No template
        
         // If the device driver wasn't started, let's dynamically load it
         // here...
         if(hDevice == INVALID_HANDLE_VALUE)
         {
             // Load and start the driver...
             LoadDynamicNTDriver();
 
             // Open the driver...
             hDevice = CreateFile("\\\\.\\Knotify",
                              GENERIC_READ | GENERIC_WRITE,
                              FILE_SHARE_READ | FILE_SHARE_WRITE,
                              0,                     // Default security
                              OPEN_EXISTING,
                              FILE_FLAG_OVERLAPPED,  // Perform asynchronous I/O
                              0);                    // No template
            
             // Set the global to indicate that we've Dynaloaded.  This will
             // Cause DllMain to stop and unload on a process detach.
             *fNTDynaLoaded = TRUE;
         }
 
         return hDevice;
     }
 }
Unotify.c
/*
   Unotify.c - 1999 James M. Finnegan - Microsoft Systems Journal
 
   This is the main module for demonstrating asynchronous notification
   from kernel mode.
 */
 #include <windows.h>
 #include <stdio.h>
 #include "resource.h"
 
 LRESULT WINAPI WndProc(HWND,UINT,WPARAM,LPARAM);
 
 HANDLE hDriver = INVALID_HANDLE_VALUE;
 
 // External functions in Dynamic.c
 extern HANDLE LoadDriver(OSVERSIONINFO *, BOOL *);
 extern BOOL UnloadDynamicNTDriver();
 
 
 // External functions in Async.c
 extern BOOL WINAPI KernelModeEvent(DWORD);
 extern BOOL WINAPI UserModeEvent(DWORD);
 extern BOOL WINAPI EmptyIRP(DWORD);
 extern void         ApcDispatch();
 extern void         ApcDispatchWithKMAlertHack();
 
 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpszCmdLine, int nCmdShow)
 {
     static char szAppName[]="UNotify";
     HWND        hWnd;
     MSG         msg;
     WNDCLASS    wndclass;
 
     if(!hPrevInstance)
     {
         wndclass.style         = CS_HREDRAW | CS_VREDRAW;
         wndclass.lpfnWndProc   = WndProc;
         wndclass.cbClsExtra    = 0;
         wndclass.cbWndExtra    = 0;
         wndclass.hInstance     = hInstance;
         wndclass.hIcon         = NULL;
         wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
         wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
         wndclass.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU1);
         wndclass.lpszClassName = szAppName;
 
         if(!RegisterClass(&wndclass))
             return -1;
     }
 
     // Create the main window
     hWnd = CreateWindow(szAppName,"MSJ Kernel Mode Async Notification App",
                 WS_OVERLAPPED | WS_THICKFRAME | WS_MINIMIZEBOX |
                 WS_MAXIMIZEBOX |WS_SYSMENU | WS_CLIPCHILDREN,
                 CW_USEDEFAULT,CW_USEDEFAULT,
                 CW_USEDEFAULT,CW_USEDEFAULT,
                 0,0,hInstance,NULL);
    
     ShowWindow(hWnd,nCmdShow);
     UpdateWindow(hWnd);
 
     while(GetMessage(&msg,NULL,0,0))
     {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
     }
    
     return msg.wParam;
 }
 
 
 
 VOID CenterWindow(HWND hWnd)
 {
     RECT rect;
     WORD wWidth,
          wHeight;
          
          
     GetWindowRect(hWnd,&rect);
 
     wWidth =GetSystemMetrics(SM_CXSCREEN);
     wHeight=GetSystemMetrics(SM_CYSCREEN);
 
     MoveWindow(hWnd,(wWidth/2)   - ((rect.right -  rect.left)/2),
                     (wHeight/2)  - ((rect.bottom - rect.top) /2),
                      rect.right  -   rect.left,
                      rect.bottom -   rect.top,
                      FALSE);
 }
 
 LRESULT WINAPI WndProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam)
 {
     static OSVERSIONINFO os={0};
     static BOOL fNTDynaLoaded;
 
     HANDLE hThread;
     DWORD dwThread;
 
 
     switch(uMessage)
     {
         case WM_CREATE:
  CenterWindow(hWnd);
 
             // Get the current OS information.
             os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
             GetVersionEx(&os);
 
             hDriver = LoadDriver(&os, &fNTDynaLoaded);
             break;
 
         case WM_COMMAND:
             switch(wParam)
             {
                 case IDM_KERNEL_EVENT:
                     if(!(hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
                        (LPTHREAD_START_ROUTINE) KernelModeEvent, NULL, 0,
                         &dwThread)))
                         MessageBox(NULL,"Cannot create thread!","Error",MB_OK);
                     break;
 
                 case IDM_USER_EVENT:
                     if(!(hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
                        (LPTHREAD_START_ROUTINE) UserModeEvent, NULL, 0,
                         &dwThread)))
                         MessageBox(NULL,"Cannot create thread!","Error",MB_OK);
                     break;
 
                 case IDM_EMPTY_IRP:
                     if(!(hThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
                        (LPTHREAD_START_ROUTINE) EmptyIRP, NULL, 0, &dwThread)))
                         MessageBox(NULL,"Cannot create thread!","Error",MB_OK);
                     break;
 
                 case IDM_APC:
                     ApcDispatch();
                     break;
 
                 case IDM_APC_KM_THREAD_ALERTING:
                     ApcDispatchWithKMAlertHack();
                     break;
                
                 case IDM_EXIT:
                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
                     break;
             }
             break;
 
         case WM_DESTROY:
             CloseHandle(hDriver);
 
             // If the Windows NT driver was previously dynamically loaded, unload
             // it here!
             if(fNTDynaLoaded)
                 UnloadDynamicNTDriver();
 
             PostQuitMessage(0);
             break;
        
         default:
             return DefWindowProc(hWnd,uMessage,wParam,lParam);
             break;
          
     }
 
     return 0L;
 }
Knotify.c
/*
   Knotify.c - 1999 James M. Finnegan - Microsoft Systems Journal
 
   This module implements the kernel code to demonstrate notification
   techniques to user-mode Win32-based applications
 */
 
 #include "ntddk.h"
 #include <stdio.h>
 
 
 #define FILE_DEVICE_UNKNOWN             0x00000022
 #define IOCTL_UNKNOWN_BASE              FILE_DEVICE_UNKNOWN
 
 #define IOCTL_NOTIFY_KERNEL_EVENT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800,
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 #define IOCTL_NOTIFY_USER_EVENT   CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0801,
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 #define IOCTL_NOTIFY_EMPTY_IRP    CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0802,
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 #define IOCTL_NOTIFY_REGISTER_APC CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803,
     METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 #define IOCTL_NOTIFY_REGISTER_APC_WITH_KM_ALERTING \ CTL_CODE(      IOCTL_UNKNOWN_BASE, 0x0804, METHOD_BUFFERED, FILE_READ_ACCESS |
     FILE_WRITE_ACCESS)
 
 // Definitions for Windows NT-supplied APC routines.  These are exported in the
 // import libraries, but are not in NTDDK.H
 void KeInitializeApc(PKAPC Apc,
                      PKTHREAD Thread,
                      CCHAR ApcStateIndex,
                      PKKERNEL_ROUTINE KernelRoutine,
                      PKRUNDOWN_ROUTINE RundownRoutine,
                      PKNORMAL_ROUTINE NormalRoutine,
                      KPROCESSOR_MODE ApcMode,
                      PVOID NormalContext);
 
 void KeInsertQueueApc(PKAPC Apc,
                       PVOID SystemArgument1,
                       PVOID SystemArgument2,
                       UCHAR unknown);
 
 void     KnotifyUnloadDriver(PDRIVER_OBJECT DriverObject);
 NTSTATUS KnotifyDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
 NTSTATUS KnotifyDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
 
 typedef struct _DEVICE_EXTENSION
 {
     PDEVICE_OBJECT DeviceObject;
     HANDLE  NotifyHandle;
     PKEVENT NotifyEvent;
 
 } DEVICE_EXTENSION, *PDEVICE_EXTENSION ;
 
 
 NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
                      IN PUNICODE_STRING RegistryPath)
 /*++
 
 Routine Description:
 
     This routine is called when the driver is loaded by Windows NT.
 
 Arguments:
 
     DriverObject - Pointer to driver object created by system.
     RegistryPath - Pointer to the name of the services node for this driver.
 
 Return Value:
 
     The function value is the final status from the initialization operation.
 
 --*/
 {
     NTSTATUS        ntStatus;
     UNICODE_STRING  uszDriverString;
     UNICODE_STRING  uszDeviceString;
     UNICODE_STRING  uszNotifyEventString;
 
     PDEVICE_OBJECT  pDeviceObject;
     PDEVICE_EXTENSION extension;
 
     // Point uszDriverString at the driver name
     RtlInitUnicodeString(&uszDriverString, L"\\Device\\Knotify");
 
     // Create and initialize device object
     ntStatus = IoCreateDevice(DriverObject,
                               sizeof(DEVICE_EXTENSION),
                               &uszDriverString,
                               FILE_DEVICE_UNKNOWN,
                               0,
                               FALSE,
                               &pDeviceObject);
 
     if(ntStatus != STATUS_SUCCESS)
         return ntStatus;
 
     // Assign extension variable...
     extension = pDeviceObject->DeviceExtension;
 
     // Point uszDeviceString at the device name
     RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\Knotify");
 
     // Create symbolic link to the user-visible name
     ntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString);
 
     if(ntStatus != STATUS_SUCCESS)
     {
         // Delete device object if not successful
         IoDeleteDevice(pDeviceObject);
         return ntStatus;
     }
 
     // Load structure to point to IRP handlers...
     DriverObject->DriverUnload = KnotifyUnloadDriver;
     DriverObject->MajorFunction[IRP_MJ_CREATE] = KnotifyDispatchCreateClose;
     DriverObject->MajorFunction[IRP_MJ_CLOSE] = KnotifyDispatchCreateClose;
     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KnotifyDispatchIoctl;
 
     // Create event for user-mode processes to monitor
     RtlInitUnicodeString(&uszNotifyEventString,
                          L"\\BaseNamedObjects\\KnotifyEvent");
     extension->NotifyEvent = IoCreateNotificationEvent(&uszNotifyEventString,
                                                        &extension->NotifyHandle);
 
     KeClearEvent(extension->NotifyEvent);
 
     // Return success
     return ntStatus;
 }
 
 NTSTATUS KnotifyDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 {
     Irp->IoStatus.Status = STATUS_SUCCESS;
     Irp->IoStatus.Information=0;
 
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
     return(STATUS_SUCCESS);
 }
 
 PWORK_QUEUE_ITEM pItem;
 
 
 void KSignalEvent(PKEVENT NotifyEvent)
 {
     LARGE_INTEGER Timeout;
 
 
     // AET - 143
     Timeout.QuadPart = -5000000;
 
     // Delay execution to show "asynchronous" processing
     KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
 
     KeSetEvent(NotifyEvent, 0, FALSE);
 
     ExFreePool(pItem);
 }
 
 void KDelayIRPCompletion(PIRP Irp)
 {
     LARGE_INTEGER Timeout;
 
     Timeout.QuadPart = -5000000;
 
     // Delay execution to show "asynchronous" processing
     KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
    
     // Set # of bytes to copy back to user mode...
     Irp->IoStatus.Information = 0;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
     ExFreePool(pItem);
 }
 
 void KMApcCallback(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine,
                    PVOID NormalContext, PVOID SystemArgument1,
                    PVOID SystemArgument2)
 {
     ExFreePool(Apc);
     return;
 }
 
 NTSTATUS KnotifyDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 {
     NTSTATUS           ntStatus;
     PIO_STACK_LOCATION irpStack  = IoGetCurrentIrpStackLocation(Irp);
     PDEVICE_EXTENSION  extension = DeviceObject->DeviceExtension;
 
     switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
     {
         case IOCTL_NOTIFY_KERNEL_EVENT:
         {
             KeClearEvent(extension->NotifyEvent);
 
             pItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
            
             // Queue execution to a system thread to permit this IRP to
             // complete...
             ExInitializeWorkItem(pItem, KSignalEvent, extension->NotifyEvent);
             ExQueueWorkItem(pItem, DelayedWorkQueue);
 
             ntStatus = STATUS_SUCCESS;
             break;
         }
 
         case IOCTL_NOTIFY_USER_EVENT:
         {
             PKEVENT UserEvent;
 
            
             // Obtain a kernel pointer to the user-mode-created event handle...
             ObReferenceObjectByHandle(*((
                                       PHANDLE)Irp->AssociatedIrp.SystemBuffer),
                                       0,
                                       (POBJECT_TYPE) NULL,
                                       UserMode,
                                       (PVOID)&UserEvent,
                                       (POBJECT_HANDLE_INFORMATION) NULL);
            
             pItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
            
             // Queue execution to a system thread to permit this IRP to
             // complete...
             ExInitializeWorkItem(pItem, KSignalEvent, UserEvent);
             ExQueueWorkItem(pItem, DelayedWorkQueue);
 
             ntStatus = STATUS_SUCCESS;
             break;
         }
 
         case IOCTL_NOTIFY_EMPTY_IRP:
             pItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
            
             // Queue execution to a system thread to permit this IRP to
             // complete...
             ExInitializeWorkItem(pItem, KDelayIRPCompletion, Irp);
             ExQueueWorkItem(pItem, DelayedWorkQueue);
 
             // Mark the IRP pending.  The driver will complete it later...
             IoMarkIrpPending(Irp);
             ntStatus = STATUS_PENDING;
             break;
 
         case IOCTL_NOTIFY_REGISTER_APC:
         {
             PKAPC Apc;
             ULONG *UserRoutine = (ULONG *)Irp->AssociatedIrp.SystemBuffer;
 
 
             Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
 
             KeInitializeApc(Apc,
                 KeGetCurrentThread(),
                 0,
                 (PKKERNEL_ROUTINE)&KMApcCallback, // kernel-mode routine
                 0, // rundown routine
                 (PKNORMAL_ROUTINE)*UserRoutine,   // user-mode routine
                 UserMode, (PVOID)(ULONG)1);
 
             KeInsertQueueApc(Apc, (PVOID)(ULONG)2, (PVOID)(ULONG)3, 0);
 
             ntStatus = STATUS_SUCCESS;
             break;
         }
 
         case IOCTL_NOTIFY_REGISTER_APC_WITH_KM_ALERTING:
         {
             KEVENT event;
             PKTHREAD pThread = KeGetCurrentThread();
             PKAPC Apc;
             ULONG *UserRoutine = (ULONG *)Irp->AssociatedIrp.SystemBuffer;
             LARGE_INTEGER Timeout;
 
            
             Timeout.QuadPart = 0;
 
             Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
 
             KeInitializeApc(Apc,
                 KeGetCurrentThread(),
                 0,
                 (PKKERNEL_ROUTINE)&KMApcCallback, // kernel-mode routine
                 0, // rundown routine
                 (PKNORMAL_ROUTINE)*UserRoutine,   // user-mode routine
                 UserMode, (PVOID)(ULONG)1);
 
             KeInsertQueueApc(Apc, (PVOID)(ULONG)2, (PVOID)(ULONG)3, 0);
            
             // Cheezy way to force the thread into being alertable :-)
             KeInitializeEvent(&event, SynchronizationEvent, FALSE);
             KeWaitForSingleObject(&event, Executive, UserMode, TRUE, &Timeout);
 
             ntStatus = STATUS_SUCCESS;
             break;
         }
        
         default:
             break;
     }
 
     Irp->IoStatus.Status = ntStatus;
    
     // Set # of bytes to copy back to user mode...
     if(ntStatus == STATUS_SUCCESS)
         Irp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
     else
         Irp->IoStatus.Information = 0;
 
     if(ntStatus != STATUS_PENDING)
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
     return ntStatus;
 }
 
 void KnotifyUnloadDriver(PDRIVER_OBJECT DriverObject)
 {
     UNICODE_STRING  uszDeviceString;
 
     IoDeleteDevice(DriverObject->DeviceObject);
 
     RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\Knotify");
     IoDeleteSymbolicLink(&uszDeviceString);
 }
 

--------------------------------------------------------------------------------

Figure 2   Using the OVERLAPPED Structure

OVERLAPPED ov={0};
 &#8226;
 &#8226;
 &#8226; // Create an event handle for async notification
 // from our driver
 ov.hEvent = CreateEvent(NULL,  // Default security
                         TRUE,  // Manual reset
                         FALSE, // non-signaled state
                         NULL); // No name
 
 // Tell the driver to signal its event...
 bReturnCode = DeviceIoControl(hDriver,
                               IOCTL_NOTIFY_USER_EVENT,
                               &UserModeEvent, sizeof(HANDLE),
                               0, 0,
                               &dwBytesReturned,
                               &ov);
        
 // Wait here for the event handle to be set, indicating
 // that the IOCTL processing is complete.
 bReturnCode = GetOverlappedResult(hDriver, &ov,
                                   &dwBytesReturned, TRUE);
 
 CloseHandle(ov.hEvent);
 

--------------------------------------------------------------------------------

Figure 3   APC Snippet from NTDDK.H

typedef CCHAR KPROCESSOR_MODE;
 
 typedef enum _MODE {
     KernelMode,
     UserMode,
     MaximumMode
 } MODE;
 
 // end_ntndis
 //
 // APC function types
 //
 
 // Put in an empty definition for the KAPC so that the
 // routines can reference it before it is declared.
 
 struct _KAPC;
 
 typedef
 VOID
 (*PKNORMAL_ROUTINE) (
     IN PVOID NormalContext,
     IN PVOID SystemArgument1,
     IN PVOID SystemArgument2
     );
 
 typedef
 VOID
 (*PKKERNEL_ROUTINE) (
     IN struct _KAPC *Apc,
     IN OUT PKNORMAL_ROUTINE *NormalRoutine,
     IN OUT PVOID *NormalContext,
     IN OUT PVOID *SystemArgument1,
     IN OUT PVOID *SystemArgument2
     );
 
 typedef
 VOID
 (*PKRUNDOWN_ROUTINE) (
     IN struct _KAPC *Apc
     );
 
 typedef
 BOOLEAN
 (*PKSYNCHRONIZE_ROUTINE) (
     IN PVOID SynchronizeContext
     );
 
 typedef
 BOOLEAN
 (*PKTRANSFER_ROUTINE) (
     VOID
     );
 
 //
 //
 // Asynchronous Procedure Call (APC) object
 //
 
 typedef struct _KAPC {
     CSHORT Type;
     CSHORT Size;
     ULONG Spare0;
     struct _KTHREAD *Thread;
     LIST_ENTRY ApcListEntry;
     PKKERNEL_ROUTINE KernelRoutine;
     PKRUNDOWN_ROUTINE RundownRoutine;
     PKNORMAL_ROUTINE NormalRoutine;
     PVOID NormalContext;
 
     //
     // N.B. The following two members MUST be together.
     //
 
     PVOID SystemArgument1;
     PVOID SystemArgument2;
     CCHAR ApcStateIndex;
     KPROCESSOR_MODE ApcMode;
     BOOLEAN Inserted;
 } KAPC, *PKAPC, *RESTRICTED_POINTER PRKAPC;
 

--------------------------------------------------------------------------------



--------------------------------------------------------------------------------
Send feedback to MSDN.Look here for MSDN Online resources.
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
johnliu
驱动小牛
驱动小牛
  • 注册日期2004-08-06
  • 最后登录2005-03-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-12-12 19:05
多谢AllenZh大虾指点
接分
游客

返回顶部