|
|
/*++
� 1998 Seagate Software, Inc. All rights reserved
Module Name:
wsbtrak.cpp
Abstract:
Utility functions to keep track of run-time information.
Author:
Ron White [ronw] 5-Dec-1997
Revision History:
--*/
#include "stdafx.h"
#include "wsbguid.h"
#if defined(WSB_TRACK_MEMORY)
#define OBJECT_TABLE_SIZE 100
#define POINTER_DATA_CURRENT 0
#define POINTER_DATA_CUMULATIVE 2
#define POINTER_DATA_MAX 1
#define POINTER_DATA_SIZE 3
#define POINTER_LIST_SIZE 1000
typedef struct { GUID guid; LONG count; LONG total_count; LONG max_count; } OBJECT_TABLE_ENTRY;
typedef struct { OLECHAR * guid_string; OLECHAR * name; GUID * pGuid; } OBJECT_NAME_ENTRY;
typedef struct { LONG count; LONGLONG size; } POINTER_DATA_ENTRY;
typedef struct { const void * addr; LONG order; ULONG size; int index; // Index into object table
const char * filename; int linenum; } POINTER_LIST_ENTRY;
// Module data
#if defined(CRT_DEBUG_MEMORY)
static _CrtMemState CrtMemState; #endif
static OBJECT_TABLE_ENTRY object_table[OBJECT_TABLE_SIZE]; static int object_table_count = 0; static POINTER_DATA_ENTRY pointer_data[POINTER_DATA_SIZE]; static BOOL pointer_data_initialized = FALSE; static POINTER_LIST_ENTRY pointer_list[POINTER_LIST_SIZE]; static int pointer_list_count = 0;
static OBJECT_NAME_ENTRY object_name_table[] = { { L"{C03D4861-70D7-11d1-994F-0060976A546D}", L"CWsbStringPtr", NULL }, { L"{C03D4862-70D7-11d1-994F-0060976A546D}", L"CWsbBstrPtr", NULL }, { L"{A0FF1F42-237A-11D0-81BA-00A0C91180F2}", L"CWsbGuid", NULL }, { L"{9C7D6F13-1562-11D0-81AC-00A0C91180F2}", L"CWsbOrderedCollection", NULL }, { L"{46CE9EDE-447C-11D0-98FC-00A0C9058BF6}", L"CWsbDbKey", NULL },
{ L"{E707D9B2-4F89-11D0-81CC-00A0C91180F2}", L"CFsaServerNTFS", NULL }, { L"{FCDC8671-7329-11d0-81DF-00A0C91180F2}", L"CFsaFilterNTFS", NULL }, { L"{112981B3-1BA5-11D0-81B2-00A0C91180F2}", L"CFsaResourceNTFS", NULL }, { L"{0B8B6F12-8B3A-11D0-990C-00A0C9058BF6}", L"CFsaPremigratedDb", NULL }, { L"{14005FF1-8B4F-11d0-81E6-00A0C91180F2}", L"CFsaTruncatorNTFS", NULL }, { L"{CECCB131-286D-11d1-993E-0060976A546D}", L"CFsaRecoveryRec", NULL }, { L"{7CA819F2-8AAB-11D0-990C-00A0C9058BF6}", L"CFsaPremigratedRec", NULL }, { L"{B2AD2931-84FD-11d0-81E4-00A0C91180F2}", L"CFsaFilterClientNTFS", NULL }, { L"{F7860350-AA27-11d0-B16D-00A0C916F120}", L"CFsaPostIt", NULL }, { L"{B2AD2932-84FD-11d0-81E4-00A0C91180F2}", L"CFsaFilterRecallNTFS", NULL }, { L"{112981B2-1BA5-11D0-81B2-00A0C91180F2}", L"CFsaScanItemNTFS", NULL },
{ L"{7B22FF29-1AD6-11D0-81B1-00A0C91180F2}", L"CHsmActionManage", NULL }, { L"{D9E04211-14D7-11d1-9938-0060976A546D}", L"CHsmActionOnResourcePostValidate", NULL }, { L"{D9E04212-14D7-11d1-9938-0060976A546D}", L"CHsmActionOnResourcePreValidate", NULL }, { L"{7B22FF24-1AD6-11D0-81B1-00A0C91180F2}", L"CHsmActionTruncate", NULL }, { L"{D3AF5DB1-1DF8-11D0-81B6-00A0C91180F2}", L"CHsmActionUnmanage", NULL }, { L"{7B22FF26-1AD6-11D0-81B1-00A0C91180F2}", L"CHsmActionValidate", NULL }, { L"{AD40235F-00FC-11D0-819C-00A0C91180F2}", L"CHsmCritAlways", NULL }, { L"{CFB04622-1C9F-11D0-81B4-00A0C91180F2}", L"CHsmCritManageable", NULL }, { L"{7B22FF2C-1AD6-11D0-81B1-00A0C91180F2}", L"CHsmCritMigrated", NULL }, { L"{7B22FF2D-1AD6-11D0-81B1-00A0C91180F2}", L"CHsmCritPremigrated", NULL }, { L"{AD402346-00FC-11D0-819C-00A0C91180F2}", L"CHsmJob", NULL }, { L"{AD402364-00FC-11D0-819C-00a0C91180F2}", L"CHsmJobContext", NULL }, { L"{AD40234B-00FC-11D0-819C-00a0C91180F2}", L"CHsmJobDef", NULL }, { L"{B8E1CD21-81D3-11d0-81E4-00A0C91180F2}", L"CHsmJobWorkItem", NULL }, { L"{AB939AD0-6D67-11d0-9E2E-00A0C916F120}", L"CHsmManagedResource", NULL }, { L"{8448dd80-7614-11d0-9e33-00a0c916f120}", L"CHsmManagedResourceCollection", NULL }, { L"{BEA60F8A-7EBA-11d0-81E4-00A0C91180F2}", L"CHsmPhase", NULL }, { L"{AD402350-00FC-11D0-819C-00A0C91180F2}", L"CHsmPolicy", NULL }, { L"{AD40235A-00FC-11D0-819C-00A0C91180F2}", L"CHsmRule", NULL }, { L"{C2E29801-B1BA-11d0-81E9-00A0C91180F2}", L"CHsmRuleStack", NULL }, { L"{2D1E3156-25DE-11D0-8073-00A0C905F098}", L"CHsmServer", NULL }, { L"{BEA60F80-7EBA-11d0-81E4-00A0C91180F2}", L"CHsmSession", NULL }, { L"{FF67BB34-8430-11d0-81E4-00A0C91180F2}", L"CHsmSessionTotals", NULL }, { L"{61F0B790-82D9-11d0-9E35-00A0C916F120}", L"CHsmStoragePool", NULL }, { L"{23E45B60-C598-11d0-B16F-00A0C916F120}", L"CHsmWorkItem", NULL }, { L"{247DF540-C558-11d0-B16F-00A0C916F120}", L"CHsmWorkQueue", NULL },
{ L"{450024A3-47D0-11D0-9E1E-00A0C916F120}", L"CBagHole", NULL }, { L"{B13FA473-4E1B-11D0-9E22-00A0C916F120}", L"CBagInfo", NULL }, { L"{F0D7AFE0-9026-11d0-9E3B-00A0C916F120}", L"CMediaInfo", NULL }, { L"{768AD5A4-40C8-11D0-9E17-00A0C916F120}", L"CSegDB", NULL }, { L"{37F704E6-3EF9-11D0-9E17-00A0C916F120}", L"CSegRec", NULL },
{ L"{BD030C00-000B-11D0-D0DD-00A0C9190459}", L"CMemIo Class", NULL }, { L"{BD040C00-000B-11D0-D0DD-00A0C9190459}", L"CNtTapeIo Class", NULL }, { L"{BD050C00-000B-11D0-D0DD-00A0C9190459}", L"CNtFileIo Class", NULL },
{ L"{FE37FA04-3729-11D0-8CF4-00A0C9190459}", L"RmsCartridge Class", NULL }, { L"{FE37FA07-3729-11D0-8CF4-00A0C9190459}", L"RmsMediumChanger Class", NULL }, { L"{FE37FA12-3729-11D0-8CF4-00A0C9190459}", L"RmsClient Class", NULL }, { L"{FE37FA03-3729-11D0-8CF4-00A0C9190459}", L"RmsDriveClass Class", NULL }, { L"{FE37FA05-3729-11D0-8CF4-00A0C9190459}", L"RmsDrive Class", NULL }, { L"{FE37FA08-3729-11D0-8CF4-00A0C9190459}", L"RmsIEPort Class", NULL }, { L"{FE37FA02-3729-11D0-8CF4-00A0C9190459}", L"RmsLibrary Class", NULL }, { L"{FE37FA09-3729-11D0-8CF4-00A0C9190459}", L"RmsMediaSet Class", NULL }, { L"{FE37FA13-3729-11D0-8CF4-00A0C9190459}", L"RmsNTMS Class", NULL }, { L"{FE37FA11-3729-11D0-8CF4-00A0C9190459}", L"RmsPartition Class", NULL }, { L"{FE37FA10-3729-11D0-8CF4-00A0C9190459}", L"RmsRequest Class", NULL }, { L"{FE37FA01-3729-11D0-8CF4-00A0C9190459}", L"RmsServer Class", NULL }, { L"{FE37FA14-3729-11D0-8CF4-00A0C9190459}", L"RmsSink Class", NULL }, { L"{FE37FA06-3729-11D0-8CF4-00A0C9190459}", L"RmsStorageSlot Class", NULL }, { L"{FE37FA15-3729-11D0-8CF4-00A0C9190459}", L"RmsTemplate Class", NULL },
{ NULL, NULL, NULL } };
// Local functions
static BOOL AddPointer(const void* addr, ULONG size, int index, const char * filename, int linenum); static OLECHAR* GuidToObjectName(const GUID& guid); static BOOL SubPointer(const void* addr, int index);
// AddPointer - add a new pointer to the pointer list
// Return FALSE on failure (list is full or pointer is already in list)
static BOOL AddPointer(const void* addr, ULONG size, int index, const char * filename, int linenum) { int empty_slot = -1; int i; BOOL status = TRUE;
if (!pointer_data_initialized) { pointer_data[POINTER_DATA_CURRENT].count = 0; pointer_data[POINTER_DATA_CURRENT].size = 0; pointer_data[POINTER_DATA_MAX].count = 0; pointer_data[POINTER_DATA_MAX].size = 0; pointer_data[POINTER_DATA_CUMULATIVE].count = 0; pointer_data[POINTER_DATA_CUMULATIVE].size = 0; pointer_data_initialized = TRUE; }
for (i = 0; i < pointer_list_count; i++) { if (NULL == pointer_list[i].addr) { empty_slot = i; } else if (addr == pointer_list[i].addr) { WsbTraceAlways(OLESTR("AddPointer: address already in list: %lx (<%ls>, line: <%ld>\n"), (ULONG)addr, (OLECHAR *)filename, index); status = FALSE; break; } }
if (i == pointer_list_count) { // Not in list. Is the list full?
if (-1 == empty_slot && POINTER_LIST_SIZE == pointer_list_count) { WsbTraceAlways(OLESTR("AddPointer: pointer list is full: %lx\n"), (ULONG)addr); status = FALSE; } else if (-1 == empty_slot) { pointer_list_count++; } else { i = empty_slot; } }
if (status) { pointer_list[i].addr = addr; pointer_list[i].size = size; pointer_list[i].index = index; pointer_list[i].filename = filename; pointer_list[i].linenum = linenum; pointer_data[POINTER_DATA_CURRENT].count++; pointer_data[POINTER_DATA_CURRENT].size += size; if (pointer_data[POINTER_DATA_CURRENT].count > pointer_data[POINTER_DATA_MAX].count) { pointer_data[POINTER_DATA_MAX].count = pointer_data[POINTER_DATA_CURRENT].count; } if (pointer_data[POINTER_DATA_CURRENT].size > pointer_data[POINTER_DATA_MAX].size) { pointer_data[POINTER_DATA_MAX].size = pointer_data[POINTER_DATA_CURRENT].size; } pointer_data[POINTER_DATA_CUMULATIVE].count++; pointer_data[POINTER_DATA_CUMULATIVE].size += size; pointer_list[i].order = pointer_data[POINTER_DATA_CUMULATIVE].count; }
return(status); }
// GuidToObjectName - convert a guid to an object name
static OLECHAR* GuidToObjectName(const GUID& guid) { HRESULT hr = S_OK; int i; OLECHAR * name = NULL;
try { // Need to do conversions from string to Guid?
if (NULL == object_name_table[0].pGuid) { i = 0; while (object_name_table[i].guid_string) { GUID * pg = new GUID;
WsbAffirmHr(WsbGuidFromString(object_name_table[i].guid_string, pg)); object_name_table[i].pGuid = pg; i++; } }
// See if this Guid is in the name table
i = 0; while (object_name_table[i].guid_string) { if (guid == *object_name_table[i].pGuid) { name = object_name_table[i].name; break; } i++; } } WsbCatch(hr);
return(name); }
// SubPointer - remove a pointer from the pointer list
// Return FALSE on failure (pointer is not in list or index doesn't match)
static BOOL SubPointer(const void* addr, int index) { int i; BOOL status = TRUE;
for (i = 0; i < pointer_list_count; i++) { if (addr == pointer_list[i].addr) { break; } }
if (i == pointer_list_count) { WsbTraceAlways(OLESTR("SubPointer: pointer not found in list: %lx\n"), (ULONG)addr); status = FALSE; } else if (index != pointer_list[i].index) { WsbTraceAlways(OLESTR("SubPointer: type index doesn't match for pointer: %lx\n"), (ULONG)addr); WsbTraceAlways(OLESTR(", original type index = %d, new type index = %d\n"), pointer_list[i].index, index); status = FALSE; }
if (status) { pointer_list[i].addr = NULL; pointer_data[POINTER_DATA_CURRENT].count--; pointer_data[POINTER_DATA_CURRENT].size -= pointer_list[i].size; }
return(status); }
HRESULT WsbObjectAdd( const GUID & guid, const void * addr ) /*++
Routine Description:
Add another object to the object table
Arguments:
guid - Guid for the object type
addr - Memory address of object
Return Value:
S_OK - Success
--*/ { HRESULT hr = S_OK;
#if defined(CRT_DEBUG_MEMORY)
// Set CRT debug flag
static BOOL first = TRUE; if (first) { int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
// Set the new state for the flag
_CrtSetDbgFlag( tmpFlag ); } #endif
try { int i;
// Reserve the first entry for non-objects and table overflow
if (0 == object_table_count) { object_table[0].guid = GUID_NULL; object_table[0].count = 0; object_table[0].total_count = 0; object_table[0].max_count = 0; object_table_count = 1; }
// Check in object type is already in table
for (i = 0; i < object_table_count; i++) { if (guid == object_table[i].guid) break; } // Add a new entry if not (and there is room)
if (i == object_table_count && i < OBJECT_TABLE_SIZE) { // WsbTraceAlways(OLESTR("WsbObjectAdd: new object, guid = %ls\n"),
// WsbGuidAsString(guid));
#if defined(CRT_DEBUG_MEMORY)
WsbTraceAlways(OLESTR("WsbObjectAdd: _CrtCheckMemory = %ls\n"), WsbBoolAsString(_CrtCheckMemory())); #endif
object_table[i].guid = guid; object_table[i].count = 0; object_table[i].total_count = 0; object_table[i].max_count = 0; object_table_count++; } else if (OBJECT_TABLE_SIZE == i) { // Use the first entry for everything else
i = 0; } object_table[i].count++; object_table[i].total_count++; if (object_table[i].count > object_table[i].max_count) { object_table[i].max_count = object_table[i].count; }
// Add to pointer list
AddPointer(addr, 0, i, NULL, 0);
} WsbCatch(hr);
return(hr); }
HRESULT WsbObjectSub( const GUID & guid, const void * addr ) /*++
Routine Description:
Subtract an object from the object table
Arguments:
guid - Guid for the object type
addr - Memory address of object
Return Value:
S_OK - Success
--*/ { HRESULT hr = S_OK;
try { int i;
// Find the object type in table
for (i = 0; i < object_table_count; i++) { if (guid == object_table[i].guid) { // Allow count to go negative since this could indicate a problem
object_table[i].count--;
// Remove from pointer list
SubPointer(addr, i); } }
} WsbCatch(hr);
return(hr); }
HRESULT WsbObjectTracePointers( ULONG flags ) /*++
Routine Description:
Dump the pointer list information to the trace file.
Arguments:
flags - WSB_OTP_ flags
Return Value:
S_OK - Success
--*/ { HRESULT hr = S_OK;
try { int i; OLECHAR string[300];
// Dump the current sequence number
if (flags & WSB_OTP_SEQUENCE) { WsbTraceAlways(OLESTR("WsbObjectTracePointers: current sequence number = %ld\n"), pointer_data[POINTER_DATA_CUMULATIVE].count); }
// Dump statistics
if (flags & WSB_OTP_STATISTICS) { WsbTraceAlways(OLESTR("WsbObjectTracePointers: count, size\n")); WsbTraceAlways(OLESTR(" Current %8ld %12ls\n"), pointer_data[POINTER_DATA_CURRENT].count, WsbLonglongAsString(pointer_data[POINTER_DATA_CURRENT].size)); WsbTraceAlways(OLESTR(" Maximum %8ld %12ls\n"), pointer_data[POINTER_DATA_MAX].count, WsbLonglongAsString(pointer_data[POINTER_DATA_MAX].size)); WsbTraceAlways(OLESTR(" Cumulative %8ld %12ls\n"), pointer_data[POINTER_DATA_CUMULATIVE].count, WsbLonglongAsString(pointer_data[POINTER_DATA_CUMULATIVE].size)); }
// Dump non-NULL pointers
if (flags & WSB_OTP_ALLOCATED) { WsbTraceAlways(OLESTR("WsbObjectTracePointers: allocated memory list (addr, size, order, name/GUID/file):\n")); for (i = 0; i < pointer_list_count; i++) { if (pointer_list[i].addr) { GUID guid = GUID_NULL; int index; OLECHAR * name = NULL; OLECHAR * pstr = NULL;
index = pointer_list[i].index; if (index > 0 && index < object_table_count) { guid = object_table[index].guid; name = GuidToObjectName(guid); } if (0 == index) { wsprintf(string, OLESTR("%hs(%d)"), pointer_list[i].filename, pointer_list[i].linenum); pstr = string; } else if (name) { pstr = name; } else { wcscpy(string, WsbGuidAsString(guid)); pstr = string; } WsbTraceAlways(OLESTR(" %8lx %8ld %8ld %ls\n"), pointer_list[i].addr, pointer_list[i].size, pointer_list[i].order, pstr); } } }
#if defined(CRT_DEBUG_MEMORY)
WsbTraceAlways(OLESTR("WsbObjectTrace: calling _CrtMemCheckpoint\n")); _CrtMemCheckpoint(&CrtMemState); WsbTraceAlways(OLESTR("WsbObjectTrace: MemState.lHighWaterCount = %ld, TotalCount = %ld\n"), CrtMemState.lHighWaterCount, CrtMemState.lTotalCount); WsbTraceAlways(OLESTR("WsbObjectTrace: MemState.blocks count & size\n")); WsbTraceAlways(OLESTR(" FREE %4ld %6ld\n"), CrtMemState.lCounts[_FREE_BLOCK], CrtMemState.lSizes[_FREE_BLOCK]); WsbTraceAlways(OLESTR(" NORMAL %4ld %6ld\n"), CrtMemState.lCounts[_NORMAL_BLOCK], CrtMemState.lSizes[_NORMAL_BLOCK]); WsbTraceAlways(OLESTR(" CRT %4ld %6ld\n"), CrtMemState.lCounts[_CRT_BLOCK], CrtMemState.lSizes[_CRT_BLOCK]); WsbTraceAlways(OLESTR(" IGNORE %4ld %6ld\n"), CrtMemState.lCounts[_IGNORE_BLOCK], CrtMemState.lSizes[_IGNORE_BLOCK]); WsbTraceAlways(OLESTR(" CLIENT %4ld %6ld\n"), CrtMemState.lCounts[_CLIENT_BLOCK], CrtMemState.lSizes[_CLIENT_BLOCK]);
// WsbTraceAlways(OLESTR("WsbObjectTrace: calling _CrtMemDumpStatistics\n"));
// _CrtMemDumpStatistics(&CrtMemState);
// _CrtDumpMemoryLeaks();
#endif
} WsbCatch(hr);
return(hr); }
HRESULT WsbObjectTraceTypes( void ) /*++
Routine Description:
Dump the object table information to the trace file.
Arguments:
None.
Return Value:
S_OK - Success
--*/ { HRESULT hr = S_OK;
try { int i;
WsbTraceAlways(OLESTR("WsbObjectTraceTypes: object table (GUID, total count, max count, current count, name):\n")); // Find the object type in table
for (i = 0; i < object_table_count; i++) { OLECHAR * name;
name = GuidToObjectName(object_table[i].guid); WsbTraceAlways(OLESTR(" %ls %6ld %5ld %5ld %ls\n"), WsbGuidAsString(object_table[i].guid), object_table[i].total_count, object_table[i].max_count, object_table[i].count, (name ? name : OLESTR(""))); }
} WsbCatch(hr);
return(hr); }
LPVOID WsbMemAlloc(ULONG cb, const char * filename, int linenum) /*++
Routine Description:
Debug tracking replacement for CoTaskAlloc.
--*/ { LPVOID p;
p = CoTaskMemAlloc(cb); if (p) { AddPointer(p, cb, 0, filename, linenum); } return(p); }
void WsbMemFree(LPVOID pv, const char *, int) /*++
Routine Description:
Debug tracking replacement for CoTaskFree.
--*/ { if (pv) { SubPointer(pv, 0); } CoTaskMemFree(pv); }
LPVOID WsbMemRealloc(LPVOID pv, ULONG cb, const char * filename, int linenum) /*++
Routine Description:
Debug tracking replacement for CoTaskRealloc.
--*/ { LPVOID p;
p = CoTaskMemRealloc(pv, cb); if (p) { if (pv) { SubPointer(pv, 0); } AddPointer(p, cb, 0, filename, linenum); } return(p); }
BSTR WsbSysAllocString(const OLECHAR FAR * sz, const char * filename, int linenum) /*++
Routine Description:
Debug tracking replacement for SysAllocString
--*/ { BSTR b;
b = SysAllocString(sz); if (b) { AddPointer(b, SysStringByteLen(b), 0, filename, linenum); } return(b); }
BSTR WsbSysAllocStringLen(const OLECHAR FAR * sz, unsigned int cc, const char * filename, int linenum) /*++
Routine Description:
Debug tracking replacement for SysAllocStringLen
--*/ { BSTR b;
b = SysAllocStringLen(sz, cc); if (b) { AddPointer(b, SysStringByteLen(b), 0, filename, linenum); } return(b); }
void WsbSysFreeString(BSTR bs, const char *, int) /*++
Routine Description:
Debug tracking replacement for SysFreeString
--*/ { if (bs) { SubPointer(bs, 0); } SysFreeString(bs); }
HRESULT WsbSysReallocString(BSTR FAR * pb, const OLECHAR FAR * sz, const char * filename, int linenum) /*++
Routine Description:
Debug tracking replacement for SysReallocString
--*/ { HRESULT hr;
if (*pb) { SubPointer(*pb, 0); } hr = SysReAllocString(pb, sz); if (*pb) { AddPointer(*pb, SysStringByteLen(*pb), 0, filename, linenum); } return(hr); }
HRESULT WsbSysReallocStringLen(BSTR FAR * pb, const OLECHAR FAR * sz, unsigned int cc, const char * filename, int linenum) /*++
Routine Description:
Debug tracking replacement for SysStringLen
--*/ { HRESULT hr;
if (*pb) { SubPointer(*pb, 0); } hr = SysReAllocStringLen(pb, sz, cc); if (*pb) { AddPointer(*pb, SysStringByteLen(*pb), 0, filename, linenum); } return(hr); }
#endif // WSB_TRACK_MEMORY
|