PCW_CALLBACK função de retorno de chamada (wdm.h)

Opcionalmente, os provedores podem implementar uma PCW_CALLBACK função para receber notificações quando os consumidores fizerem solicitações, como enumerar instâncias ou coletar dados de contraconjunto. A Biblioteca de Contadores de Desempenho (PERFLIB versão 2.0) chama a PCW_CALLBACK função antes de concluir a solicitação do consumidor.

Sintaxe

PCW_CALLBACK PcwCallback;

NTSTATUS PcwCallback(
  [in]           PCW_CALLBACK_TYPE Type,
  [in]           PPCW_CALLBACK_INFORMATION Info,
  [in, optional] PVOID Context
)
{...}

Parâmetros

[in] Type

Um valor de enumeração PCW_CALLBACK_TYPE indicando por que o retorno de chamada foi invocado. Os valores possíveis são PcwCallbackAddCounter, PcwCallbackRemoveCounter, PcwCallbackEnumerateInstances e PcwCallbackCollectData.

[in] Info

Um ponteiro para um sindicato PCW_CALLBACK_INFORMATION que fornece detalhes sobre por que o retorno de chamada do provedor foi invocado. Os detalhes estarão no campo correspondente ao Type parâmetro. Por exemplo, se Type == PcwCallbackEnumerateInstances os detalhes estiverem em Info->EnumerateInstances.

[in, optional] Context

O contexto de retorno de chamada fornecido pelo provedor ao chamar PcwRegister ou ao chamar a função Registro gerado por CTRPP (que invoca PcwRegister).

Valor retornado

A PCW_CALLBACK função de retorno de chamada deverá retornar STATUS_SUCCESS se o retorno de chamada for concluído sem erros ou um NTSTATUS código de erro, caso contrário. Observe que esse código de retorno é apenas para fins informativos e que o processamento da solicitação do consumidor continuará mesmo se o retorno de chamada retornar um erro.

Comentários

Os provedores de contraconjunto podem fornecer informações ao consumidor por meio de dois sistemas diferentes:

  • O provedor pode usar PcwCreateInstance e PcwCloseInstance manter uma lista de instâncias disponíveis e os dados de contador correspondentes. Esse sistema é simples de implementar, mas limitado em flexibilidade. Ao usar esse sistema, o provedor não precisa fornecer uma função de retorno de chamada. Para obter mais informações sobre esse sistema, consulte a documentação de PcwCreateInstance.
  • O provedor pode fornecer uma PCW_CALLBACK função que será invocada pela Biblioteca de Contadores de Desempenho conforme necessário para coletar dados.

A implementação de retorno de chamada deve ser thread-safe. Vários consumidores diferentes podem solicitar dados simultaneamente do provedor em threads diferentes.

O retorno de chamada deve lidar com os PcwCallbackEnumerateInstances tipos e PcwCallbackCollectData solicitações. O retorno de chamada geralmente não precisa lidar com outros tipos de solicitação, mas em cenários complexos o retorno de chamada também pode manipular PcwCallbackAddCounter e PcwCallbackRemoveCounter otimizar a coleta de dados (ou seja, desabilitar o controle de estatísticas quando nenhuma consulta estiver ativa).

O retorno de chamada é responsável por gerar Name e Id valores para as instâncias de contraconjunto.

  • Os valores de instância Id DEVEM ser estáveis ao longo do tempo (a mesma instância lógica deve usar o mesmo Id valor para todas as invocações do retorno de chamada), deve ser exclusivo (por exemplo, não basta usar 0 para todas as instâncias) e deve ser menor que 0xFFFFFFFE (não usar PCW_ANY_INSTANCE_ID). Quando possível, a instância Id deve ser significativa (por exemplo, um contador de processo pode usar um PID como o Id) em vez de arbitrário (por exemplo, um número de sequência).
  • Os valores de instância Name DEVEM ser estáveis ao longo do tempo (a mesma instância lógica deve usar o mesmo Name valor para todas as invocações do retorno de chamada) e DEVE ser exclusiva. Se o contador der suporte a várias instâncias, a instância Name não deverá ficar em branco. A correspondência de cadeia de caracteres é feita usando uma comparação que não diferencia maiúsculas de minúsculas, portanto Name , os valores não devem ser diferentes apenas por caso.

