Keyboard Filter Driver

Source: Internet
Author: User
Tags comparison table

As I have been in touch with the driver for more than half a month since now, I have deeply realized the difficulties at the beginning of everything and the importance of learning perseverance. I am also a new driver. When I started to get started with the driver, I looked at Zhang Fan's "windows driver development technology concrete explanation", which is a good learning material for new users, but more importantly, I need to do more hands-on exercises. When I learn about synchronization operations, I read tianshu. Finally, I gave up learning this book. After searching for the materials of the crazy man in Chu, I feel that this book is still more difficult for beginners. In this case, I have found that many knowledge points are not very clear, you can do it with your own feeling, but the consequence is the relentless blue screen ^_^. Finally, I want to stick to it.


Today, I will share my experience in writing keyboard Filter during my learning process. I will not elaborate on the working principle because I have a thorough understanding.

 


Our goal is to connect our own driver to all the devices under the/driver/kbdclass driver. What we see is:

 

 

 

 

Then, filter the desired key information through processing. The first device in the mounted driver is our filter device. When a key is triggered, the key information is first intercepted by the device we write, but at this time, the intercepted button information is not processed. How can this problem be solved? Let's ask the keyboard driver. When we intercept the key IRP, we will not process it first. After setting the callback function for the IRP, we will pass it to the keyboard driver. In this way, when the key IRP is processed by the keyboard driver, our callback function is run, and the key information is being processed. When we uninstall our filter device, there will be a problem: there will be a callback routine for the IRP device, and waiting for the button to trigger. Assume that this IRP will unmount our filter driver before processing it, and a blue drive will be triggered. Why is blue screen? Since this IRP has already been set with a callback function, after the IRP is processed, go to the callback function we set, because we have uninstalled it before it is processed, therefore, IRP cannot find the callback function, which causes the blue screen. Most of the solutions are to place a counter when processing the IRP. If the counter is not 0, it indicates that there is still an IRP, this is when the uninstallation is done. If we don't press the keyboard, it will wait endlessly and affect the system performance.
After reading the relevant information, the author works as a proxy IRP and saves the original IRP because we can cancel our IRP. When uninstalling, uninstall our proxy IRP first, and then send the previously saved IRP, which effectively overcomes the infinite waiting bug... but I did not find the relevant code, just try it myself. After one afternoon's crash test, I found that we only need to do a proxy IRP, and do not need to save the original IRP. When uninstalling the agent, we directly cancel our IRP, you do not need to send an IRP again. The following code describes the keyboard filter driver.

 

First:

 

 // Driver entry extern "C" ntstatus DriverEntry (in pdriver_object pdriverobject, in punicode_string pregistrypath) {ntstatus status; dbuplint ("Driver loading starts... /n "); pdriverobject-> driverunload = filterunload; // set the read dispatch function pdriverobject-> majorfunction [irp_mj_read] = filterdispatchroutin; binddevice (pdriverobject ); dbuplint ("The driver load ends... /n "); return STATUS_SUCCESS ;}

 

In the main function, binddevice is called to create and bind a filter driver. The Code is as follows:

 // Device type extern "C" pobject_type iodriverobjecttype; ntstatus binddevice (pdriver_object pdriverobject) {ntstatus status; unicode_string unintnamestring; // drive object to be opened pdriver_object kbddriverobject = NULL; // The device pdevice_object kbddeviceojbect of the driver object; // initialize a string that is the name of the kbdclass driver rtlinitunicodestring (& unintnamestring, kbd_driver_name ); // open the driver object status = obreferenceobjectbyname (& unintnamestring, obj_case_insensitive, null, 0, iodriverobjecttype, kernelmode, null, (pvoid *) & kbddriverobject); // if it fails, the system returns if (! Nt_success (Status) {dbuplint ("failed to enable the device... /n "); Return status;} // calling obreferenceobjectbyname will cause the reference count of the driver object to be added. // the call that must be responded will unreference obdereferenceobjectobdereferenceobject (pdriverobject ); dbuplint ("Open successfully, release reference... /n "); // kbddeviceojbect = kbddriverobject-> deviceobject; while (kbddeviceojbect! = NULL) {// create and bind the filter device createdevice (pdriverobject, kbddeviceojbect); // The next device kbddeviceojbect = kbddeviceojbect-> nextdevice;} return status ;}

Here we will talk about the obreferenceobjectbyname function. This method has not been exported. We can declare it in the header file. The declaration is as follows:

