Partager via


DevCreateObjectQuery, fonction (devquery.h)

Crée une requête d’appareil pour récupérer des propriétés en fonction des paramètres de requête spécifiés.

Syntaxe

HRESULT DevCreateObjectQuery(
  [in]           DEV_OBJECT_TYPE                 ObjectType,
  [in]           ULONG                           QueryFlags,
  [in]           ULONG                           cRequestedProperties,
  [in]           const DEVPROPCOMPKEY            *pRequestedProperties,
  [in]           ULONG                           cFilterExpressionCount,
  [in, optional] const DEVPROP_FILTER_EXPRESSION *pFilter,
  [in]           PDEV_QUERY_RESULT_CALLBACK      pCallback,
  [in, optional] PVOID                           pContext,
  [out]          PHDEVQUERY                      phDevQuery
);

Paramètres

[in] ObjectType

Valeur de l’énumération DEV_OBJECT_TYPE qui détermine le type d’objet sur lequel cette requête doit fonctionner.

[in] QueryFlags

Combinaison de valeurs DEV_QUERY_FLAGS combinées à l’aide d’une opération OR au niveau du bit.

[in] cRequestedProperties

Nombre de structures DEVPROPCOMPKEY fournies dans pRequestedProperties. Si DevQueryFlagAllProperties est spécifié, cette valeur doit être définie sur 0.

[in] pRequestedProperties

Fournit éventuellement un tableau de structures DEVPROPCOMPKEY qui spécifient les propriétés qui doivent être récupérées pour les objets dans le jeu de résultats de la requête lorsque pCallback est appelé pour notifier la requête d’un ajout d’un objet à son jeu de résultats.
Si DevQueryFlagUpdateResults a été spécifié dans QueryFlags, la requête est avertie si la valeur de l’une de ces propriétés change pour un objet dans le jeu de résultats de la requête.

Le champ LocaleName de la structure DEVPROPCOMPKEY est ignoré et doit être défini sur NULL.

Si cRequestedProperties est 0, cette valeur doit être NULL.

[in] cFilterExpressionCount

Nombre de structures DEVPROP_FILTER_EXPRESSION fournies dans pFilter .

[in, optional] pFilter

Fournit éventuellement un tableau de structures DEVPROP_FILTER_EXPRESSION qui spécifient des critères de filtre pour les objets qui doivent faire partie du jeu de résultats de la requête. Si cFilterExpressionCount est 0, cette valeur doit être NULL.

[in] pCallback

Une fonction de rappel PDEV_QUERY_RESULT_CALLBACK à laquelle les résultats de cette requête doivent être envoyés.

[in, optional] pContext

Contexte fourni par l’appelant. Cette valeur est passée à la fonction de rappel non modifiée.

[out] phDevQuery

Pointeur qui reçoit le handle représentant la requête. Si DevQueryFlagsUpdateResults est spécifié, la requête reçoit les mises à jour jusqu’à ce que le handle soit fermé. Appelez DevCloseObjectQuery pour fermer ce handle pour arrêter la requête.

Valeur de retour

S_OK est retourné si une requête a été créée avec succès ; sinon, valeur d’erreur appropriée.

Remarques

Utilisez le DevCreateObjectQuery pour interroger des données sur le DEV_OBJECT_TYPEspécifié. Les objets sont représentés par un type d’objet, une identité de chaîne et un magasin de propriétés de paires clé/valeur. Chaque requête a un jeu de résultats associé. Les objets sont ajoutés, mis à jour ou supprimés du jeu de résultats en fonction de l’état du système et des modifications et la fonction de rappel associée est avertie. Chaque appel à la fonction de rappel représente un instantané des valeurs de propriété au moment où le rappel est appelé. Seuls les objets qui correspondent aux critères exprimés dans l’expression pFilter sont retournés à l’appelant. Outre les appels de rappel qui mettent à jour le jeu de résultats, il existe également des rappels de modification d’état qui informent le client des modifications apportées à l’état de la requête.

