Condividi tramite


Uso dei GUID ID attività nelle tracce USB ETW

In questo argomento vengono fornite informazioni sui GUID ID attività, su come aggiungere tali GUID nei provider di traccia eventi e visualizzarli in Netmon.

I driver nello stack di driver USB (sia 2.0 che 3.0) sono provider di traccia eventi ETW. In Windows 7, durante l'acquisizione di tracce di eventi dallo stack di driver USB, è possibile acquisire tracce da altri provider, ad esempio altri driver e applicazioni. È quindi possibile leggere il log combinato , presupponendo che sia stato creato un parser Netmon per le tracce degli eventi del provider.

A partire da Windows 8, è possibile associare eventi tra provider (da applicazioni, driver client e stack di driver USB) usando i GUID ID attività. Gli eventi di più provider possono essere associati in Netmon quando gli eventi hanno lo stesso GUID DELL'ATTIVITÀ. In base a tali GUID, Netmon può mostrare il set di eventi USB che hanno causato un'attività instrumentata a un livello superiore.

Durante la visualizzazione di tracce di eventi combinate da altri provider in Netmon, fare clic con il pulsante destro del mouse su un evento da un'applicazione e scegliere Trova conversazioni -> NetEvent per visualizzare gli eventi driver associati.

Questa immagine mostra gli eventi correlati da un'applicazione, un driver UMDF e Ucx01000.sys (uno dei driver nello stack di driver USB). Questi eventi hanno lo stesso GUID ID attività.

monitoraggio di rete microsoft.

Come aggiungere un GUID ID attività in un'applicazione

Un'applicazione può includere GUID ID attività chiamando EventActivityIdControl. Per altre informazioni, vedere Funzioni di traccia eventi.

Questo codice di esempio illustra come un'applicazione può impostare un GUID ID attività e inviarlo al provider ETW, un driver UMDF.

EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_ID, &activityIdStruct.ActivityId); 
EventActivityIdControl(EVENT_ACTIVITY_CTRL_SET_ID,    &activityIdStruct.ActivityId); 

if (!DeviceIoControl(hRead,
                     IOCTL_OSRUSBFX2_SET_ACTIVITY_ID,
                     &activityIdStruct,         // Ptr to InBuffer
                     sizeof(activityIdStruct),  // Length of InBuffer
                     NULL,                      // Ptr to OutBuffer
                     0,                         // Length of OutBuffer
                     NULL,                      // BytesReturned
                     0))                        // Ptr to Overlapped structure
{         

          wprintf(L"Failed to set activity ID - error %d\n", GetLastError());
}

...

success = ReadFile(hRead, pinBuf, G_ReadLen, (PULONG) &nBytesRead, NULL);

if(success == 0) 
{
          wprintf(L"ReadFile failed - error %d\n", GetLastError());

          EventWriteReadFail(0, GetLastError());

          ...

}

Nell'esempio precedente un'applicazione chiama EventActivityIdControl per creare un ID attività (EVENT_ACTIVITY_CTRL_CREATE_ID) e quindi impostarlo (EVENT_ACTIVITY_CTRL_SET_ID) per il thread corrente. L'applicazione specifica che il GUID dell'attività al provider di eventi ETW, ad esempio un driver in modalità utente, inviando un IOCTL definito dal driver (descritto nella sezione successiva).

