Структуры WNODE_XXX WMI

WMI использует набор стандартных структур данных, называемых WNODE_XXX для передачи данных между потребителями данных в пользовательском режиме и поставщиками данных в режиме ядра, такими как драйверы. Если драйвер обрабатывает запросы WMI путем вызова WmiSystemControl, драйвер не требуется для чтения или записи WNODE_структур XXX. В противном случае драйвер должен интерпретировать входные WNODE_XXX в Parameters.WMI.Buffer и /или записать выходные данные WNODE_XXX в это расположение.

В следующей таблице перечислены IP-адреса WMI и соответствующие структуры WNODE_XXX.

WMI IRP Связанная структура WNODE_XXX

IRP_MN_CHANGE_SINGLE_INSTANCE

WNODE_SINGLE_INSTANCE

IRP_MN_CHANGE_SINGLE_ITEM

WNODE_SINGLE_ITEM

IRP_MN_EXECUTE_METHOD

WNODE_METHOD_ITEM

IRP_MN_QUERY_ALL_DATA

WNODE_ALL_DATA

IRP_MN_QUERY_SINGLE_INSTANCE

WNODE_SINGLE_INSTANCE

Для отправки уведомлений о включенных событиях используются две дополнительные структуры WNODE_XXX, WNODE_EVENT_ITEM и WNODE_EVENT_REFERENCE. Драйвер, который регистрирует блоки событий, если событие включено и происходит событие, отправьте уведомление о событии в WMI путем вызова IoWMIWriteEvent и передачи структуры WNODE_EVENT_XXX. Сведения о отправке событий WMI см. в отправке событий WMI.

Каждая структура WNODE_XXX состоит из следующих элементов:

  • Внедренная WNODE_HEADER структура, содержащая сведения, общие для всех WNODE_XXX включая размер буфера, GUID, представляющий блок данных, и флаги, указывающие тип структуры WNODE_XXX, будь то статические или динамические имена экземпляров, и другие характеристики блока.

  • Фиксированные члены конкретной структуры WNODE_XXX, такие как смещение имен экземпляров и данных.

Структура WNODE_XXX в буфере IRP (Parameters.WMI.Buffer) обычно следует переменным данным, связанным с запросом, например динамическими именами экземпляров, строками статических имен экземпляров, входными данными метода или выходными данными для одного или нескольких экземпляров блока данных. Таким образом, размер буфера должен превышать sizeof(WNODE_XXX) объемом данных переменной.

Обратите внимание, что WMI не выполняет проверку типов для данных переменных, предоставленных драйвером. Драйвер должен выровнять выходные данные на соответствующей границе в выходном буфере, чтобы потребитель данных смог правильно проанализировать данные. В частности, каждый экземпляр должен начинаться с 8-байтовой границы, и каждый из его элементов должен быть выровнен по естественной границе в соответствии с схемой блока данных, ранее зарегистрированной драйвером. Динамические имена экземпляров можно выровнять по 2-байтовой границе.

На следующем рисунке показана блок-схема буфера IRP, содержащего структуру WNODE_SINGLE_INSTANCE, которую драйвер может вернуть в ответ на запрос IRP_MN_QUERY_SINGLE_INSTANCE.

диаграмме, иллюстрирующая буфер irp, содержащий wnode-single-instance.

