186 lines
4.2 KiB
C
186 lines
4.2 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|