Compartir a través de


Función DevCreateObjectQuery (devquery.h)

Crea una consulta de dispositivo para recuperar propiedades basadas en los parámetros de consulta especificados.

Sintaxis

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
);

Parámetros

[in] ObjectType

Valor de la enumeración DEV_OBJECT_TYPE que determina el tipo de objeto en el que debe funcionar esta consulta.

[in] QueryFlags

Combinación de DEV_QUERY_FLAGS valores que se combinan mediante una operación OR bit a bit.

[in] cRequestedProperties

Número de estructuras de DEVPROPCOMPKEY proporcionadas en pRequestedProperties. Si se especifica DevQueryFlagAllProperties, debe establecerse en 0.

[in] pRequestedProperties

Opcionalmente, proporciona una matriz de estructuras de DEVPROPCOMPKEY que especifican las propiedades que se deben recuperar para los objetos del conjunto de resultados de la consulta cuando se llama a pCallback para notificar a la consulta una adición de un objeto a su conjunto de resultados.
Si se especificó DevQueryFlagUpdateResults en QueryFlags, se notificará a la consulta si el valor de cualquiera de estas propiedades cambia para cualquier objeto del conjunto de resultados de la consulta.

El campo LocaleName del estructura de DEVPROPCOMPKEY se omite y debe establecerse en NULL.

Si cRequestedProperties es 0, debe ser NULL.

[in] cFilterExpressionCount

Número de estructuras de DEVPROP_FILTER_EXPRESSION proporcionadas en pFilter.

[in, optional] pFilter

Opcionalmente, proporciona una matriz de estructuras de DEVPROP_FILTER_EXPRESSION que especifican criterios de filtro para qué objetos deben formar parte del conjunto de resultados de la consulta. Si cFilterExpressionCount es 0, debe ser NULL.

[in] pCallback

Una función de devolución de llamada PDEV_QUERY_RESULT_CALLBACK a la que se deben enviar los resultados de esta consulta.

[in, optional] pContext

Contexto proporcionado por el autor de la llamada. Este valor se pasa a la función de devolución de llamada sin modificar.

[out] phDevQuery

Puntero que recibe el identificador que representa la consulta. Si se especifica DevQueryFlagsUpdateResults, la consulta recibirá actualizaciones hasta que se cierre el identificador. Llame a DevCloseObjectQuery para cerrar este identificador para detener la consulta.

Valor devuelto

S_OK se devuelve si una consulta se creó correctamente; de lo contrario, es un valor de error adecuado.

Observaciones

Use el de DevCreateObjectQuery para consultar datos sobre el DEV_OBJECT_TYPEespecificado. Los objetos se representan mediante un tipo de objeto, una identidad de cadena y un almacén de propiedades de pares clave-valor. Cada consulta tiene asociado un conjunto de resultados. Los objetos se agregan, actualizan o quitan del conjunto de resultados en función del estado del sistema y los cambios y se notifica a la función de devolución de llamada asociada. Cada llamada a la función de devolución de llamada representa una instantánea de los valores de propiedad en el momento en que se invoca la devolución de llamada. Solo los objetos que coinciden con los criterios expresados en el pFilter expresión se devuelven al autor de la llamada. Además de las invocaciones de devolución de llamada que actualizan el conjunto de resultados, también hay devoluciones de llamada de cambio de estado que notifican al cliente los cambios en el estado de la consulta.

De forma predeterminada, las consultas no reciben actualizaciones después de procesar el estado actual del sistema. Una vez agregados todos los objetos coincidentes al conjunto de resultados, la consulta escribe el DevQueryStateEnumCompleted estado y no se realizará ninguna devolución de llamada adicional. Cuando una consulta se registra para las actualizaciones especificando la marca de DevQueryFlagUpdateResults, su conjunto de resultados seguirá actualizándose y se notificará la devolución de llamada asociada, después de que la consulta escriba el estado DevQueryStateEnumCompleted a medida que se produzcan cambios en el sistema que agreguen o quiten objetos en función de la coincidencia de expresiones de filtro.

Se puede anular una consulta. Esto sucede cuando se produce un error interno que hace imposible comunicar una notificación al cliente. Por ejemplo, esto puede ocurrir cuando el sistema está en una condición fuera de memoria. Cuando esto sucede, el conjunto de resultados del autor de la llamada ya no refleja una representación verdadera del estado de la consulta. El autor de la llamada recibirá una devolución de llamada de DevQueryStateAborted. No se recibirán más devoluciones de llamada. El autor de la llamada debe cerrar la consulta y crear una nueva consulta para recuperarse de esta condición.

Ejemplos

En el ejemplo siguiente, el método PDEV_QUERY_RESULT_CALLBACK se implementa para imprimir mensajes de estado cuando cambia el estado de la consulta, cuando los elementos se han agregado, actualizado o quitado del resultado de la consulta. A continuación, se implementa un escenario de consulta simple en el que se llama DevCreateObjectQuery con una matriz DEVPROPCOMPKEY y un DEVPROP_FILTER_EXPRESSION para consultar objetos DevObjectTypeDevice con una propiedad DEVPKEY_Device_ClassGuid con un valor 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;
}

En el ejemplo siguiente, el parámetro pContext definido por el llamador opcional se usa para pasar un identificador de evento al método PDEV_QUERY_RESULT_CALLBACK. Cuando la devolución de llamada detecta que el estado de la consulta es DevQueryStateAborted, el evento se indica para notificar al autor de la llamada que debe eliminar la consulta existente y volver a crear una nueva consulta.

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;
}

Requisitos

Requisito Valor
cliente mínimo admitido Windows 10, versión 1809
servidor mínimo admitido Windows Server 2019
encabezado de devquery.h
biblioteca de onecore.lib
DLL de Cfgmgr32.dll

Consulte también

DevCreateObjectQueryEx