Mouse filter driver to user mode application communication

Hello,
I have successfully written a very basic filter driver for my hid mouse. This filter sends events to a user mode application each time a button is pressed. However, I’m using WMI as a way to communicate between the two entities, and I’m quite sure there must be other better ways to achieve the same thing.

I know that a user mode application can’t read a file from a keyboard or a mouse. Can I (using a filter driver), create a second device (with IoCreateDevice or anything else) that I could open, read, and write with a user application? Or is there any other way for my filter driver and my application to exchange events and data?

Thank you for your answers.

Erwan Martin.

I apologize if I made any grammar mistakes, English is not my primary language.

ZeWaren wrote:

I know that a user mode application can’t read a file from a
keyboard or a mouse. Can I (using a filter driver), create a
second device (with IoCreateDevice or anything else) that I
could open, read, and write with a user application?

At least two ways: 1) create a one-to-many control device from your driver, 2) create a raw PDO from each instance of your driver.

In each case you can open the device from user mode.

I got my hand on this article: http://www.osronline.com/article.cfm?article=446 using the keywords you got me.
This is quite what I wanted.

Now my problem is the communication between the driver and the application. In the example, the driver creates a buffer, which is emptied each time the user application ask for it.

What I need is some sort of “event”, that the driver would fire, which would be caught by the user part, waiting for it.

Is there any way to achieve this?

You already have the mechanism in place if the application is sending a request to the driver which will receive the buffer. The application should open the file handle as overlapped. The driver will complete the irp when it has data, otherwise it will be pended. The “Event” is the completion of the io request when the driver has data.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@fzwte.net
Sent: Monday, April 07, 2008 11:06 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Mouse filter driver to user mode application communication

I got my hand on this article: http://www.osronline.com/article.cfm?article=446 using the keywords you got me.
This is quite what I wanted.

Now my problem is the communication between the driver and the application. In the example, the driver creates a buffer, which is emptied each time the user application ask for it.

What I need is some sort of “event”, that the driver would fire, which would be caught by the user part, waiting for it.

Is there any way to achieve this?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Overlapped I/O provides just what you’re asking for here. Read the
documentation for ReadFile, and pay attention to those parts.

The app submits a read and waits on the overlapped event. The driver
pends that I/O until it’s got data to report, then completes it.

xxxxx@fzwte.net wrote:

I got my hand on this article: http://www.osronline.com/article.cfm?article=446 using the keywords you got me.
This is quite what I wanted.

Now my problem is the communication between the driver and the application. In the example, the driver creates a buffer, which is emptied each time the user application ask for it.

What I need is some sort of “event”, that the driver would fire, which would be caught by the user part, waiting for it.

Is there any way to achieve this?


Ray
(If you want to reply to me off list, please remove “spamblock.” from my
email address)

Thank you very much for your answers.
I made some research about overlapped I/O, and I understand that this is what I need.
However, I’m having some problem with its implementation.

