Keyboard filter driver for driver development-traditional keyboard Filter

Source: Internet
Author: User

Recently, I 've been reading "programming for Windows Kernel fishing in Hanjiang". I 've seen the keyboard filter section and noted down the notes for your reference only. I hope you can correct me if you understand something wrong.

Now, for traditional keyboard filtering, You can bind your device object to a kbdclass device object. The IRP sent to the kbdclass will first pass through the device object. We can set the completion routine in the dispatch letter number. After the IRP is completed, we will obtain the key information during the completion process.

Kbdclass is called a keyboard driver. in windows, a class driver usually refers to a driver that manages a category of devices. No matter whether it is a USB keyboard or a PS/2 keyboard, blocking on this layer can achieve good versatility.

Use the devicetree tool to view


Install the ctl2cap instance in "programming for Windows Kernel of Hanjiang standalone fishing", and check again


The Code is as follows:

# Include <WDM. h> // name of the kbdclass driver # define kbd_driver_name l "\ driver \ kbdclass" typedef struct _ c2p_dev_ext {// size of the structure ulong nodesize; // filter the device object pdevice_object pfilterdeviceobject; // The kspin_lock iorequestsspinlock during simultaneous calls; // process kevent ioinprogressevent synchronously between processes; // The bound device object pdevice_object targetdeviceobject; // The underlying device object pdevice_object lowerdeviceobject before binding;} c2p_dev_ext, * pc2p_dev_ext; ntstatus c2pdevext Init (in pc2p_dev_ext devext, in pdevice_object pfilterdeviceobject, in pdevice_object ptargetdeviceobject, in pdevice_object plowerdeviceobject) {memset (devext, 0, sizeof (c2p_dev_ext )); devext-> nodesize = sizeof (c2p_dev_ext); devext-> pfilterdeviceobject = plugin; keinitializespinlock (& (devext-> events); keinitializeevent (& (devext-> events), icationicationevent, False); devext-> targetdeviceobject = ptargetdeviceobject; devext-> lowerdeviceobject = plowerdeviceobject; Return (STATUS_SUCCESS);} // This function exists, but it is not disclosed in the document. Declare // and you can use it directly. Struct (punicode_string objectname, ulong attributes, paccess_state accessstate, access_mask desiredaccess, incluobjecttype, incluaccessmode, pvoid parsecontext, pvoid * object); extern implements iodriverobjecttype; ulong bytes = 0; pdriver_object gdriverobject = NULL; // This function has been transformed. Enable the drive object kbdclass, and then bind // all devices under it: ntstatus c2pattachdevices (in pdriver_object driverobject, in punicode_string registrypath) {ntstatus status = 0; unicode_string unintnamestring; includevext; pdevice_object pfilterdeviceobject = NULL; pdevice_object ptargetdeviceobject = NULL; pdevice_object plowerdeviceobject = NULL; pdriver_object kbddriverobject = NULL; kdprint ("myattach \ n"); // initialize a device Is the name of the kdbclass driver. Rtlinitunicodestring (& unintnamestring, kbd_driver_name); // see the previous example of opening a device object. The driver object is opened here. Status = obreferenceobjectbyname (& unintnamestring, obj_case_insensitive, null, 0, iodriverobjecttype, kernelmode, null, & kbddriverobject); // if it fails, the system returns if (! Nt_success (Status) {kdprint ("myattach: couldn't get the mytest device object \ n"); Return (Status );} else {// you need to deploy the application to enable this feature. Release earlier, so that you do not forget it. Obdereferenceobject (driverobject);} // this is the first device in the device chain, ptargetdeviceobject = kbddriverobject-> deviceobject; // start traversing this device chain now while (ptargetdeviceobject) {// generate a filter device, which was previously learned by the reader. Both the in macro and out macro here are // empty macro, which only indicates that this parameter is an input or output parameter. Status = iocreatedevice (in driverobject, in sizeof (c2p_dev_ext), In null, in ptargetdeviceobject-> devicetype, in ptargetdeviceobject-> characteristics, in false, out & pfilterdeviceobject ); // exit if it fails. If (! Nt_success (Status) {kdprint ("myattach: couldn't create the myfilter filter device object \ n"); Return (Status) ;}// bind. Plowerdeviceobject is the next device after binding. That is, // the so-called real device. Plowerdeviceobject = ioattachdevicetodevicestack (pfilterdeviceobject, ptargetdeviceobject); // If the binding fails, discard the previous operation and exit. If (! Plowerdeviceobject) {kdprint ("myattach: Couldn't attach to mytest device object \ n"); iodeletedevice (pfilterdeviceobject); pfilterdeviceobject = NULL; Return (Status );} // device extension! The following describes the application of device extension in detail. Devext = (extensions) (pfilterdeviceobject-> deviceextension); c2pdevextinit (devext, pfilterdeviceobject, ptargetdeviceobject, and plowerdeviceobject); // The following operations are basically the same as those for filtering the serial port. I will not explain it here. Pfilterdeviceobject-> devicetype = plowerdeviceobject-> devicetype; feature-> characteristics = plowerdeviceobject-> characteristics; pfilterdeviceobject-> stacksize = plowerdeviceobject-> stacksize + 1; pfilterdeviceobject-> flags | = plowerdeviceobject-> flags & (packages | do_direct_io | do_power_pagable); // next device ptargetdeviceobject = ptargetdeviceobject-> nextdevice;} return status ;} Void c2pdetach (in pdevice_object pdeviceobject) {pc2p_dev_ext devext; Boolean norequestsoutstanding = false; devext = (pc2p_dev_ext) pdeviceobject-> deviceextension; _ Try {iodetachdevice (devext-> targetdeviceobject); devext-> targetdeviceobject = NULL; iodeletedevice (pdeviceobject); devext-> pfilterdeviceobject = NULL; dbuplint ("detach finished \ n");} _ random t (exception_execute_handler ){}} _ Finally {} return;} # define delay_one_microsecond (-10) # define Merge (latency * 1000) # define delay_one_second (latency * 1000) void c2punload (in pdriver_object driverobject) {pdevice_object deviceobject; pdevice_object olddeviceobject; pc2p_dev_ext devext; large_integerldelay; prkthread currentthread; // delay some time ldelay = rtlconvertlongtolargeinteg Er (100 * delay_one_millisecond); currentthread = kegetcurrentthread (); // set the current thread to a low real-time mode, so that its operation can affect other programs as little as possible. Kesetprioritythread (currentthread, low_realtime_priority); unreferenced_parameter (driverobject); kdprint ("DriverEntry unloading... \ n "); // traverse all devices and unbind them from deviceobject = driverobject-> deviceobject; while (deviceobject) {// unbind and delete all devices c2pdetach (deviceobject); deviceobject = deviceobject-> nextdevice;} assert (null = driverobject-> deviceobject); While (gc2pkeycount) {kedelayexecutionthread (kerne Lmode, false, & ldelay);} kdprint ("DriverEntry unload OK! \ N "); return;} ntstatus c2pdispatchgeneral (in pdevice_object deviceobject, in pirp IRP) {// other distribution functions, directly use the Skip and then use iocalldriver to send the IRP to the device object of the real device. Kdprint ("Other diapatch! "); Callback (IRP); Return iocalldriver (pc2p_dev_ext) deviceobject-> deviceextension)-> lowerdeviceobject, IRP);} ntstatus c2ppower (in pdevice_object deviceobject, in pirp) {pc2p_dev_ext devext; devext = (pc2p_dev_ext) deviceobject-> deviceextension; postartnextpowerirp (IRP); reply (IRP); Return pocalldriver (devext-> lowerdeviceobject, IRP );} Tstatus c2ppnp (in pdevice_object deviceobject, in pirp IRP) {pc2p_dev_ext devext; pio_stack_location irpstack; ntstatus status = STATUS_SUCCESS; kirql oldirql; kevent event; // obtain real devices. Devext = (pc2p_dev_ext) (deviceobject-> deviceextension); irpstack = iogetcurrentirpstacklocation (irpstack); Switch (irpstack-> minorfunction) {Case irp_mn_remove_device: kdprint ("irp_mn_remove_device \ n"); // first, send the request to ioskipcurrentirpstacklocation (IRP); iocalldriver (devext-> lowerdeviceobject, IRP); // then unbind it. Iodetachdevice (devext-> lowerdeviceobject); // delete our own virtual devices. Iodeletedevice (deviceobject); status = STATUS_SUCCESS; break; default: // all other types of IRPs can be directly delivered. Ioskipcurrentirpstacklocation (IRP); status = iocalldriver (devext-> lowerdeviceobject, IRP);} return status ;}// This is the prototype of an IRP callback function. ntstatus c2preadcomplete (in pdevice_object deviceobject, in pirp, in pvoid context) {pio_stack_location irpsp; ulong buf_len = 0; puchar Buf = NULL; size_t I; irpsp = iogetcurrentirpstacklocation (IRP ); // if the request is successful. Obviously, if the request fails, it is meaningless to obtain // further information. If (nt_success (IRP-> iostatus. Status) {// obtain the buffer Buf = IRP-> associatedirp. systembuffer output after the Read Request is complete; // obtain the length of the buffer. Generally, the returned values are stored in // information. Buf_len = IRP-> iostatus. Information ;//... Further processing can be performed here. I will simply print out all the scanning codes here. For (I = 0; I <buf_len; ++ I) {dbuplint ("ctrl2cap: % 2x \ r \ n", Buf [I]) ;}} gc2pkeycount --; if (IRP-> pendingreturned) {iomarkirppending (IRP);} return IRP-> iostatus. status;} ntstatus c2pdispatchread (in pdevice_object deviceobject, in pirp) {ntstatus status = success; paidevext; pio_stack_location currentirpstack; kevent waitevent; keinitializeevent (& waitevent, icationevent, False); If (IRP-> currentlocation = 1) {ulong returnedinformation = 0; kdprint ("dispatch encountered bogus current location \ n"); status = status_invalid_device_request; IRP-> iostatus. status = status; IRP-> iostatus. information = returnedinformation; iocompleterequest (IRP, io_no_increment); Return (Status) ;}// Add 1 gc2pkeycount ++ to the global variable key counter; // get the device extension. The purpose is to obtain the pointer of the next device. Devext = (pc2p_dev_ext) deviceobject-> deviceextension; // set the callback function and pass the IRP. Then the read processing is complete. // The remaining task is waiting for the completion of the read request. Currentirpstack = iogetcurrentirpstacklocation (IRP); reverse (IRP); iosetcompletionroutine (IRP, c2preadcomplete, deviceobject, true); Return iocalldriver (devext-> lowerdeviceobject, IR );} ntstatus DriverEntry (in pdriver_object driverobject, in punicode_string registrypath) {ulong I; ntstatus status; kdprint ("c2p. SYS: Entering DriverEntry \ n "); // enter Some distribution function pointers for (I = 0; I <irp_mj_maximum_function; I ++) {driverobject-> majorfunction [I] = c2pdispatchgeneral ;} // enter a read distribution function separately. Because the filtering is to read the key information // others are not important. This distribution function is written separately. Driverobject-> majorfunction [irp_mj_read] = c2pdispatchread; // enter an irp_mj_power function separately. This is because such requests need to call // A pocalldriver and a postartnextpowerirp, which is special. Driverobject-> majorfunction [irp_mj_power] = c2ppower; // We want to know when a device we have bound has been detached (for example, from the machine. // is it unplugged ?) Therefore, write a dedicated PNP (plug-and-play) Distribution Function driverobject-> majorfunction [irp_mj_pnp] = c2ppnp; // uninstall the function. Driverobject-> driverunload = c2punload; gdriverobject = driverobject; // bind all keyboard devices. Status = c2pattachdevices (driverobject, registrypath); Return status ;}






Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.