// Obtain the device object based on the name. This function is not public. You can directly use the extern "C" ntstatus obreferenceobjectbyname (punicode_string objectname, ulong attributes, paccess_state accessstate, access_mask desiredaccess, pobject_type objecttype, kprocessor_mode accessmode, pvoid parsecontext, pvoid * object );

 

In the binddevice method, a createdevice method is called to create a filter device and attach it to the target device. The detailed code is as follows:

// Create a device ntstatus createdevice (in pdriver_object pdriverobject, in pdevice_object old1_bj) {ntstatus status; pdevice_object p1_bj; // who is extended pdevice_extension pdevext; status = iocreatedevice (pdriverobject, sizeof (pdevice_extension), null, old1_bj-> devicetype, // The device type must be equal to the attached device type of 0, false, // assume that the specified device is exclusive, this value is set to false for most drivers. If it is not exclusive, it is set to true. & p1_bj); If (! Nt_success (Status) {dbuplint ("An error occurred while creating the device .... /n "); return NULL;} pdevext = (pdevice_extension) p1_bj-> deviceextension; // storage device object pdevext-> pdevice = p1_bj; // bind the original device pdevext-> polddevice = old1_bj; // flag p1_bj-> flags | = old1_bj-> flags & (do_buffered_io | do_direct_io | do_power_pagable ); // This ID indicates that the I/O manager performs a security check on all open requests sent to the control device object. Then, the manager performs a security check. Then, characteristics = old1_bj-> characteristics; // binds the device pdevice_object topdev = ioattach. Devicetodevicestack (p1_bj, old1_bj); If (topdev = NULL) {// If the binding fails, destroy the iodeletedevice (p1_bj); status = status_unsuccessful; return status ;} // Add the bound device and original device to the device extension pdevext-> polddevice = old1_bj; pdevext-> pbinddevice = topdev; p1_bj-> flags = p1_bj-> flags &~ Do_device_initializing; kdprint ("bound successfully ../N"); return STATUS_SUCCESS ;}

 

 

The code above can be used to bind a filter device. After binding, it mainly processes the dispatch function. The function is as follows:

// Dispatch function ntstatus Merge (in pdevice_object p1_bj, in pirp) {export currentirpstack; pdevice_extension pdevext; // get the pdevicext extension (pdevice_extension) p1_bj-> deviceextension; // obtain the current IRP package currentirpstack = iogetcurrentirpstacklocation (pirp); // copy the current IRP to the lower-layer device IRP stack iocopycurrentirpstacklocationtonext (pirp ); // Save the original IRP // pdevext-> tagirp = pirp; // The proxy irppdevext-> proxyirp = pirp; // set the callback routine iosetcompletionroutine (pdevext-> proxyirp, callbackkbdfilter, p1_bj, true) when the IRP is complete; dbuplint ("the IRP callback routine is set up... /n "); Return iocalldriver (pdevext-> polddevice, pdevext-> proxyirp );}

 

Note that when processing the dispatch function, we replace the IRP with our own IRP, so that we can cancel the IRP. We have set a callback function for the IRP, when the IRP processing is complete, run the callback function. The callback function is as follows:

// Flags for keyboard status # defines_shift1 # defines_caps2 # defines_num4static int kb_status = s_num; void _ stdcall print_keystroke (uchar Sch) {ucharch = 0; 0000ff = 0; if (Sch & 0x80) = 0) // make {If (Sch <0x47) | (Sch> = 0x47 & Sch <0x54) & (kb_status & s_num ))) // Num Lock {CH = asciitbl [off + Sch];} switch (Sch) {Case 0x3a: kb_status ^ = s_caps; break; Case 0x2a: Case 0x36: kb_status | = s_shift; break; CA Se 0x45: kb_status ^ = s_num;} else // break {If (Sch = 0xaa | Sch = 0xb6) kb_status & = ~ S_shift;} If (CH> = 0x20 & Ch <0x7f) {dbuplint ("% C/N", CH) ;}} ntstatus callbackkbdfilter (in pdevice_object deviceobject, in pirp, in pvoid context) {pio_stack_location currentirp; pkeyboard_input_data keydata; currentirp = iogetcurrentirpstacklocation (IRP); If (nt_success (IRP-> iostatus. status) {keydata = (pkeyboard_input_data) IRP-> associatedirp. systembuffer; // dbuplint ("Scan code: % x", keydata-> makecode); dbupli NT ("keyboard: % s", keydata-> flags? "Bounce": "Press"); print_keystroke (uchar) keydata-> makecode);} If (IRP-> pendingreturned) {iomarkirppending (IRP );} return IRP-> iostatus. status ;}

