Estructuras de WNODE_XXX WMI

WMI usa un conjunto de estructuras de datos estándar denominadas WNODE_XXX para pasar datos entre consumidores de datos en modo de usuario y proveedores de datos en modo kernel, como controladores. Si un controlador controla las solicitudes WMI llamando a WmiSystemControl, el controlador no es necesario para leer ni escribir estructuras WNODE_XXX . De lo contrario, el controlador debe interpretar el WNODE_XXX de entrada en Parameters.WMI.Buffer o escribir una salida WNODE_XXX en esa ubicación.

En la tabla siguiente se enumeran los IRP de WMI y sus estructuras WNODE_XXX correspondientes.

WMI IRP Estructura de WNODE_XXX relacionada

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

Se usan dos estructuras WNODE_XXX adicionales, WNODE_EVENT_ITEM y WNODE_EVENT_REFERENCE, para enviar notificaciones de eventos habilitados. Un controlador que registra bloques de eventos lo hará, si un evento está habilitado y se produce el evento, envíe una notificación del evento a WMI llamando a IoWMIWriteEvent y pasando una estructura WNODE_EVENT_XXX . Para obtener información sobre cómo enviar eventos WMI, vea Envío de eventos WMI.

Cada estructura WNODE_XXX consta de lo siguiente:

  • Estructura de WNODE_HEADER incrustada que contiene información común a todos los WNODE_XXX , incluido el tamaño del búfer, el GUID que representa el bloque de datos y las marcas que indican el tipo de estructura WNODE_XXX , ya sea que use nombres de instancia estáticos o dinámicos y otras características del bloque.

  • Miembros fijos de la estructura WNODE_XXX determinada, como desplazamientos a los nombres y datos de instancia.

Una estructura WNODE_XXX en un búfer IRP (Parameters.WMI.Buffer) suele ir seguida de datos de variables relacionados con la solicitud, como nombres de instancia dinámicos, cadenas de nombre de instancia estáticas, entradas o salidas de un método, o datos para una o varias instancias de un bloque de datos. Por lo tanto, el tamaño del búfer debe superar sizeof(WNODE_XXX) por la cantidad de datos variables implicados.

Tenga en cuenta que WMI no realiza la comprobación de tipos en los datos de variables proporcionados por un controlador. El controlador debe alinear los datos de salida en un límite adecuado en el búfer de salida para que un consumidor de datos pueda analizar los datos correctamente. En concreto, cada instancia debe iniciarse en un límite de 8 bytes y cada uno de sus elementos debe alinearse en un límite natural según el esquema de bloque de datos registrado previamente por el controlador. Los nombres de instancia dinámicos se pueden alinear en un límite de 2 bytes.

En la ilustración siguiente se muestra un diagrama de bloques de un búfer IRP que contiene una estructura de WNODE_SINGLE_INSTANCE que un controlador podría devolver en respuesta a una solicitud de IRP_MN_QUERY_SINGLE_INSTANCE .

diagrama que ilustra un búfer irp que contiene una instancia única de wnode.

A partir de la parte superior de la ilustración anterior:

  • La estructura WNODE_HEADER al principio del WNODE_SINGLE_INSTANCE se encuentra en un miembro WnodeHeader . WMI rellena todos los miembros del WNODE_HEADER antes de enviar la solicitud. En el WNODE_HEADER:

    • WnodeHeader.Buffersize indica el tamaño del WNODE_SINGLE_INSTANCE, incluidos los datos que siguen a los miembros fijos de la estructura. (El valor de WnodeHeader.Buffersize suele ser menor que Parameters.WMI.Buffersize, que indica el tamaño del búfer asignado por WMI para recibir la salida del controlador).
    • WnodeHeader.Guid contiene el GUID que identifica el bloque de datos.
    • En este ejemplo, WnodeHeader.Flags indica que esta estructura es un WNODE_SINGLE_INSTANCE y que el bloque de datos usa nombres de instancia estáticos.
  • Dado que el bloque de datos usa nombres de instancia estáticos, WMI establece InstanceIndex en el índice de la instancia en la lista de nombres de instancia estáticos pasados por el controlador cuando registró el bloque. OffsetInstanceNames no se usa.

  • WMI establece DataBlockOffset para indicar el desplazamiento desde el principio del búfer hasta el primer byte de los datos de instancia. (El controlador no debe cambiar este valor) De nuevo porque el bloque de datos usa nombres de instancia estáticos, este desplazamiento indica la misma ubicación que VariableData. Si el bloque de datos usaba nombres de instancia dinámicos, los nombres de instancia se iniciarían en VariableData y DataBlockOffset especificarían un desplazamiento mayor en el búfer.

  • El controlador establece SizeDataBlock en el número de bytes de datos de instancia que se devuelven.

  • En VariableData (después de los datos de nombre de instancia, si están presentes), el controlador escribe los datos de instancia para la instancia solicitada en el búfer de salida.

