Creating a mouse filter with an INF

Which messages are you trying to intersept? Each driver layer has its own set of internal and external ioctls.

@Tim_Roberts said:
Which messages are you trying to intersept? Each driver layer has its own set of internal and external ioctls.

I am trying to modify mouse input from the CallBack function I am not listening to messages. DebugMessage just prints data to my network debugger which verifies what I already knew that the CallBack function does not get called with the appended version.

Why must you be above Mouclass? The moufiltr example was designed to filter BELOW mouclass, not above it. You can’t just move the filters around and expect it to work. Everything you have described in this and the previous post leads me to believe you don’t need to be above mouclass, rather you don’t know how the stack works and are grasping for solutions and getting frustrated when it doesn’t work. Take a step back and learn how the mouse stack works. You can look at old WDKs which included mouclass as an example. The service callback only works for drivers below mouclass. Mouclass is the driver that sends IOCTL_INTERNAL_MOUSE_CONNECT *down* the stack. So if you are above mouclass you won’t see this ioctl because it is **not sent to the top of the stack**.

@Doron_Holan said:
Why must you be above Mouclass? The moufiltr example was designed to filter BELOW mouclass, not above it. You can’t just move the filters around and expect it to work. Everything you have described in this and the previous post leads me to believe you don’t need to be above mouclass, rather you don’t know how the stack works and are grasping for solutions and getting frustrated when it doesn’t work. Take a step back and learn how the mouse stack works. You can look at old WDKs which included mouclass as an example.

The service callback only works for drivers below mouclass. Mouclass is the driver that sends IOCTL_INTERNAL_MOUSE_CONNECT down the stack. So if you are above mouclass you won’t see this ioctl because it is not sent to the top of the stack.

Why are you asking me why it has to be above Mouclass? I was just stating a fact that it ONLY works when its above despite the example being designed for it being bellow. This whole question is asking how to get it to work with it BELLOW like the example. This is not me complaining about it not working above because it works perfectly above when, this post is me asking how to get it to work with it bellow.

I provided an example of print statements that shows you that Connect Device is not called hence the CallBack is never registered making my filter driver not work. Having it bellow does not work at all because a device is never passed in while it works perfectly above. Stop stating the same thing over again and provide evidence to support your claim like my print examples above.

Enjoy debugging it on your own. Peace out.

Dude, you need to settle down. Doron is a Microsoft engineer who was in charge of maintaining and improving the HID driver stack for many, many years. If he says it, then it is true. If your driver doesn’t work in the position it is in, then YOUR DESIGN IS FLAWED. You need to change your driver to fit the model, and not change the model to fit your design.

@Tim_Roberts said:
Dude, you need to settle down. Doron is a Microsoft engineer who was in charge of maintaining and improving the HID driver stack for many, many years. If he says it, then it is true. If your driver doesn’t work in the position it is in, then YOUR DESIGN IS FLAWED. You need to change your driver to fit the model, and not change the model to fit your design.

I am aware that he is very knowledgeable and knows this stuff way better than I ever will and yes he already told me his qualifications. The part I don’t like is when someone skims my whole question randomly jumps to a conclusion and degrades me for asking a question while boasting about how smart they are.

I have talked to multiple other engineers on this topic after reading countless other questions regarding this same problem without there ever being an answer. If someone claims to be at the top of a field then I don’t understand why that person (in this case “Doron Holan”) does not just give a solution that countless others have asked instead of being defensive at the first glimpse of being questioned. This was not my first post on this topic so I responded the way I did after being talked down to numerous times.

Let me restate my question again in response to the bellow statement.

@Doron_Holan said:
The service callback only works for drivers below mouclass. Mouclass is the driver that sends IOCTL_INTERNAL_MOUSE_CONNECT down the stack. So if you are above mouclass you won’t see this ioctl because it is not sent to the top of the stack.

According to Microsoft Docs it is true that the class driver (which is mouclass) handles sending IOCTL_INTERNAL_MOUSE_CONNECT down the device stack and handles the CallBack. I never argued anything else and it is also true that this must mean that mouclass must be above my filter driver so that it can pass down the handles.

The point of contention is where my driver should be positioned when using an INF to accomplish this. Testing this btw is very easy for example removing mouclass from your UpperFilters while leaving your filter driver results in IOCTL_INTERNAL_MOUSE_CONNECT never being sent which is what we would expect. However, when you use an INF file you append your driver to the end of the UpperFilters meaning its the last to be called. This is where the issue lies because we now go (mouhid → mouclass → my driver) because append means add to the end. This means my driver will not work because mouclass needs to be the highest Filter Driver in the stack (in terms of UpperFilters). Without it being the highestt it wont be able to pass IOCTL_INTERNAL_MOUSE_CONNECT down the stack to my driver.

