MEMORY.C

// --memory.c------------------------------------------------------------------- 
//
// Memory wrapping functions for DEBUG builds.
//
// Copyright 1986 - 1998 Microsoft Corporation. All Rights Reserved.
// -----------------------------------------------------------------------------

#define _PRIVATE_EDKDEBUG_H
#define _PRIVATE_MEMORY_H

#include <malloc.h>

#define _INC_MALLOC

#include "edk.h"
#include "_exchdbg.h"

#ifdef _NTSDK
#undef _NTSDK
#endif

#include <stddef.h>

#undef _INC_MALLOC


//$--_DebugMemoryStatus---------------------------------------------------------
// Writes an entry in the debug log for memory status.
// -----------------------------------------------------------------------------
void _DebugMemoryStatus( // RETURNS: nothing
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN ULONG cBytes) // count of bytes
{
CHAR buf[BUFSIZ+1] = {0};
MEMORYSTATUS ms = {0};

ZeroMemory(&ms, sizeof(MEMORYSTATUS));

ms.dwLength = sizeof(MEMORYSTATUS);

GlobalMemoryStatus(&ms);

_snprintf(
buf,
BUFSIZ,
"\n\tMEMORY:\tAllocBytes: %lu\n"
"\t\tMemoryLoad: %lu\n"
"\t\tTotalPhys: %lu ; AvailPhys: %lu\n"
"\t\tTotalPageFile: %lu ; AvailPageFile: %lu\n"
"\t\tTotalVirtual: %lu ; AvailVirtual: %lu\n",
cBytes,
ms.dwMemoryLoad,
ms.dwTotalPhys,
ms.dwAvailPhys,
ms.dwTotalPageFile,
ms.dwAvailPageFile,
ms.dwTotalVirtual,
ms.dwAvailVirtual);

REPORT_STATUS(buf);
}

//$--_DebugHeapStatus-----------------------------------------------------------
// Writes an entry in the debug log.
// -----------------------------------------------------------------------------
static void _DebugHeapStatus( // RETURNS: nothing
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN int heapstatus) // heap status
{
CHAR buf[BUFSIZ+1] = {0};

switch (heapstatus)
{
case _FREEENTRY:
_snprintf(buf,BUFSIZ,"HEAP: free entry in heap\n");
break;
case _HEAPOK:
break;
case _HEAPEMPTY:
_snprintf(buf,BUFSIZ,"HEAP: heap is empty\n");
break;
case _HEAPEND:
_snprintf(buf,BUFSIZ,"HEAP: end of heap\n");
break;
case _HEAPBADPTR:
_snprintf(buf,BUFSIZ,"HEAP: bad pointer to heap\n");
break;
case _HEAPBADBEGIN:
_snprintf(buf,BUFSIZ,"HEAP: bad start of heap\n");
break;
case _HEAPBADNODE:
_snprintf(buf,BUFSIZ,"HEAP: bad node in heap\n");
break;
default:
_snprintf(buf,BUFSIZ,"HEAP: _heapchk returned [%u]\n", heapstatus);
}

if(heapstatus != _HEAPOK)
{
REPORT_ERROR(buf);
}
}

//$--_DebugHeapCheck------------------------------------------------------------
// Writes an entry in the debug log. This function is only called in
// DEBUG builds through the DebugHeapCheck() macro.
// -----------------------------------------------------------------------------
void _DebugHeapCheck( // RETURNS: return code
IN ULONG ulLine, // line number
IN LPSTR lpszFile) // file name
{
int heapstatus = _HEAPOK;

heapstatus = _heapchk();

_DebugHeapStatus(ulLine, lpszFile, heapstatus);
}

//$--_DebugDumpHeap-------------------------------------------------------------
// Writes an entry in the debug log. This function is only called in
// DEBUG builds through the DebugDumpHeap() macro.
// -----------------------------------------------------------------------------
void _DebugDumpHeap( // RETURNS: nothing
IN ULONG ulLine, // line number
IN LPSTR lpszFile) // file name
{
_HEAPINFO hi = {0};
int heapstatus = _HEAPOK;
CHAR buf[BUFSIZ+1] = {0};

ZeroMemory(&hi, sizeof(_HEAPINFO));

while((heapstatus = _heapwalk (&hi)) == _HEAPOK)
{
if (hi._useflag == _USEDENTRY)
{
_snprintf(buf, BUFSIZ, "HEAP: used block at %08lx of size %u\n",
hi._pentry,
hi._size );

REPORT_STATUS(buf);
}
}

if(heapstatus != _HEAPOK)
{
_DebugHeapStatus(ulLine, lpszFile, heapstatus);
}
}