So the first thing I do is create the device:
Device = CreateFile(“\\.\TestDevice”,GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

Then I create a OVERLAPPED structure, set all its bytes to zero, and created an event for it.
ovl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

Then I called ReadFile:
ReadFile(Device, data, 5, &bytesread, &ovl)

ReadFile returns ERROR_IO_PENDING, which I read is normal. From what I understood this means that the read request isn’t completed, and so I have to wait for it to be.
My question is: How do I know when it is?

I tried to call
GetOverlappedResult(Device, &ovl, &bytesread, FALSE);
just after, but it fails and getlasterror return 1 (ERROR_INVALID_FUNCTION).

Does anyone know what I’m doing wrong?

xxxxx@fzwte.net wrote:

Thank you very much for your answers.
I made some research about overlapped I/O, and I understand that this is what I need.
However, I’m having some problem with its implementation.

So the first thing I do is create the device:
Device = CreateFile(“\\.\TestDevice”,GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

Then I create a OVERLAPPED structure, set all its bytes to zero, and created an event for it.
ovl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

Then I called ReadFile:
ReadFile(Device, data, 5, &bytesread, &ovl)

ReadFile returns ERROR_IO_PENDING, which I read is normal. From what I understood this means that the read request isn’t completed, and so I have to wait for it to be.
My question is: How do I know when it is?

I tried to call
GetOverlappedResult(Device, &ovl, &bytesread, FALSE);
just after, but it fails and getlasterror return 1 (ERROR_INVALID_FUNCTION).

Does anyone know what I’m doing wrong?

That’s the right way to do it. The error suggests that the driver
doesn’t support read requests. Are you handling IRP_MJ_READ in your
filter? Is the request getting into your filter?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Start off with a manual reset event.

You can call GetOverlappedResult with the 4th parameter set to TRUE to wait
until the read is complete. You know when it is done by the event being
signalled, but if you use an auto reset event, you can only test it once to
know it is done. A second test will wait forever.

“Tim Roberts” wrote in message news:xxxxx@ntdev…
> xxxxx@fzwte.net wrote:
>> Thank you very much for your answers.
>> I made some research about overlapped I/O, and I understand that this is
>> what I need.
>> However, I’m having some problem with its implementation.
>>
>> So the first thing I do is create the device:
>> Device = CreateFile(“\\.\TestDevice”,GENERIC_READ|GENERIC_WRITE, 0, 0,
>> OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
>>
>> Then I create a OVERLAPPED structure, set all its bytes to zero, and
>> created an event for it.
>> ovl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
>>
>> Then I called ReadFile:
>> ReadFile(Device, data, 5, &bytesread, &ovl)
>>
>> ReadFile returns ERROR_IO_PENDING, which I read is normal. From what I
>> understood this means that the read request isn’t completed, and so I
>> have to wait for it to be.
>> My question is: How do I know when it is?
>>
>> I tried to call
>> GetOverlappedResult(Device, &ovl, &bytesread, FALSE);
>> just after, but it fails and getlasterror return 1
>> (ERROR_INVALID_FUNCTION).
>>
>> Does anyone know what I’m doing wrong?
>>
>
> That’s the right way to do it. The error suggests that the driver doesn’t
> support read requests. Are you handling IRP_MJ_READ in your filter? Is
> the request getting into your filter?
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>

>>>That’s the right way to do it. The error suggests that the driver doesn’t support read requests. Are you handling IRP_MJ_READ in your filter? Is the request getting into your filter?

How stupid of me! You’re right: my filter handles IRP_MJ_READ, but not my control device.
So I created another EvtIoRead function for it, and informed the driver of its existence in the WdfIoQueueCreate call.
Now I can send a regular read request in usermode through readfile and get the data I set in kernelmode.

Now I need to make the connexion between the filter device and the control device.
Here is the typical scenario I’m trying to achieve:

  1. The user application start a readfile and waits.
  2. The filter device gets an event (read, iocontrol or whatever).
  3. It notifies the control device and sends it the data of the event.
  4. The control device completes the read request of the user with the data of the filter.
  5. The user gets the data.

I completely have no clue of how to implement step 3 and 4.

Can you help me?

xxxxx@fzwte.net wrote:

Now I need to make the connexion between the filter device and the control device.
Here is the typical scenario I’m trying to achieve:

  1. The user application start a readfile and waits.
  2. The filter device gets an event (read, iocontrol or whatever).
  3. It notifies the control device and sends it the data of the event.
  4. The control device completes the read request of the user with the data of the filter.
  5. The user gets the data.

I completely have no clue of how to implement step 3 and 4.

Both devices are implemented in the same driver, right? Are you using
the KMDF toaster/filter model, where there is one control device for
multiple filters? If so, then your driver has a global variable that
contains the control device’s WDF device object. From that, you can
fetch the device extension, find your pended request, and complete it.

Just because they are two different devices does not mean there is a
firewall between them.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> I completely have no clue of how to implement step 3 and 4.

Exactly the same way you return data for any request - copy data to the buffer that is associated with IRP, and call IoCompleteRequest() on IRP (you have earlier returned STATUS_PENDING for this IRP, so that you must have saved it in some global memory location)…

Anton Bassov

>returned STATUS_PENDING for this IRP, so that you must have saved it in some

global memory location)…

…or in KMDF queue.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com