106 lines
2.9 KiB
C++
106 lines
2.9 KiB
C++
|
extern "C" {
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
}
|
||
|
#include "log.hxx"
|
||
|
|
||
|
#ifdef DBG
|
||
|
|
||
|
/*
|
||
|
* Debuggers should not use this value (which is why it's in the source, not
|
||
|
* the header. Don't get confused! Look for g_OleLogLen instead!
|
||
|
*/
|
||
|
#define OLE32_LOG_MAX (4096)
|
||
|
|
||
|
// The actual log. Allocated on first access to the log function
|
||
|
DebugEvent *gOleLog = NULL;
|
||
|
|
||
|
/*
|
||
|
* The size of the log. While technically I could just use the define,
|
||
|
* changing the value would then break debugger extensions that read this
|
||
|
* stuff, and that would then destroy the whole point of this, now wouldn't
|
||
|
* it?
|
||
|
*/
|
||
|
DWORD gOleLogLen = OLE32_LOG_MAX;
|
||
|
|
||
|
/*
|
||
|
* This is where the next event is going to go.
|
||
|
* To read the log, start with the entry g_OleLog[g_OleLogNext], and work your
|
||
|
* way around to g_OleLog[g_OleLogNext-1]. Ignore every reference to the
|
||
|
* subject SU_NOTHING.... those are entries that haven't been used yet.
|
||
|
*
|
||
|
* Don't you DARE try to log an event that has SU_NOTHING as the subject.
|
||
|
*/
|
||
|
long gOleLogNext = 0;
|
||
|
|
||
|
unsigned char gIgnoreSubject[256] = {0};
|
||
|
unsigned char gIgnoreVerb[256] = {0};
|
||
|
BOOL gfDisableLog = 0;
|
||
|
|
||
|
/*
|
||
|
* Currently there are a couple issues that this does not attempt to solve.
|
||
|
* For example, this does nothing in the case of contention of threads for
|
||
|
* a particular entry in the log. This only happens when the log wraps
|
||
|
* WAY over. The solution requires locking, and I think it's more important
|
||
|
* to be fast in the majority of cases than correct in the extreme minority.
|
||
|
*/
|
||
|
void __Ole32Log (unsigned char Subject, unsigned char Verb,
|
||
|
void *SubjectPtr, void *ObjectPtr, ULONG_PTR UserData,
|
||
|
BOOL fGrabStack, int FramesToSkip)
|
||
|
{
|
||
|
DebugEvent *log;
|
||
|
DWORD myIndex;
|
||
|
|
||
|
if (gIgnoreSubject[Subject] || gIgnoreVerb[Verb] || gfDisableLog)
|
||
|
return;
|
||
|
|
||
|
// Allocate the log...
|
||
|
if (gOleLog == NULL)
|
||
|
{
|
||
|
log = (DebugEvent *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||
|
gOleLogLen * sizeof(DebugEvent));
|
||
|
if (log == NULL)
|
||
|
return;
|
||
|
|
||
|
if (InterlockedCompareExchangePointer((void **)&gOleLog, (void *)log,
|
||
|
NULL) != NULL)
|
||
|
HeapFree(GetProcessHeap(), 0, log);
|
||
|
}
|
||
|
|
||
|
myIndex = InterlockedIncrement(&gOleLogNext) % gOleLogLen;
|
||
|
|
||
|
gOleLog[myIndex].Time = GetTickCount();
|
||
|
gOleLog[myIndex].ThreadID = GetCurrentThreadId();
|
||
|
gOleLog[myIndex].Subject = Subject;
|
||
|
gOleLog[myIndex].Verb = Verb;
|
||
|
gOleLog[myIndex].SubjectPtr= SubjectPtr;
|
||
|
gOleLog[myIndex].ObjectPtr = ObjectPtr;
|
||
|
gOleLog[myIndex].UserData = UserData;
|
||
|
|
||
|
if (fGrabStack)
|
||
|
{
|
||
|
ULONG ignore;
|
||
|
RtlCaptureStackBackTrace( 1 + FramesToSkip, STACKTRACE_DEPTH,
|
||
|
gOleLog[myIndex].Stack, &ignore );
|
||
|
} else {
|
||
|
gOleLog[myIndex].Stack[0] = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // DBG
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|