Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе содержатся сведения об идентификаторах GUID действия, об их добавлении в поставщики трассировки событий и просмотре в Netmon.
Драйверы в стеке USB-драйверов (версий 2.0 и 3.0) являются поставщиками трассировки событий ETW. В Windows 7 при записи трассировок событий из стека USB-драйверов можно записывать трассировки от других поставщиков, таких как другие драйверы и приложения. Затем вы сможете прочитать объединенный журнал (при условии, что вы создали Netmon-средство для анализа трассировок событий вашего поставщика).
Начиная с Windows 8, можно связать события между поставщиками (от приложений, клиентского драйвера и стека драйверов USB) с помощью идентификаторов действий . События из нескольких поставщиков могут быть связаны в Netmon, если у них один и тот же GUID идентификатора действия. На основе этих графических идентификаторов Netmon может показать набор событий USB, которые привели к инструментированному действию на верхнем слое.
Просматривая объединенные трассировки событий от других поставщиков в Netmon, щелкните правой кнопкой мыши событие из приложения и выберите Поиск бесед —> NetEvent, чтобы просмотреть связанные события драйвера.
На этом рисунке показаны связанные события из приложения, драйвера UMDF и Ucx01000.sys (один из драйверов в стеке USB-драйверов). Эти события имеют один и тот же ИДЕНТИФИКАТОР действия GUID.
- Добавление GUID идентификатора активности в приложение
- Настройка GUID идентификатора действия в драйвере UMDF
- Как добавить GUID идентификатор активности в драйвер режима ядра
Как добавить GUID идентификатор активности в приложение
Приложение может включать идентификаторы действий с помощью вызова EventActivityIdControl. Дополнительные сведения см. в разделе Функции трассировки событий.
В этом примере кода показано, как приложение может задать идентификатор действия GUID и отправить его поставщику ETW, драйверу 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());
...
}
В предыдущем примере приложение вызывает EventActivityIdControl для создания идентификатора действия (EVENT_ACTIVITY_CTRL_CREATE_ID), а затем, чтобы задать его (EVENT_ACTIVITY_CTRL_SET_ID) для текущего потока. Приложение указывает GUID активности поставщику событий ETW, например драйверу в пользовательском режиме, отправляя IOCTL, определяемый драйвером (описано в следующем разделе).
Поставщик событий должен опубликовать файл манифеста инструментирования (.MAN-файл). При запуске компилятора сообщений (Mc.exe)создается файл заголовка, содержащий определения для поставщика событий, атрибутов событий, каналов и самих событий. В примере приложение вызывает EventWriteReadFail, определенный в созданном файле заголовка, для записи сообщений о событиях трассировки в случае сбоя.
Настройка GUID идентификатора активности в драйвере UMDF
Драйвер пользовательского режима создает и задает идентификаторы действий, вызывая EventActivityIdControl, и эти вызовы аналогичны вызовам, которые делает приложение, как описано в предыдущем разделе. Эти вызовы добавляют идентификатор действия GUID в текущий поток и идентификатор действия используется всякий раз, когда поток регистрирует событие. Дополнительные сведения см. в разделе Использование идентификаторов действий.
В этом примере кода показано, как драйвер UMDF задает идентификатор действия, созданный и заданный приложением с помощью 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;
}
Давайте посмотрим, как GUID идентификатора действия, созданный приложением, связывается с клиентским драйвером (UMDF) в рамкахUser-Mode Driver Framework. Когда драйвер получает запрос IOCTL от приложения, он копирует GUID в приватный элемент. В какой-то момент приложение вызывает ReadFile для выполнения операции чтения. Платформа создает запрос и вызывает обработчик драйвера ForwardFormattedRequest. В обработчике драйвер задает ранее сохраненный идентификатор активности в потоке, вызывая EventActivityIdControl и EventWriteReadFail для отслеживания сообщений о событиях.
Примечание Драйвер UMDF также должен включать файл заголовка, созданный с помощью файла манифеста инструментирования. Файл заголовка определяет макросы, такие как EventWriteReadFail, которые записывают сообщения трассировки.
Как добавить GUID идентификатора активности в драйвере в режиме ядра
В режиме ядра драйвер может отслеживать сообщения в потоке, исходном в пользовательском режиме или потоке, который создает драйвер. В обоих случаях драйверу требуется идентификатор активности GUID потока.
Чтобы отслеживать сообщения, драйвер должен получить дескриптор регистрации в качестве поставщика событий (см. EtwRegister), а затем вызвать EtwWrite, указав GUID и сообщение о событии. Дополнительные сведения см. в разделе Добавление трассировки событий к драйверам Kernel-Mode.
Если драйвер режима ядра обрабатывает запрос, созданный приложением или драйвером пользовательского режима, драйвер режима ядра не создает и не задает ИДЕНТИФИКАТОР действия. Вместо этого диспетчер ввода-вывода обрабатывает большую часть распространения идентификатора действия. Когда поток пользовательского режима инициирует запрос, диспетчер операций ввода-вывода создает IRP для этого запроса и автоматически копирует GUID идентификатора активности текущего потока в новый IRP. Если драйвер в режиме ядра хочет трассировать события в этом потоке, он должен получить GUID, вызвав IoGetActivityIdIrp, а затем вызвать EtwWrite.
Если драйвер в режиме ядра создает IRP, содержащий GUID активности, он может вызвать EtwActivityIdControl с EVENT_ACTIVITY_CTRL_CREATE_SET_ID для создания нового GUID. Затем драйвер может связать новый GUID с IRP, вызвав IoSetActivityIdIrp, а затем вызвать EtwWrite.
GUID идентификатора действия передается вместе с IRP следующим по уровню драйверам. Драйверы нижнего уровня могут добавлять сообщения трассировки в поток.