Начиная с верхней части предыдущего рисунка:

  • Структура WNODE_HEADER в начале WNODE_SINGLE_INSTANCE содержится в элементе WnodeHeader. WMI заполняет все элементы WNODE_HEADER перед отправкой запроса. В WNODE_HEADER:

    • WnodeHeader.Buffersize указывает размер WNODE_SINGLE_INSTANCE, включая данные, следующие за фиксированными элементами структуры. (Значение WnodeHeader.Buffersize обычно меньше Parameters.WMI.Buffersize, что указывает размер буфера, выделенного WMI для получения выходных данных от драйвера.)
    • WnodeHeader.Guid содержит GUID, определяющий блок данных.
    • В этом примере WnodeHeader.Flags указывает, что эта структура является WNODE_SINGLE_INSTANCE и что блок данных использует статические имена экземпляров.
  • Так как блок данных использует статические имена экземпляров, WMI задает InstanceIndex индекс экземпляра в списке статических имен экземпляров, передаваемых драйвером при регистрации блока. OffsetInstanceNames не используется.

  • WMI задает DataBlockOffset, чтобы указать смещение с начала буфера до первого байта данных экземпляра. (Драйвер не должен изменять это значение) Опять же, так как блок данных использует статические имена экземпляров, это смещение указывает то же расположение, что и VariableData. Если блок данных использовал динамические имена экземпляров, имена экземпляров начинаются с VariableData и DataBlockOffset указать большее смещение в буфер.

  • Драйвер задает SizeDataBlock количество байт возвращаемых данных экземпляра.

  • В VariableData (после данных имени экземпляра, если он присутствует), драйвер записывает данные экземпляра для запрошенного экземпляра в выходном буфере.

Драйвер считывает и записывает структуры WNODE_METHOD_ITEM и WNODE_SINGLE_ITEM точно так же, как и WNODE_SINGLE_INSTANCE. Эти структуры похожи друг на друга, что у каждого есть фиксированные члены OffsetInstanceName, InstanceIndex, DataBlockOffset, SizeDataBlock (или, в случае WNODE_SINGLE_ITEM, SizeDataItem) и VariableData. WNODE_METHOD_ITEM включает MethodId и WNODE_SINGLE_ITEM включает ItemId, которые WNODE_SINGLE_INSTANCE отсутствуют.

WNODE_ALL_DATA отличается от предыдущих структур, которые используются для передачи нескольких экземпляров блока данных, в том числе динамических имен экземпляров и, возможно, различных размеров.

На следующем рисунке показана блок-схема буфера IRP, содержащего WNODE_ALL_DATA, что драйвер может вернуться в ответ на запрос IRP_MN_QUERY_ALL_DATA.

диаграмме, иллюстрирующая буфер irp, содержащий wnode-all-data.

Начиная с верхней части предыдущего рисунка:

  • Как описано на предыдущем рисунке, структура WNODE_HEADER в начале WNODE_ALL_DATA содержится в элементе WnodeHeader. WnodeHeader.Buffersize и WnodeHeader.Guid указывают размер WNODE_ALL_DATA и GUID блока данных соответственно.

    В этом примере WMI задает WnodeHeader.Flags, чтобы указать, что эта структура является WNODE_ALL_DATA и что блок данных был зарегистрирован с динамическими именами экземпляров (то есть WMI очищает WNODE_FLAG_STATIC_INSTANCE_NAMES и WNODE_FLAG_PDO_INSTANCE_NAMES). В выходных данных драйвер задает WNODE_FLAG_FIXED_INSTANCE_SIZE, чтобы указать, что все экземпляры одинаковы.

  • WMI задает DataBlockOffset, чтобы указать смещение с начала буфера до первого байта данных экземпляра. (Драйвер не должен изменять это значение). В этом примере данные экземпляра следует именам экземпляров OffsetInstanceNameOffsets.

  • Драйвер задает InstanceCount, чтобы указать количество возвращаемых экземпляров.

  • WNODE_XXX для блоков данных, использующих динамические имена экземпляров, всегда содержат строки имен экземпляров. Так как в этом примере используются имена динамических экземпляров, OffsetInstanceNameOffsets указывает смещение от начала буфера к массиву смещения к именам динамических экземпляров в буфере.

  • FixedInstanceSize указывает количество байтов данных в каждом экземпляре, возвращаемом драйвером. Если экземпляры этого блока данных зависят от размера, Драйвер очищает WNODE_FLAG_FIXED_INSTANCE_SIZE в WnodeHeader.Flags и задает OffsetInstanceDataAndLength массиву структур OFFSETINSTANCEDATAANDLENGTH, каждый из которых указывает смещение к данным для одного экземпляра и количество байтов в этом экземпляре вместо установки FixedInstanceSize.

Дополнительные сведения о структурах WNODE_XXX см. в системных структур.