May 15th, 2024

Building the most efficient device selector query that selects no devices

I had an occasion to write a device selector query that selects no devices. The idea is that you have a function that returns a device selector query for “Find all devices that can X”, but you happen to know that X can’t be done because of some unmet prerequisite unrelated to the devices themselves. What’s the most efficient device selector query that selects no devices?

One thing that doesn’t work is returning the empty string. In Advanced Query Syntax, the empty string is the opposite of what we want: The empty string selects everything.

Each clause in Advanced Query Syntax takes the form of (property) (match operator) (value). For example,

System.Devices.InterfaceClassGuid:="{DEEBE6AD-9E01-47E2-A3B2-A66AA2C036C9}"
System.Size:>1kb
System.FileName:~<"Copy of"

One way to specify a query that matches no devices is to specify contradictory requirements.

System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND
    System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#False

The Interface­Enabled property cannot be both True and False, so this will match no devices.

On the other hand, I wondered whether this would make two passes, one to gather all the devices where the interface is enabled, and then (to process the AND clause) a second pass over those devices to find the ones where the interface is disabled. Should I add a garbage query at the front to reduce the search space as quickly as possible?

System.Devices.InterfaceClassGuid:="{91F9F631-CD92-42C5-91A4-FBAEAF4DBF09}" AND
    System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND
    System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#False

The interface class GUID I picked is one that I generated just now, so I know it won’t match any valid interface GUID.

It turns out that this garbage query at the front does help.

The device selector query evaluator contains optimizations if the query includes an AND clause that does an equality comparison against one of the following properties:

Property Optimized for DeviceInformationKind
DeviceInterface Device
System.Devices.DeviceInstanceId Yes  
System.Devices.ClassGuid Yes Yes
System.Devices.ContainerId Yes Yes
System.Devices.PanelId   Yes

There are shortcuts in the device management subsystem that can find all devices that match one of those properties, so if one of those properties is involved in the query as an AND clause, the query evaluator can use those shortcuts to get the list of candidate devices quickly, rather than having to enumerate all the devices. Once it gets the list of candidates, it can then evaluate the other AND conditions to filter the results.

Therefore, a fast query that produces no results could be

System.Devices.DeviceInstanceId:="{91F9F631-CD92-42C5-91A4-FBAEAF4DBF09}" AND
    System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND
    System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#False

We filter against one of the magic optimized properties (the device instance ID), which will quickly produce no results. The last two clauses (looking for something that is both true and false) ensure that even if something by some freak of bad luck happens to match our GUID, it will nevertheless be rejected.

Update: Commenter Henrik Arlinghaus pointed out a simpler query: Just require the DeviceInstanceId to be two different GUIDs simultaneously.

System.Devices.DeviceInstanceId:="{91F9F631-CD92-42C5-91A4-FBAEAF4DBF09}" AND
System.Devices.DeviceInstanceId:="{E6D41CCF-B31E-45C6-AF59-1B45BB431F6D}"
Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

9 comments

Discussion is closed. Login to edit/delete existing comments.

  • Jonathan Potter

    Whoever designed AQS never thought about making it support “true” and “false” natively?

  • Henrik Arlinghaus

    I assume you are limited to a single GUID clause? Otherwise, if GUID := {X} AND GUID := {Y} should also work.

  • Neil Rashbrook

    Can UUIDs be validated? Are you allowed to search for the Nil UUID {00000000-0000-0000-0000-000000000000}? Or something that looks enough like a UUID but can’t actually be generated in practice?

  • Yuri Khan

    Surely that uuid should have been generated from the MAC address of that same network card that defined the DirectX capability that no sane driver would claim to support?

    (The one you cite is a UUID4 (random) though.)

    • alan robinson

      Nice callback! But isn’t the point of the UUID that it’s astronomically unlikely to get a collision even though each one is randomly generated? Rendering the long-obsolete network card in question destroyed before it’s time…

  • Ian Boyd

    When i ask ISearchQueryHelper to "GenerateSQLFromUserQuery" using:

    <code>

    It generates the SQL query containing the `System.Devices.InterfaceClassGuid`:

    <code>

    Except the column System.Devices.InterfaceClassGuid is not found in the SystemIndex.

    I even set the query syntax mode to "advanced":

    <code>

    So i'm obviously conceptually missing something. Is this field not something that is can be found in the Windows Search catalog? Is this for querying some other area of the system?

    Read more
      • Ian Boyd

        That’s an interesting function design pattern. I might have to steal that.

        It’s nice that an API would write all the plumbing to do an

        ILeafCompare

        on all the fields in all the objects in its memory.

  • Matthew van Eerde (^_^)Microsoft employee

    I wonder if which properties are indexed? E.g. if there was an index on the InterfaceClassGuid property, searching for a non-existent property would require only an index lookup rather than a full table scan