Solved

Keyboard events in a Kernel mode driver

Posted on 1998-06-16
2
3,525 Views
Last Modified: 2013-12-03
I would like to receive the events from keyboard in my kernel-mode
driver (Windows NT 4.0), not using the Win32 application.
Is it possible?
Thank you. Alex.
0
Comment
Question by:Madorsky
2 Comments
 
LVL 4

Accepted Solution

by:
agreen earned 500 total points
ID: 1407923
Yes it's possible by hooking onto the keyboard I/O path.
Here's the sample (by M. Russinovich). Converts caps-locks into controls.

NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath )
{
    PDEVICE_OBJECT         deviceObject        = NULL;
    NTSTATUS               ntStatus;
    WCHAR                  deviceNameBuffer[]  = L"\\Device\\Ctrl2cap";
    UNICODE_STRING         deviceNameUnicodeString;
    WCHAR                  deviceLinkBuffer[]  = L"\\DosDevices\\Ctrl2cap";
    UNICODE_STRING         deviceLinkUnicodeString;

    DbgPrint (("Ctrl2cap.SYS: entering DriverEntry\n"));

    //
    // Create our device.
    //
          
    RtlInitUnicodeString (&deviceNameUnicodeString,
                          deviceNameBuffer );
   
    ntStatus = IoCreateDevice (DriverObject,
                               0,
                               &deviceNameUnicodeString,
                               FILE_DEVICE_CTRL2CAP,
                               0,
                               TRUE,
                               &deviceObject );

    if (NT_SUCCESS(ntStatus)) {

       //
       // Create a symbolic link so that ctr2lcap can be dynamically loaded.
         //

       RtlInitUnicodeString (&deviceLinkUnicodeString,
                         deviceLinkBuffer );
       ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
                                &deviceNameUnicodeString );
       if (!NT_SUCCESS(ntStatus))
            DbgPrint (("Ctrl2cap.SYS: IoCreateSymbolicLink failed\n"));

       //
       // Create dispatch points for all the IRPs the keyboard class device
         // handles.
         //

        DriverObject->MajorFunction[IRP_MJ_READ]         
                     = Ctrl2capDispatchRead;
       DriverObject->MajorFunction[IRP_MJ_CREATE]         =
       DriverObject->MajorFunction[IRP_MJ_CLOSE]          =
       DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]  =
       DriverObject->MajorFunction[IRP_MJ_CLEANUP]        =
       DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
                         = Ctrl2capDispatchGeneral;
    }

    if (!NT_SUCCESS(ntStatus)) {

       //
       // Something went wrong, so clean up (free resources etc)
       //

         if (deviceObject )
            IoDeleteDevice (deviceObject);
    }

    return Ctrl2capInit( DriverObject );
}
NTSTATUS Ctrl2capInit( IN PDRIVER_OBJECT DriverObject )
{
    CCHAR             ntNameBuffer[64];
    STRING             ntNameString;
    UNICODE_STRING       ntUnicodeString;
    NTSTATUS             status;

    //
    // Only hook onto the first keyboard's chain.
    //

    sprintf( ntNameBuffer, "\\Device\\KeyboardClass0" );
    RtlInitAnsiString( &ntNameString, ntNameBuffer );
    RtlAnsiStringToUnicodeString( &ntUnicodeString, &ntNameString, TRUE );

    //
    // Create device object for the keyboard.
    //

    status = IoCreateDevice( DriverObject,
                       0,
                       NULL,
                       FILE_DEVICE_KEYBOARD,
                       0,
                       FALSE,
                       &HookDeviceObject );

    if( !NT_SUCCESS(status) ) {

       DbgPrint(("Ctrl2cap: Keyboard hook failed to create device!\n"));

       RtlFreeUnicodeString( &ntUnicodeString );

       return STATUS_SUCCESS;
    }
   
    //
    // Keyboard uses buffered I/O so we must as well.
    //

    HookDeviceObject->Flags |= DO_BUFFERED_IO;

    //
    // Attach to the keyboard chain.
    //

    status = IoAttachDevice( HookDeviceObject, &ntUnicodeString, &kbdDevice );

    if( !NT_SUCCESS(status) ) {

       DbgPrint(("Ctrl2cap: Connect with keyboard failed!\n"));

       IoDeleteDevice( HookDeviceObject );

       RtlFreeUnicodeString( &ntUnicodeString );
      
       return STATUS_SUCCESS;
    }

    //
    // Done! Just free our string and be on our way...
    //

    RtlFreeUnicodeString( &ntUnicodeString );

    DbgPrint(("Ctrl2cap: Successfully connected to keyboard device\n"));

    //
    // This line simply demonstrates how a driver can print
    // stuff to the bluescreen during system initialization.
    //
 
    HalDisplayString( "Ctrl2cap Initialized\n" );

    return STATUS_SUCCESS;
}
NTSTATUS Ctrl2capReadComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
                        IN PVOID Context )
{
    PIO_STACK_LOCATION        IrpSp;
    PKEYBOARD_INPUT_DATA      KeyData;
    int                       numKeys, i;

    //
    // Request completed - look at the result.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    if( NT_SUCCESS( Irp->IoStatus.Status ) ) {

        //
      // Do caps-lock down and caps-lock up. Note that
        // just frobbing the MakeCode handles both the up-key
        // and down-key cases since the up/down information is specified
        // seperately in the Flags field of the keyboard input data
        // (0 means key-down, 1 means key-up).
        //

        KeyData = Irp->AssociatedIrp.SystemBuffer;
        numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

        for( i = 0; i < numKeys; i++ ) {

            DbgPrint(("ScanCode: %x ", KeyData[i].MakeCode ));
            DbgPrint(("%s\n", KeyData[i].Flags ? "Up" : "Down" ));

            if( KeyData[i].MakeCode == CAPS_LOCK) {

              KeyData[i].MakeCode = LCONTROL;
            }
        }
    }

    if( Irp->PendingReturned ) {

        IoMarkIrpPending( Irp );

    }

    return Irp->IoStatus.Status;
}
NTSTATUS Ctrl2capDispatchRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    PIO_STACK_LOCATION nextIrpStack    = IoGetNextIrpStackLocation(Irp);

    //
    // Push params down for keyboard class driver.
    //

    *nextIrpStack = *currentIrpStack;

    //  
    // Set the completion callback, so we can "frob" the keyboard data.
    //         

    IoSetCompletionRoutine( Irp, Ctrl2capReadComplete, DeviceObject, TRUE, TRUE, TRUE );

    //
    // Return the results of the call to the keyboard class driver.
    //
          
    return IoCallDriver( kbdDevice, Irp );
}
NTSTATUS Ctrl2capDispatchGeneral(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp )
{
    PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    PIO_STACK_LOCATION nextIrpStack    = IoGetNextIrpStackLocation(Irp);

    //
    // Default to success.
    //

    Irp->IoStatus.Status      = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    //
    // If this call was directed at the hook device, pass it to
    // the keyboard class device, else handle it ourselves.
    //

   if( DeviceObject == HookDeviceObject ) {

       *nextIrpStack = *currentIrpStack;

       return IoCallDriver( kbdDevice, Irp );

   } else {

       return STATUS_SUCCESS;

   }
}

0
 
LVL 1

Expert Comment

by:shankar_ms
ID: 1407924
agreen:
  I would like to simulate "ctrl+alt+del" event through program. I think it should be handled using interrupts at driver level. Any help on this.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
I designed this idea while studying technology in the classroom.  This is a semester long project.  Students are asked to take photographs on a specific topic which they find meaningful, it can be a place or situation such as travel or homelessness.…

929 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now