WMI WNODE_XXX Structures

WMI uses a set of standard data structures called WNODE_XXX to pass data between user-mode data consumers and kernel-mode data providers such as drivers. If a driver handles WMI requests by calling WmiSystemControl, the driver is not required to read or write WNODE_XXX structures. Otherwise, the driver must interpret the input WNODE_XXX at Parameters.WMI.Buffer and/or write an output WNODE_XXX to that location.

The following table lists WMI IRPs and their corresponding WNODE_XXX structures.

WMI IRP Related WNODE_XXX Structure

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

Two additional WNODE_XXX structures, WNODE_EVENT_ITEM and WNODE_EVENT_REFERENCE, are used to send notifications of enabled events. A driver that registers event blocks will, if an event is enabled and the event occurs, send notification of the event to WMI by calling IoWMIWriteEvent and passing a WNODE_EVENT_XXX structure. For information about sending WMI events, see Sending WMI Events.

Each WNODE_XXX structure consists of the following:

  • An embedded WNODE_HEADER structure that contains information common to all WNODE_XXX including the size of the buffer, the GUID that represents the data block, and flags that indicate the type of WNODE_XXX structure, whether it uses static or dynamic instance names, and other characteristics of the block.

  • The fixed members of the particular WNODE_XXX structure, such as offsets to instance names and data.

A WNODE_XXX structure in an IRP buffer (Parameters.WMI.Buffer) is typically followed by variable data related to the request, such as dynamic instance names, static instance name strings, input for or output from a method, or data for one or more instances of a data block. The size of the buffer must therefore exceed sizeof(WNODE_XXX) by the amount of variable data involved.

Note that WMI does not perform type-checking on variable data supplied by a driver. The driver must align output data on an appropriate boundary in the output buffer so that a data consumer can parse the data correctly. In particular, each instance must start on an 8-byte boundary and each of its items must be aligned on a natural boundary according to the data block schema previously registered by the driver. Dynamic instance names can be aligned on a 2-byte boundary.

The following figure shows a block diagram of an IRP buffer containing a WNODE_SINGLE_INSTANCE structure that a driver might return in response to an IRP_MN_QUERY_SINGLE_INSTANCE request.

diagram illustrating an irp buffer containing a wnode-single-instance.

Starting at the top of the previous figure:

  • The WNODE_HEADER structure at the beginning of the WNODE_SINGLE_INSTANCE is contained in a WnodeHeader member. WMI fills in all members of the WNODE_HEADER before sending the request. In the WNODE_HEADER:

    • WnodeHeader.Buffersize indicates the size of the WNODE_SINGLE_INSTANCE, including data that follows the fixed members of the structure. (The value of WnodeHeader.Buffersize is typically less than Parameters.WMI.Buffersize, which indicates the size of the buffer allocated by WMI to receive output from the driver.)
    • WnodeHeader.Guid contains the GUID that identifies the data block.
    • In this example, WnodeHeader.Flags indicates that this structure is a WNODE_SINGLE_INSTANCE and that the data block uses static instance names.
  • Because the data block uses static instance names, WMI sets InstanceIndex to the index of the instance in the list of static instance names passed by the driver when it registered the block. OffsetInstanceNames is not used.

  • WMI sets DataBlockOffset to indicate the offset from the beginning of the buffer to the first byte of instance data. (The driver must not change this value) Again because the data block uses static instance names, this offset indicates the same location as VariableData. If the data block used dynamic instance names, the instance names would start at VariableData and DataBlockOffset would specify a greater offset into the buffer.

  • The driver sets SizeDataBlock to the number of bytes of instance data being returned.

  • At VariableData (after instance name data, if present), the driver writes instance data for the requested instance in the output buffer.

A driver reads and writes WNODE_METHOD_ITEM and WNODE_SINGLE_ITEM structures in much the same way as WNODE_SINGLE_INSTANCE. These structures resemble each other in that each has the fixed members OffsetInstanceName, InstanceIndex, DataBlockOffset, SizeDataBlock (or, in the case of WNODE_SINGLE_ITEM, SizeDataItem) and VariableData. WNODE_METHOD_ITEM includes a MethodId and WNODE_SINGLE_ITEM includes an ItemId which WNODE_SINGLE_INSTANCE lacks.

WNODE_ALL_DATA differs from the preceding structures in that it is used to pass multiple instances of a data block, possibly including dynamic instance names and possibly of different sizes.

The following figure shows a block diagram of an IRP buffer containing a WNODE_ALL_DATA that a driver might return in response to an IRP_MN_QUERY_ALL_DATA request.

diagram illustrating an irp buffer containing a wnode-all-data.

Starting at the top of the previous figure:

  • As described in the previous figure, the WNODE_HEADER structure at the beginning of the WNODE_ALL_DATA is contained in a WnodeHeader member. WnodeHeader.Buffersize and WnodeHeader.Guid indicate the size of the WNODE_ALL_DATA and the GUID of the data block, respectively.

    In this example, WMI sets WnodeHeader.Flags to indicate that this structure is a WNODE_ALL_DATA and that the data block was registered with dynamic instance names (that is, WMI clears WNODE_FLAG_STATIC_INSTANCE_NAMES and WNODE_FLAG_PDO_INSTANCE_NAMES). On output, the driver sets WNODE_FLAG_FIXED_INSTANCE_SIZE to indicate that all of the instances are the same size.

  • WMI sets DataBlockOffset to indicate the offset from the beginning of the buffer to the first byte of instance data. (The driver must not change this value). In this example, instance data follows the instance names at OffsetInstanceNameOffsets.

  • The driver sets InstanceCount to indicate the number of instances being returned.

  • WNODE_XXX for data blocks that use dynamic instance names always contain the instance name strings. Because this example uses dynamic instance names, OffsetInstanceNameOffsets indicates the offset from the beginning of the buffer to an array of offsets to dynamic instance names in the buffer.

  • FixedInstanceSize indicates the number of bytes of data in each instance being returned by the driver. If instances of this data block were to vary in size, the driver would clear WNODE_FLAG_FIXED_INSTANCE_SIZE in WnodeHeader.Flags and set OffsetInstanceDataAndLength to an array of OFFSETINSTANCEDATAANDLENGTH structures, each specifying an offset to the data for one instance and the number of bytes in that instance instead of setting FixedInstanceSize.

For more information about WNODE_XXX structures, see System Structures.