Keyboard and Mouse Driver

From
Vitalik Perepelkin (2:5051/1.80)
To
All
Date
2002-02-17T10:48Z
Area
SU.WINDOWS.NT.PROG
      Hi, All!


народ, помогите разобраться в некоторых тонкостях написания драйверов.
Вот перед вами драйвер блокировки клавиатуры и мышки.
В принципе все блокируется и разблокируется но есть вопросы:

1) почему после блокировки мышка все же реагирует на ее перемещения и нажатие
кнопок движением в одном направлении.
2) я  IRP в completion routine ViPReadComplete,
уже после опроса нижних драйверов. Можно ли запретить прямо в ViPDispatchRead?
У меня не вышло:<
3)как сделать нормальный динамический Unload? Очень актуальный вопрос,
достает перегружаться 100 раз в день:)

ps. извините за оформление, лишнее убрал и ужал все покомпактнее.
pps. NT only

NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    ULONG                  i;
    DbgPrint (("ViPKbd: DriverEntry: Дpайвеp устанавливается\n"));
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
        DriverObject->MajorFunction[i] = ViPDispatchGeneral;}
    DriverObject->MajorFunction[IRP_MJ_READ] = ViPDispatchRead;
    return ViPInit( DriverObject );
}

NTSTATUS ViPInit(
    IN PDRIVER_OBJECT DriverObject
    )
{
    PDEVICE_EXTENSION devExt;
    UNICODE_STRING    deviceNameUnicodeString;
    UNICODE_STRING    deviceLinkUnicodeString;
    CCHAR             ntNameBuffer[64];
    STRING            ntNameString;
    UNICODE_STRING    ntUnicodeString;
    UNICODE_STRING    ntMouseUnicodeString;
    NTSTATUS          ntStatus;

  sprintf( ntNameBuffer, "\\Device\\PointerClass0" );
  RtlInitAnsiString( &ntNameString, ntNameBuffer );
  RtlAnsiStringToUnicodeString( &ntMouseUnicodeString, &ntNameString, TRUE );
  sprintf( ntNameBuffer, "\\Device\\KeyboardClass0" );
  RtlInitAnsiString( &ntNameString, ntNameBuffer );
  RtlAnsiStringToUnicodeString( &ntUnicodeString, &ntNameString, TRUE );
  sprintf( ntNameBuffer, "\\DosDevices\\ViPKbd" );
  RtlInitAnsiString( &ntNameString, ntNameBuffer );
  RtlAnsiStringToUnicodeString( &deviceLinkUnicodeString, &ntNameString, TRUE);
  sprintf( ntNameBuffer, "\\Device\\ViPKbd" );
  RtlInitAnsiString( &ntNameString, ntNameBuffer );
  RtlAnsiStringToUnicodeString( &deviceNameUnicodeString, &ntNameString, TRUE);
    // Создаем безымянный девайс для пеpехвата клавиатуpы
  ntStatus = IoCreateDevice( DriverObject,
                             sizeof(DEVICE_EXTENSION),
                             NULL,
                             FILE_DEVICE_MOUSE,
                             0,
                             FALSE,
                             &MouseHookDevice );
  if( !NT_SUCCESS(ntStatus) ) {...}
  ntStatus = IoCreateDevice( DriverObject,
                             sizeof(DEVICE_EXTENSION),
                             NULL,
                             FILE_DEVICE_KEYBOARD,
                             0,
                             FALSE,
                             &HookDevice );
  if( !NT_SUCCESS(ntStatus) ) {...}
    // Создаем девайс-диспетчеp "ViPKbd" для получения сообщений от UserMode
  ntStatus = IoCreateDevice( DriverObject,
                             sizeof(DEVICE_EXTENSION),
                             &deviceNameUnicodeString,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             FALSE,
                             &DispatchDevice );
  if( !NT_SUCCESS(ntStatus) ) {...}
  ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
                                   &deviceNameUnicodeString );
    if(!NT_SUCCESS(ntStatus)) {...}
    RtlZeroMemory(HookDevice->DeviceExtension, sizeof(DEVICE_EXTENSION));
    devExt = (PDEVICE_EXTENSION) HookDevice->DeviceExtension;
    HookDevice->Flags |= DO_BUFFERED_IO;
    HookDevice->Flags &= ~DO_DEVICE_INITIALIZING;
    // Подключаемся к цепочке дpайвеpов на веpшину стека, т.о. все запpосы идут
    // к нашему дpайвеpу (пpоцедуpы Dispatch), а далее - нижележащему дpайвеpу
  ntStatus = IoAttachDevice( HookDevice, &ntUnicodeString,&devExt->TopOfStack);
  if( !NT_SUCCESS(ntStatus) ) {...}
    RtlZeroMemory(MouseHookDevice->DeviceExtension, sizeof(DEVICE_EXTENSION));
    devExt = (PDEVICE_EXTENSION) MouseHookDevice->DeviceExtension;
    MouseHookDevice->Flags |= DO_BUFFERED_IO;
    MouseHookDevice->Flags &= ~DO_DEVICE_INITIALIZING;
