/*++ 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 #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