Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1337 lines
26 KiB

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: alloc.cpp
//
// Contents: Cert Server debug implementation
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <assert.h>
#include <psapi.h>
#define __dwFILE__ __dwFILE_CERTCLIB_ALLOC_CPP__
#if DBG_CERTSRV
#undef FormatMessageW
#undef LocalAlloc
#undef LocalReAlloc
#undef LocalFree
#undef CoTaskMemAlloc
#undef CoTaskMemRealloc
#undef CoTaskMemFree
#undef StringFromCLSID
#undef StringFromIID
#undef SysAllocString
#undef SysReAllocString
#undef SysAllocStringLen
#undef SysReAllocStringLen
#undef SysFreeString
#undef SysAllocStringByteLen
#undef PropVariantClear
#undef VariantClear
#undef VariantChangeType
#undef VariantChangeTypeEx
#undef AllocateAndInitializeSid
#undef FreeSid
#ifndef CSM_TRACEASSERT
#define CSM_TRACEASSERT 0x400
#endif
DWORD g_MemTrack = 0;
#define MTF_UNREGISTERED 0x00000002
#define MTF_ALLOCTRACE 0x00000004
#define MTF_FREETRACE 0x00000008
#define MTF_STACKTRACE 0x00000010
typedef struct _RMALLOC
{
LONG cAlloc;
LONG cAllocTotal;
} RMALLOC;
RMALLOC g_armAlloc[CSM_MAX];
#define C_BP_FRAME 16
#define C_BACK_TRACE_CHUNK 100
#define C_MEM_HEADER_CHUNK 100
typedef struct _BACKTRACE
{
LONG cAlloc; // count of outstanding allocations
LONG cAllocTotal; // count of total allocations
LONG cbAlloc; // size of outstanding allocations
LONG cbAllocTotal; // size of total allocations
ULONG apCaller[C_BP_FRAME]; // stack trace
} BACKTRACE;
typedef struct _MEMHEADER
{
DWORD iBackTrace; // backtrace index
VOID const *pvMemory; // Pointer to memory block allocated
LONG cbMemory; // Size of memory block allocated
DWORD Flags; // Allocator flags
} MEMHEADER;
WCHAR s_wszProcess[MAX_PATH];
// critical section around myRegister APIs since they
// operate on global data structures
CRITICAL_SECTION g_critsecRegisterMemory;
BOOL g_fRegisterMemoryCritSecInit = FALSE;
VOID
RegisterMemoryEnterCriticalSection(VOID)
{
HRESULT hr;
__try
{
if (!g_fRegisterMemoryCritSecInit)
{
InitializeCriticalSection(&g_critsecRegisterMemory);
g_fRegisterMemoryCritSecInit = TRUE;
}
EnterCriticalSection(&g_critsecRegisterMemory);
if (s_wszProcess[0] == L'\0')
{
GetModuleBaseName(
GetCurrentProcess(),
GetModuleHandle(NULL),
s_wszProcess,
ARRAYSIZE(s_wszProcess));
s_wszProcess[ARRAYSIZE(s_wszProcess) - 1] = L'\0';
if (s_wszProcess[0] == L'\0')
{
wcscpy(s_wszProcess, L"???");
}
}
}
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
{
}
}
VOID
RegisterMemoryLeaveCriticalSection(VOID)
{
if (g_fRegisterMemoryCritSecInit)
{
LeaveCriticalSection(&g_critsecRegisterMemory);
}
}
VOID
RegisterMemoryDeleteCriticalSection()
{
if (g_fRegisterMemoryCritSecInit)
{
DeleteCriticalSection(&g_critsecRegisterMemory);
g_fRegisterMemoryCritSecInit = FALSE;
}
}
BACKTRACE *g_rgbt = NULL;
DWORD g_cbtMax = 0;
DWORD g_cbt = 0;
MEMHEADER *g_rgmh = NULL;
DWORD g_cmhMax = 0;
DWORD g_cmh = 0;
MEMHEADER *
AllocMemHeader()
{
if (g_cmh >= g_cmhMax)
{
DWORD cb = (C_MEM_HEADER_CHUNK + g_cmhMax) * sizeof(g_rgmh[0]);
MEMHEADER *rgmhT;
if (NULL == g_rgmh)
{
rgmhT = (MEMHEADER *) LocalAlloc(LMEM_FIXED, cb);
}
else
{
rgmhT = (MEMHEADER *) LocalReAlloc(g_rgmh, cb, LMEM_MOVEABLE);
}
if (NULL == rgmhT)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"Error allocating memtrack header\n"));
return(NULL);
}
g_rgmh = rgmhT;
g_cmhMax += C_MEM_HEADER_CHUNK;
}
return(&g_rgmh[g_cmh++]);
}
MEMHEADER *
LookupMemHeader(
IN VOID const *pv)
{
MEMHEADER *pmh;
MEMHEADER *pmhEnd;
pmh = g_rgmh;
pmhEnd = &g_rgmh[g_cmh];
while (pmh < pmhEnd)
{
if (pv == pmh->pvMemory)
{
// Catch all activity on "interesting" blocks of memory.
// Ususally set in the debugger on a particular block of memory,
// to stop in the debugger when it is freed.
CSASSERT(0 == (CSM_TRACEASSERT & pmh->Flags));
return(pmh);
}
pmh++;
}
return(NULL);
}
VOID
FreeMemHeader(
IN MEMHEADER *pmh)
{
MEMHEADER *pmhLast;
assert(1 <= g_cmh);
pmhLast = &g_rgmh[g_cmh - 1];
*pmh = *pmhLast;
g_cmh--;
}
BACKTRACE *
AllocBackTrace(
OUT DWORD *pibt)
{
BOOL fRealloc = FALSE;
BACKTRACE *rgbtOld = g_rgbt;
BACKTRACE *pbtRet;
if (g_cbt >= g_cbtMax)
{
DWORD cb = (C_BACK_TRACE_CHUNK + g_cbtMax) * sizeof(g_rgbt[0]);
BACKTRACE *rgbtT;
if (NULL == g_rgbt)
{
rgbtT = (BACKTRACE *) LocalAlloc(LMEM_FIXED, cb);
}
else
{
rgbtT = (BACKTRACE *) LocalReAlloc(g_rgbt, cb, LMEM_MOVEABLE);
fRealloc = TRUE;
}
if (NULL == rgbtT)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"Error allocating memtrack backtrace\n"));
return(NULL);
}
g_rgbt = rgbtT;
g_cbtMax += C_BACK_TRACE_CHUNK;
}
*pibt = g_cbt + 1;
pbtRet = &g_rgbt[g_cbt++];
if (fRealloc)
{
// Wait to DBGPRINT here to avoid recursing with inconsistent data.
DBGPRINTW((
DBG_SS_CERTLIBI,
L"Realloc'd memtrack backtrace from %x to %x\n",
rgbtOld,
g_rgbt));
}
return(pbtRet);
}
BACKTRACE *
LookupBackTrace(
IN BACKTRACE *pbtIn,
OUT DWORD *pibt)
{
BACKTRACE *pbt;
BACKTRACE *pbtEnd;
pbt = g_rgbt;
pbtEnd = &g_rgbt[g_cbt];
while (pbt < pbtEnd)
{
if (0 == memcmp(pbt->apCaller, pbtIn->apCaller, sizeof(pbt->apCaller)))
{
*pibt = SAFE_SUBTRACT_POINTERS(pbt, g_rgbt) + 1;
return(pbt);
}
pbt++;
}
return(NULL);
}
BACKTRACE *
BackTraceFromIndex(
IN DWORD ibt)
{
BACKTRACE *pbt = NULL;
if (0 == ibt)
{
DBGPRINTW((DBG_SS_CERTLIB, L"BackTraceFromIndex(0)\n"));
}
else if (g_cbt < ibt)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"BackTraceFromIndex(%u) -- out of range\n",
ibt));
}
else
{
pbt = &g_rgbt[ibt - 1];
}
return(pbt);
}
VOID
ReadEnvironmentFlags(VOID)
{
HRESULT hr;
DWORD MemTrack;
DWORD cb;
DWORD dwType;
HKEY hkey = NULL;
char *pszEnvVar;
pszEnvVar = getenv(szCERTSRV_MEMTRACK);
if (NULL != pszEnvVar)
{
g_MemTrack = (DWORD) strtol(pszEnvVar, NULL, 16);
}
else
{
hr = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
wszREGKEYCONFIGPATH,
0,
KEY_READ,
&hkey);
if (S_OK == hr)
{
cb = sizeof(MemTrack);
hr = RegQueryValueEx(
hkey,
wszREGCERTSRVMEMTRACK,
0,
&dwType,
(BYTE *) &MemTrack,
&cb);
if (S_OK == hr && REG_DWORD == dwType && sizeof(MemTrack) == cb)
{
g_MemTrack = MemTrack;
}
}
}
//error:
if (NULL != hkey)
{
RegCloseKey(hkey);
}
}
VOID
CaptureStackBackTrace(
EXCEPTION_POINTERS *pep,
ULONG cSkip,
ULONG cFrames,
ULONG *aeip)
{
ZeroMemory(aeip, cFrames * sizeof(aeip[0]));
#if i386 == 1
ULONG ieip, *pebp;
ULONG *pebpMax = (ULONG *) MAXLONG; // 2 * 1024 * 1024 * 1024; // 2 gig - 1
ULONG *pebpMin = (ULONG *) (64 * 1024); // 64k
if (pep == NULL)
{
ieip = 0;
cSkip++; // always skip current frame
pebp = ((ULONG *) &pep) - 2;
}
else
{
ieip = 1;
assert(cSkip == 0);
aeip[0] = pep->ContextRecord->Eip;
pebp = (ULONG *) pep->ContextRecord->Ebp;
}
if (pebp >= pebpMin && pebp < pebpMax)
{
__try
{
for ( ; ieip < cSkip + cFrames; ieip++)
{
if (ieip >= cSkip)
{
aeip[ieip - cSkip] = *(pebp + 1); // save an eip
}
ULONG *pebpNext = (ULONG *) *pebp;
if (pebpNext < pebp + 2 ||
pebpNext >= pebpMax - 1 ||
pebpNext >= pebp + (256 * 1024) / sizeof(pebp[0]))
{
break;
}
pebp = pebpNext;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
;
}
}
#endif // i386 == 1
}
WCHAR const *
wszAllocator(
IN DWORD Flags)
{
WCHAR const *pwsz;
switch (~CSM_TRACEASSERT & Flags)
{
case CSM_LOCALALLOC: pwsz = L"LocalAlloc"; break;
case CSM_COTASKALLOC: pwsz = L"CoTaskMemAlloc"; break;
case CSM_SYSALLOC: pwsz = L"SysAllocString"; break;
case CSM_MALLOC: pwsz = L"malloc"; break;
case CSM_NEW: pwsz = L"new"; break;
case CSM_NEW | CSM_GLOBALDESTRUCTOR:
pwsz = L"new-global"; break;
case CSM_SID: pwsz = L"allocSid"; break;
default: pwsz = L"???"; break;
}
return(pwsz);
}
WCHAR const *
wszFreeer(
IN DWORD Flags)
{
WCHAR const *pwsz;
switch (~CSM_TRACEASSERT & Flags)
{
case CSM_LOCALALLOC: pwsz = L"LocalFree"; break;
case CSM_COTASKALLOC: pwsz = L"CoTaskMemFree"; break;
case CSM_SYSALLOC: pwsz = L"SysFreeString"; break;
case CSM_MALLOC: pwsz = L"free"; break;
case CSM_NEW: pwsz = L"delete"; break;
case CSM_NEW | CSM_GLOBALDESTRUCTOR:
pwsz = L"delete-global"; break;
case CSM_SID: pwsz = L"FreeSid"; break;
default: pwsz = L"???"; break;
}
return(pwsz);
}
VOID
DumpMemBlock(
IN WCHAR const *pwsz,
IN VOID const *pvMemory,
IN DWORD cbMemory,
IN DWORD Flags,
IN DWORD ibt,
OPTIONAL IN BACKTRACE const *pbt)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"%ws%wspv=%-6x cb=%-4x f=%x(%ws) pbt[%d]=%x:\n",
pwsz,
L'\0' != *pwsz? L": " : L"",
pvMemory,
cbMemory,
Flags,
wszAllocator(Flags),
ibt,
pbt));
if (NULL != pbt && DbgIsSSActive(DBG_SS_CERTLIB))
{
DBGPRINTW((MAXDWORD, L"%d: ", ibt));
for (int i = 0; i < ARRAYSIZE(pbt->apCaller); i++)
{
if (NULL == pbt->apCaller[i])
{
break;
}
DBGPRINTW((MAXDWORD, L"ln %x;", pbt->apCaller[i]));
}
DBGPRINTW((MAXDWORD, L"\n"));
}
}
VOID
myRegisterMemDump()
{
MEMHEADER *pmh;
MEMHEADER *pmhEnd;
LONG cTotal;
LONG cbTotal;
cTotal = 0;
cbTotal = 0;
RegisterMemoryEnterCriticalSection();
__try
{
pmh = g_rgmh;
pmhEnd = &g_rgmh[g_cmh];
while (pmh < pmhEnd)
{
if (0 == (CSM_GLOBALDESTRUCTOR & pmh->Flags) ||
(MTF_ALLOCTRACE & g_MemTrack))
{
if (0 == cTotal)
{
if (DbgIsSSActive(DBG_SS_CERTLIB))
{
DBGPRINTW((MAXDWORD, L"\n"));
}
DBGPRINTW((
DBG_SS_CERTLIB,
L"%ws: Allocated Memory Blocks:\n",
s_wszProcess));
}
cTotal++;
cbTotal += pmh->cbMemory;
DumpMemBlock(
L"",
pmh->pvMemory,
pmh->cbMemory,
pmh->Flags,
pmh->iBackTrace,
BackTraceFromIndex(pmh->iBackTrace));
}
pmh++;
}
if (0 != cTotal)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"%ws: Total: c=%x cb=%x\n\n",
s_wszProcess,
cTotal,
cbTotal));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
RegisterMemoryLeaveCriticalSection();
}
VOID *
_VariantMemory(
IN PROPVARIANT const *pvar,
OUT DWORD *pFlags,
OPTIONAL OUT DWORD *pcb)
{
VOID *pv = NULL;
DWORD cb = 0;
BOOL fString = FALSE;
*pFlags = CSM_COTASKALLOC;
if (NULL != pcb)
{
*pcb = 0;
}
switch (pvar->vt)
{
case VT_BSTR:
pv = pvar->bstrVal;
fString = TRUE;
*pFlags = CSM_SYSALLOC;
break;
case VT_BYREF | VT_BSTR:
pv = *pvar->pbstrVal;
fString = TRUE;
*pFlags = CSM_SYSALLOC;
break;
case VT_LPWSTR:
pv = pvar->pwszVal;
fString = TRUE;
break;
case VT_BLOB:
pv = pvar->blob.pBlobData;
cb = pvar->blob.cbSize;
break;
}
if (NULL != pcb)
{
if (fString)
{
cb = (wcslen((WCHAR const *) pv) + 1) * sizeof(WCHAR);
}
*pcb = cb;
}
return(pv);
}
VOID
myRegisterMemAlloc(
IN VOID const *pv,
IN LONG cb,
IN DWORD Flags)
{
BACKTRACE bt;
MEMHEADER *pmh;
BACKTRACE *pbt;
DWORD FlagsIn = Flags;
Flags &= ~CSM_TRACEASSERT;
if (CSM_VARIANT == Flags)
{
pv = _VariantMemory((PROPVARIANT const *) pv, &Flags, (DWORD *) &cb);
if (NULL == pv)
{
return; // nothing to register
}
}
RegisterMemoryEnterCriticalSection();
__try
{
static BOOL s_fFirst = TRUE;
if (s_fFirst)
{
ReadEnvironmentFlags();
s_fFirst = FALSE;
}
if (0 != g_MemTrack)
{
// Do not register NULL as an allocation
CSASSERT(NULL != pv);
// see if we already have a reference to this memory
pmh = LookupMemHeader(pv);
if (NULL != pmh)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"%ws: Memory Leak: Tracked memory address reused. Previously allocated:\n",
s_wszProcess));
DumpMemBlock(
L"Memory leak",
pv,
pmh->cbMemory,
pmh->Flags,
pmh->iBackTrace,
BackTraceFromIndex(pmh->iBackTrace));
CSASSERT(!"Tracked memory address reused");
FreeMemHeader(pmh);
}
pmh = AllocMemHeader();
if (NULL != pmh)
{
DWORD ibt;
CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
pbt = LookupBackTrace(&bt, &ibt);
if (NULL != pbt)
{
pbt->cAlloc++;
pbt->cAllocTotal++;
pbt->cbAlloc += cb;
pbt->cbAllocTotal += cb;
}
else
{
pbt = AllocBackTrace(&ibt);
if (NULL != pbt)
{
pbt->cAlloc = 1;
pbt->cAllocTotal = 1;
pbt->cbAlloc = cb;
pbt->cbAllocTotal = cb;
CopyMemory(pbt->apCaller, bt.apCaller, sizeof(pbt->apCaller));
}
}
if (NULL != pbt)
{
pmh->iBackTrace = ibt;
pmh->pvMemory = pv;
pmh->cbMemory = cb;
pmh->Flags = Flags | (CSM_TRACEASSERT & FlagsIn);
CSASSERT(ARRAYSIZE(g_armAlloc) > Flags);
g_armAlloc[Flags].cAlloc++;
g_armAlloc[Flags].cAllocTotal++;
if (MTF_ALLOCTRACE & g_MemTrack)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"Alloc: pmh=%x: pv=%x cb=%x f=%x(%ws) -- pbt[%d]=%x: c=%x, cb=%x\n",
pmh,
pmh->pvMemory,
pmh->cbMemory,
pmh->Flags,
wszAllocator(pmh->Flags),
SAFE_SUBTRACT_POINTERS(pbt, g_rgbt),
pbt,
pbt->cAlloc,
pbt->cbAlloc));
if (MTF_STACKTRACE & g_MemTrack)
{
DumpMemBlock(
L"Alloc Trace memory block",
pv,
pmh->cbMemory, // cbMemory
pmh->Flags, // Flags
pmh->iBackTrace, // ibt
pbt);
}
}
}
else
{
FreeMemHeader(pmh);
}
} // if no problem allocating pmh
} // if g_MemTrack
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
RegisterMemoryLeaveCriticalSection();
}
VOID
myRegisterMemFree(
IN VOID const *pv,
IN DWORD Flags)
{
MEMHEADER *pmh;
if (NULL == pv)
{
return;
}
if (CSM_VARIANT == Flags)
{
pv = _VariantMemory((PROPVARIANT const *) pv, &Flags, NULL);
if (NULL == pv)
{
return; // nothing to register
}
}
RegisterMemoryEnterCriticalSection();
CSASSERT(CSM_MAX > (~CSM_GLOBALDESTRUCTOR & Flags));
__try
{
pmh = LookupMemHeader(pv);
if (NULL != pmh)
{
BACKTRACE *pbt = BackTraceFromIndex(pmh->iBackTrace);
if (CSM_GLOBALDESTRUCTOR & Flags)
{
if ((CSM_GLOBALDESTRUCTOR | pmh->Flags) != Flags)
{
BACKTRACE bt;
CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
DumpMemBlock(
L"Wrong memory allocator for global destructor",
pv,
MAXDWORD, // cbMemory
MAXDWORD, // Flags
MAXDWORD, // ibt
&bt);
CSASSERT(!"Wrong memory allocator for global destructor");
}
else
{
pmh->Flags |= CSM_GLOBALDESTRUCTOR;
}
}
else
{
g_armAlloc[Flags].cAlloc--;
pbt->cAlloc--;
pbt->cbAlloc -= pmh->cbMemory;
if (CSM_GLOBALDESTRUCTOR & pmh->Flags)
{
Flags |= CSM_GLOBALDESTRUCTOR;
}
if (CSM_TRACEASSERT & pmh->Flags)
{
Flags |= CSM_TRACEASSERT;
}
if (pmh->Flags != Flags)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"%ws: Wrong memory allocator: Freed with %ws, Allocated by %ws\n",
s_wszProcess,
wszFreeer(Flags),
wszAllocator(pmh->Flags)));
DumpMemBlock(
L"Wrong memory allocator",
pv,
pmh->cbMemory,
pmh->Flags,
pmh->iBackTrace,
BackTraceFromIndex(pmh->iBackTrace));
CSASSERT(pmh->Flags == Flags);
}
else if (MTF_FREETRACE & g_MemTrack)
{
DBGPRINTW((
DBG_SS_CERTLIB,
L"Free: pmh=%x: pv=%x cb=%x f=%x(%ws) -- pbt[%d]=%x: c=%x, cb=%x\n",
pmh,
pv,
pmh->cbMemory,
pmh->Flags,
wszAllocator(pmh->Flags),
pmh->iBackTrace,
pbt,
pbt->cAlloc,
pbt->cbAlloc));
if (MTF_STACKTRACE & g_MemTrack)
{
BACKTRACE bt;
CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
DumpMemBlock(
L"Free Trace memory block(alloc)",
pv,
pmh->cbMemory, // cbMemory
pmh->Flags, // Flags
pmh->iBackTrace, // ibt
pbt);
DumpMemBlock(
L"Free Trace memory block(free)",
pv,
pmh->cbMemory, // cbMemory
pmh->Flags, // Flags
MAXDWORD, // ibt
&bt);
}
}
FreeMemHeader(pmh);
}
}
else if (MTF_UNREGISTERED & g_MemTrack)
{
BACKTRACE bt;
CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
DumpMemBlock(
L"Unregistered memory block",
pv,
MAXDWORD, // cbMemory
MAXDWORD, // Flags
MAXDWORD, // ibt
&bt);
CSASSERT(!"Unregistered memory block");
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
RegisterMemoryLeaveCriticalSection();
}
DWORD
myFormatMessageW(
IN DWORD dwFlags,
IN LPCVOID lpSource,
IN DWORD dwMessageId,
IN DWORD dwLanguageId,
OUT LPWSTR lpBuffer,
IN DWORD nSize,
IN va_list *Arguments)
{
DWORD cwc;
cwc = FormatMessage(
dwFlags,
lpSource,
dwMessageId,
dwLanguageId,
lpBuffer,
nSize,
Arguments);
if (cwc != 0 && (FORMAT_MESSAGE_ALLOCATE_BUFFER & dwFlags))
{
myRegisterMemAlloc(
*(WCHAR **) lpBuffer,
(cwc + 1) * sizeof(WCHAR),
CSM_LOCALALLOC);
}
return(cwc);
}
HLOCAL
myLocalAlloc(
IN UINT uFlags,
IN UINT uBytes)
{
HLOCAL hMem;
// one of these should always be specified (see LocalAlloc specification)
assert((LMEM_FIXED == (uFlags & LMEM_FIXED)) ||
(LMEM_MOVEABLE == (uFlags & LMEM_MOVEABLE)) );
hMem = LocalAlloc(uFlags, uBytes);
if (NULL != hMem)
{
myRegisterMemAlloc(hMem, uBytes, CSM_LOCALALLOC);
}
return(hMem);
}
HLOCAL
myLocalReAlloc(
IN HLOCAL hMem,
IN UINT uBytes,
IN UINT uFlags)
{
HLOCAL hMemNew;
// if realloc called without MOVEABLE flag, realloc can't relocate allocation
assert(LMEM_MOVEABLE == (uFlags & LMEM_MOVEABLE));
hMemNew = LocalReAlloc(hMem, uBytes, uFlags);
if (NULL != hMemNew)
{
myRegisterMemFree(hMem, CSM_LOCALALLOC);
myRegisterMemAlloc(hMemNew, uBytes, CSM_LOCALALLOC);
}
return(hMemNew);
}
HLOCAL
myLocalFree(
IN HLOCAL hMem)
{
myRegisterMemFree(hMem, CSM_LOCALALLOC);
return(LocalFree(hMem));
}
VOID *
myCoTaskMemAlloc(
IN ULONG cb)
{
VOID *pv;
pv = CoTaskMemAlloc(cb);
if (NULL != pv)
{
myRegisterMemAlloc(pv, cb, CSM_COTASKALLOC);
}
return(pv);
}
VOID *
myCoTaskMemRealloc(
IN VOID *pv,
IN ULONG cb)
{
VOID *pvNew;
pvNew = CoTaskMemRealloc(pv, cb);
if (NULL != pvNew)
{
myRegisterMemFree(pv, CSM_COTASKALLOC);
myRegisterMemAlloc(pvNew, cb, CSM_COTASKALLOC);
}
return(pvNew);
}
VOID
myCoTaskMemFree(
IN VOID *pv)
{
myRegisterMemFree(pv, CSM_COTASKALLOC);
CoTaskMemFree(pv);
}
HRESULT
myStringFromCLSID(
IN REFCLSID rclsid,
OUT LPOLESTR FAR *ppwsz)
{
HRESULT hr;
hr = StringFromCLSID(rclsid, ppwsz);
_JumpIfError(hr, error, "StringFromCLSID");
if (NULL != *ppwsz)
{
myRegisterMemAlloc(
*ppwsz, (wcslen(*ppwsz) + 1) * sizeof(WCHAR),
CSM_COTASKALLOC);
}
error:
return(hr);
}
HRESULT
myStringFromIID(
IN REFIID rclsid,
OUT LPOLESTR FAR *ppwsz)
{
HRESULT hr;
hr = StringFromIID(rclsid, ppwsz);
_JumpIfError(hr, error, "StringFromIID");
if (NULL != *ppwsz)
{
myRegisterMemAlloc(
*ppwsz, (wcslen(*ppwsz) + 1) * sizeof(WCHAR),
CSM_COTASKALLOC);
}
error:
return(hr);
}
BSTR
mySysAllocString(
IN const OLECHAR *pwszIn)
{
BSTR str;
str = SysAllocString(pwszIn);
if (NULL != str)
{
myRegisterMemAlloc(str, (wcslen(pwszIn) + 1) * sizeof(WCHAR), CSM_SYSALLOC);
}
return(str);
}
INT
mySysReAllocString(
IN OUT BSTR *pstr,
IN const OLECHAR *pwszIn)
{
BSTR str = *pstr;
INT i;
i = SysReAllocString(pstr, pwszIn);
if (i)
{
myRegisterMemFree(str, CSM_SYSALLOC);
myRegisterMemAlloc(*pstr, (wcslen(pwszIn) + 1) * sizeof(WCHAR), CSM_SYSALLOC);
}
return(i);
}
BSTR
mySysAllocStringLen(
IN const OLECHAR *pwcIn,
IN UINT cwc)
{
BSTR str;
str = SysAllocStringLen(pwcIn, cwc);
if (NULL != str)
{
myRegisterMemAlloc(str, cwc * sizeof(WCHAR), CSM_SYSALLOC);
}
return(str);
}
INT
mySysReAllocStringLen(
IN OUT BSTR *pstr,
IN const OLECHAR *pwcIn,
IN UINT cwc)
{
BSTR str = *pstr;
INT i;
i = SysReAllocStringLen(pstr, pwcIn, cwc);
if (i)
{
myRegisterMemFree(str, CSM_SYSALLOC);
myRegisterMemAlloc(*pstr, cwc * sizeof(WCHAR), CSM_SYSALLOC);
}
return(i);
}
VOID
mySysFreeString(
IN BSTR str)
{
if (NULL != str)
{
myRegisterMemFree(str, CSM_SYSALLOC);
}
SysFreeString(str);
}
BSTR
mySysAllocStringByteLen(
LPCSTR pszIn,
UINT cb)
{
BSTR str;
str = SysAllocStringByteLen(pszIn, cb);
if (NULL != str)
{
myRegisterMemAlloc(str, cb, CSM_SYSALLOC);
}
return(str);
}
VOID
_RegisterVariantMemAlloc(
IN PROPVARIANT *pvar)
{
VOID *pv;
DWORD Flags;
DWORD cb;
pv = _VariantMemory(pvar, &Flags, &cb);
if (NULL != pv)
{
myRegisterMemAlloc(pv, cb, Flags);
}
}
VOID
_RegisterVariantMemFree(
IN PROPVARIANT *pvar)
{
VOID *pv;
DWORD Flags;
pv = _VariantMemory(pvar, &Flags, NULL);
if (NULL != pv)
{
myRegisterMemFree(pv, Flags);
}
}
HRESULT
myPropVariantClear(
IN PROPVARIANT *pvar)
{
_RegisterVariantMemFree(pvar);
return(PropVariantClear(pvar));
}
HRESULT
myVariantClear(
IN VARIANTARG *pvar)
{
_RegisterVariantMemFree((PROPVARIANT *) pvar);
return(VariantClear(pvar));
}
HRESULT
myVariantChangeType(
OUT VARIANTARG *pvarDest,
IN VARIANTARG *pvarSrc,
IN unsigned short wFlags,
IN VARTYPE vt)
{
HRESULT hr;
// if converting in-place, memory will be freed by the API call
if (pvarDest == pvarSrc)
{
_RegisterVariantMemFree((PROPVARIANT *) pvarSrc);
}
hr = VariantChangeType(pvarDest, pvarSrc, wFlags, vt);
_RegisterVariantMemAlloc((PROPVARIANT *) pvarDest);
return(hr);
}
HRESULT
myVariantChangeTypeEx(
OUT VARIANTARG *pvarDest,
IN VARIANTARG *pvarSrc,
IN LCID lcid,
IN unsigned short wFlags,
IN VARTYPE vt)
{
HRESULT hr;
// if converting in-place, memory will be freed by the API call
if (pvarDest == pvarSrc)
{
_RegisterVariantMemFree((PROPVARIANT *) pvarSrc);
}
hr = VariantChangeTypeEx(pvarDest, pvarSrc, lcid, wFlags, vt);
_RegisterVariantMemAlloc((PROPVARIANT *) pvarDest);
return(hr);
}
VOID *
myNew(
IN size_t size)
{
VOID *pv;
pv = LocalAlloc(LMEM_FIXED, size);
if (NULL != pv)
{
myRegisterMemAlloc(pv, size, CSM_NEW);
}
return(pv);
}
VOID
myDelete(
IN VOID *pv)
{
myRegisterMemFree(pv, CSM_NEW);
LocalFree(pv);
}
BOOL
myAllocateAndInitializeSid(
IN PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
IN BYTE nSubAuthorityCount,
IN DWORD nSubAuthority0,
IN DWORD nSubAuthority1,
IN DWORD nSubAuthority2,
IN DWORD nSubAuthority3,
IN DWORD nSubAuthority4,
IN DWORD nSubAuthority5,
IN DWORD nSubAuthority6,
IN DWORD nSubAuthority7,
OUT PSID *ppSid)
{
BOOL b;
b = AllocateAndInitializeSid(
pIdentifierAuthority,
nSubAuthorityCount,
nSubAuthority0,
nSubAuthority1,
nSubAuthority2,
nSubAuthority3,
nSubAuthority4,
nSubAuthority5,
nSubAuthority6,
nSubAuthority7,
ppSid);
if (b && NULL != *ppSid)
{
myRegisterMemAlloc(*ppSid, 32, CSM_SID);
}
return(b);
}
VOID *
myFreeSid(
IN PSID pSid)
{
myRegisterMemFree(pSid, CSM_SID);
return(FreeSid(pSid));
}
#endif // DBG_CERTSRV