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
|