475 lines
11 KiB
C
475 lines
11 KiB
C
/*++
|
|
|
|
Copyright (c) 1997-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
WmiLog.c
|
|
|
|
Abstract:
|
|
|
|
This module contains Wmi loging support.
|
|
|
|
Author:
|
|
|
|
Hanumant Yadav (hanumany) 18-Dec-2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
#include <evntrace.h>
|
|
|
|
|
|
|
|
#ifdef WMI_TRACING
|
|
//
|
|
//Globals
|
|
//
|
|
GUID GUID_List[] =
|
|
{
|
|
{0xF2E0E060L, 0xBF32, 0x4B88, 0xB8, 0xE4, 0x5C, 0xAD, 0x15, 0xAF, 0x6A, 0xE9} /* AMLI log GUID */
|
|
/* Add new logging GUIDS here */
|
|
};
|
|
|
|
|
|
|
|
ULONG ACPIWmiTraceEnable = 0;
|
|
ULONG ACPIWmiTraceGlobalEnable = 0;
|
|
TRACEHANDLE ACPIWmiLoggerHandle = 0;
|
|
|
|
// End Globals
|
|
|
|
|
|
|
|
VOID
|
|
ACPIWmiInitLog(
|
|
IN PDEVICE_OBJECT ACPIDeviceObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is a initialization function in which we call IoWMIRegistrationControl
|
|
to register for WMI loging.
|
|
|
|
Arguments:
|
|
ACPIDeviceObject.
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
//
|
|
// Register with WMI.
|
|
//
|
|
status = IoWMIRegistrationControl(ACPIDeviceObject,
|
|
WMIREG_ACTION_REGISTER);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
ACPIPrint( (
|
|
DPFLTR_ERROR_LEVEL,
|
|
"ACPIWmiInitLog: Failed to register for WMI support\n"
|
|
) );
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
ACPIWmiUnRegisterLog(
|
|
IN PDEVICE_OBJECT ACPIDeviceObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is a unregistration function in which we call IoWMIRegistrationControl
|
|
to unregister for WMI loging.
|
|
|
|
Arguments:
|
|
ACPIDeviceObject.
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
//
|
|
// Register with WMI.
|
|
//
|
|
status = IoWMIRegistrationControl(ACPIDeviceObject,
|
|
WMIREG_ACTION_DEREGISTER);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
ACPIPrint( (
|
|
DPFLTR_ERROR_LEVEL,
|
|
"ACPIWmiInitLog: Failed to unregister for WMI support\n"
|
|
) );
|
|
}
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
ACPIWmiRegisterGuids(
|
|
IN PWMIREGINFO WmiRegInfo,
|
|
IN ULONG wmiRegInfoSize,
|
|
IN PULONG pReturnSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function handles WMI GUID registration goo.
|
|
|
|
Arguments:
|
|
WmiRegInfo,
|
|
wmiRegInfoSize,
|
|
pReturnSize
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS on success.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Register a Control Guid as a Trace Guid.
|
|
//
|
|
|
|
ULONG SizeNeeded;
|
|
PWMIREGGUIDW WmiRegGuidPtr;
|
|
ULONG Status;
|
|
ULONG GuidCount;
|
|
LPGUID ControlGuid;
|
|
ULONG RegistryPathSize;
|
|
ULONG MofResourceSize;
|
|
PUCHAR ptmp;
|
|
GUID ACPITraceGuid = {0xDAB01D4DL, 0x2D48, 0x477D, 0xB1, 0xC3, 0xDA, 0xAD, 0x0C, 0xE6, 0xF0, 0x6B};
|
|
|
|
|
|
*pReturnSize = 0;
|
|
GuidCount = 1;
|
|
ControlGuid = &ACPITraceGuid;
|
|
|
|
//
|
|
// Allocate WMIREGINFO for controlGuid + GuidCount.
|
|
//
|
|
RegistryPathSize = sizeof(ACPI_REGISTRY_KEY) - sizeof(WCHAR) + sizeof(USHORT);
|
|
MofResourceSize = sizeof(ACPI_TRACE_MOF_FILE) - sizeof(WCHAR) + sizeof(USHORT);
|
|
SizeNeeded = sizeof(WMIREGINFOW) + GuidCount * sizeof(WMIREGGUIDW) +
|
|
RegistryPathSize +
|
|
MofResourceSize;
|
|
|
|
|
|
if (SizeNeeded > wmiRegInfoSize) {
|
|
*((PULONG)WmiRegInfo) = SizeNeeded;
|
|
*pReturnSize = sizeof(ULONG);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
RtlZeroMemory(WmiRegInfo, SizeNeeded);
|
|
WmiRegInfo->BufferSize = SizeNeeded;
|
|
WmiRegInfo->GuidCount = GuidCount;
|
|
WmiRegInfo->RegistryPath = sizeof(WMIREGINFOW) + GuidCount * sizeof(WMIREGGUIDW);
|
|
WmiRegInfo->MofResourceName = WmiRegInfo->RegistryPath + RegistryPathSize; //ACPI_TRACE_MOF_FILE;
|
|
|
|
WmiRegGuidPtr = &WmiRegInfo->WmiRegGuid[0];
|
|
WmiRegGuidPtr->Guid = *ControlGuid;
|
|
WmiRegGuidPtr->Flags |= WMIREG_FLAG_TRACED_GUID;
|
|
WmiRegGuidPtr->Flags |= WMIREG_FLAG_TRACE_CONTROL_GUID;
|
|
WmiRegGuidPtr->InstanceCount = 0;
|
|
WmiRegGuidPtr->InstanceInfo = 0;
|
|
|
|
ptmp = (PUCHAR)&WmiRegInfo->WmiRegGuid[1];
|
|
*((PUSHORT)ptmp) = sizeof(ACPI_REGISTRY_KEY) - sizeof(WCHAR);
|
|
|
|
ptmp += sizeof(USHORT);
|
|
RtlCopyMemory(ptmp, ACPI_REGISTRY_KEY, sizeof(ACPI_REGISTRY_KEY) - sizeof(WCHAR));
|
|
|
|
ptmp = (PUCHAR)WmiRegInfo + WmiRegInfo->MofResourceName;
|
|
*((PUSHORT)ptmp) = sizeof(ACPI_TRACE_MOF_FILE) - sizeof(WCHAR);
|
|
|
|
ptmp += sizeof(USHORT);
|
|
RtlCopyMemory(ptmp, ACPI_TRACE_MOF_FILE, sizeof(ACPI_TRACE_MOF_FILE) - sizeof(WCHAR));
|
|
|
|
*pReturnSize = SizeNeeded;
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
ACPIGetWmiLogGlobalHandle(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function gets the global wmi logging handle. We need this to log
|
|
at boot time, before we start getting wmi messages.
|
|
|
|
Arguments:
|
|
None.
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
WmiSetLoggerId(WMI_GLOBAL_LOGGER_ID, &ACPIWmiLoggerHandle);
|
|
if(ACPIWmiLoggerHandle)
|
|
{
|
|
ACPIPrint( (
|
|
DPFLTR_INFO_LEVEL,
|
|
"ACPIGetWmiLogGlobalHandle: Global handle aquired. Handle = %I64u\n",
|
|
ACPIWmiLoggerHandle
|
|
) );
|
|
|
|
ACPIWmiTraceGlobalEnable = 1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ACPIWmiEnableLog(
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the handler for IRP_MN_ENABLE_EVENTS.
|
|
|
|
Arguments:
|
|
Buffer,
|
|
BufferSize
|
|
|
|
Return Value:
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PWNODE_HEADER Wnode=NULL;
|
|
|
|
InterlockedExchange(&ACPIWmiTraceEnable, 1);
|
|
|
|
Wnode = (PWNODE_HEADER)Buffer;
|
|
if (BufferSize >= sizeof(WNODE_HEADER)) {
|
|
ACPIWmiLoggerHandle = Wnode->HistoricalContext;
|
|
//
|
|
// reset the global logger if it is active.
|
|
//
|
|
if(ACPIWmiTraceGlobalEnable)
|
|
ACPIWmiTraceGlobalEnable = 0;
|
|
|
|
ACPIPrint( (
|
|
DPFLTR_INFO_LEVEL,
|
|
"ACPIWmiEnableLog: LoggerHandle = %I64u. BufferSize = %d. Flags = %x. Version = %x\n",
|
|
ACPIWmiLoggerHandle,
|
|
Wnode->BufferSize,
|
|
Wnode->Flags,
|
|
Wnode->Version
|
|
) );
|
|
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
ACPIWmiDisableLog(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the handler for IRP_MN_DISABLE_EVENTS.
|
|
|
|
Arguments:
|
|
None.
|
|
|
|
Return Value:
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
InterlockedExchange(&ACPIWmiTraceEnable, 0);
|
|
ACPIWmiLoggerHandle = 0;
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
ACPIWmiLogEvent(
|
|
IN UCHAR LogLevel,
|
|
IN UCHAR LogType,
|
|
IN GUID LogGUID,
|
|
IN PUCHAR Format,
|
|
IN ...
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the main wmi logging funcion. This function should be used
|
|
throughtout the ACPI driver where WMI logging is required.
|
|
|
|
Arguments:
|
|
LogLevel,
|
|
LogType,
|
|
LogGUID,
|
|
Format,
|
|
...
|
|
|
|
Return Value:
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
static char Buffer[1024];
|
|
va_list marker;
|
|
WMI_LOG_DATA Wmi_log_data ={0,0};
|
|
EVENT_TRACE_HEADER *Wnode;
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
va_start(marker, Format);
|
|
vsprintf(Buffer, Format, marker);
|
|
va_end(marker);
|
|
|
|
if(ACPIWmiTraceEnable || ACPIWmiTraceGlobalEnable)
|
|
{
|
|
if(ACPIWmiLoggerHandle)
|
|
{
|
|
Wmi_log_data.Data.DataPtr = (ULONG64)&Buffer;
|
|
Wmi_log_data.Data.Length = strlen(Buffer) + 1;
|
|
Wmi_log_data.Header.Size = sizeof(WMI_LOG_DATA);
|
|
Wmi_log_data.Header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR;
|
|
Wmi_log_data.Header.Class.Type = LogType;
|
|
Wmi_log_data.Header.Class.Level = LogLevel;
|
|
Wmi_log_data.Header.Guid = LogGUID;
|
|
Wnode = &Wmi_log_data.Header;
|
|
((PWNODE_HEADER)Wnode)->HistoricalContext = ACPIWmiLoggerHandle;
|
|
|
|
//
|
|
// Call TraceLogger to write this event
|
|
//
|
|
|
|
status = IoWMIWriteEvent((PVOID)&(Wmi_log_data.Header));
|
|
|
|
//
|
|
// if IoWMIWriteEvent fails and we are using the global logger handle,
|
|
// we need to stop loging.
|
|
//
|
|
if(status != STATUS_SUCCESS)
|
|
{
|
|
if(ACPIWmiTraceGlobalEnable)
|
|
{
|
|
ACPIWmiLoggerHandle = 0;
|
|
ACPIWmiTraceGlobalEnable = 0;
|
|
ACPIPrint( (
|
|
ACPI_PRINT_INFO,
|
|
"ACPIWmiLogEvent: Disabling WMI loging using global handle. status = %x\n",
|
|
status
|
|
) );
|
|
}
|
|
else
|
|
{
|
|
ACPIPrint( (
|
|
DPFLTR_ERROR_LEVEL,
|
|
"ACPIWmiLogEvent: Failed to log. status = %x\n",
|
|
status
|
|
) );
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ACPIDispatchWmiLog(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PIO_STACK_LOCATION irpSp;
|
|
UCHAR minorFunction;
|
|
|
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
//
|
|
// Get the dispatch table that we will be using and the minor code as well,
|
|
// so that we can look it when required
|
|
//
|
|
ASSERT(RootDeviceExtension->DeviceObject == DeviceObject);
|
|
|
|
if (DeviceObject != (PDEVICE_OBJECT) irpSp->Parameters.WMI.ProviderId) {
|
|
|
|
return ACPIDispatchForwardIrp(DeviceObject, Irp);
|
|
}
|
|
|
|
minorFunction = irpSp->MinorFunction;
|
|
|
|
switch(minorFunction){
|
|
|
|
case IRP_MN_REGINFO:{
|
|
|
|
ULONG ReturnSize = 0;
|
|
ULONG BufferSize = irpSp->Parameters.WMI.BufferSize;
|
|
PVOID Buffer = irpSp->Parameters.WMI.Buffer;
|
|
|
|
status=ACPIWmiRegisterGuids(
|
|
Buffer,
|
|
BufferSize,
|
|
&ReturnSize
|
|
);
|
|
|
|
Irp->IoStatus.Information = ReturnSize;
|
|
Irp->IoStatus.Status = status;
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
return status;
|
|
}
|
|
case IRP_MN_ENABLE_EVENTS:{
|
|
|
|
status=ACPIWmiEnableLog(
|
|
irpSp->Parameters.WMI.Buffer,
|
|
irpSp->Parameters.WMI.BufferSize
|
|
);
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
return status;
|
|
}
|
|
case IRP_MN_DISABLE_EVENTS:{
|
|
|
|
status=ACPIWmiDisableLog();
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
return status;
|
|
}
|
|
default:{
|
|
|
|
status = ACPIDispatchForwardIrp(DeviceObject, Irp);
|
|
return status;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
#endif //WMI_TRACING
|