Il provider di eventi deve pubblicare un file manifesto di strumentazione (. File MAN. Eseguendo il compilatore di messaggi (Mc.exe), viene generato un file di intestazione che contiene definizioni per il provider di eventi, gli attributi degli eventi, i canali e gli eventi. Nell'esempio l'applicazione chiama EventWriteReadFail, definito nel file di intestazione generato, per scrivere messaggi di evento di traccia in caso di errore.

Come impostare il GUID dell'ID attività in un driver UMDF

Un driver in modalità utente crea e imposta i GUID id attività chiamando EventActivityIdControl e le chiamate sono simili al modo in cui un'applicazione li chiama, come descritto nella sezione precedente. Tali chiamate aggiungono il GUID dell'ID attività al thread corrente e tale GUID id attività viene usato ogni volta che il thread registra un evento. Per altre informazioni, vedere Uso degli identificatori di attività.

Questo codice di esempio illustra come un driver UMDF imposta il GUID dell'ID attività creato e specificato dall'applicazione tramite un IOCTL.

VOID
STDMETHODCALLTYPE
CMyControlQueue::OnDeviceIoControl(
    _In_ IWDFIoQueue *FxQueue,
    _In_ IWDFIoRequest *FxRequest,
    _In_ ULONG ControlCode,
    _In_ SIZE_T InputBufferSizeInBytes,
    _In_ SIZE_T OutputBufferSizeInBytes
    )
/*++

Routine Description:

    DeviceIoControl dispatch routine

Arguments:

    FxQueue - Framework Queue instance
    FxRequest - Framework Request  instance
    ControlCode - IO Control Code
    InputBufferSizeInBytes - Lenth of input buffer
    OutputBufferSizeInBytes - Lenth of output buffer

    Always succeeds DeviceIoIoctl
Return Value:

    VOID

--*/
{
    ...

    switch (ControlCode)
    {

        ....

        case IOCTL_OSRUSBFX2_SET_ACTIVITY_ID:
        {
            if (InputBufferSizeInBytes < sizeof(UMDF_ACTIVITY_ID))
            {
                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
            }
            else
            {
                FxRequest->GetInputMemory(&memory );
            }

            if (SUCCEEDED(hr)) 
            {
                buffer = memory->GetDataBuffer(&bigBufferCb);
                memory->Release();

                m_Device->SetActivityId(&((PUMDF_ACTIVITY_ID)buffer)->ActivityId);
                hr = S_OK;
            }

            break;
        }
    } 
}

VOID
 SetActivityId(
        LPCGUID ActivityId
        )
    {
        CopyMemory(&m_ActivityId, ActivityId, sizeof(m_ActivityId));
    }

void
CMyReadWriteQueue::ForwardFormattedRequest(
    _In_ IWDFIoRequest*                         pRequest,
    _In_ IWDFIoTarget*                          pIoTarget
    )
{
...
    pRequest->SetCompletionCallback(
        pCompletionCallback,
        NULL
        );

...
    hrSend = pRequest->Send(pIoTarget,
                            0,  //flags
                            0); //timeout

...
    if (FAILED(hrSend))
    {
        contextHr = pRequest->RetrieveContext((void**)&pRequestContext);

        if (SUCCEEDED(contextHr)) {

            EventActivityIdControl(EVENT_ACTIVITY_CTRL_SET_ID, &pRequestContext->ActivityId);

            if (pRequestContext->RequestType == RequestTypeRead)
            {
                EventWriteReadFail(m_Device, hrSend);
            }

            delete pRequestContext;
        }

        pRequest->CompleteWithInformation(hrSend, 0);
    }

    return;
}

Vediamo come il GUID dell'ID attività creato dall'applicazione viene associato a un driver client UMDF ( User-Mode Driver Framework ). Quando il driver riceve la richiesta IOCTL dall'applicazione, copia il GUID in un membro privato. A un certo punto, l'applicazione chiama ReadFile per eseguire un'operazione di lettura. Il framework crea una richiesta e richiama il gestore del driver, ForwardFormattedRequest. Nel gestore, il driver imposta il GUID dell'ID attività archiviato in precedenza nel thread chiamando EventActivityIdControl e EventWriteReadFail per tracciare i messaggi di evento.

Nota Il driver UMDF deve includere anche il file di intestazione generato tramite il file manifesto di strumentazione. Il file di intestazione definisce macro, ad esempio EventWriteReadFail, che scrivono messaggi di traccia.

Come aggiungere GUID ID attività in un driver in modalità kernel

In modalità kernel, un driver può tracciare i messaggi nel thread che ha origine in modalità utente o un thread creato dal driver. In entrambi i casi, il driver richiede il GUID DELL'ID attività del thread.

Per tracciare i messaggi, il driver deve ottenere l'handle di registrazione come provider di eventi (vedere EtwRegister) e quindi chiamare EtwWrite specificando il GUID e il messaggio di evento. Per altre informazioni, vedere Aggiunta di Traccia eventi ai driver di Kernel-Mode.

Se il driver in modalità kernel gestisce una richiesta creata da un'applicazione o da un driver in modalità utente, il driver in modalità kernel non crea e imposta un GUID id attività. Il gestore di I/O gestisce invece la maggior parte della propagazione dell'ID attività. Quando un thread in modalità utente avvia una richiesta, la gestione I/O crea un'istanza di IRP per la richiesta e copia automaticamente il GUID dell'ID attività del thread corrente nella nuova IRP. Se il driver in modalità kernel vuole tracciare gli eventi nel thread, deve ottenere il GUID chiamando IoGetActivityIdIrp e quindi chiamare EtwWrite.

Se il driver in modalità kernel crea un GUID con ID attività, il driver può chiamare EtwActivityIdControl con EVENT_ACTIVITY_CTRL_CREATE_SET_ID per generare un nuovo GUID. Il driver può quindi associare il nuovo GUID all'IRP chiamando IoSetActivityIdIrp e quindi chiamare EtwWrite.

Il GUID ID attività viene passato insieme all'IRP ai driver inferiori successivi. I driver inferiori possono aggiungere i messaggi di traccia al thread.