This is further verified by my and others numerous tests. Adding a print DebugMessage to each of my functions results in the MouFilter_EvtIoInternalDeviceControl() function never being called which is also why IOCTL_INTERNAL_MOUSE_CONNECT never gets passed in. Just to recap appending adds my driver to the end of the stack which is an issue when mouclass needs to be at the end since that handles sending IOCTL_INTERNAL_MOUSE_CONNECT down the device stack.

On the other hand prepending makes my driver and multiple others work PERFCTLY because our driver stack will now look like (mouhid → my driver → mouclass). This is because prepending means to add to the start and if our scope of UpperFilters is just mouclass the start is the lowest point in the device stack. So the correct way is to make our RegEdit look like the following.

your driver
mouclass

This is only done by prepending which is something the INF cannot do. If we expand this out to include our function driver the above hierarchy would take the following shape.

mouhid
your driver
mouclass

Tim, now if you want to say that my entire explanation is wrong and that Dorian is automatically right then that is fine but please describe to me why all the evidence I gathered can actually be applied to making a driver work while Dorians doesn’t. I don’t mine being wrong that is part of learning but from actual tests I can prove that prepending makes the device stack take the hierarchy of (mouhid → mouclass → my driver). I can understand disregarding everything I said if my method did not produce reliable correct results but that is not the case prepending works 100% of the time for me while appending has worked 0% of the time.

@Doron_Holan said:
Enjoy debugging it on your own. Peace out.

I am not sure why you are getting so defensive when being pressed on a topic you are so knowledgeable about. If this paradigm has existed for this many years then its for sure possible me and everyone else who has this issue is just wrong. I don’t know more than you on this topic and all this question was about was to ask a common question I and multiple other more accomplished driver devs (than I) have had issues with. If prepending works in production grade filter drivers there is no point in blowing everything I say off without even looking into it.

Please review my comment above and let me know why my prepending technique works.

If you are a device upper filter you don’t have the prepend problem. Why must you be a class upper filter? Filtering by device is by the simple path. Either work within the bounds of what the INF can declare or programmatically change the state to what you want Starting in windows 10 1903 there is a new way to declare filters which does overcome the append problem IF the base INF declares levels. https://learn.microsoft.com/en-us/windows-hardware/drivers/develop/device-filter-driver-ordering. I don’t know if the system keyboard or mouse INFs provide the levels or not, you should look and see what’s defined. And my name is not Dorian. Nor is my name used in quotes.

1 Like

@Doron_Holan said:
If you are a device upper filter you don’t have the prepend problem. Why must you be a class upper filter? Filtering by device is by the simple path. Either work within the bounds of what the INF can declare or programmatically change the state to what you want

Starting in windows 10 1903 there is a new way to declare filters which does overcome the append problem IF the base INF declares levels. https://learn.microsoft.com/en-us/windows-hardware/drivers/develop/device-filter-driver-ordering. I don’t know if the system keyboard or mouse INFs provide the levels or not, you should look and see what’s defined.

And my name is not Dorian. Nor is my name used in quotes.

Oh my bad on that name mix up. What would you suggest over a UpperFilter driver in order to listen and manipulate mouse input as early as possible? I know its possible to manually include the tag to RegEdit without using an INF I just thought it would be nicer if the INF worked for this. In terms of your link I see that there might be a way to specify a “level” from A-C but I have not found a single example of this so I am not too sure how to implement it due to the lack of documentation. For example here is how I do it now which is classified as the “Legacy” way of doing it.

[DefaultInstall.NT]
CopyFiles = YourDriver.CopyFiles
Addreg = YourDriver.AddReg

[YourDriver.AddReg]
"HKLM", System\CurrentControlSet\Control\Class\%ClassGUIDToFilter%, "UpperFilters", 0x00010008, %DriverName%   

We haven’t really turned on any class filtering yet with the levels, we have to be pretty careful with it due to how many devices it might impact. If you have a device INF I think this should be doable though by setting the filter levels.

@Zac_Lockard said:
We haven’t really turned on any class filtering yet with the levels, we have to be pretty careful with it due to how many devices it might impact. If you have a device INF I think this should be doable though by setting the filter levels.

Do you mind giving me an example of setting the filter level with an INF? I have still not been able to find an example that actually works yet.

