Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
olestuff.cpp
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 22k
Category:
Windows Kernel
Development Platform:
Visual C++
- #include "priv.h"
- #undef new // Hack! Need to resolve this. (edwardp)
- #define _NO_DBGMEMORY_REDEFINITION_
- #include "dbgmem.h"
- #include <platform.h>
- #define DM_MISC2 0 // misc stuff (verbose)
- #ifdef DEBUG // {
- EXTERN_C LONG g_cmem = 0;
- EXTERN_C DWORD g_TlsMem;
- // BUGBUG:: Gross but simply a static table of people who registered callbacks...
- #define MAX_INTELLI_CALLBACKS 10
- // We will psuedo register our own callback as part of this as to remove a lot of special case code...
- STDAPI_(void) DumpLeakedMemory(PLEAKMEMINFO pmeminfo);
- STDAPI_(LPWSTR) GetLeakSymbolicName(PLEAKMEMINFO pmeminfo, LPWSTR pwszBuf, int cchBuf);
- static const INTELLILEAKDUMPCBFUNCTIONS c_ildcbf = {
- DumpLeakedMemory,
- GetLeakSymbolicName
- };
- int g_cIntelliCallbacks = 1;
- struct INTELLILEAKCALLBACKENTRY
- {
- HMODULE hmod;
- const INTELLILEAKDUMPCBFUNCTIONS *pfns;
- } g_pfnLeakCallbacks[MAX_INTELLI_CALLBACKS] = {{0, &c_ildcbf}};
- STDAPI_(void) _add_to_memlist( HMODULE hmod, void *pv, unsigned int nSize, UINT nType, LPCSTR pszFile, const int iLine )
- {
- // must cache the error so that we can restore it if necessary
- DWORD dwErr = GetLastError();
- HDSA hdsa = (HDSA)TlsGetValue(g_TlsMem);
- if ((hdsa) && (pv)) {
- LEAKMEMINFO memi = { hmod, pv, nSize, nType, pszFile, iLine };
- LEAKMEMINFO *pmemi = &memi;
- if (pmemi->nType == DBGMEM_UNKNOBJ) {
- #if ( _X86_) // { QIStub (and GetStackBack) only work for X86
- if (IsFlagSet(g_dwDumpFlags, DF_DEBUGQI)) {
- extern void * QIStub_CreateInstance(void* that, IUnknown* punk, REFIID riid);
- HRESULT QISearch(void* that, LPCQITAB pqitab, REFIID riid, void ** ppv);
- // if QIStub is on, our frame should look like:
- // ... -> leaker -> [SUPER::QI]* -> xxx::QI -> QISearch ->
- // -> QIStub_CreateInst -> ::new
- // we do our best to follow it back to get to leaker. getting
- // to xxx::QI is pretty easy, getting thru the SUPER::QI's a
- // bit more iffy (but usually works).
- //
- // note that we need to allow for some fudge since a child
- // returns into the middle of a func (i.e. func+FUDGE), not
- // to the beginning (i.e. func+0).
- #define FUDGE(n) (n)
- //
- // TODO: eventually we may hook up to imagehlp's GetStackBacktrace
- // to give a deeper backtrace, but it's a bit heavyweight.
- int fp, n, i, pfunc;
- struct DBstkback sbtab[6]; // enough for a couple SUPER's
- fp = pmemi->iLine;
- n = DBGetStackBack(&fp, sbtab, ARRAYSIZE(sbtab));
- #define INFUNC(p, pfunc, cb) ((pfunc) <= (p) && (p) <= (pfunc) + (cb))
- // skip over QIStub_CI and QISearch explicitly
- pfunc = (int) QIStub_CreateInstance;
- i = 0;
- if (INFUNC(sbtab[0].ret, (int)QIStub_CreateInstance, FUDGE(16))) {
- i++;
- if (INFUNC(sbtab[1].ret, (int)QISearch, FUDGE(512)))
- i++;
- }
- // skip over any known/suspected QI's
- for ( ; i < n; i++) {
- if (! DBIsQIFunc(sbtab[i].ret, FUDGE(64)))
- break;
- }
- TraceMsg(DM_MISC2, "v.atm: n=%d i=%d ret[]=%x,%x,%x,%x,%x,%x", n, i,
- sbtab[0].ret, sbtab[1].ret, sbtab[2].ret, sbtab[3].ret,
- sbtab[4].ret, sbtab[5].ret);
- // this should be the leaker
- pmemi->iLine = sbtab[i].ret;
- }
- else
- {
- // beats me if/why this works for non-x86,
- // but it's what the old code did
- pmemi->iLine = *((int *)iLine + 1); // aka BP_GETRET(iLine)
- }
- #else
- // It beats the non-x86 cpus also.
- // Need to fix this (edwardp).
- pmemi->iLine = 0;
- #endif
- }
- if (DSA_AppendItem(hdsa, &memi) >=0) {
- InterlockedIncrement(&g_cmem);
- }
- }
- // only restore it if it changed,
- // that way people with SLE bps wont be startled
- if (dwErr != GetLastError())
- SetLastError(dwErr);
- }
- void * __cdecl operator new( size_t nSize, LPCSTR pszFile, const int iLine )
- {
- // Zero init just to save some headaches
- void * pv = (void *)LocalAlloc(LPTR, nSize);
- #ifdef DEBUG
- HMODULE hmod = 0;
- if (g_bUseNewLeakDetection)
- hmod = HINST_THISDLL;
- add_to_memlist( hmod, pv, nSize, DBGMEM_OBJECT, pszFile, iLine );
- #endif
- return pv;
- }
- void * __cdecl operator new( size_t nSize )
- {
- //
- // HACK! The compiler is putting hmod as the first local (EBP - 4). So
- // point pstack to &hmod. We need to get rid of this scumbag code!
- // (edwardp)
- //
- void * pv;
- #ifdef DEBUG
- HMODULE hmod = 0;
- LPDWORD pstack = (LPDWORD) &hmod; // HACK! compiler is putting hmod as first local.
- #endif
- // Zero init just to save some headaches
- pv = (void *)LocalAlloc(LPTR, nSize);
- #ifdef DEBUG
- if (g_bUseNewLeakDetection)
- hmod = HINST_THISDLL;
- add_to_memlist( hmod, pv, nSize, DBGMEM_UNKNOBJ, "UNKNOWN", (INT_PTR) &pstack[1] );
- #endif
- return pv;
- }
- int _DSA_GetPtrIndex(HDSA hdsa, void* pv)
- {
- for (int i=0; i<DSA_GetItemCount(hdsa); i++) {
- LEAKMEMINFO* pmemi = (LEAKMEMINFO*)DSA_GetItemPtr(hdsa, i);
- if (pmemi->pv == pv) {
- return i;
- }
- }
- return -1;
- }
- STDAPI_(void) _remove_from_memlist(void *pv)
- {
- // must cache the error so that we can restore it if necessary
- DWORD dwErr = GetLastError();
- HDSA hdsa = (HDSA)TlsGetValue(g_TlsMem);
- if (hdsa) {
- int index = _DSA_GetPtrIndex(hdsa, pv);
- if (index >=0) {
- DSA_DeleteItem(hdsa, index);
- InterlockedDecrement(&g_cmem);
- }
- }
- // only restore it if it changed,
- // that way people with SLE bps wont be startled
- if (dwErr != GetLastError())
- SetLastError(dwErr);
- }
- static UINT g_uMemMove = 0;
- STDAPI_(UINT) _mem_thread_message()
- {
- if ( !g_uMemMove )
- g_uMemMove = RegisterWindowMessage(TEXT("Shdocvw_ThreadMemTransfer"));
- return g_uMemMove;
- }
- STDAPI_(void) _transfer_to_thread_memlist(DWORD dwThreadId, void *pv)
- {
- UINT uMsg = mem_thread_message();
- // must cache the error so that we can restore it if necessary
- DWORD dwErr = GetLastError();
- HDSA hdsa = (HDSA)TlsGetValue(g_TlsMem);
- if ( hdsa )
- {
- int index = _DSA_GetPtrIndex( hdsa, pv );
- if ( index >= 0)
- {
- LEAKMEMINFO *pMemBlock = (LEAKMEMINFO*) DSA_GetItemPtr(hdsa, index);
- LEAKMEMINFO *pNewBlock = (LEAKMEMINFO*) LocalAlloc( LPTR, sizeof(LEAKMEMINFO ));
- if ( pNewBlock )
- {
- *pNewBlock = *pMemBlock;
- // post a message to the thread giving it the memblock
- PostThreadMessage( dwThreadId, uMsg, 0, (LPARAM) pNewBlock );
- }
- // remove from the current thread's list...
- DSA_DeleteItem( hdsa, index );
- InterlockedDecrement(&g_cmem);
- }
- }
- // only restore it if it changed,
- // that way people with SLE bps wont be startled
- if (dwErr != GetLastError())
- SetLastError(dwErr);
- }
- STDAPI_(void) _remove_from_thread_memlist( DWORD dwThreadId, void * pv )
- {
- UINT uMsg = mem_thread_message();
- PostThreadMessage( dwThreadId, uMsg, 1, (LPARAM) pv );
- }
- STDAPI_(void) _received_for_thread_memlist( DWORD dwFlags, void * pData )
- {
- // must cache the error so that we can restore it if necessary
- DWORD dwErr = GetLastError();
- LEAKMEMINFO * pMem = (LEAKMEMINFO *) pData;
- if ( pMem ){
- if ( dwFlags )
- {
- // we are being told to remove it from our thread list because it
- // is actually being freed on the other thread....
- remove_from_memlist( pMem->pv );
- return;
- }
- HDSA hdsa = (HDSA)TlsGetValue(g_TlsMem);
- if (hdsa) {
- if (DSA_AppendItem(hdsa, pMem) >=0) {
- InterlockedIncrement(&g_cmem);
- }
- }
- LocalFree( pMem );
- }
- // only restore it if it changed,
- // that way people with SLE bps wont be startled
- if (dwErr != GetLastError())
- SetLastError(dwErr);
- }
- void __cdecl operator delete(void *pv)
- {
- if (pv) {
- remove_from_memlist(pv);
- memset(pv, 0xfe, (UINT)LocalSize((HLOCAL)pv));
- LocalFree((HLOCAL)pv);
- }
- }
- EXTERN_C int __cdecl _purecall(void) {return 0;}
- //*** heuristics {
- //*** GetLeakSymbolic -- get human-readable name for object
- //
- TCHAR *GetLeakSymbolic(LEAKMEMINFO *pLeak)
- {
- extern TCHAR *DBGetQIStubSymbolic(void* that);
- extern TCHAR *DBGetClassSymbolic(int cbSize);
- TCHAR *pszSym;
- #if ( _X86_) // { QIStub only works for X86
- if (pLeak->nType == DBGMEM_UNKNOBJ && DBIsQIStub(pLeak->pv))
- pszSym = DBGetQIStubSymbolic(pLeak->pv);
- else
- #endif // }
- if (pszSym = DBGetClassSymbolic(pLeak->cb))
- ;
- else {
- // if you get this string, go into debdump.cpp and add a
- // DBGetClassSymbolic table entry for the class
- pszSym = TEXT("?debdump!DBGetClassSymbolic");
- }
- return pszSym;
- }
- //*** _ConvertHModToIntelliDumpIndex
- // DESCRIPTION
- // main heuristics:
- int _ConvertHModToIntelliDumpIndex(HMODULE hmod)
- {
- for (int i = 0; i < g_cIntelliCallbacks; i++) {
- if ((hmod == g_pfnLeakCallbacks[i].hmod) &&
- !IsBadCodePtr((FARPROC)g_pfnLeakCallbacks[i].pfns->pfnDumpLeakedMemory)) {
- return i;
- }
- }
- return -1;
- }
- //*** _DoDumpMemLeakIntelli -- attempt to interpret leak info
- // DESCRIPTION
- // main heuristics:
- // try to detect refs from one object to another by walking all DWORDs
- // this gives us a graph description
- // more importantly, it tells us which are the 'root' leaks
- // identify classes so we can label them w/ a symbolic name
- // identify QIStub's so we can dump them nicely
- // e.g. symbolic IID and a sequence # for that IID
- // the sequence # can be used to find the exact QI call
- // others:
- // see the code (sorry)...
- // NOTES
- // algorithm is n^2, so sue me...
- // we assume (hopefully correctly...) that all memory is aligned to a
- // 'strict' boundary so we'll never fault dereferencing DWORDs. if that
- // turns out to be wrong we can wrap in a __try...__except.
- void _DoDumpMemLeakIntelli(HDSA hdsa, DWORD wFlags)
- {
- int cLeak;
- ASSERT(wFlags & DML_END);
- ASSERT(hdsa);
- cLeak = DSA_GetItemCount(hdsa);
- if (!cLeak)
- return;
- TraceMsg(TF_ALWAYS, "intelli-leak heuristics...");
- for (int iDef = 0; iDef < cLeak; iDef++) {
- LEAKMEMINFO* pDef = (LEAKMEMINFO*)DSA_GetItemPtr(hdsa, iDef);
- BOOL fHasRef;
- int iDumpModule;
- if (IsBadReadPtr(pDef->pv, pDef->cb))
- continue;
- // see if we should hand this one off to a different dumper?
- if ((iDumpModule = _ConvertHModToIntelliDumpIndex(pDef->hmod)) >= 0) {
- g_pfnLeakCallbacks[iDumpModule].pfns->pfnDumpLeakedMemory(pDef);
- }
- else {
- ASSERT(FALSE);
- }
- // find all (likely) refs to this leak. we do this by walking
- // the full set of leaks and looking for DWORDs that point to
- // the base of this leak. we only look at the base on the
- // assumption that ptrs will go thru QIStub's (and this bounds
- // the search which is nice).
- fHasRef = FALSE;
- for (int iRef = 0; iRef < cLeak; iRef++) {
- LEAKMEMINFO* pRef = (LEAKMEMINFO*)DSA_GetItemPtr(hdsa, iRef);
- int dOff;
- if (IsBadReadPtr(pRef->pv, pRef->cb))
- continue;
- #define TRUNCPOW2(n, p) ((n) & ~((p) - 1))
- dOff = SearchDW((DWORD*)pRef->pv, TRUNCPOW2(pRef->cb, SIZEOF(DWORD)), PtrToLong(pDef->pv));
- if (dOff != -1) {
- // found a ref to the leak def!
- if ((iDumpModule = _ConvertHModToIntelliDumpIndex(pRef->hmod)) >= 0) {
- WCHAR szBuf[80];
- LPWSTR pwszRef = g_pfnLeakCallbacks[iDumpModule].pfns->pfnGetLeakSymbolicName(pDef,
- szBuf, ARRAYSIZE(szBuf));
- TraceMsg(TF_ALWAYS, "tref=%x,%x+%x(%ls)",
- pRef->pv, pRef->cb, dOff, pwszRef);
- }
- else {
- ASSERT(FALSE);
- }
- // a fair number of objects actually point back to themselves
- // print out the ref just in case, but don't count it as a
- // real one (which will make us look like a non-root)
- if (pRef->pv != pDef->pv)
- fHasRef = TRUE;
- else
- TraceMsg(TF_ALWAYS, "tref=self");
- // (we could iterate on pRef->pv+dOff+SIZEOF(DWORD),
- // but probably the 1st hit is all we need)
- }
- }
- if (!fHasRef) {
- // these are the guys we really care about
- TraceMsg(TF_ALWAYS, "tref=root ***");
- }
- }
- // drop into debugger for further analysis
- ASSERT_MSG(0, "Take this opportunity to debug the leak");
- return;
- }
- // }
- void _DoDumpMemLeak(HDSA hdsa, DWORD wFlags)
- {
- BOOL fLeaked = FALSE;
- ASSERT(wFlags & DML_END);
- ASSERT(hdsa);
- if (DSA_GetItemCount(hdsa)) {
- // Let's always dump them.
- TraceMsg(TF_ALWAYS, "****************************************************");
- TraceMsg(TF_ALWAYS, "* !!!!! WARNING : MEMORY LEAK DETECTED !!!!! *");
- TraceMsg(TF_ALWAYS, "****************************************************");
- TraceMsg(TF_ALWAYS, "* For Object: address: Vtbl, ...Vtbl, _cRef *");
- TraceMsg(TF_ALWAYS, "* For StrDup: address: 'text' *");
- TraceMsg(TF_ALWAYS, "* For Traced: address: *");
- TraceMsg(TF_ALWAYS, "* For Memory: address: *");
- TraceMsg(TF_ALWAYS, "****************************************************");
- {
- for (int i=0; i<DSA_GetItemCount(hdsa); i++) {
- LEAKMEMINFO* pmemi = (LEAKMEMINFO*)DSA_GetItemPtr(hdsa, i);
- DWORD* pdw = (DWORD*)pmemi->pv;
- // sometimes we think we have leaked something and its really been freed,
- // so check here first
- if (IsBadReadPtr((void *)pdw, pmemi->cb))
- continue;
- switch( pmemi->nType ) {
- case DBGMEM_STRDUP:
- TraceMsgA(TF_ALWAYS, "StrDup: %8x: "%s"ntt size=%d (%s, line %d)",
- pdw, pdw, pmemi->cb, PathFindFileNameA(pmemi->pszFile), pmemi->iLine);
- break;
- case DBGMEM_UNKNOBJ:
- case DBGMEM_OBJECT:
- {
- if ( pmemi->cb >= 32 )
- {
- TraceMsg(TF_ALWAYS, "Object: %8x: %8x %8x %8x %8x",
- pdw, pdw[0], pdw[1], pdw[2], pdw[3] );
- }
- else
- {
- TraceMsg(TF_ALWAYS, "Object: %8x: Size<32 bytes. No Vtbl.", pdw );
- }
- }
- break;
- case DBGMEM_TRACED:
- TraceMsg(TF_ALWAYS, "Traced: %8x:", pdw );
- break;
- case DBGMEM_MEMORY:
- default:
- TraceMsg(TF_ALWAYS, "Memory: %8x:", pdw );
- break;
- }
- if ( pmemi->nType == DBGMEM_UNKNOBJ )
- {
- TraceMsg(TF_ALWAYS, "t size=%d, created from %8x (return address)",
- pmemi->cb, pmemi->iLine);
- }
- else
- {
- TraceMsgA(TF_ALWAYS, "t size=%d (%s, line %d)",
- pmemi->cb, PathFindFileNameA(pmemi->pszFile), pmemi->iLine);
- }
- }
- }
- TraceMsg(TF_ALWAYS, "*************************************************");
- AssertMsg(0, TEXT("*** ALL MEMORY LEAK MUST BE FIXED BEFORE WE RELEASE (continue for intelli-leak on x86) ***"));
- fLeaked = TRUE;
- }
- if (!fLeaked) {
- TraceMsg(TF_GENERAL, "Thread Terminated: -- No Memory Leak Detected for this thread --");
- }
- }
- void _DumpMemLeak(DWORD wFlags)
- {
- HDSA hdsa;
- if (wFlags & DML_END) {
- hdsa = (HDSA)TlsGetValue(g_TlsMem);
- if (hdsa) {
- _DoDumpMemLeak(hdsa, wFlags);
- _DoDumpMemLeakIntelli(hdsa, wFlags);
- DSA_Destroy(hdsa);
- TlsSetValue(g_TlsMem, NULL);
- }
- } else {
- hdsa = DSA_Create(SIZEOF(LEAKMEMINFO),8);
- TlsSetValue(g_TlsMem, (void *)hdsa);
- }
- }
- STDAPI_(void) _DebugMemLeak(UINT wFlags, LPCTSTR pszFile, UINT iLine)
- {
- LPCTSTR pszSuffix = (wFlags & DML_END) ? TEXT("END") : TEXT("BEGIN");
- switch(wFlags & DML_TYPE_MASK) {
- case DML_TYPE_MAIN:
- _DumpMemLeak(wFlags);
- if (g_cmem) {
- AssertMsg(0, TEXT("MAIN: %s, line %d: %d blocks of C++ objects left in memory. Read shdocvw") TEXT(FILENAME_SEPARATOR_STR) TEXT("memleak.txt for detail"),
- PathFindFileName(pszFile), iLine, g_cmem);
- }
- break;
- case DML_TYPE_THREAD:
- if (g_tidParking != GetCurrentThreadId())
- _DumpMemLeak(wFlags);
- break;
- case DML_TYPE_NAVIGATE:
- TraceMsg(TF_SHDLIFE, "NAVIGATEW_%s: %s, line %d: %d blocks of C++ objects in memory",
- pszSuffix, PathFindFileName(pszFile), iLine, g_cmem);
- break;
- }
- }
- // LocalXXXXX functions
- STDAPI_(HLOCAL) _TrcLocalAlloc(
- UINT uFlags, // flags used in LocalAlloc
- UINT uBytes, // number of bytes to be allocated
- LPCSTR pszFile, // file which allocced memory
- const int iLine // line which allocced memory
- )
- {
- HLOCAL lpv = (HLOCAL) LocalAlloc( uFlags, uBytes );
- if ( lpv )
- add_to_memlist( 0, lpv, uBytes, DBGMEM_MEMORY, pszFile, iLine );
- return lpv;
- }
- STDAPI_(LPTSTR) _TrcStrDup(
- LPTSTR lpSrch, // pointer to string to StrDup
- LPCSTR pszFile, // file which allocced memory
- const int iLine // line which allocced memory
- )
- {
- UINT uBytes = 0;
- if ( lpSrch )
- uBytes = lstrlen( lpSrch ) + 1;
- LPTSTR lpstr = StrDup( lpSrch );
- if ( lpstr )
- add_to_memlist( 0, lpstr, uBytes, DBGMEM_STRDUP, pszFile, iLine );
- return lpstr;
- }
- STDAPI_(HLOCAL) _TrcLocalFree(
- HLOCAL hMem // memory to be freed
- )
- {
- if ( hMem )
- {
- remove_from_memlist( hMem );
- memset( hMem, 0xfe, (UINT)LocalSize( hMem ));
- }
- return LocalFree( hMem );
- }
- STDAPI_(void) _register_intelli_dump(HMODULE hmod, const INTELLILEAKDUMPCBFUNCTIONS *pfns)
- {
- if (g_cIntelliCallbacks < (MAX_INTELLI_CALLBACKS - 1))
- {
- g_pfnLeakCallbacks[g_cIntelliCallbacks].hmod = hmod;
- g_pfnLeakCallbacks[g_cIntelliCallbacks].pfns = pfns;
- g_cIntelliCallbacks++;
- }
- }
- #else // }{
- #define CPP_FUNCTIONS
- #include <crtfree.h>
- #endif // }
- BOOL GetLeakDetectionFunctionTable(LEAKDETECTFUNCS *pTable)
- {
- #ifdef DEBUG
- if(pTable)
- {
- pTable->pfnDumpMemLeak = _DumpMemLeak;
- pTable->pfnTrcLocalAlloc = _TrcLocalAlloc;
- pTable->pfnTrcLocalFree = _TrcLocalFree;
- pTable->pfnTrcStrDup = _TrcStrDup;
- pTable->pfnDumpMemLeak = _DumpMemLeak;
- pTable->pfnDebugMemLeak = MemLeakInit; //_DebugMemLeak;
- pTable->pfnreceived_for_thread_memlist = received_for_thread_memlist;
- pTable->pfnremove_from_thread_memlist = remove_from_thread_memlist;
- pTable->pfnmem_thread_message = mem_thread_message;
- pTable->pfnremove_from_memlist = remove_from_memlist;
- pTable->pfnadd_to_memlist = add_to_memlist;
- pTable->pfnregister_hmod_intelli_dump = register_intelli_dump;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- #else
- return FALSE;
- #endif
- }
- // We export all the memory leak detection functions in the form of a table of
- // pointers so that all other shell components can share in the same leak
- // detection code
- // -----------------------------------------------------------------------------
- // These two functions are our DLLS callback functions to dump the acutal leaks...
- #ifdef DEBUG
- //*** GetLeakSymbolicName
- // DESCRIPTION
- STDAPI_(LPWSTR) GetLeakSymbolicName(PLEAKMEMINFO pmeminfo, LPWSTR pwszBuf, int cchBuf)
- {
- LPTSTR pszDef = GetLeakSymbolic(pmeminfo); // human-readable name
- // they only want the class name...
- return pszDef;
- }
- //*** Dump LeakedMemory
- // DESCRIPTION
- STDAPI_(void) DumpLeakedMemory(LEAKMEMINFO* pmeminfo)
- {
- LPTSTR pszDef = GetLeakSymbolic(pmeminfo); // human-readable name
- TraceMsg(TF_ALWAYS, "leak=0x%x,%x(%s)", pmeminfo->pv, pmeminfo->cb, pszDef);
- if (pmeminfo->nType == DBGMEM_UNKNOBJ)
- TraceMsg(TF_ALWAYS, "tcreated from 0x%x", pmeminfo->iLine);
- else
- TraceMsgA(TF_ALWAYS, "tcreated from %hs:%d",
- PathFindFileNameA(pmeminfo->pszFile), pmeminfo->iLine);
- #if ( _X86_) // { QIStub only works for X86
- if (pmeminfo->nType == DBGMEM_UNKNOBJ && DBIsQIStub(pmeminfo->pv)) {
- // it's a QIStub, dump it
- // of particular interest is the 'sequence #' (esp. for roots)
- DBDumpQIStub(pmeminfo->pv);
- }
- #endif // }
- }
- #endif