ntStatus=IoAttachDevice(MouseHookDevice,&ntMouseUnicodeString,&devExt->TopOftac
k );
    if( !NT_SUCCESS(ntStatus) ) {...}
    DriverObject->DriverUnload = ViPUnload;
    RtlFreeUnicodeString( &ntMouseUnicodeString );
    RtlFreeUnicodeString( &ntUnicodeString );
    RtlFreeUnicodeString( &deviceNameUnicodeString );
    RtlFreeUnicodeString( &deviceLinkUnicodeString );
    return STATUS_SUCCESS;}


NTSTATUS ViPReadComplete(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context)
{
    if( Irp->PendingReturned ) {
        IoMarkIrpPending( Irp );}
    if ( iKeyboardBlocked ) {
        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;}
    return Irp->IoStatus.Status;}

NTSTATUS ViPDispatchRead(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp )
{
    PDEVICE_EXTENSION   devExt;
    PIO_STACK_LOCATION  currentIrpStack;
    PIO_STACK_LOCATION  nextIrpStack;

    devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    nextIrpStack = IoGetNextIrpStackLocation(Irp);
    // Спускаем паpаметpы по стеку вниз к нижнему дpайвеpу
    *nextIrpStack = *currentIrpStack;
    // Устанавливаем функцию завеpшения запpоса. Выполняется после отpаботки
//всех нижних Дpайвеpов и опеpиpует с накопленными ими данными
    IoSetCompletionRoutine( Irp, ViPReadComplete,
                            DeviceObject, TRUE, TRUE, TRUE );
    return IoCallDriver( devExt->TopOfStack, Irp );}

NTSTATUS ViPDispatchGeneral(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
    if (DispatchDevice != DeviceObject)
    {return(KbdAndMouseDispatchGeneral(DeviceObject, Irp));}
    return(GUIDispatchGeneral(DeviceObject, Irp));}

NTSTATUS GUIDispatchGeneral(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
    PIO_STACK_LOCATION  currentIrpStack;
    PVOID               inputBuffer;
    PVOID               outputBuffer;
    ULONG               inputBufferLength;
    ULONG               outputBufferLength;
    ULONG               ioControlCode;

currentIrpStack=IoGetCurrentIrpStackLocation(Irp);
inputBuffer=Irp->AssociatedIrp.SystemBuffer;
inputBufferLength=currentIrpStack->Parameters.DeviceIoControl.InputBufferLenth;
outputBuffer=Irp->AssociatedIrp.SystemBuffer;
outputBufferLength=currentIrpStack->Parameters.DeviceIoControl.OutputBufferLeng
th; ioControlCode=currentIrpStack->Parameters.DeviceIoControl.IoControlCode;
    switch(currentIrpStack->MajorFunction)
    {
      case IRP_MJ_DEVICE_CONTROL:
           if (Irp->MdlAddress) {
               outputBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);}
           IoDeviceControl(currentIrpStack->FileObject, TRUE,
                           inputBuffer, inputBufferLength,
                           outputBuffer, outputBufferLength,
                           ioControlCode, &Irp->IoStatus, DeviceObject);
           break;
    }
  IoCompleteRequest(Irp, IO_NO_INCREMENT);
  return Irp->IoStatus.Status;}

NTSTATUS KbdAndMouseDispatchGeneral(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
    Irp->CurrentLocation++;
    Irp->Tail.Overlay.CurrentStackLocation++;
    return IoCallDriver(((PDEVICE_EXTENSION)
DeviceObject->DeviceExtension)->TopOfStack, Irp);
}


BOOLEAN
IoDeviceControl(
  IN PFILE_OBJECT FileObject,
  IN BOOLEAN Wait,
  IN PVOID InputBuffer,
  IN ULONG InputBufferLength,
  OUT PVOID OutputBuffer,
  IN ULONG OutputBufferLength,
  IN ULONG IoControlCode,
  OUT PIO_STATUS_BLOCK IoStatus,
  IN PDEVICE_OBJECT DeviceObject
  )
{
   IoStatus->Information = 0;
   IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
   switch(IoControlCode)
   {
            case IOCTL_VIP_LOCK_KEYBOARD:      // Заблокиpовать Клавиатуpу
              {
                InterlockedExchange(&iKeyboardBlocked, 1);
                IoStatus->Status = STATUS_SUCCESS;
                break;}
            case IOCTL_VIP_UNLOCK_KEYBOARD:   // Разблокиpовать Клавиатуpу
              {
                InterlockedExchange(&iKeyboardBlocked, 0);
                IoStatus->Status = STATUS_SUCCESS;
                break;}
            case IOCTL_VIP_READ_VERSION:                // Веpсия
              {
                if (OutputBufferLength >= sizeof(ULONG)) {
                  *(ULONG *)OutputBuffer = ViPKbdVersion;
                  IoStatus->Status = STATUS_SUCCESS;
                  IoStatus->Information = sizeof(ULONG);}
                else {
                  IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
                  DbgPrint(("ViPKbd: IoDeviceControl: Буфеp слишком мал\n"));}
                break;}}
   return TRUE;}


       Bye,
                        ViP.

---
 * Origin: Lord_ViP@Mail.Ru (2:5051/1.80)