Estruturas de WNODE_XXX WMI
O WMI usa um conjunto de estruturas de dados padrão chamado WNODE_XXX para passar dados entre consumidores de dados do modo usuário e provedores de dados no modo kernel, como drivers. Se um driver manipular solicitações WMI chamando WmiSystemControl, o driver não precisará ler ou gravar estruturas WNODE_XXX . Caso contrário, o driver deve interpretar a entrada WNODE_XXX em Parameters.WMI.Buffer e/ou gravar uma saída WNODE_XXX nesse local.
A tabela a seguir lista os IRPs WMI e suas estruturas WNODE_XXX correspondentes.
WMI IRP | Estrutura de WNODE_XXX relacionada |
---|---|
Duas estruturas WNODE_XXX adicionais, WNODE_EVENT_ITEM e WNODE_EVENT_REFERENCE, são usadas para enviar notificações de eventos habilitados. Um driver que registra blocos de eventos, se um evento estiver habilitado e o evento ocorrer, enviará uma notificação do evento para o WMI chamando IoWMIWriteEvent e passando uma estrutura WNODE_EVENT_XXX . Para obter informações sobre como enviar eventos WMI, consulte Enviando eventos WMI.
Cada estrutura WNODE_XXX consiste no seguinte:
Uma estrutura de WNODE_HEADER inserida que contém informações comuns a todos os WNODE_XXX, incluindo o tamanho do buffer, o GUID que representa o bloco de dados e sinalizadores que indicam o tipo de estrutura WNODE_XXX , se ele usa nomes de instância estáticos ou dinâmicos e outras características do bloco.
Os membros fixos da estrutura WNODE_XXX específica, como deslocamentos para nomes e dados de instância.
Uma estrutura WNODE_XXX em um buffer IRP (Parameters.WMI.Buffer) normalmente é seguida por dados variáveis relacionados à solicitação, como nomes de instância dinâmica, cadeias de caracteres de nome de instância estática, entrada ou saída de um método ou dados para uma ou mais instâncias de um bloco de dados. Portanto, o tamanho do buffer deve exceder sizeof(WNODE_XXX) pela quantidade de dados variáveis envolvidos.
Observe que o WMI não executa verificação de tipo em dados variáveis fornecidos por um driver. O driver deve alinhar os dados de saída em um limite apropriado no buffer de saída para que um consumidor de dados possa analisar os dados corretamente. Em particular, cada instância deve começar em um limite de 8 bytes e cada um de seus itens deve ser alinhado em um limite natural de acordo com o esquema de bloco de dados registrado anteriormente pelo driver. Os nomes de instância dinâmica podem ser alinhados em um limite de 2 bytes.
A figura a seguir mostra um diagrama de bloco de um buffer IRP que contém uma estrutura WNODE_SINGLE_INSTANCE que um driver pode retornar em resposta a uma solicitação de IRP_MN_QUERY_SINGLE_INSTANCE .
Começando na parte superior da figura anterior:
A estrutura WNODE_HEADER no início do WNODE_SINGLE_INSTANCE está contida em um membro WnodeHeader . O WMI preenche todos os membros do WNODE_HEADER antes de enviar a solicitação. No WNODE_HEADER:
- WnodeHeader.Buffersize indica o tamanho do WNODE_SINGLE_INSTANCE, incluindo dados que seguem os membros fixos da estrutura. (O valor de WnodeHeader.Buffersize normalmente é menor que Parameters.WMI.Buffersize, o que indica o tamanho do buffer alocado pelo WMI para receber a saída do driver.)
- WnodeHeader.Guid contém o GUID que identifica o bloco de dados.
- Neste exemplo, WnodeHeader.Flags indica que essa estrutura é uma WNODE_SINGLE_INSTANCE e que o bloco de dados usa nomes de instância estáticos.
Como o bloco de dados usa nomes de instância estática, o WMI define InstanceIndex como o índice da instância na lista de nomes de instância estáticos passados pelo driver quando ele registrou o bloco. OffsetInstanceNames não é usado.
O WMI define DataBlockOffset para indicar o deslocamento do início do buffer para o primeiro byte de dados de instância. (O driver não deve alterar esse valor) Novamente, como o bloco de dados usa nomes de instância estática, esse deslocamento indica o mesmo local que VariableData. Se o bloco de dados usasse nomes de instância dinâmica, os nomes de instância começariam em VariableData e DataBlockOffset especificaria um deslocamento maior para o buffer.
O driver define SizeDataBlock como o número de bytes de dados de instância que estão sendo retornados.
Em VariableData (após dados de nome de instância, se houver), o driver grava dados de instância para a instância solicitada no buffer de saída.
Um driver lê e grava estruturas WNODE_METHOD_ITEM e WNODE_SINGLE_ITEM da mesma maneira que WNODE_SINGLE_INSTANCE. Essas estruturas se assemelham umas às outras, pois cada uma tem os membros fixos OffsetInstanceName, InstanceIndex, DataBlockOffset, SizeDataBlock (ou, no caso de WNODE_SINGLE_ITEM, SizeDataItem) e VariableData. WNODE_METHOD_ITEM inclui um MethodId e WNODE_SINGLE_ITEM inclui um ItemId que WNODE_SINGLE_INSTANCE não tem.
WNODE_ALL_DATA difere das estruturas anteriores, pois ela é usada para passar várias instâncias de um bloco de dados, possivelmente incluindo nomes de instância dinâmica e possivelmente de tamanhos diferentes.
A figura a seguir mostra um diagrama de bloco de um buffer IRP que contém um WNODE_ALL_DATA que um driver pode retornar em resposta a uma solicitação de IRP_MN_QUERY_ALL_DATA .
Começando na parte superior da figura anterior:
Conforme descrito na figura anterior, a estrutura WNODE_HEADER no início do WNODE_ALL_DATA está contida em um membro WnodeHeader . WnodeHeader.Buffersize e WnodeHeader.Guid indicam o tamanho do WNODE_ALL_DATA e o GUID do bloco de dados, respectivamente.
Neste exemplo, o WMI define WnodeHeader.Flags para indicar que essa estrutura é uma WNODE_ALL_DATA e que o bloco de dados foi registrado com nomes de instância dinâmica (ou seja, o WMI limpa WNODE_FLAG_STATIC_INSTANCE_NAMES e WNODE_FLAG_PDO_INSTANCE_NAMES). Na saída, o driver define WNODE_FLAG_FIXED_INSTANCE_SIZE para indicar que todas as instâncias têm o mesmo tamanho.
O WMI define DataBlockOffset para indicar o deslocamento do início do buffer para o primeiro byte de dados de instância. (O driver não deve alterar esse valor). Neste exemplo, os dados de instância seguem os nomes de instância em OffsetInstanceNameOffsets.
O driver define InstanceCount para indicar o número de instâncias que estão sendo retornadas.
WNODE_XXX para blocos de dados que usam nomes de instância dinâmica sempre contêm as cadeias de caracteres de nome da instância. Como este exemplo usa nomes de instância dinâmica, OffsetInstanceNameOffsets indica o deslocamento do início do buffer para uma matriz de deslocamentos para nomes de instância dinâmica no buffer.
FixedInstanceSize indica o número de bytes de dados em cada instância que está sendo retornada pelo driver. Se as instâncias desse bloco de dados variassem de tamanho, o driver limparia WNODE_FLAG_FIXED_INSTANCE_SIZE em WnodeHeader.Flags e definiria OffsetInstanceDataAndLength como uma matriz de estruturas OFFSETINSTANCEDATAANDLENGTH , cada uma especificando um deslocamento para os dados de uma instância e o número de bytes nessa instância em vez de definir FixedInstanceSize.
Para obter mais informações sobre estruturas WNODE_XXX , consulte Estruturas do sistema.