|
|
//
//
//
// This file cannot be compiled as a C++ file, otherwise the linker
// will bail on unresolved externals (even with extern "C" wrapping
// this).
#include "precomp.h"
// Define some things for debug.h
//
#define SZ_DEBUGINI "ccshell.ini"
#define SZ_DEBUGSECTION "deskcpl"
#define SZ_MODULE "DESKCPL"
#define DECLARE_DEBUG
#include "debug.h"
// Include the standard helper functions to dump common ADTs
//#include "..\lib\dump.c"
#ifdef DEBUG
//
// Typedefs
//
typedef struct _ALLOCHEADER { LIST_ENTRY ListEntry; PTCHAR File; ULONG Line; LONG AllocNumber; ULONG Size; } ALLOCHEADER, *PALLOCHEADER;
//
// Globals
//
LIST_ENTRY AllocListHead = { &AllocListHead, &AllocListHead };
#undef LocalAlloc
#undef LocalReAlloc
#undef LocalFree
INT g_BreakAtAlloc = -1; INT g_BreakAtFree = -1; ULONG g_AllocNumber = 0;
#define TRAP() DbgBreakPoint()
//*****************************************************************************
//
// MyAlloc()
//
//*****************************************************************************
HLOCAL DeskAllocPrivate ( const TCHAR *File, ULONG Line, ULONG Flags, DWORD dwBytes ) { static ULONG allocNumber = 0; DWORD bytes; PALLOCHEADER header;
if (dwBytes) { bytes = dwBytes + sizeof(ALLOCHEADER);
header = (PALLOCHEADER)LocalAlloc(Flags, bytes);
if (header != NULL) { InsertTailList(&AllocListHead, &header->ListEntry);
header->File = (TCHAR*) File; header->Line = Line; header->AllocNumber = ++allocNumber; header->Size = dwBytes;
if (header->AllocNumber == g_BreakAtAlloc) { // user set assert
TRAP(); }
return (HLOCAL)(header + 1); } }
return NULL; }
//*****************************************************************************
//
// MyReAlloc()
//
//*****************************************************************************
HLOCAL DeskReAllocPrivate ( const TCHAR *File, ULONG Line, HLOCAL hMem, DWORD dwBytes, ULONG Flags ) { PALLOCHEADER header; PALLOCHEADER headerNew;
if (hMem) { header = (PALLOCHEADER)hMem;
header--;
// Remove the old address from the allocation list
//
RemoveEntryList(&header->ListEntry);
headerNew = (PALLOCHEADER) LocalReAlloc((HLOCAL)header, dwBytes, Flags);
if (headerNew != NULL) { // Add the new address to the allocation list
//
headerNew->File = (TCHAR*) File; headerNew->Line = Line; headerNew->AllocNumber = ++g_AllocNumber; headerNew->Size = dwBytes;
if (headerNew->AllocNumber == g_BreakAtAlloc) { // user set assert
TRAP(); }
InsertTailList(&AllocListHead, &headerNew->ListEntry);
return (HLOCAL)(headerNew + 1); } else { // If GlobalReAlloc fails, the original memory is not freed,
// and the original handle and pointer are still valid.
// Add the old address back to the allocation list.
//
InsertTailList(&AllocListHead, &header->ListEntry); }
}
return NULL; }
//*****************************************************************************
//
// MyFree()
//
//*****************************************************************************
HLOCAL DeskFreePrivate ( HLOCAL hMem ) { PALLOCHEADER header; TCHAR buf[128];
if (hMem) { header = (PALLOCHEADER)hMem; header--;
if (header->AllocNumber == g_BreakAtFree) { TRAP(); }
wsprintf(buf, TEXT("free alloc number %d, size %d\r\n"), header->AllocNumber, header->Size);
RemoveEntryList(&header->ListEntry);
return LocalFree((HLOCAL)header); } return LocalFree(hMem); }
HLOCAL DeskFreeDirect (HLOCAL hMem)
{ return(LocalFree(hMem)); }
//*****************************************************************************
//
// MyCheckForLeaks()
//
//*****************************************************************************
VOID DeskCheckForLeaksPrivate ( VOID ) { PALLOCHEADER header; TCHAR buf[1024+40], tmpBuf[512]; unsigned int i, size, size2, ic; DWORD *pdw; char *pch, *pch2; LPVOID mem;
#if UNICODE
#define DeskIsPrintable iswprint
#else
#define DeskIsPrintable isprint
#endif
while (!IsListEmpty(&AllocListHead)) { header = (PALLOCHEADER)RemoveHeadList(&AllocListHead); mem = header + 1; wsprintf(buf, TEXT("Desk.cpl mem leak in File: %s\r\n Line: %d Size: %d Allocation: %d Buffer: 0x%x\r\n"), header->File, header->Line, header->Size, header->AllocNumber, mem); OutputDebugString(buf);
//
// easy stuff, print out all the 4 DWORDS we can
//
pdw = (DWORD *) mem; pch = (char *) mem; *buf = TEXT('\0'); for (i = 0; i < header->Size/16; i++, pdw += 4) { wsprintf(tmpBuf, TEXT(" %08x %08x %08x %08x "), pdw[0], pdw[1], pdw[2], pdw[3]); lstrcat(buf, tmpBuf);
for (ic = 0; ic < 16; ic++, pch++) { tmpBuf[ic] = DeskIsPrintable(*pch) ? *pch : TEXT('.'); } tmpBuf[ic] = TEXT('\0'); lstrcat(buf, tmpBuf); OutputDebugString(buf); OutputDebugString(TEXT("\n"));
*buf = TEXT('\0'); }
//
// Is there less than a 16 byte chunk left?
//
size = header->Size % 16; if (size) { //
// Print all the DWORDs we can
//
for (i = 0; i < size / 4; i++, pdw++) { wsprintf(tmpBuf, TEXT(" %08x"), *pdw); lstrcat(buf, tmpBuf); }
if (size % 4) { //
// Print the remaining bytes
//
lstrcat(buf, TEXT(" "));
pch2 = (char*) pdw; for (i = 0; i < size % 4; i++, pch2++) { wsprintf(tmpBuf, TEXT("%02x"), (DWORD) *pch2); lstrcat(buf, tmpBuf); }
//
// Align with 4 bytes
//
for ( ; i < 4; i++) { lstrcat(buf, TEXT(" ")); } }
//
// Print blanks for any remaining DWORDs (ie to match the 4 above)
//
size2 = (16 - (header->Size % 16)) / 4; for (i = 0; i < size2; i++) { lstrcat(buf, TEXT(" ")); }
lstrcat(buf, TEXT(" ")); //
// Print the actual remain bytes as chars
//
for (i = 0; i < size; i++, pch++) { tmpBuf[i] = DeskIsPrintable(*pch) ? *pch : TEXT('.'); } tmpBuf[i] = TEXT('\0'); lstrcat(buf, tmpBuf);
OutputDebugString(buf); OutputDebugString(TEXT("\n")); }
OutputDebugString(TEXT("\n")); ASSERT(0); } }
#endif
|