//$--EDKDBG_malloc--------------------------------------------------------------
// Wrapper for malloc().
// -----------------------------------------------------------------------------
LPVOID EDKDBG_malloc( // RETURNS: pointer to memory block
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN ULONG ulSize) // size of memory block
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};

_DebugHeapCheck(ulLine, lpszFile);

lpv = malloc(ulSize);

if(lpv != NULL)
{
if(ulSize > 0)
{
FillMemory(lpv, ulSize, 0xCC);
}
}
else
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",ulSize,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,ulSize);
}

return(lpv);
}

//$--EDKDBG_calloc--------------------------------------------------------------
// Wrapper for calloc().
// -----------------------------------------------------------------------------
LPVOID EDKDBG_calloc( // RETURNS: pointer to memory block
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN ULONG ulNum, // number of elements
IN ULONG ulSize) // size of element
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};

_DebugHeapCheck(ulLine, lpszFile);

lpv = calloc(ulNum, ulSize);

// Calloc cannot fill with 0xCC since that changes the known behaviour of calloc

if(lpv == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",ulSize,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,ulSize);
}

return(lpv);
}

//$--EDKDBG_realloc-------------------------------------------------------------
// Wrapper for realloc().
// -----------------------------------------------------------------------------
LPVOID EDKDBG_realloc( // RETURNS: pointer to memory block
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN LPVOID lpvBlock, // pointer to memory block
IN ULONG ulSize) // new size of memory block
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};

_DebugHeapCheck(ulLine, lpszFile);

lpv = realloc(lpvBlock, ulSize);

if(lpv == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",ulSize,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,ulSize);
}

return(lpv);
}

//$--EDKDBG_strdup--------------------------------------------------------------
// Wrapper for strdup().
// -----------------------------------------------------------------------------
char* EDKDBG_strdup( // RETURNS: pointer to allocated string
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN const char *lpsz) // pointer to string
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};

if(IsBadStringPtrA(lpsz, INFINITE))
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid pointer [%08lx]\n", lpsz);

REPORT_ERROR(buf);

return(lpv);
}

_DebugHeapCheck(ulLine, lpszFile);

lpv = _strdup(lpsz);

if(lpv == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",0,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,0);
}

return((char *)lpv);
}

//$--EDKDBG_wcsdup--------------------------------------------------------------
// Wrapper for _wcsdup().
// -----------------------------------------------------------------------------
wchar_t* EDKDBG_wcsdup( // RETURNS: pointer to allocated string
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN const wchar_t *lpsz) // pointer to string
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};

if(IsBadStringPtrW(lpsz, INFINITE))
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid pointer [%08lx]\n", lpsz);

REPORT_ERROR(buf);

return(lpv);
}

_DebugHeapCheck(ulLine, lpszFile);

lpv = _wcsdup(lpsz);

if(lpv == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",0,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,0);
}

return((wchar_t *)lpv);
}

//$--EDKDBG_free----------------------------------------------------------------
// Wrapper for free().
// -----------------------------------------------------------------------------
void EDKDBG_free( // RETURNS: nothing
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN LPVOID lpv) // pointer to memory block
{
_DebugHeapCheck(ulLine, lpszFile);

free(lpv);

return;
}

//$--EDKDBG_GlobalAlloc---------------------------------------------------------
// Wrapper for GlobalAlloc().
// -----------------------------------------------------------------------------
HGLOBAL EDKDBG_GlobalAlloc( // RETURNS: pointer to memory block
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN UINT fuFlags, // allocation flags
IN DWORD dwSize) // size of memory block
{
LPVOID lpv = NULL;
HGLOBAL hglb = NULL;
DWORD cBytes = 0;
CHAR buf[BUFSIZ+1] = {0};

_DebugHeapCheck(ulLine, lpszFile);

if((fuFlags != 0) && (! (fuFlags & GMEM_VALID_FLAGS)))
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid allocation flags [%08lx]\n", fuFlags);

REPORT_ERROR(buf);
}

hglb = GlobalAlloc(fuFlags, dwSize);

if(hglb == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",dwSize,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,dwSize);
}

return(hglb);
}

//$--EDKDBG_GlobalReAlloc-------------------------------------------------------
// Wrapper for GlobalReAlloc().
// -----------------------------------------------------------------------------
HGLOBAL EDKDBG_GlobalReAlloc( // RETURNS: pointer to memory block
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN HGLOBAL hglb, // pointer to memory block
IN DWORD cbBytes, // new size of memory block
IN UINT fuFlags) // allocation flags
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};
UINT gflags = 0;
HGLOBAL hglbMem = 0;

_DebugHeapCheck(ulLine, lpszFile);

if((fuFlags != 0) && (! (fuFlags & GMEM_VALID_FLAGS)))
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid allocation flags [%08lx]\n", fuFlags);

