windows-nt/Source/XPSP1/NT/base/busdrv/acpi/driver/nt/wmilog.c
2020-09-26 16:20:57 +08:00

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