USB IrDA + SlyControl

Тема в разделе "WASM.NT.KERNEL", создана пользователем RedField, 25 окт 2010.

  1. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    Идея - дистанционно управлять ПК подобно тому как мы управляем TV.

    В качестве ПДУ - ИК пульт от бытовой техники.
    В качестве приёмника - устройство USB-IrDA.

    Программа, которая будет управлять ПО компьютера - SlyControl (http://slydiman.narod.ru/scr/slycontrol2.htm).

    Вообщем то я уже закончил этот проект. Писал на скоряк так что кол-во багов может быть много, но вообщем вполне стабильно работает.

    Тестировал с использованием ИК-Приёмника: Sigmatel USB-IrDA и простой USB-Мыши.
    В последнем варианте при отсоединении мыши от компа возникает синий экран.
    ------------------------------
    Помогите отыскать и исправить любые баги, приводящие (могущие привести) к синему эрану или хоть как то затормозить работу компьютера.
    -------------------------------


    Стек драйверов для ИК-устройств, подключенных к usb порту будет примерно таким:
    =IrRemote.sys= < вершина стека >
    =Драйвер ИК-устройства USB-IrDA=
    =USBD.sys= < дно стека >

    Драйвер USB-IrDA постоянно опрашивает своё устройство на предмет, например, приёма данных. Для этого он посылает IRP-пакет драйверу USB шины - USBD. Драйвер USBD возвращает принятый IRP-пакет с принятыми данными, которые пришли на ИК-устройство (либо пустой пакет, т.е. данные не пришли).

    Идея в нем такая:
    1) Установить свой фильтр-драйвер "IrRemote.sys" в приведенный выше стек для перехвата принятых данных. Таким образом он приобритёт следующий вид:
    =IrRemote.sys= < вершина стека >
    =Драйвер ИК-устройства USB-IrDA=
    =IrRemote.sys= <Драйвер для перехвата принятых данных>
    =USBD.sys= < дно стека >
    2) С помощью плагина к программе SlyControl - "UsbIrRemote.dll" принимать данные от драйвера IrRemote.sys
     
  2. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    Драйвер IrRemote.sys
    Файл init.cpp

    Код (Text):
    1. #include "driver.h"
    2. #include "usbioctl.h"
    3. #include "usbdi.h"
    4. #include "usbdlib.h"
    5.  
    6. NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo);
    7. VOID DriverUnload(IN PDRIVER_OBJECT fido);
    8. NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    9. NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    10. NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    11. NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    12. NTSTATUS DispatchInternalIOCTL(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    13.  
    14. #pragma LOCKEDDATA
    15. UCHAR CODE[32];
    16. UCHAR ToUser[32];
    17. ULONG nSendBytes;
    18. ULONG nBytesRead;
    19. ULONG CountNullBytes;
    20. KEVENT Done;
    21. //-------------------------------------------------------------------------------
    22. #pragma INITCODE
    23. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
    24. {   nBytesRead=0;
    25.     nSendBytes=0;
    26.     CountNullBytes=0;  
    27.     // Операционка должна поддерживать модель драйвера WDM 1.0 (Win98 DDK) и выше
    28.     if (!IoIsWdmVersionAvailable(1, 0))
    29.     {
    30. /*DEBUG*/   KdPrint(("UsbIrDA_RC - Expected version of WDM (%d.%2.2d) not available\n", 1, 0));
    31.         return STATUS_UNSUCCESSFUL;
    32.     }
    33.     DriverObject->DriverUnload = DriverUnload;            //Для выгрузки драйвера
    34.     DriverObject->DriverExtension->AddDevice = AddDevice; //Для использования WDM модели
    35.  
    36.     for (int i = 0; i < arraysize(DriverObject->MajorFunction); ++i)
    37.         DriverObject->MajorFunction[i] = DispatchAny;
    38.        
    39.     DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; //Диспетчер энергобережения
    40.     DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;     //Диспетчер PnP
    41.     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi; //Диспетчер WMI
    42.     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalIOCTL;
    43.  
    44.     return STATUS_SUCCESS;
    45. }
    46. //-------------------------------------------------------------------------------
    47. #pragma PAGEDCODE
    48. // Процедура выгрузки драйвера
    49. VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
    50. {   PAGED_CODE();
    51. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DriverUnload] DriverObject %8.8lX\n", DriverObject));
    52. }
    53. //-------------------------------------------------------------------------------
    54. NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
    55. {   PAGED_CODE();
    56.     NTSTATUS status;
    57.     UNICODE_STRING LinkName, devName;
    58.     // Создание буферов для имен
    59.     RtlInitUnicodeString(&LinkName, L"\\DosDevices\\IR_REMOTE");
    60.     RtlInitUnicodeString(&devName,   L"\\Device\\devIR_REMOTE");
    61.    
    62.     // Создаем объект UsbIrDA_RC чтобы перехватывать irp-запросы.
    63.     PDEVICE_OBJECT fido; // Объект фильтра для устройства
    64.     PDEVICE_OBJECT edo;  // Именнованный объект устройства
    65.     status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &fido);
    66.     if (!NT_SUCCESS(status))
    67.     {                       // Объект устройства не был создан
    68.         KdPrint(("UsbIrDA_RC - FIDO IoCreateDevice failed  - %X\n", status));
    69.         return status;
    70.     }              
    71.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    72.     __try
    73.     {   MyIoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 255);
    74.         pdx->DeviceObject = fido;
    75.         pdx->Pdo = pdo;
    76.         pdx->flag=FIDO_EXTENSION; // Объект устройства, подключенный к стеку
    77.        
    78.         // Вставляем фильтр драйвер в стек нижележайшего драйвера
    79.         PDEVICE_OBJECT fdo = IoAttachDeviceToDeviceStack(fido, pdo);
    80.         pdx->LowerDeviceObject = fdo;
    81.         fido->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH);
    82.         fido->DeviceType = fdo->DeviceType;
    83.         fido->Flags &= ~DO_DEVICE_INITIALIZING;
    84.     }
    85.     __finally
    86.     {   if (!NT_SUCCESS(status))  // В случае сбоя
    87.         {   IoDeleteDevice(fido); // Удаляем фильтр
    88.             return status;
    89.         }                  
    90.     }
    91.     // Создаем именнованный объект устройства фильтр-драйвера
    92.     // для связи с пользовательским приложением
    93.     status = IoCreateDevice(DriverObject, sizeof(EXTRA_DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &edo);
    94.     if (!NT_SUCCESS(status))
    95.     {                       // Объект устройства не был создан
    96. /*DEBUG*/ KdPrint(("UsbIrDA_RC - EDO IoCreateDevice failed - %X\n", status));
    97.         return status;
    98.     }
    99.     PEXTRA_DEVICE_EXTENSION edx = (PEXTRA_DEVICE_EXTENSION) edo->DeviceExtension;
    100.     edx->flag = EDO_EXTENSION; // Объект устройства для связи с пользовательскм приложением
    101.     edx->pdx = pdx;
    102.     pdx->edx = edx;
    103.     edx->DeviceObject = edo;
    104.     edo->Flags |= DO_BUFFERED_IO;
    105.     edo->Flags &= ~DO_DEVICE_INITIALIZING;
    106.    
    107.     // Создание символьного имени драйвера
    108.     status = IoCreateSymbolicLink (&LinkName, &devName);
    109.     if (!NT_SUCCESS(status))return status;
    110.     KeInitializeEvent(&Done,SynchronizationEvent,FALSE);
    111. /*DEBUG*/   KdPrint(("UsbIrDA_RC - I s      L O A D E D"));
    112.     return status;
    113. }
    114. //-------------------------------------------------------------------------------
    115. #pragma LOCKEDCODE
    116. NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info)
    117. {   Irp->IoStatus.Status = status;
    118.     Irp->IoStatus.Information = info;
    119.     IoCompleteRequest(Irp, IO_NO_INCREMENT);
    120.     return status;
    121. }
    122. //-------------------------------------------------------------------------------
    123. #pragma LOCKEDCODE 
    124. NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    125. {   PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    126.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    127.    
    128.     NTSTATUS status = STATUS_SUCCESS;
    129.     if(pdx->flag==FIDO_EXTENSION)
    130.     {
    131.         status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    132.         if (!NT_SUCCESS(status))
    133.             return CompleteRequest(Irp, status, 0);
    134.         IoSkipCurrentIrpStackLocation(Irp);
    135.         status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    136.         MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    137.     }
    138.     else
    139.     {
    140.         ULONG info = 0;
    141.         PCHAR ToUserBuffer;
    142.         NTSTATUS stRead;
    143.         LARGE_INTEGER Delay = {10000000}; // 1 секунда
    144.         switch(stack->MajorFunction)
    145.         {
    146.             case IRP_MJ_CREATE:
    147.             case IRP_MJ_CLOSE:
    148.                 break;
    149.             case IRP_MJ_READ:
    150. /*DEBUG*/       KdPrint(("UsbIrDA_RC - [IRP_MJ_READ]  WAITING..."));
    151.                 stRead = KeWaitForSingleObject(&Done,Executive, KernelMode, FALSE, &Delay); //Ждём 1 секунду
    152.                 if (!NT_SUCCESS(stRead))
    153.                 {// KdPrint(("UsbIrDA_RC - IRP_MJ_READ  Time is exceeded..."));
    154.                     info = 0; // Хотя это не обязательно
    155.                     break;
    156.                 }
    157.                
    158. /*DEBUG*/       KdPrint(("UsbIrDA_RC - [IRP_MJ_READ]  DONE..."));
    159.                 ToUserBuffer = (PCHAR)Irp->AssociatedIrp.SystemBuffer;
    160.                 if(stack->Parameters.Read.Length<nSendBytes)
    161.                 {   status = STATUS_BUFFER_TOO_SMALL;
    162.                     break;
    163.                 }
    164. /*DEBUG*/       KdPrint(("UsbIrDA_RC - nSendBytes=%i...",nSendBytes));
    165.                 for(ULONG i=0; i<nSendBytes; i++)ToUserBuffer[i] = ToUser[i];
    166.                 info = nSendBytes;
    167.                 nSendBytes=0;
    168.                 break;
    169.             default: status = STATUS_INVALID_DEVICE_REQUEST;
    170.         }
    171.         CompleteRequest(Irp, status, info);
    172.     }
    173.     return status;
    174. }
    175. //-------------------------------------------------------------------------------
    176. NTSTATUS InternalIOCTLCompletion(IN PDEVICE_OBJECT fido, IN PIRP Irp, IN PVOID Context)
    177. {   PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    178.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    179.  
    180.     if(Irp->PendingReturned)IoMarkIrpPending( Irp );
    181.     ULONG uSequenceNumber = (ULONG)Context;
    182.     ULONG dwControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
    183.     if(IOCTL_INTERNAL_USB_SUBMIT_URB == dwControlCode)
    184.     {
    185.         PURB pUrb = (PURB)stack->Parameters.Others.Argument1;
    186.         if(pUrb==0) return STATUS_SUCCESS;
    187.         if(pUrb->UrbHeader.Function==URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER)
    188.         {
    189.             struct _URB_BULK_OR_INTERRUPT_TRANSFER *pBulkOrInterruptTransfer = (struct _URB_BULK_OR_INTERRUPT_TRANSFER *) pUrb;
    190.  
    191.             if(pBulkOrInterruptTransfer->TransferBufferLength==0)
    192.             {   CountNullBytes++;
    193.                 if(CountNullBytes>=5 && nBytesRead>0)
    194.                 {
    195.                     KeSetEvent(&Done, IO_NO_INCREMENT, FALSE);
    196.                     CountNullBytes=0;
    197.                     for(ULONG n=0; n<nBytesRead; n++)
    198.                     {  
    199.                         if(nSendBytes==0)ToUser[n]=CODE[n];
    200. /*DEBUG*/               KdPrint(("UsbIrDA_RC - %02x", CODE[n]));
    201.                     }
    202. /*DEBUG*/           KdPrint(("UsbIrDA_RC - [INCOMMING PACKET] DONE..."));                  
    203.                     nSendBytes = nBytesRead;
    204.                     nBytesRead=0;
    205.                 }
    206.                 return STATUS_SUCCESS;
    207.             }
    208.             BOOLEAN bReadFromDevice = (BOOLEAN)(pBulkOrInterruptTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN);
    209.             if(bReadFromDevice && pBulkOrInterruptTransfer->TransferBufferMDL)
    210.             {
    211.                 PUCHAR pMDLBuf = (PUCHAR)MmGetSystemAddressForMdl(pBulkOrInterruptTransfer->TransferBufferMDL);
    212.                 if(pMDLBuf)
    213.                 {
    214.                     for(ULONG b=0; b<pBulkOrInterruptTransfer->TransferBufferLength; b++)
    215.                     {   // ОГРАНИЧЕНИЕ: длина пакета до 32 байт
    216.                         if(b<32 && nBytesRead<32)CODE[nBytesRead++]=pMDLBuf[b];
    217.                     }
    218. /*DEBUG*/           KdPrint(("UsbIrDA_RC - [INCOMMING PACKET] SIZE = %i", pBulkOrInterruptTransfer->TransferBufferLength));
    219. /*DEBUG*/           KdPrint(("UsbIrDA_RC - [INCOMMING PACKET] nBytesRead = %i", nBytesRead));
    220.                 }
    221.             }
    222.         }
    223.     }
    224.     return STATUS_SUCCESS;
    225. }
    226. //-------------------------------------------------------------------------------
    227. NTSTATUS DispatchInternalIOCTL(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    228. {   PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    229.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    230.     ULONG dwControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
    231.  
    232.     NTSTATUS status;
    233.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    234.     if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0);
    235.  
    236.     if(IOCTL_INTERNAL_USB_SUBMIT_URB == dwControlCode)
    237.     {
    238.         ULONG uSequenceNumber = InterlockedIncrement((PLONG)&pdx->uSequenceNumber);
    239.         IoCopyCurrentIrpStackLocationToNext(Irp);
    240.         IoSetCompletionRoutine(Irp, InternalIOCTLCompletion, (PVOID)uSequenceNumber, TRUE, TRUE, TRUE);
    241.         status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    242.         MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    243.     }
    244.     else
    245.     {
    246.         IoSkipCurrentIrpStackLocation(Irp);
    247.         status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    248.         MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    249.     }
    250.     return status;
    251. }
    252. //-------------------------------------------------------------------------------
    253. NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    254. {  
    255. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchPower] Enter..."));
    256.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    257.     PoStartNextPowerIrp(Irp);   // must be done while we own the IRP
    258.     NTSTATUS status;
    259.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    260.     if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0);
    261.     IoSkipCurrentIrpStackLocation(Irp);
    262.     status = PoCallDriver(pdx->LowerDeviceObject, Irp);
    263.     MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    264. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchPower] Quit..."));
    265.     return status;
    266. }
    267. //-------------------------------------------------------------------------------
    268. NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    269. {  
    270. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchPnp] Enter..."));
    271.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    272.     ULONG fcn = stack->MinorFunction;
    273.    
    274.     NTSTATUS status;
    275.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    276.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    277.     if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0);
    278.     IoSkipCurrentIrpStackLocation(Irp);
    279.     status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    280.    
    281.     if(fcn == IRP_MN_REMOVE_DEVICE)
    282.     {
    283. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchPnp] IRP_MN_REMOVE_DEVICE..."));
    284.         MyIoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
    285.         RemoveDevice(fido);
    286.     }
    287.     else MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    288. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchPnp] Quit..."));
    289.     return status;
    290. }
    291. //-------------------------------------------------------------------------------
    292. NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    293. {   // DispatchWmi
    294. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchWmi] Enter..."));
    295.     NTSTATUS status;
    296.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    297.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    298.     if (!NT_SUCCESS(status))
    299.     {
    300. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchWmi] Error(%i)...", status));
    301.         return CompleteRequest(Irp, status, 0);
    302.     }
    303.     IoSkipCurrentIrpStackLocation(Irp);
    304.     status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    305.     MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    306. /*DEBUG*/   KdPrint(("UsbIrDA_RC - [DispatchWmi] Quit..."));
    307.     return status;
    308. }
    309. //-------------------------------------------------------------------------------
    310. #pragma PAGEDCODE
    311. VOID RemoveDevice(IN PDEVICE_OBJECT fido)
    312. {   PAGED_CODE();
    313.     UNICODE_STRING LinkName;
    314.     // Создание буферов для имен
    315.     RtlInitUnicodeString(&LinkName, L"\\DosDevices\\IR_REMOTE");
    316.     IoDeleteSymbolicLink(&LinkName);
    317.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fido->DeviceExtension;
    318.     if(pdx->LowerDeviceObject)IoDetachDevice(pdx->LowerDeviceObject);
    319.     IoDeleteDevice(pdx->edx->DeviceObject);
    320.     IoDeleteDevice(fido);
    321. /*DEBUG*/   KdPrint(("UsbIrDA_RC - I S    U N L O A D E D"));
    322. }
    323. //-------------------------------------------------------------------------------
    324. #pragma LOCKEDCODE
    325. extern "C" void __declspec(naked) __cdecl _chkesp()
    326. {   _asm je okay
    327.     ASSERT(!"Stack pointer mismatch!");
    328. okay:
    329.     _asm ret
    330. }
    Файл Driver.h

    Код (Text):
    1. #ifndef _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_
    2. #define _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_
    3.  
    4. #ifdef __cplusplus
    5. extern "C"
    6. {
    7. #endif
    8.     #include "wdm.h"
    9. #ifdef __cplusplus
    10. }
    11. #endif
    12. ///////////////////////////////////////////////////////////////////////////////
    13. #define PAGEDCODE code_seg("page")
    14. #define LOCKEDCODE code_seg()
    15. #define INITCODE code_seg("init")
    16. //-------------------------------------------------------------------------------
    17. #define PAGEDDATA data_seg("page")
    18. #define LOCKEDDATA data_seg()
    19. #define INITDATA data_seg("init")
    20. //-------------------------------------------------------------------------------
    21. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
    22. //-------------------------------------------------------------------------------
    23. #if DBG && defined(_X86_)
    24. #undef ASSERT
    25. #define ASSERT(e) if(!(e)){DbgPrint("Assertion failure in "\
    26.     __FILE__ ", line %d: " #e "\n", __LINE__);\
    27.     _asm int 1\
    28. }
    29. #endif
    30. ///////////////////////////////////////////////////////////////////////////////
    31. typedef struct _MY_IO_REMOVE_LOCK {
    32.     LONG usage;                 // reference count
    33.     BOOLEAN removing;           // true if removal is pending
    34.     KEVENT evRemove;            // event to wait on
    35. } MY_IO_REMOVE_LOCK, *PMY_IO_REMOVE_LOCK;
    36.  
    37. VOID MyIoInitializeRemoveLock(PMY_IO_REMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount);
    38. NTSTATUS MyIoAcquireRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag);
    39. VOID MyIoReleaseRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag);
    40. VOID MyIoReleaseRemoveLockAndWait(PMY_IO_REMOVE_LOCK lock, PVOID tag);
    41. ///////////////////////////////////////////////////////////////////////////////
    42. // Device extension structure
    43. typedef struct _COMMON_DEVICE_EXTENSION{
    44.     ULONG flag;
    45. }COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
    46.  
    47. typedef struct _DEVICE_EXTENSION: public _COMMON_DEVICE_EXTENSION {
    48.     struct _EXTRA_DEVICE_EXTENSION* edx;
    49.     PDEVICE_OBJECT DeviceObject;           
    50.     PDEVICE_OBJECT LowerDeviceObject;       // next lower driver in same stack
    51.     PDEVICE_OBJECT Pdo;                     // the PDO
    52.     MY_IO_REMOVE_LOCK RemoveLock;
    53.     ULONG          uSequenceNumber;
    54. }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    55.  
    56. typedef struct _EXTRA_DEVICE_EXTENSION: public _COMMON_DEVICE_EXTENSION{
    57.     PDEVICE_OBJECT DeviceObject;
    58.     PDEVICE_EXTENSION pdx;
    59. }EXTRA_DEVICE_EXTENSION, *PEXTRA_DEVICE_EXTENSION;
    60.  
    61. #define FIDO_EXTENSION 0
    62. #define EDO_EXTENSION 1
    63. ///////////////////////////////////////////////////////////////////////////////
    64. // Global functions
    65.  
    66. VOID RemoveDevice(IN PDEVICE_OBJECT fdo);
    67. NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info);
    68.  
    69. extern UCHAR CODE[32];
    70. extern ULONG nBytesRead;
    71. extern ULONG CountNullBytes;
    72. extern KEVENT Done;
    73.  
    74. #endif // DRIVER_H
    Файл RemoveLoc.cpp

    Код (Text):
    1. #include "Driver.h"
    2. //-------------------------------------------------------------------------------
    3. #pragma PAGEDCODE
    4. VOID MyIoInitializeRemoveLock(PMY_IO_REMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount)
    5. {
    6.     PAGED_CODE();
    7.     KeInitializeEvent(&lock->evRemove, NotificationEvent, FALSE);
    8.     lock->usage = 1;
    9.     lock->removing = FALSE;
    10. }
    11. //-------------------------------------------------------------------------------
    12. #pragma LOCKEDCODE
    13. NTSTATUS MyIoAcquireRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag)
    14. {
    15.     LONG usage = InterlockedIncrement(&lock->usage);
    16.     if (lock->removing)
    17.     {                       // removal in progress
    18.         if (InterlockedDecrement(&lock->usage) == 0)
    19.             KeSetEvent(&lock->evRemove, 0, FALSE);
    20.         return STATUS_DELETE_PENDING;
    21.     }                       // removal in progress
    22.     return STATUS_SUCCESS;
    23. }
    24. //-------------------------------------------------------------------------------
    25. VOID MyIoReleaseRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag)
    26. {
    27.     if (InterlockedDecrement(&lock->usage) == 0)
    28.         KeSetEvent(&lock->evRemove, 0, FALSE);
    29. }
    30. //-------------------------------------------------------------------------------
    31. #pragma PAGEDCODE
    32. VOID MyIoReleaseRemoveLockAndWait(PMY_IO_REMOVE_LOCK lock, PVOID tag)
    33. {
    34.     PAGED_CODE();
    35.     lock->removing = TRUE;
    36.     MyIoReleaseRemoveLock(lock, tag);
    37.     MyIoReleaseRemoveLock(lock, NULL);
    38.     KeWaitForSingleObject(&lock->evRemove, Executive, KernelMode, FALSE, NULL);
    39. }
    40. //-------------------------------------------------------------------------------
    Файл Sources

    Код (Text):
    1. TARGETNAME=IrRemote
    2.  
    3. TARGETPATH=obj
    4. TARGETTYPE=DRIVER
    5.  
    6. SOURCES= init.cpp \
    7.          RemoveLock.cpp