Par défaut, les requêtes ne reçoivent pas de mises à jour après le traitement de l’état actuel du système. Une fois que tous les objets correspondants ont été ajoutés au jeu de résultats, la requête entre dans l’état DevQueryStateEnumCompleted et aucun rappel supplémentaire n’est effectué. Lorsqu’une requête s’inscrit pour les mises à jour en spécifiant l’indicateur DevQueryFlagUpdateResults , son jeu de résultats continue d’être mis à jour et le rappel associé est averti, une fois la requête entrée dans la DevQueryStateEnumCompleted'état lorsque des modifications dans le système se produisent qui ajoutent ou suppriment des objets en fonction de la correspondance d’expression de filtre.

Une requête peut être abandonnée. Cela se produit lorsqu’une erreur interne se produit, ce qui rend impossible la communication d’une notification au client. Par exemple, cela peut se produire lorsque le système est dans une condition de mémoire insuffisante. Lorsque cela se produit, le jeu de résultats de l’appelant ne reflète plus une véritable représentation de l’état de la requête. L’appelant reçoit un rappel DevQueryStateAborted. Aucun rappel supplémentaire n’est reçu. L’appelant doit fermer la requête et créer une requête à récupérer à partir de cette condition.

Exemples

Dans l’exemple suivant, la méthode PDEV_QUERY_RESULT_CALLBACK est implémentée pour imprimer les messages d’état lorsque l’état de la requête change, lorsque les éléments ont été ajoutés, mis à jour ou supprimés du résultat de la requête. Ensuite, un scénario de requête simple est implémenté où DevCreateObjectQuery est appelé avec un tableau DEVPROPCOMPKEY et un DEVPROP_FILTER_EXPRESSION pour interroger objets DevObjectTypeDevice avec une propriété DEVPKEY_Device_ClassGuid avec une valeur de GUID_DEVCLASS_NET.