The linked page had the full guidance, but you’d need this:

[DDInstall.HW]
AddReg = FilterLevel_Definition

[FilterLevel_Definition]
HKR,,UpperFilterLevels,%REG_MULTI_SZ%,"LevelA","LevelB","LevelC"
HKR,,UpperFilterDefaultLevel,,"LevelB"

With this, any filters that were in the UpperFilters registry value would be put into LevelB, so you could then use AddFilter to add a filter into LevelA or LevelC to ensure you’re below or above the registry-specified filters.

@Zac_Lockard said:
The linked page had the full guidance, but you’d need this:

[DDInstall.HW]
AddReg = FilterLevel_Definition

[FilterLevel_Definition]
HKR,,UpperFilterLevels,%REG_MULTI_SZ%,"LevelA","LevelB","LevelC"
HKR,,UpperFilterDefaultLevel,,"LevelB"

With this, any filters that were in the UpperFilters registry value would be put into LevelB, so you could then use AddFilter to add a filter into LevelA or LevelC to ensure you’re below or above the registry-specified filters.

I am slightly confused on how I can get this to work with my current set up because the formatting is completely different. For example what does %REG_MULTI_SZ% represent also why are you using HKR over HKLM and then including the path? Lastly, do I not need to supply my drivers name like I did right here?

@IgnoreException said:

[DefaultInstall.NT]
CopyFiles = YourDriver.CopyFiles
Addreg = YourDriver.AddReg

[YourDriver.AddReg]
"HKLM", System\CurrentControlSet\Control\Class\%ClassGUIDToFilter%, "UpperFilters", 0x00010008, %DriverName%   

You can do the reading about this. That first section is from an INF for a specific device. The “HKR” symbol in that case means “the registry key for this device”. You are installing a class filter using a non-PnP INF, which is essentially a lightweight installer application. Your INF is not for a specific device, so there isn’t any place for “HKR” to point to.

And you are using the magic number 0x00010000, which indicates that the value should REG_MULTI_SZ. Most people define symbols for those, so they don’t have to remember the magic numbers each time. In the string section, you’ll find

REG_MULTI_SZ = 0x00010000
1 Like

@Tim_Roberts said:
You can do the reading about this. That first section is from an INF for a specific device. The “HKR” symbol in that case means “the registry key for this device”. You are installing a class filter using a non-PnP INF, which is essentially a lightweight installer application. Your INF is not for a specific device, so there isn’t any place for “HKR” to point to.

And you are using the magic number 0x00010000, which indicates that the value should REG_MULTI_SZ. Most people define symbols for those, so they don’t have to remember the magic numbers each time. In the string section, you’ll find

REG_MULTI_SZ = 0x00010000

Alright thank you for that info. I tried this out but it now does not even add my driver to the filter section inside reg edit. I assume its because the old version takes in %DriverName% as a parameter while the new version seemingly has no reference to the drivers name. How should I change the following entry in order for my drivers name to be placed above mouclass?

[DefaultInstall.NT]
CopyFiles = KMDF.CopyFiles
Addreg = KMDF.AddReg

[KMDF.AddReg]
HKR,, UpperFilterLevels, 0x00010000, "LevelA", "LevelB", "LevelC"
HKR,, UpperFilterDefaultLevel,, "LevelB"

I tried this out …

You tried what out? I told you that HKR doesn’t work for a non-PnP install, which is what [DefaultInstall.NT] does. I have no idea if the relatively new UpperFilterLevels thing works with class filters, which is what you have.

@Tim_Roberts said:
I have no idea if the relatively new UpperFilterLevels thing works with class filters, which is what you have.

It will in the future, but currently does not. When enabled, the class definition will need to specify the filter levels, and then an INF using DefaultInstall can add a filter to one of those levels. An INF with DefaultInstall won’t be able to define the filter levels for a class.

@Zac_Lockard said:

@Tim_Roberts said:
I have no idea if the relatively new UpperFilterLevels thing works with class filters, which is what you have.

It will in the future, but currently does not. When enabled, the class definition will need to specify the filter levels, and then an INF using DefaultInstall can add a filter to one of those levels. An INF with DefaultInstall won’t be able to define the filter levels for a class.

So as of now its not possible to add my filters drivers name above the mouse class driver? Is this a feature that will be implemented in the future? What other options are there for achieving this?

Not in an INF, but it is trivially easy with a user-mode installer application. With most filter drivers, it’s easier to install them with a user-mode application instead of hacking up an INF.