The function is not described, mainly for makecode processing, but the comparison table is referenced in the callback function, for example:

 

 Unsigned char asciitbl [] = {0x00, 0x1b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2d, 0x3d, 0x08, 0x09, // normal0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6f, 0x70, 0x5b, 0x5d, 0x0d, 0x00, 0x61, 0x73,0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x3b, 0x27, 0x60, 0x00, 0x5c, 0x7a, 0x78, 0x63, 0x76, 0x62, 0x6e, 0x6d, 0x2c, 0x2e, 0x2f, 0x00, 0x2a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2d, 0x34, 0x35, 0x36, 0x2b, 0x31,0x32, 0x33, 0x30, 0x2e, 0x00, 0x1b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2d, 0x3d, 0x08, 0x09, // caps0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4f, 0x50, 0x5b, 0x5d, 0x0d, 0x00, 0x41, 0x53,0x44, 0x46, 0x47, 0x48, 0x4a, 0x4b, 0x4c, 0x3b, 0x27, 0x60, 0x00, 0x5c, 0x5a, 0x58, 0x43, 0x56, 0x42, 0x4e, 0x4d, 0x2c, 0x2e, 0x2f, 0x00, 0x2a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2d, 0x34, 0x35, 0x36, 0x2b, 0x31,0x32, 0x33, 0x30, 0x2e, 0x00, 0x1b, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5e, 0x26, 0x2a, 0x28, 0x29, 0x5f, 0x2b, 0x08, 0x09, // shift0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4f, 0x50, 0x7b, 0x7d, 0x0d, 0x00, 0x41, 0x53,0x44, 0x46, 0x47, 0x48, 0x4a, 0x4b, 0x4c, 0x3a, 0x22, 0x7e, 0x00, 0x7c, 0x5a, 0x58, 0x43, 0x56, 0x42, 0x4e, 0x4d, 0x3c, 0x3e, 0x3f, 0x00, 0x2a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2d, 0x34, 0x35, 0x36, 0x2b, 0x31,0x32, 0x33, 0x30, 0x2e, 0x00, 0x1b, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5e, 0x26, 0x2a, 0x28, 0x29, 0x5f, 0x2b, 0x08, 0x09, // caps + shift0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6f, 0x70, 0x7b, 0x7d, 0x0d, 0x00, 0x61, 0x73,0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x3a, 0x22, 0x7e, 0x00, 0x7c, 0x7a, 0x78, 0x63, 0x76, 0x62, 0x6e, 0x6d, 0x3c, 0x3e, 0x3f, 0x00, 0x2a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2d, 0x34, 0x35, 0x36, 0x2b, 0x31,0x32, 0x33, 0x30, 0x2e };

The uninstallation function is used. When uninstalling the function, we need to delete the device and the attached device, and then cancel the last IRP. The Code is as follows:

// Uninstall routine void filterunload (in pdriver_object pdriverobject) {// get the device pdevice_object p1_bj = pdriverobject-> deviceobject; while (p1_bj! = NULL) {// device extension pdevice_extension pdevext = (pdevice_extension) p1_bj-> deviceextension; pdevice_object ptagobj = pdevext-> pbinddevice; // unbind if (pdevext-> pbinddevice! = NULL) {iodetachdevice (pdevext-> pbinddevice);} // delete a device if (pdevext-> pdevice! = NULL) {iodeletedevice (pdevext-> pdevice);} If (pdevext-> proxyirp! = NULL) {If (cancelirp (pdevext-> proxyirp) {dbuplint ("canceled successfully... /N ");} else {dbuplint (" cancellation failed... /N ") ;}/// the next device p0000bj = p0000bj-> nextdevice ;}}

 

Call a method to cancel IRP. The Code is as follows:

Boolean cancelirp (pirp) {If (pirp = NULL) {dbuplint ("cancelling IRP error... /n "); Return false;} If (pirp-> cancel | pirp-> cancelroutine = NULL) {dbuplint (" IRP cancellation error... /n "); Return false;} If (false = iocancelirp (pirp) {dbuplint (" iocancelirp to IRP error... /n "); Return false;} // reset this example to null iosetcancelroutine (pirp, null); Return true ;}

 

The entire keyboard filter driver is complete. You have to learn more and summarize it later.

Reprinted please indicate from: http://blog.csdn.net/ms2146

Keyboard Filter Driver

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.