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.
308 lines
7.6 KiB
308 lines
7.6 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// Module: perf.c
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
//@@BEGIN_MSINTERNAL
|
|
//
|
|
// History: Date Author Comment
|
|
// --------------------------------------------------------------
|
|
// 12/12/00 ArthurZ Created
|
|
//
|
|
//@@END_MSINTERNAL
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
// PURPOSE.
|
|
//
|
|
// Copyright (c) 1995-1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "private.h"
|
|
#include "perf.h"
|
|
|
|
#define PROC_REG_PATH L"System\\CurrentControlSet\\Services\\Portcls"
|
|
|
|
GUID ControlGuid =
|
|
{ 0x28cf047a, 0x2437, 0x4b24, 0xb6, 0x53, 0xb9, 0x44, 0x6a, 0x41, 0x9a, 0x69 };
|
|
|
|
GUID TraceGuid =
|
|
{ 0x9d447297, 0xc576, 0x4015, 0x87, 0xb5, 0xa5, 0xa6, 0x98, 0xfd, 0x4d, 0xd1 };
|
|
|
|
GUID TraceDMAGuid =
|
|
{ 0xf27b2e65, 0x15f0, 0x4d01, 0xab, 0xe2, 0xf7, 0x68, 0x5d, 0xf6, 0xe5, 0x72 };
|
|
|
|
ULONG TraceEnable;
|
|
TRACEHANDLE LoggerHandle;
|
|
|
|
typedef struct PERFINFO_AUDIOGLITCH {
|
|
ULONGLONG cycleCounter;
|
|
ULONG glitchType;
|
|
LONGLONG sampleTime;
|
|
LONGLONG previousTime;
|
|
ULONG_PTR instanceId;
|
|
} PERFINFO_AUDIOGLITCH, *PPERFINFO_AUDIOGLITCH;
|
|
|
|
typedef struct PERFINFO_WMI_AUDIOGLITCH {
|
|
EVENT_TRACE_HEADER header;
|
|
PERFINFO_AUDIOGLITCH data;
|
|
} PERFINFO_WMI_AUDIO_GLITCH, *PPERFINFO_WMI_AUDIOGLITCH;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
PerfRegisterProvider (
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine registers this component as a WMI event tracing provider.
|
|
|
|
--*/
|
|
|
|
{
|
|
IoWMIRegistrationControl (DeviceObject, WMIREG_ACTION_REGISTER);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
PerfUnregisterProvider (
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine unregisters this component as a WMI event tracing provider.
|
|
|
|
--*/
|
|
|
|
{
|
|
IoWMIRegistrationControl (DeviceObject, WMIREG_ACTION_DEREGISTER);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS
|
|
RegisterWmiGuids (
|
|
IN PWMIREGINFO WmiRegInfo,
|
|
IN ULONG RegInfoSize,
|
|
IN PULONG ReturnSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine registers WMI event tracing streams.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG SizeNeeded;
|
|
PWMIREGGUIDW WmiRegGuidPtr;
|
|
ULONG status;
|
|
ULONG GuidCount;
|
|
ULONG RegistryPathSize;
|
|
PUCHAR Temp;
|
|
|
|
if (WmiRegInfo == NULL ||
|
|
ReturnSize == NULL ) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
GuidCount = 1;
|
|
|
|
RegistryPathSize = sizeof (PROC_REG_PATH) - sizeof (WCHAR) + sizeof (USHORT);
|
|
SizeNeeded = sizeof (WMIREGINFOW) + GuidCount * sizeof (WMIREGGUIDW) + RegistryPathSize;
|
|
|
|
if (SizeNeeded > RegInfoSize) {
|
|
if ( RegInfoSize >= sizeof(ULONG) ) {
|
|
*((PULONG)WmiRegInfo) = SizeNeeded;
|
|
*ReturnSize = sizeof (ULONG);
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
else {
|
|
*ReturnSize = 0;
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
|
|
RtlZeroMemory (WmiRegInfo, SizeNeeded);
|
|
WmiRegInfo->BufferSize = SizeNeeded;
|
|
WmiRegInfo->GuidCount = GuidCount;
|
|
|
|
WmiRegGuidPtr = WmiRegInfo->WmiRegGuid;
|
|
WmiRegGuidPtr->Guid = ControlGuid;
|
|
WmiRegGuidPtr->Flags |= (WMIREG_FLAG_TRACED_GUID | WMIREG_FLAG_TRACE_CONTROL_GUID);
|
|
|
|
Temp = (PUCHAR)(WmiRegGuidPtr + 1);
|
|
WmiRegInfo->RegistryPath = PtrToUlong ((PVOID)(Temp - (PUCHAR)WmiRegInfo));
|
|
*((PUSHORT)Temp) = (USHORT)(sizeof (PROC_REG_PATH) - sizeof (WCHAR));
|
|
|
|
Temp += sizeof (USHORT);
|
|
RtlCopyMemory (Temp, PROC_REG_PATH, sizeof (PROC_REG_PATH) - sizeof (WCHAR));
|
|
|
|
*ReturnSize = SizeNeeded;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
NTSTATUS
|
|
PcDispatchSystemControl
|
|
(
|
|
IN PDEVICE_OBJECT pDeviceObject,
|
|
IN PIRP pIrp
|
|
);
|
|
|
|
NTSTATUS
|
|
PerfWmiDispatch (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles IRP_MJ_SYSTEM_CONTROL calls. It processes
|
|
WMI requests and passes everything else on to KS.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (Irp);
|
|
ULONG ReturnSize=0;
|
|
PWNODE_HEADER Wnode;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
if ((PDEVICE_OBJECT)IrpSp->Parameters.WMI.ProviderId != DeviceObject) {
|
|
return PcDispatchSystemControl(DeviceObject, Irp);
|
|
}
|
|
|
|
switch (IrpSp->MinorFunction) {
|
|
|
|
case IRP_MN_REGINFO:
|
|
ntStatus = RegisterWmiGuids ((PWMIREGINFO)IrpSp->Parameters.WMI.Buffer,
|
|
IrpSp->Parameters.WMI.BufferSize,
|
|
&ReturnSize);
|
|
break;
|
|
|
|
case IRP_MN_ENABLE_EVENTS:
|
|
InterlockedExchange ((PLONG)&TraceEnable, 1);
|
|
Wnode = (PWNODE_HEADER)IrpSp->Parameters.WMI.Buffer;
|
|
if (IrpSp->Parameters.WMI.BufferSize >= sizeof (WNODE_HEADER)) {
|
|
LoggerHandle = Wnode->HistoricalContext;
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_DISABLE_EVENTS:
|
|
InterlockedExchange ((PLONG)&TraceEnable, 0);
|
|
break;
|
|
|
|
case IRP_MN_ENABLE_COLLECTION:
|
|
case IRP_MN_DISABLE_COLLECTION:
|
|
break;
|
|
|
|
default:
|
|
ntStatus = STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
// Do not modify Irp Status if this WMI call is not
|
|
// handled.
|
|
//
|
|
if (STATUS_NOT_SUPPORTED == ntStatus)
|
|
{
|
|
ntStatus = Irp->IoStatus.Status;
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = ReturnSize;
|
|
}
|
|
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
return ntStatus;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
VOID
|
|
PerfLogGlitch (
|
|
IN GUID Guid,
|
|
IN ULONG_PTR InstanceId,
|
|
IN ULONG Type,
|
|
IN LONGLONG CurrentTime,
|
|
IN LONGLONG PreviousTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine logs a WMI event tracing event with an audio glitch GUID
|
|
and the supplied glitch type.
|
|
|
|
--*/
|
|
|
|
{
|
|
PERFINFO_WMI_AUDIO_GLITCH Event;
|
|
|
|
if (LoggerHandle == (TRACEHANDLE)NULL || TraceEnable == 0) {
|
|
return;
|
|
}
|
|
|
|
RtlZeroMemory (&Event, sizeof (Event));
|
|
Event.header.Size = sizeof (Event);
|
|
Event.header.Flags = WNODE_FLAG_TRACED_GUID;
|
|
Event.header.Guid = Guid;
|
|
Event.data.glitchType = Type;
|
|
Event.data.instanceId = InstanceId;
|
|
Event.data.sampleTime = CurrentTime;
|
|
Event.data.previousTime = PreviousTime;
|
|
|
|
((PWNODE_HEADER)&Event)->HistoricalContext = LoggerHandle;
|
|
|
|
IoWMIWriteEvent ((PVOID)&Event);
|
|
}
|
|
|
|
|
|
VOID
|
|
PerfLogInsertSilenceGlitch (
|
|
IN ULONG_PTR InstanceId,
|
|
IN ULONG Type,
|
|
IN LONGLONG CurrentTime,
|
|
IN LONGLONG PreviousTime
|
|
)
|
|
|
|
{
|
|
PerfLogGlitch (TraceGuid,InstanceId,Type,CurrentTime,PreviousTime);
|
|
}
|
|
|
|
VOID
|
|
PerfLogDMAGlitch (
|
|
IN ULONG_PTR InstanceId,
|
|
IN ULONG Type,
|
|
IN LONGLONG CurrentTime,
|
|
IN LONGLONG PreviousTime
|
|
)
|
|
|
|
{
|
|
PerfLogGlitch (TraceDMAGuid,InstanceId,Type,CurrentTime,PreviousTime);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// End of File: perf.c
|
|
//---------------------------------------------------------------------------
|
|
|