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
使用位 OR 運算結合 DEV_QUERY_FLAGS 值的組合。
[in] cRequestedProperties
pRequestedProperties中提供的 DEVPROPCOMPKEY 結構數目。 如果指定 DevQueryFlagAllProperties,則必須將此值設定為 0。
[in] pRequestedProperties
選擇性地提供
如果在 QueryFlags中指定了 DevQueryFlagUpdateResults,則查詢會在查詢結果集中的任何物件有任何這些屬性的值變更時收到通知。
DEVPROPCOMPKEY 結構的 LocaleName 字段會被忽略,而且必須設定為 NULL。
如果 cRequestedProperties 為 0,這必須是 NULL。
[in] cFilterExpressionCount
pFilter中提供的 DEVPROP_FILTER_EXPRESSION 結構數目。
[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的相關數據。 物件是以物件類型、字串識別和索引鍵/值組的屬性存放區表示。 每個查詢都有與其相關聯的結果集。 系統會根據系統狀態和變更,從結果集新增、更新或移除物件,並通知相關聯的回呼函式。 每次呼叫回呼函式時,都代表叫用回呼時屬性值的快照集。 只有符合 pFilter 表示式中所表示準則的物件會傳回給呼叫端。 除了更新結果集的回呼調用之外,還有狀態變更回呼會通知用戶端對查詢狀態所做的變更。
根據預設,查詢不會在處理系統的目前狀態之後收到更新。 將所有相符的物件新增至結果集之後,查詢就會進入 DevQueryStateEnumCompleted 狀態,而且不會再進行任何回呼。 當查詢藉由指定 DevQueryFlagUpdateResults 旗標來註冊更新時,其結果集將會繼續更新,並在查詢輸入 DevQueryStateEnumCompleted 狀態,因為系統發生根據篩選表達式比對新增或移除對象的變更。
查詢可能會中止。 當發生內部錯誤,使得無法將通知傳達給用戶端時,就會發生這種情況。 例如,當系統處於記憶體不足狀況時,就會發生這種情況。 發生這種情況時,呼叫端的結果集不再反映查詢狀態的真實表示法。 呼叫端會收到 DevQueryStateAborted 回呼。 將不會收到任何進一步的回呼。 呼叫端必須關閉查詢,並建立新的查詢,才能從這個條件中復原。
例子
在下列範例中,會實作 PDEV_QUERY_RESULT_CALLBACK 方法,以在查詢狀態變更、專案已加入、更新或從查詢結果中移除時列印出狀態消息。 接下來,會實作簡單的查詢案例,其中會使用 DEVPROPCOMPKEY 陣列呼叫 DevCreateObjectQuery,以及 DEVPROP_FILTER_EXPRESSION 來查詢具有 GUID_DEVCLASS_NET值的 DEVPKEY_Device_ClassGuidDevObjectTypeDevice 物件。
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 |