REPORT_ERROR(buf);
}

gflags = GlobalFlags(hglb);

if(gflags == GMEM_INVALID_HANDLE)
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid handle [%08lx]\n", hglb);

REPORT_ERROR(buf);

return(hglbMem);
}

hglbMem = GlobalReAlloc(hglb, cbBytes, fuFlags);

if(hglbMem == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",cbBytes,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,cbBytes);
}

return(hglbMem);
}

//$--EDKDBG_GlobalFree----------------------------------------------------------
// Wrapper for GlobalFree().
// -----------------------------------------------------------------------------
HGLOBAL EDKDBG_GlobalFree( // RETURNS: nothing
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN HGLOBAL hglb) // pointer to memory block
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};
UINT gflags = 0;
HGLOBAL hglbMem = 0;

_DebugHeapCheck(ulLine, lpszFile);

gflags = GlobalFlags(hglb);

if(gflags == GMEM_INVALID_HANDLE)
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid handle [%08lx]\n", hglb);

REPORT_ERROR(buf);

SetLastError(ERROR_INVALID_HANDLE);

return(hglb);
}

if(hglb == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid handle [%08lx]\n", hglb);

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,0);
}

hglbMem = GlobalFree(hglb);

if(hglbMem != NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: deallocation failed [%08lx]\n", GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,0);
}

return(hglbMem);
}

//$--EDKDBG_LocalAlloc----------------------------------------------------------
// Wrapper for LocalAlloc().
// -----------------------------------------------------------------------------
HGLOBAL EDKDBG_LocalAlloc( // RETURNS: pointer to memory block
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN UINT fuFlags, // allocation flags
IN DWORD dwSize) // size of memory block
{
LPVOID lpv = NULL;
HGLOBAL hglb = NULL;
CHAR buf[BUFSIZ+1] = {0};

_DebugHeapCheck(ulLine, lpszFile);

if((fuFlags != 0) && (! (fuFlags & LMEM_VALID_FLAGS)))
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid allocation flags [%08lx]\n", fuFlags);

REPORT_ERROR(buf);
}

hglb = LocalAlloc(fuFlags, dwSize);

if(hglb == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",dwSize,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,dwSize);
}

return(hglb);
}

//$--EDKDBG_LocalReAlloc--------------------------------------------------------
// Wrapper for LocalReAlloc().
// -----------------------------------------------------------------------------
HGLOBAL EDKDBG_LocalReAlloc( // RETURNS: pointer to memory block
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN HGLOBAL hglb, // pointer to memory block
IN DWORD cbBytes, // new size of memory block
IN UINT fuFlags) // allocation flags
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};
UINT gflags = 0;
HGLOBAL hglbMem = 0;

_DebugHeapCheck(ulLine, lpszFile);

if((fuFlags != 0) && (! (fuFlags & LMEM_VALID_FLAGS)))
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid allocation flags [%08lx]\n", fuFlags);

REPORT_ERROR(buf);
}

gflags = LocalFlags(hglb);

if(gflags == LMEM_INVALID_HANDLE)
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid handle [%08lx]\n", hglb);

REPORT_ERROR(buf);

return(hglbMem);
}

hglbMem = LocalReAlloc(hglb, cbBytes, fuFlags);

if(hglbMem == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: allocation of [%lu] bytes failed [%08lx]\n",cbBytes,GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,cbBytes);
}

return(hglbMem);
}

//$--EDKDBG_LocalFree-----------------------------------------------------------
// Wrapper for LocalFree().
// -----------------------------------------------------------------------------
HGLOBAL EDKDBG_LocalFree( // RETURNS: nothing
IN ULONG ulLine, // line number
IN LPSTR lpszFile, // file name
IN HGLOBAL hglb) // pointer to memory block
{
LPVOID lpv = NULL;
CHAR buf[BUFSIZ+1] = {0};
UINT gflags = 0;
HGLOBAL hglbMem = 0;

_DebugHeapCheck(ulLine, lpszFile);

gflags = LocalFlags(hglb);

if(gflags == LMEM_INVALID_HANDLE)
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid handle [%08lx]\n", hglb);

REPORT_ERROR(buf);

SetLastError(ERROR_INVALID_HANDLE);

return(hglb);
}

if(hglb == NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: invalid handle [%08lx]\n", hglb);

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,0);
}

hglbMem = LocalFree(hglb);

if(hglbMem != NULL)
{
_snprintf(buf,BUFSIZ,"MEMORY: deallocation failed [%08lx]\n", GetLastError());

REPORT_ERROR(buf);

_DebugMemoryStatus(ulLine,lpszFile,0);
}

return(hglbMem);
}