How to disable the keyboard Sleep button with a filter driver (302092)



The information in this article applies to:

  • Microsoft Windows 2000 Professional
  • Microsoft Windows XP Home Edition
  • Microsoft Windows XP Professional
  • Microsoft Windows Server 2003 Driver Development Kit (DDK)
  • Microsoft Windows 2000 Driver Development Kit (DDK)
  • Microsoft Windows XP Driver Development Kit (DDK)

This article was previously published under Q302092

SUMMARY

The Sleep hot key that exists on newer keyboards allows you to suspend the computer to a lower power state. For certain systems the lower power state may not be beneficial. This article explains how to disable the Sleep hot key feature by using a filter driver in the target device stack.

MORE INFORMATION

To disable the Sleep hot key, you must filter the IOCTL_GET_SYS_BUTTON_CAPS device I/O control request IRP sent by the Power Manager to the devices that register one of the following device interface classes:

GUID_CLASS_INPUT or GUID_DEVINTERFACE_HID
GUID_DEVICE_SYS_BUTTON

The IOCTL_GET_SYS_BUTTON_CAPS request is sent by the Power Manager to obtain the system button capabilities from Human Input Device (HID) devices. The drivers for the HID devices return the capabilities as a bitmask in the Irp->AssociatedIrp.SystemBuffer field. The bits values are defined as:

#define SYS_BUTTON_POWER        0x00000001 // Power toggle key
#define SYS_BUTTON_SLEEP        0x00000002 // Sleep key
#define SYS_BUTTON_LID          0x00000004 
#define SYS_BUTTON_WAKE         0x80000000 // Wake key could be any key
					

The following code snippet demonstrates how to modify the Sleep hot key information in the completion routine of IOCTL_GET_SYS_BUTTON_CAPS by using the Filter.sys sample code present in the NTDDK\Src\General\Toaster\Filter folder of Microsoft Windows 2000 DDK:
... 
...
#include <poclass.h>
NTSTATUS 
FilterPass (IN PDEVICE_OBJECT DeviceObject, 
            IN PIRP Irp)
{
    PDEVICE_EXTENSION           deviceExtension; 
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    // 
    // Check to see if this is the IOCTL we are interested in.
    // 
    if((IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction) && 
    (IOCTL_GET_SYS_BUTTON_CAPS  ==     irpStack->Parameters.DeviceIoControl.IoControlCode)) { 

        // 
        // If so set a completion routine.
        // 
        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutine(Irp, SleepButtonComplete, NULL, TRUE, TRUE, TRUE );
        return IoCallDriver (deviceExtension->NextLowerDriver, Irp);
    }
    
    IoSkipCurrentIrpStackLocation (Irp);
    return IoCallDriver (deviceExtension->NextLowerDriver, Irp);
}
         
NTSTATUS 
SleepButtonComplete(IN PDEVICE_OBJECT DeviceObject,
                    IN PIRP Irp, PVOID context)
{
    NTSTATUS status;
    ULONG caps;

    caps = 0x0;

    if(Irp->PendingReturned)
        IoMarkIrpPending(Irp);

    // 
    // Get the current value.
    // 
    caps = *(PULONG) Irp->AssociatedIrp.SystemBuffer;
    // 
    // Clear all the bits related to power.
    // 
    caps &= ~(SYS_BUTTON_SLEEP | SYS_BUTTON_POWER | SYS_BUTTON_WAKE);

    // 
    // Set the new value.
    // 
    *(PULONG) Irp->AssociatedIrp.SystemBuffer = caps;
    
    status = Irp->IoStatus.Status;
    
    return status;
}
				
For a PS/2 keyboard, you should install the filter driver as a device upper filter driver to the PS/2 port driver (i8042prt.sys). The Kbdfilter.inf INF file present in the NTDDK\Src\Input\Kbdfiltr folder shows how to install a device filter for PS/2 devices.

For the HID keyboard, the filter driver should be an upper device filter driver for the System Control device. The power keys on HID devices are reported not as part of the Keyboard top-level collection but as part of the System Control collection, and enumerated as a separate raw device. So, to install the filter, you should enumerate HID devices to look for HID_DEVICE_SYSTEM_CONTROL in the HardwareID list and place the filter as an upper device filter. As a result you will directly attach to the Physical Device Object (PDO) of the system control device and filter the IOCTL_GET_SYS_BUTTON_CAPS as shown previously.

Modification Type:MajorLast Reviewed:8/1/2005
Keywords:kbHID kbhowto kbInput kbKMode KB302092 kbAudDeveloper