windows-nt/Source/XPSP1/NT/base/ntos/perf/logging.c

186 lines
4.2 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
logging.c
Abstract:
This module contains routines for trace logging.
Author:
Stephen Hsiao (shsiao) 01-Jan-2000
Revision History:
--*/
#include "perfp.h"
#ifndef NTPERF
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGEWMI, PerfInfoReserveBytes)
#pragma alloc_text(PAGEWMI, PerfInfoLogBytes)
#endif //ALLOC_PRAGMA
#endif // !NTPERF
NTSTATUS
PerfInfoReserveBytes(
PPERFINFO_HOOK_HANDLE Hook,
USHORT HookId,
ULONG BytesToReserve
)
/*++
Routine Description:
Reserves memory for the hook via WMI and initializes the header.
Arguments:
Hook - pointer to hook handle (used for reference decrement)
HookId - Id for the hook
BytesToLog - size of data in bytes
Return Value:
STATUS_SUCCESS on success
STATUS_UNSUCCESSFUL if the buffer memory couldn't be allocated.
--*/
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PPERFINFO_TRACE_HEADER PPerfTraceHeader = NULL;
PWMI_BUFFER_HEADER PWmiBufferHeader = NULL;
PERF_ASSERT((BytesToReserve + FIELD_OFFSET(PERFINFO_TRACE_HEADER, Data)) <= MAXUSHORT);
PERF_ASSERT(Hook != NULL);
PPerfTraceHeader = WmiReserveWithPerfHeader(BytesToReserve, &PWmiBufferHeader);
if (PPerfTraceHeader != NULL) {
PPerfTraceHeader->Packet.HookId = HookId;
Hook->PerfTraceHeader = PPerfTraceHeader;
Hook->WmiBufferHeader = PWmiBufferHeader;
Status = STATUS_SUCCESS;
} else {
*Hook = PERF_NULL_HOOK_HANDLE;
}
return Status;
}
NTSTATUS
PerfInfoLogBytes(
USHORT HookId,
PVOID Data,
ULONG BytesToLog
)
/*++
Routine Description:
Reserves memory for the hook, copies the data, and unref's the hook entry.
Arguments:
HookId - Id for the hook
Data - pointer to the data to be logged
BytesToLog - size of data in bytes
Return Value:
STATUS_SUCCESS on success
--*/
{
PERFINFO_HOOK_HANDLE Hook;
NTSTATUS Status;
Status = PerfInfoReserveBytes(&Hook, HookId, BytesToLog);
if (!NT_SUCCESS(Status)) {
return Status;
}
RtlCopyMemory(PERFINFO_HOOK_HANDLE_TO_DATA(Hook, PPERF_BYTE), Data, BytesToLog);
PERF_FINISH_HOOK(Hook);
return STATUS_SUCCESS;
}
#ifdef NTPERF
PVOID
FASTCALL
PerfInfoReserveBytesFromPerfMem(
ULONG BytesToReserve
)
/*++
Routine Description:
Reserves memory for the hook from the buffer, initializes the header,
and the hook handle.
Arguments:
Hook - pointer to hook handle (used for reference decrement)
HookId - Id for the hook
BytesToLog - size of data in bytes
Return Value:
STATUS_SUCCESS on success
STATUS_UNSUCCESSFUL if the buffer memory couldn't be allocated.
--*/
{
PPERFINFO_TRACEBUF_HEADER pPerfBufHdr;
PPERF_BYTE CurrentPtr;
PPERF_BYTE NewPtr;
PPERF_BYTE OriginalPtr;
BOOLEAN Done = FALSE;
ULONG AlignedTotBytes;
pPerfBufHdr = PerfBufHdr();
AlignedTotBytes = ALIGN_TO_POWER2(BytesToReserve, DEFAULT_TRACE_ALIGNMENT);
OriginalPtr = pPerfBufHdr->Current.Ptr;
while (!Done) {
NewPtr = OriginalPtr + AlignedTotBytes;
if (NewPtr <= pPerfBufHdr->Max.Ptr) {
//
// If the buffer pointer has not changed, returned value will be == to the comparand,
// OriginalPointer, and the Destenation will be updated with the new end of buffer.
//
// If it did change, the Destination will not change and the a new end of buffer will
// be returned. We loop until we get it in or the buffer is full.
//
CurrentPtr = (PPERF_BYTE) InterlockedCompareExchangePointer(
(PVOID *)&(pPerfBufHdr->Current.Ptr),
(PVOID)NewPtr,
(PVOID)OriginalPtr
);
if (OriginalPtr == CurrentPtr) {
Done = TRUE;
} else {
OriginalPtr = CurrentPtr;
}
} else {
//
// Buffer overflow
//
Done = TRUE;
CurrentPtr = NULL;
}
}
return CurrentPtr;
}
#endif //NTPERF