void WINAPI
Example1Callback(
    HDEVQUERY hDevQuery,
    PVOID pContext,
    const DEV_QUERY_RESULT_ACTION_DATA *pActionData
    )
{
    const DEVPROPERTY* NameProperty = NULL;

    UNREFERENCED_PARAMETER(hDevQuery);
    UNREFERENCED_PARAMETER(pContext);

    switch (pActionData->Action)
    {
    case DevQueryResultStateChange:
        if (pActionData->Data.State == DevQueryStateEnumCompleted)
        {
            wprintf(L"Enumeration of current system state complete.\n");
        }
        else if (pActionData->Data.State == DevQueryStateAborted)
        {
            wprintf(L"Query has aborted. No further results will be received.\n");
            // Communicate back to the creator of the query that it has aborted
            // so it can handle that appropriately, such as by recreating the
            // query
        }
        break;

    case DevQueryResultAdd:
        wprintf(L"Object '%ws' has been added to the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        NameProperty = DevFindProperty(&DEVPKEY_NAME,
                                       DEVPROP_STORE_SYSTEM,
                                       NULL,
                                       pActionData->Data.DeviceObject.cPropertyCount,
                                       pActionData->Data.DeviceObject.pProperties);

        if ((NameProperty == NULL) ||
            (NameProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (NameProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((NameProperty->Type != DEVPROP_TYPE_STRING) ||
                 (NameProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' has name '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)NameProperty->Buffer);
        }

        break;

    case DevQueryResultUpdate:
        wprintf(L"Object '%ws' was updated.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        NameProperty = DevFindProperty(&DEVPKEY_NAME,
                                       DEVPROP_STORE_SYSTEM,
                                       NULL,
                                       pActionData->Data.DeviceObject.cPropertyCount,
                                       pActionData->Data.DeviceObject.pProperties);

        if ((NameProperty == NULL) ||
            (NameProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (NameProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((NameProperty->Type != DEVPROP_TYPE_STRING) ||
                 (NameProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted name property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' has name '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)NameProperty->Buffer);
        }

        break;

    case DevQueryResultRemove:
        wprintf(L"Object '%ws' has been removed from the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);
        break;
    }
}

void
Example1()
{
    DEVPROPCOMPKEY RequestedProperties[] =
    {
        { DEVPKEY_NAME, DEVPROP_STORE_SYSTEM, NULL }
    };
    DEVPROP_FILTER_EXPRESSION ObjectFilter[] =
    {
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_Device_ClassGuid, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_GUID,
                sizeof(GUID),
                (void*)&GUID_DEVCLASS_NET
            }
        }
    };

    HDEVQUERY hDevQuery = NULL;
    HRESULT hr = DevCreateObjectQuery(DevObjectTypeDevice,
                                      DevQueryFlagUpdateResults,
                                      RTL_NUMBER_OF(RequestedProperties),
                                      RequestedProperties,
                                      RTL_NUMBER_OF(ObjectFilter),
                                      ObjectFilter,
                                      Example1Callback,
                                      NULL,
                                      &hDevQuery);

    if (FAILED(hr))
    {
        wprintf(L"Failed to create query. hr = 0x%08x\n", hr);
        goto exit;
    }

    // do other work while the query monitors system state in the background

  exit:

    if (hDevQuery != NULL)
    {
        DevCloseObjectQuery(hDevQuery);
    }

    return;
}

Dans l’exemple suivant, le paramètre pContext défini par l’appelant facultatif est utilisé pour passer un handle d’événement à la méthode PDEV_QUERY_RESULT_CALLBACK. Lorsque le rappel détecte que l’état de la requête est DevQueryStateAborted, l’événement est signalé pour avertir l’appelant qu’il doit supprimer la requête existante et recréer une nouvelle requête.

typedef struct _MY_QUERY_CONTEXT {
    HANDLE CompletionEvent;
    HRESULT hr;
} MY_QUERY_CONTEXT, *PMY_QUERY_CONTEXT;

void WINAPI
Example2Callback(
    HDEVQUERY hDevQuery,
    PVOID pContext,
    const DEV_QUERY_RESULT_ACTION_DATA *pActionData
    )
{
    PMY_QUERY_CONTEXT QueryContext = (PMY_QUERY_CONTEXT)pContext;
    const DEVPROPERTY* DevProperty = NULL;

    UNREFERENCED_PARAMETER(hDevQuery);

    switch (pActionData->Action)
    {
    case DevQueryResultStateChange:
        if (pActionData->Data.State == DevQueryStateEnumCompleted)
        {
            wprintf(L"Enumeration of current system state complete.\n");
            // The query did not use DevQueryFlagUpdateResults so the result set
            // is now complete. Signal the caller to stop waiting.
            if (!SetEvent(QueryContext->CompletionEvent))
            {
                wprintf(L"Failed to signal completion event. Err = 0x%08x\n",
                        GetLastError());
            }
        }
        else if (pActionData->Data.State == DevQueryStateAborted)
        {
            wprintf(L"Query has aborted. No further results will be received.\n");
            QueryContext->hr = E_FAIL;
            // Communicate back to the creator of the query that it has aborted
            // so it can handle that appropriately, such as by recreating the
            // query.
            if (!SetEvent(QueryContext->CompletionEvent))
            {
                wprintf(L"Failed to signal completion event. Err = 0x%08x\n",
                        GetLastError());
            }
        }
        break;

    case DevQueryResultAdd:
        wprintf(L"Object '%ws' has been added to the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        DevProperty = DevFindProperty(&DEVPKEY_Device_InstanceId,
                                      DEVPROP_STORE_SYSTEM,
                                      NULL,
                                      pActionData->Data.DeviceObject.cPropertyCount,
                                      pActionData->Data.DeviceObject.pProperties);

        if ((DevProperty == NULL) ||
            (DevProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (DevProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((DevProperty->Type != DEVPROP_TYPE_STRING) ||
                 (DevProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' was exposed by instance ID '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)DevProperty->Buffer);
        }

        break;

    case DevQueryResultUpdate:
        wprintf(L"Object '%ws' was updated.\n",
                pActionData->Data.DeviceObject.pszObjectId);

        DevProperty = DevFindProperty(&DEVPKEY_Device_InstanceId,
                                      DEVPROP_STORE_SYSTEM,
                                      NULL,
                                      pActionData->Data.DeviceObject.cPropertyCount,
                                      pActionData->Data.DeviceObject.pProperties);

        if ((DevProperty == NULL) ||
            (DevProperty->Type == DEVPROP_TYPE_EMPTY) ||
            (DevProperty->Buffer == NULL))
        {
            wprintf(L"Object '%ws' had no instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else if ((DevProperty->Type != DEVPROP_TYPE_STRING) ||
                 (DevProperty->BufferSize < sizeof(WCHAR)))
        {
            wprintf(L"Object '%ws' had a corrupted instance ID property.\n",
                    pActionData->Data.DeviceObject.pszObjectId);
        }
        else
        {
            wprintf(L"Object '%ws' was exposed by instance ID '%ws'.\n",
                    pActionData->Data.DeviceObject.pszObjectId,
                    (PWSTR)DevProperty->Buffer);
        }

        break;

    case DevQueryResultRemove:
        wprintf(L"Object '%ws' has been removed from the result set.\n",
                pActionData->Data.DeviceObject.pszObjectId);
        break;
    }
}

void
Example2()
{
    HRESULT hr = S_OK;
    MY_QUERY_CONTEXT QueryContext = {0};
    HDEVQUERY hDevQuery = NULL;
    DEVPROP_BOOLEAN DevPropTrue = DEVPROP_TRUE;
    DEVPROPCOMPKEY RequestedProperties[] =
    {
        { DEVPKEY_Device_InstanceId, DEVPROP_STORE_SYSTEM, NULL }
    };
    DEVPROP_FILTER_EXPRESSION ObjectFilter[] =
    {
        {
            DEVPROP_OPERATOR_AND_OPEN, {0}
        },
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_DeviceInterface_Enabled, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_BOOLEAN,
                sizeof(DevPropTrue),
                (void*)&DevPropTrue
            }
        },
        {
            DEVPROP_OPERATOR_OR_OPEN, {0}
        },
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_GUID,
                sizeof(GUID),
                (void*)&GUID_DEVINTERFACE_MOUSE
            }
        },
        {
            DEVPROP_OPERATOR_EQUALS,
            {
                { DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_STORE_SYSTEM, NULL },
                DEVPROP_TYPE_GUID,
                sizeof(GUID),
                (void*)&GUID_DEVINTERFACE_KEYBOARD
            }
        },
        {
            DEVPROP_OPERATOR_OR_CLOSE, {0}
        },
        {
            DEVPROP_OPERATOR_AND_CLOSE, {0}
        }
    };

    QueryContext.CompletionEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (!QueryContext.CompletionEvent)
    {
        wprintf(L"Failed to create event. Error = 0x%08x\n",
                GetLastError());
        goto exit;
    }

    hr = DevCreateObjectQuery(DevObjectTypeDeviceInterface,
                              DevQueryFlagNone,
                              RTL_NUMBER_OF(RequestedProperties),
                              RequestedProperties,
                              RTL_NUMBER_OF(ObjectFilter),
                              ObjectFilter,
                              Example2Callback,
                              &QueryContext,
                              &hDevQuery);

    if (FAILED(hr))
    {
        wprintf(L"Failed to create query. hr = 0x%08x\n", hr);
        goto exit;
    }

    switch (WaitForSingleObject(QueryContext.CompletionEvent, INFINITE))
    {
    case WAIT_OBJECT_0:
        if (SUCCEEDED(QueryContext.hr))
        {
            wprintf(L"Successfully enumerated results.\n");
        }
        else
        {
            wprintf(L"Failed to Successfully enumerate results. hr = 0x%08x\n",
                    QueryContext.hr);
        }
        break;

    default:
        wprintf(L"An error waiting occurred.\n");
        break;
    }

  exit:

    if (hDevQuery != NULL)
    {
        DevCloseObjectQuery(hDevQuery);
    }

    if (QueryContext.CompletionEvent != NULL)
    {
        CloseHandle(QueryContext.CompletionEvent);
    }

    return;
}

Exigences

Exigence Valeur
client minimum pris en charge Windows 10 version 1809
serveur minimum pris en charge Windows Server 2019
d’en-tête devquery.h
bibliothèque onecore.lib
DLL Cfgmgr32.dll

Voir aussi

DevCreateObjectQueryEx