Поделиться через


Структуры WNODE_XXX WMI

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

В следующей таблице перечислены WMI IRP и соответствующие им структуры 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.

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

  • Структура 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 включает Идентификатор метода, а 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 см. в разделе Системные структуры.