00001
00002
00003
00004
00005
00006
00007
00008 #include "common.h"
00009 #include <stdio.h>
00010 #include <stdarg.h>
00011
00012
00013
00014
00015 ULONG IncRefCount( inout ULONG* refCount )
00016 {
00017 return (ULONG)InterlockedIncrement( (LONG*)refCount );
00018 }
00019
00020 ULONG DecRefCount( inout ULONG* refCount )
00021 {
00022 return (ULONG)InterlockedDecrement( (LONG*)refCount );
00023 }
00024
00025
00026
00027
00028
00029
00030 static const char* g_traceModuleName = NULL;
00031 static CRITICAL_SECTION g_traceGuard;
00032 static DWORD g_traceThreadID;
00033
00034 void Trace( const char* format, ... )
00035 {
00036 va_list args;
00037 va_start( args, format );
00038
00039 EnterCriticalSection( &g_traceGuard );
00040
00041 if (g_traceModuleName)
00042 {
00043 OutputDebugStringA(g_traceModuleName);
00044 OutputDebugStringA( ": " );
00045 }
00046
00047 char buffer[1024];
00048
00049 DWORD threadID = GetCurrentThreadId();
00050 if (threadID != g_traceThreadID)
00051 {
00052 _snprintf( buffer, 1023, "tid 0x%x: ", threadID );
00053 buffer[1023] = 0;
00054 OutputDebugStringA(buffer);
00055 }
00056
00057 _vsnprintf( buffer, 1024, format, args );
00058 buffer[1023] = 0;
00059 OutputDebugStringA(buffer);
00060
00061 OutputDebugStringA( "\n" );
00062
00063 LeaveCriticalSection( &g_traceGuard );
00064
00065 va_end( args );
00066 return;
00067 }
00068
00069
00070
00071
00072
00073 struct ObjectInfo
00074 {
00075 ObjectInfo* next;
00076 const char* name;
00077 IUnknown* obj;
00078 };
00079
00080 static ObjectInfo* objectList = NULL;
00081
00082 void TraceDumpObjects()
00083 {
00084 EnterCriticalSection( &g_traceGuard );
00085
00086 TRACE("live objects:");
00087 for (ObjectInfo* objectInfo = objectList; objectInfo; objectInfo = objectInfo->next )
00088 {
00089 ULONG refCount = objectInfo->obj->AddRef();
00090 if (refCount > 0)
00091 {
00092 objectInfo->obj->Release();
00093 refCount--;
00094 }
00095 TRACE3( " 0x%x, refcount %u, %s", objectInfo->obj, refCount, objectInfo->name);
00096 }
00097
00098 LeaveCriticalSection( &g_traceGuard );
00099 }
00100
00101 void TraceInit( in const char* moduleName )
00102 {
00103 InitializeCriticalSection( &g_traceGuard );
00104 g_traceThreadID = GetCurrentThreadId();
00105
00106 g_traceModuleName = moduleName;
00107 objectList = NULL;
00108
00109 }
00110
00111 void TraceDone()
00112 {
00113 EnterCriticalSection( &g_traceGuard );
00114
00115 if (objectList)
00116 {
00117 TRACE( "found live objects:" );
00118 TraceDumpObjects();
00119 }
00120
00121 ObjectInfo* objectInfo;
00122 ObjectInfo* objectNext;
00123
00124 objectInfo = objectList;
00125 while (objectInfo)
00126 {
00127 objectNext = objectInfo->next;
00128 FREE(objectInfo);
00129 objectInfo = objectNext;
00130 }
00131
00132 objectList = NULL;
00133
00134 LeaveCriticalSection( &g_traceGuard );
00135 DeleteCriticalSection( &g_traceGuard );
00136 }
00137
00138
00139
00140 void TraceCreate( const char* name, IUnknown* obj )
00141 {
00142 EnterCriticalSection( &g_traceGuard );
00143
00144 ObjectInfo* objectInfo = ALLOC(ObjectInfo);
00145 if (!objectInfo) return;
00146 if (!obj)
00147 {
00148 TRACE1("TraceCreate: creation of %s failed", name );
00149 return;
00150 }
00151
00152 TRACE2( "create %s at 0x%x", name, obj );
00153 objectInfo->name = name;
00154 objectInfo->obj = obj;
00155 objectInfo->next = objectList;
00156 objectList = objectInfo;
00157
00158 LeaveCriticalSection( &g_traceGuard );
00159 }
00160
00161 void TraceDestroy( IUnknown* obj )
00162 {
00163 EnterCriticalSection( &g_traceGuard );
00164
00165 ObjectInfo* objectInfo;
00166 ObjectInfo* objectPrev = NULL;
00167
00168 for (objectInfo = objectList; objectInfo; objectInfo = objectInfo->next)
00169 {
00170 if (objectInfo->obj == obj) break;
00171 objectPrev = objectInfo;
00172 }
00173
00174 if (!objectInfo)
00175 {
00176 TRACE1( "TraceDestroy: destroying unknown object at 0x%x", obj );
00177 }
00178 else
00179 {
00180 TRACE2( "destroy %s at 0x%8x", objectInfo->name, objectInfo->obj );
00181 if (objectPrev)
00182 objectPrev->next = objectInfo->next;
00183 else
00184 objectList = objectInfo->next;
00185
00186 FREE(objectInfo);
00187 }
00188
00189 LeaveCriticalSection( &g_traceGuard );
00190 }