Un controlador lee y escribe WNODE_METHOD_ITEM y WNODE_SINGLE_ITEM estructuras de la misma manera que WNODE_SINGLE_INSTANCE. Estas estructuras se parecen entre sí en que cada una tiene los miembros fijos OffsetInstanceName, InstanceIndex, DataBlockOffset, SizeDataBlock (o, en el caso de WNODE_SINGLE_ITEM, SizeDataItem) y VariableData. WNODE_METHOD_ITEM incluye methodId y WNODE_SINGLE_ITEM incluye un itemId que WNODE_SINGLE_INSTANCE carece.

WNODE_ALL_DATA difiere de las estructuras anteriores en que se usa para pasar varias instancias de un bloque de datos, posiblemente incluyendo nombres de instancia dinámicos y posiblemente de diferentes tamaños.

En la ilustración siguiente se muestra un diagrama de bloques de un búfer IRP que contiene un WNODE_ALL_DATA que un controlador podría devolver en respuesta a una solicitud de IRP_MN_QUERY_ALL_DATA .

diagrama que ilustra un búfer irp que contiene datos wnode-all-data.

A partir de la parte superior de la ilustración anterior:

  • Como se describe en la ilustración anterior, la estructura WNODE_HEADER al principio del WNODE_ALL_DATA se encuentra en un miembro WnodeHeader . WnodeHeader.Buffersize y WnodeHeader.Guid indican el tamaño del WNODE_ALL_DATA y el GUID del bloque de datos, respectivamente.

    En este ejemplo, WMI establece WnodeHeader.Flags para indicar que esta estructura es una WNODE_ALL_DATA y que el bloque de datos se registró con nombres de instancia dinámicos (es decir, WMI borra WNODE_FLAG_STATIC_INSTANCE_NAMES y WNODE_FLAG_PDO_INSTANCE_NAMES). En la salida, el controlador establece WNODE_FLAG_FIXED_INSTANCE_SIZE para indicar que todas las instancias tienen el mismo tamaño.

  • WMI establece DataBlockOffset para indicar el desplazamiento desde el principio del búfer hasta el primer byte de los datos de instancia. (El controlador no debe cambiar este valor). En este ejemplo, los datos de instancia siguen los nombres de instancia en OffsetInstanceNameOffsets.

  • El controlador establece InstanceCount para indicar el número de instancias devueltas.

  • WNODE_XXX para bloques de datos que usan nombres de instancia dinámicos siempre contienen las cadenas de nombre de instancia. Dado que en este ejemplo se usan nombres de instancia dinámicos, OffsetInstanceNameOffsets indica el desplazamiento desde el principio del búfer a una matriz de desplazamientos a nombres de instancia dinámicos en el búfer.

  • FixedInstanceSize indica el número de bytes de datos en cada instancia devuelta por el controlador. Si las instancias de este bloque de datos tenían que variar en tamaño, el controlador borraría WNODE_FLAG_FIXED_INSTANCE_SIZE en WnodeHeader.Flags y establecer OffsetInstanceDataAndLength en una matriz de estructuras OFFSETINSTANCEDATAANDLENGTH , cada una especificando un desplazamiento a los datos de una instancia y el número de bytes en esa instancia en lugar de establecer FixedInstanceSize.

Para obtener más información sobre las estructuras WNODE_XXX , vea Estructuras del sistema.