Функция DevCreateObjectQuery (devquery.h)
Создает запрос устройства для получения свойств на основе указанных параметров запроса.
Синтаксис
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
);
Параметры
[in] ObjectType
Значение из перечисления DEV_OBJECT_TYPE, определяющего тип объекта, на который должен работать этот запрос.
[in] QueryFlags
Сочетание значений DEV_QUERY_FLAGS, объединенных с помощью побитовой операции OR.
[in] cRequestedProperties
Количество структур DEVPROPCOMPKEY, предоставляемых в pRequestedProperties. Если указан DevQueryFlagAllProperties, это значение должно иметь значение 0.
[in] pRequestedProperties
При необходимости предоставляет массив
Если devQueryFlagUpdateResults был указан в QueryFlags, запрос будет уведомлен, если значение любого из этих свойств изменяется для любого объекта в результирующем наборе запроса.
Поле LocaleName структуры DEVPROPCOMPKEY игнорируется и должно иметь значение NULL.
Если cRequestedProperties равно 0, это значение должно иметь значение NULL.
[in] cFilterExpressionCount
Количество структур DEVPROP_FILTER_EXPRESSION, предоставляемых в pFilter.
[in, optional] pFilter
При необходимости предоставляет массив структур DEVPROP_FILTER_EXPRESSION, определяющих критерии фильтрации для объектов, которые должны быть частью результирующий набор запроса. Если cFilterExpressionCount равно 0, это значение должно иметь значение NULL.
[in] pCallback
Функция обратного вызова PDEV_QUERY_RESULT_CALLBACK, в которую должны быть отправлены результаты этого запроса.
[in, optional] pContext
Контекст, предоставленный вызывающей компанией. Это значение передается функции обратного вызова, не измененной.
[out] phDevQuery
Указатель, который получает дескриптор, представляющий запрос. Если DevQueryFlagsUpdateResults, запрос получит обновления до закрытия дескриптора. Вызовите DevCloseObjectQuery, чтобы закрыть этот дескриптор, чтобы остановить запрос.
Возвращаемое значение
S_OK возвращается, если запрос был успешно создан; в противном случае соответствующее значение ошибки.
Замечания
Используйте DevCreateObjectQuery для запроса данных о указанном DEV_OBJECT_TYPE. Объекты представлены типом объекта, строковым удостоверением и хранилищем свойств пар "ключ - значение". Каждый запрос имеет результирующий набор, связанный с ним. Объекты добавляются, обновляются или удаляются из результирующей группы на основе состояния системы и изменений, а связанная функция обратного вызова уведомляется. Каждый вызов функции обратного вызова представляет моментальный снимок значений свойств во время вызова обратного вызова. В вызывающий объект возвращаются только объекты, соответствующие условиям, выраженным в выражении
По умолчанию запросы не получают обновления после обработки текущего состояния системы. После добавления всех соответствующих объектов в результирующий набор запрос вводит состояние DevQueryStateEnumCompleted и никаких дополнительных обратных вызовов. Если запрос регистрирует обновления, указав флаг DevQueryFlagUpdateResults, его результирующий набор будет обновляться, а связанный обратный вызов уведомляется после ввода запроса состояния DevQueryStateEnumCompleted, так как изменения в системе будут добавлять или удалять объекты на основе сопоставления выражений фильтра.
Запрос может быть прерван. Это происходит, когда возникает внутренняя ошибка, что делает невозможной связь уведомления с клиентом. Например, это может произойти, когда система находится в состоянии вне памяти. В этом случае результирующий набор вызывающего объекта больше не отражает истинное представление состояния запроса. Вызывающий объект получит обратный вызов DevQueryStateAborted. Дальнейшие обратные вызовы не будут получены. Вызывающий объект должен закрыть запрос и создать новый запрос, чтобы восстановить это условие.
Примеры
В следующем примере метод PDEV_QUERY_RESULT_CALLBACK реализуется для вывода сообщений о состоянии запроса при изменении состояния запроса, когда элементы были добавлены, обновлены или удалены из результата запроса. Далее реализуется простой сценарий запроса, в котором вызывается DevCreateObjectQuery с массивом DEVPROPCOMPKEY и DEVPROP_FILTER_EXPRESSION для запроса объектов DevObjectTypeDev ice со свойством DEVPKEY_Device_ClassGuid со значением 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;
}
В следующем примере необязательный параметр pContext используется для передачи дескриптора событий в метод PDEV_QUERY_RESULT_CALLBACK. Когда обратный вызов обнаруживает, что состояние запроса DevQueryStateAborted, событие сообщает вызывающему объекту о том, что он должен удалить существующий запрос и повторно создать новый запрос.
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;
}
Требования
Требование | Ценность |
---|---|
минимальные поддерживаемые клиентские | Windows 10 версии 1809 |
минимальный поддерживаемый сервер | Windows Server 2019 |
заголовка | devquery.h |
библиотеки |
onecore.lib |
DLL | Cfgmgr32.dll |