You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
9.9 KiB
411 lines
9.9 KiB
/*++
|
|
|
|
Copyright (c) 2001-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
uletw.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code for WDM WMI Irps and wrapper functions
|
|
to send trace events to ETW.
|
|
|
|
Author:
|
|
|
|
Melur Raghuraman (mraghu) 14-Feb-2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.h"
|
|
#include "uletwp.h"
|
|
|
|
//
|
|
// Private globals.
|
|
//
|
|
LONG g_UlEtwTraceEnable = 0;
|
|
TRACEHANDLE g_UlEtwLoggerHandle = 0;
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text( PAGE, UlEtwInitLog )
|
|
#pragma alloc_text( PAGE, UlEtwUnRegisterLog )
|
|
#pragma alloc_text( PAGE, UlEtwRegisterGuids )
|
|
#pragma alloc_text( PAGE, UlEtwEnableLog )
|
|
#pragma alloc_text( PAGE, UlEtwDisableLog )
|
|
#pragma alloc_text( PAGE, UlEtwDispatch )
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
#if 0
|
|
NOT PAGEABLE -- UlEtwTraceEvent
|
|
NOT PAGEABLE -- UlEtwGetTraceEnableFlags
|
|
#endif
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
This is the routine in which we call IoWMIRegistrationControl to
|
|
register for ETW logging.
|
|
|
|
Arguments:
|
|
|
|
pDeviceObject - Supplies a pointer to the target device object.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
|
|
NTSTATUS
|
|
UlEtwInitLog(
|
|
IN PDEVICE_OBJECT pDeviceObject
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Register wtih ETW
|
|
//
|
|
status = IoWMIRegistrationControl(pDeviceObject, WMIREG_ACTION_REGISTER);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
UlTrace(ETW, (
|
|
"UlEtwInitLog: IoWMIRegistrationControl failed with %x\n",
|
|
status
|
|
));
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
This is the routine in which we call IoWMIRegistrationControl to
|
|
Unregister from ETW logging.
|
|
|
|
Arguments:
|
|
|
|
pDeviceObject - Supplies a pointer to the target device object.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
|
|
NTSTATUS
|
|
UlEtwUnRegisterLog(
|
|
IN PDEVICE_OBJECT pDeviceObject
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
//
|
|
// Register with ETW.
|
|
//
|
|
status = IoWMIRegistrationControl(pDeviceObject,
|
|
WMIREG_ACTION_DEREGISTER);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
UlTrace(ETW, (
|
|
"UlEtwUnRegisterLog: Failed to unregister for ETW support\n"
|
|
));
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
This function handles ETW GUID registration.
|
|
|
|
Arguments:
|
|
EtwRegInfo
|
|
etwRegInfoSize,
|
|
pReturnSize
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
|
|
NTSTATUS
|
|
UlEtwRegisterGuids(
|
|
IN PWMIREGINFO EtwRegInfo,
|
|
IN ULONG etwRegInfoSize,
|
|
IN PULONG pReturnSize
|
|
)
|
|
{
|
|
//
|
|
// Register a Control Guid as a Trace Guid.
|
|
//
|
|
|
|
ULONG SizeNeeded;
|
|
PWMIREGGUIDW EtwRegGuidPtr;
|
|
ULONG GuidCount;
|
|
ULONG RegistryPathSize;
|
|
ULONG MofResourceSize;
|
|
PUCHAR ptmp;
|
|
|
|
#if DBG
|
|
GUID UlTestGuid = {0xdd5ef90a, 0x6398, 0x47a4, 0xad, 0x34, 0x4d, 0xce, 0xcd, 0xef, 0x79, 0x5f};
|
|
ASSERT(IsEqualGUID(&UlControlGuid, &UlTestGuid));
|
|
#endif
|
|
|
|
*pReturnSize = 0;
|
|
GuidCount = 1;
|
|
|
|
//
|
|
// Allocate WMIREGINFO for controlGuid + GuidCount.
|
|
//
|
|
RegistryPathSize = sizeof(REGISTRY_UL_INFORMATION) - sizeof(WCHAR) + sizeof(USHORT);
|
|
MofResourceSize = sizeof(UL_TRACE_MOF_FILE) - sizeof(WCHAR) + sizeof(USHORT);
|
|
SizeNeeded = sizeof(WMIREGINFOW) + GuidCount * sizeof(WMIREGGUIDW) +
|
|
RegistryPathSize +
|
|
MofResourceSize;
|
|
|
|
if (SizeNeeded > etwRegInfoSize) {
|
|
*((PULONG)EtwRegInfo) = SizeNeeded;
|
|
*pReturnSize = sizeof(ULONG);
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
|
|
RtlZeroMemory(EtwRegInfo, SizeNeeded);
|
|
EtwRegInfo->BufferSize = SizeNeeded;
|
|
EtwRegInfo->GuidCount = GuidCount;
|
|
EtwRegInfo->RegistryPath = sizeof(WMIREGINFOW) + GuidCount * sizeof(WMIREGGUIDW);
|
|
EtwRegInfo->MofResourceName = EtwRegInfo->RegistryPath + RegistryPathSize;
|
|
EtwRegGuidPtr = &EtwRegInfo->WmiRegGuid[0];
|
|
EtwRegGuidPtr->Guid = UlControlGuid;
|
|
EtwRegGuidPtr->Flags |= WMIREG_FLAG_TRACED_GUID;
|
|
EtwRegGuidPtr->Flags |= WMIREG_FLAG_TRACE_CONTROL_GUID;
|
|
EtwRegGuidPtr->InstanceCount = 0;
|
|
EtwRegGuidPtr->InstanceInfo = 0;
|
|
|
|
ptmp = (PUCHAR)&EtwRegInfo->WmiRegGuid[1];
|
|
*((PUSHORT)ptmp) = sizeof(REGISTRY_UL_INFORMATION) - sizeof(WCHAR);
|
|
ptmp += sizeof(USHORT);
|
|
RtlCopyMemory(ptmp,
|
|
REGISTRY_UL_INFORMATION,
|
|
sizeof(REGISTRY_UL_INFORMATION) - sizeof(WCHAR)
|
|
);
|
|
|
|
ptmp = (PUCHAR)EtwRegInfo + EtwRegInfo->MofResourceName;
|
|
*((PUSHORT)ptmp) = sizeof(UL_TRACE_MOF_FILE) - sizeof(WCHAR);
|
|
|
|
ptmp += sizeof(USHORT);
|
|
RtlCopyMemory(ptmp,
|
|
UL_TRACE_MOF_FILE,
|
|
sizeof(UL_TRACE_MOF_FILE) - sizeof(WCHAR)
|
|
);
|
|
|
|
*pReturnSize = SizeNeeded;
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
UlEtwEnableLog(
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize
|
|
)
|
|
{
|
|
PWNODE_HEADER Wnode=NULL;
|
|
|
|
ASSERT(Buffer);
|
|
ASSERT(BufferSize >= sizeof(WNODE_HEADER));
|
|
|
|
Wnode = (PWNODE_HEADER)Buffer;
|
|
if (BufferSize >= sizeof(WNODE_HEADER)) {
|
|
ULONG Level;
|
|
g_UlEtwLoggerHandle = Wnode->HistoricalContext;
|
|
|
|
Level = (ULONG) WmiGetLoggerEnableLevel ( g_UlEtwLoggerHandle );
|
|
|
|
if (Level > ULMAX_TRACE_LEVEL) {
|
|
Level = ULMAX_TRACE_LEVEL;
|
|
}
|
|
g_UlEtwTraceEnable = (1 << Level);
|
|
}
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
UlEtwDisableLog(
|
|
)
|
|
{
|
|
g_UlEtwTraceEnable = 0;
|
|
g_UlEtwLoggerHandle = 0;
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
UlEtwDispatch(
|
|
IN PDEVICE_OBJECT pDO,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
|
|
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
ULONG BufferSize = irpSp->Parameters.WMI.BufferSize;
|
|
PVOID Buffer = irpSp->Parameters.WMI.Buffer;
|
|
ULONG ReturnSize = 0;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
UNREFERENCED_PARAMETER(pDO);
|
|
|
|
switch (irpSp->MinorFunction) {
|
|
|
|
case IRP_MN_REGINFO:
|
|
{
|
|
status = UlEtwRegisterGuids( (PWMIREGINFO) Buffer,
|
|
BufferSize,
|
|
&ReturnSize);
|
|
Irp->IoStatus.Information = ReturnSize;
|
|
Irp->IoStatus.Status = status;
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
break;
|
|
}
|
|
case IRP_MN_ENABLE_EVENTS:
|
|
{
|
|
status = UlEtwEnableLog(
|
|
Buffer,
|
|
BufferSize
|
|
);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
break;
|
|
}
|
|
case IRP_MN_DISABLE_EVENTS:
|
|
{
|
|
status = UlEtwDisableLog();
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
Irp->IoStatus.Status = status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
This is the routine that is called to log a trace event with ETW
|
|
logger.
|
|
|
|
Arguments:
|
|
|
|
pGuid - Supplies a pointer to the Guid of the event
|
|
EventType - Type of the event being logged.
|
|
... - List of arguments to be logged with this event
|
|
These are in pairs of
|
|
PVOID - ptr to argument
|
|
ULONG - size of argument
|
|
and terminated by a pointer to NULL, length of zero pair
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
|
|
NTSTATUS
|
|
UlEtwTraceEvent(
|
|
IN LPCGUID pGuid,
|
|
IN ULONG EventType,
|
|
...
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
UL_ETW_TRACE_EVENT UlEvent;
|
|
|
|
ULONG i;
|
|
va_list ArgList;
|
|
PVOID source;
|
|
SIZE_T len;
|
|
|
|
RtlZeroMemory(& UlEvent, sizeof(EVENT_TRACE_HEADER));
|
|
|
|
va_start(ArgList, EventType);
|
|
for (i = 0; i < MAX_MOF_FIELDS; i ++) {
|
|
source = va_arg(ArgList, PVOID);
|
|
if (source == NULL)
|
|
break;
|
|
len = va_arg(ArgList, SIZE_T);
|
|
if (len == 0)
|
|
break;
|
|
UlEvent.MofField[i].DataPtr = (ULONGLONG) source;
|
|
UlEvent.MofField[i].Length = (ULONG) len;
|
|
}
|
|
va_end(ArgList);
|
|
|
|
UlEvent.Header.Flags = WNODE_FLAG_TRACED_GUID |
|
|
WNODE_FLAG_USE_MOF_PTR |
|
|
WNODE_FLAG_USE_GUID_PTR;
|
|
|
|
UlEvent.Header.Size = (USHORT) (sizeof(EVENT_TRACE_HEADER) + (i * sizeof(MOF_FIELD)));
|
|
UlEvent.Header.Class.Type = (UCHAR) EventType;
|
|
UlEvent.Header.GuidPtr = (ULONGLONG)pGuid;
|
|
((PWNODE_HEADER)&UlEvent)->HistoricalContext = g_UlEtwLoggerHandle;
|
|
status = IoWMIWriteEvent((PVOID)&UlEvent);
|
|
#if DBG
|
|
if (!NT_SUCCESS(status) ) {
|
|
UlTrace(ETW, ("UL: TraceEvent ErrorCode %x EventType %x\n",
|
|
status, EventType));
|
|
}
|
|
#endif // DBG
|
|
return status;
|
|
}
|
|
|
|
ULONG
|
|
UlEtwGetTraceEnableFlags(
|
|
VOID
|
|
)
|
|
{
|
|
return WmiGetLoggerEnableFlags ( g_UlEtwLoggerHandle );
|
|
}
|
|
|
|
|