Ao lidar com PcwCallbackCollectData solicitações, uma implementação de retorno de chamada básica simplesmente invocará PcwAddInstance (ou a função AddXxx gerada por CTRPP) uma vez para cada instância de contraconjunto. Para obter mais informações, consulte a função AddXxx gerada por CTRPP.

As seguintes otimizações podem ser usadas em implementações mais avançadas quando necessário:

  • Se Info->CollectData.CounterMask != (UINT64)-1 o consumidor não precisar de todos os contadores no contador. Nesse caso, o retorno de chamada pode otimizar a coleta de dados deixando os valores correspondentes como 0 no bloco de dados do contador.
  • Se Info->CollectData.InstanceId != PCW_ANY_INSTANCE_ID o consumidor quiser apenas dados sobre instâncias com igual InstanceId a CollectData.InstanceId. O retorno de chamada pode otimizar a coleta de dados ignorando a chamada para PcwAddInstance instâncias sem correspondência InstanceId.
  • Se Info->CollectData.InstanceMask != "*" o consumidor quiser apenas dados sobre instâncias com um InstanceName que corresponda ao padrão curinga de CollectData.InstanceMask. O retorno de chamada pode otimizar a coleta de dados ignorando a chamada para PcwAddInstance instâncias sem correspondência InstanceName. A correspondência curinga é difícil de implementar corretamente, portanto, essa otimização é recomendada somente quando a coleta de dados da instância é muito cara.

Na maioria dos casos, a implementação de retorno de chamada para uma PcwCallbackEnumerateInstances solicitação será idêntica à implementação de um PcwCallbackCollectData. Opcionalmente, o retorno de chamada pode otimizar a coleta de dados omitindo os dados reais do contador na chamada PcwAddInstance (ou seja, passando 0 e NULL para os parâmetros eData.Count

Uma implementação de retorno de chamada pode ser estruturada da seguinte maneira:

NTSTATUS NTAPI
MyProviderCallback(
    _In_ PCW_CALLBACK_TYPE Type,
    _In_ PPCW_CALLBACK_INFORMATION Info,
    _In_opt_ PVOID Context)
{
    PCW_MASK_INFORMATION* MaskInfo;
    PAGED_CODE();

    switch (Type)
    {
    case PcwCallbackCollectData:
        MaskInfo = &Info->CollectData;
        break;

    case PcwCallbackEnumerateInstances:
        MaskInfo = &Info->EnumerateInstances;
        break;

    case PcwCallbackAddCounter:
        // Optional (for optimizing data collection):
        // InterlockedIncrement(&CollectionEnableCount);
        return STATUS_SUCCESS; // Normally no action needed.

    case PcwCallbackRemoveCounter:
        // Optional (for optimizing data collection):
        // InterlockedDecrement(&CollectionEnableCount);
        return STATUS_SUCCESS; // Normally no action needed.
    }

    // Common code for CollectData and EnumerateInstances.
    // Note that this code needs to be thread-safe, as multiple
    // threads might invoke this callback at the same time.

    for (Instance : InstanceList) { // Pseudocode, need thread-safe enumeration
        NTSTATUS Status;

        // Optional optimization:
        // if (MaskInfo->InstanceId != PCW_ANY_INSTANCE_ID && Instance->Id != MaskInfo->InstanceId) {
        //     continue;
        // }

        // Note that in most cases, you'll use a CTRPP-generated Add wrapper instead of directly
        // calling PcwAddInstance.
        Status = PcwAddInstance(MaskInfo->Buffer,
                                &Instance->Name,
                                Instance->Id,
                                1, // Number of items in PcwData array
                                &Instance->PcwData);
        if (!NT_SUCCESS(Status)) {
            return Status;
        }
    }

    return STATUS_SUCCESS;
}

Requisitos

   
Cliente mínimo com suporte Disponível no Windows 7 e versões posteriores do Windows.
Plataforma de Destino Desktop
Cabeçalho wdm.h (include Wdm.h, Ntddk.h)
IRQL <=APC_LEVEL

Confira também

Função PcwRegister

Função PcwAddInstance

Função PcwCreateInstance

PCW_CALLBACK_TYPE enumeração

estrutura PCW_CALLBACK_INFORMATION

CTRPP

Biblioteca de Contadores de Desempenho (PERFLIB versão 2.0)