extern "C" { #include #include #include #include } #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