329 lines
7.5 KiB
C
329 lines
7.5 KiB
C
|
/*
|
||
|
- P V A L L O C . C
|
||
|
-
|
||
|
* Copyright (C) 1995 Microsoft Corporation
|
||
|
* Purpose:
|
||
|
* Implementation of a chained memory manager.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <pvalloc.h>
|
||
|
|
||
|
#undef _PVALLOC_LOG
|
||
|
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
static CB cbTotalAlloc = 0;
|
||
|
static CB ulTotalBlockNum = 0;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
- PvAlloc
|
||
|
-
|
||
|
* Purpose:
|
||
|
* Allocates a chunk of memory on the global heap.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* cbSize - Count of bytes requested.
|
||
|
*
|
||
|
* Returns:
|
||
|
* lpv - Pointer to the allocated memory
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
PV PvAlloc(CB cbSize)
|
||
|
{
|
||
|
PV lpv = pvNull;
|
||
|
HANDLE hMem;
|
||
|
PPVINFO ppvinfo;
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
char szFileName[80];
|
||
|
LPSTR lpszTemp = NULL;
|
||
|
FILE *pFile = NULL;
|
||
|
char szBuff[128];
|
||
|
#endif
|
||
|
|
||
|
/* Make sure allocations are in multiples of 4 */
|
||
|
|
||
|
if(cbSize < 4)
|
||
|
cbSize = 4;
|
||
|
else if(cbSize & 3)
|
||
|
cbSize += 4 - (cbSize & 3);
|
||
|
|
||
|
/* Allocate the block */
|
||
|
|
||
|
hMem = GlobalAlloc(GMEM_MOVEABLE, cbSize + sizeof(PVINFO));
|
||
|
if(hMem)
|
||
|
{
|
||
|
ppvinfo = (PPVINFO)GlobalLock(hMem);
|
||
|
ppvinfo->hMem = hMem;
|
||
|
ppvinfo->lpvNext = pvNull;
|
||
|
ppvinfo->lpvBuf = ((PB)ppvinfo) + sizeof(PVINFO);
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
ppvinfo->cbSize = cbSize;
|
||
|
ulTotalBlockNum++;
|
||
|
ppvinfo->ulBlockNum = ulTotalBlockNum;
|
||
|
cbTotalAlloc += cbSize;
|
||
|
|
||
|
// log to file
|
||
|
lpszTemp = getenv("TEMP");
|
||
|
|
||
|
if(lpszTemp)
|
||
|
strcpy(szFileName, lpszTemp);
|
||
|
else
|
||
|
strcpy(szFileName, "c:\\temp");
|
||
|
|
||
|
strcat(szFileName, "\\pvalloc.log");
|
||
|
|
||
|
|
||
|
pFile = fopen(szFileName,"a");
|
||
|
if (pFile == NULL)
|
||
|
goto NoFile;
|
||
|
// return NULL;
|
||
|
|
||
|
fprintf(pFile, "Block: \t%lu\tPvAlloc: %ld Bytes\t\tTotal: %ld Bytes\n",
|
||
|
ulTotalBlockNum, cbSize, cbTotalAlloc);
|
||
|
|
||
|
if (pFile)
|
||
|
fclose(pFile);
|
||
|
|
||
|
// log to comm port
|
||
|
wsprintf(szBuff,"Block: \t%lu\tPvAlloc: %ld Bytes\t\tTotal: %ld Bytes\n",
|
||
|
ulTotalBlockNum, cbSize, cbTotalAlloc);
|
||
|
OutputDebugString(szBuff);
|
||
|
|
||
|
NoFile:
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
memset(ppvinfo->lpvBuf, 0xaa, (size_t)cbSize);
|
||
|
#else
|
||
|
_fmemset(ppvinfo->lpvBuf, 0xaa, (size_t)cbSize);
|
||
|
#endif /* _WIN32 */
|
||
|
|
||
|
#endif /* _PVALLOC_LOG */
|
||
|
lpv = ppvinfo->lpvBuf;
|
||
|
}
|
||
|
|
||
|
return lpv;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- PvAllocMore
|
||
|
-
|
||
|
* Purpose:
|
||
|
* Allocates a chunk of memory and chains it to a parent block.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* cbSize - Count of additional bytes to allocate
|
||
|
* lpvParent - Pointer to parent in memory chain
|
||
|
*
|
||
|
* Returns:
|
||
|
* lpv - Pointer to the allocated memory
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
PV PvAllocMore(CB cbSize, PV lpvParent)
|
||
|
{
|
||
|
PV lpvStep = lpvParent;
|
||
|
PV lpv = pvNull;
|
||
|
PPVINFO ppvinfoMore;
|
||
|
HANDLE hMem;
|
||
|
PPVINFO ppvinfo;
|
||
|
|
||
|
/* Step to the last link */
|
||
|
do
|
||
|
{
|
||
|
ppvinfoMore = (PPVINFO)(((PB)lpvStep) - sizeof(PVINFO));
|
||
|
lpvStep = ppvinfoMore->lpvNext;
|
||
|
}
|
||
|
while(ppvinfoMore->lpvNext != pvNull);
|
||
|
|
||
|
// beginning of section that was taken from PvAlloc
|
||
|
|
||
|
if(cbSize < 4)
|
||
|
cbSize = 4;
|
||
|
else if(cbSize & 3)
|
||
|
cbSize += 4 - (cbSize & 3);
|
||
|
|
||
|
|
||
|
hMem = GlobalAlloc(GMEM_MOVEABLE, cbSize + sizeof(PVINFO));
|
||
|
if(hMem)
|
||
|
{
|
||
|
ppvinfo = (PPVINFO)GlobalLock(hMem);
|
||
|
ppvinfo->hMem = hMem;
|
||
|
ppvinfo->lpvNext = pvNull;
|
||
|
ppvinfo->lpvBuf = ((PB)ppvinfo) + sizeof(PVINFO);
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
ppvinfo->cbSize = cbSize;
|
||
|
ppvinfo->ulBlockNum = ppvinfoMore->ulBlockNum;
|
||
|
cbTotalAlloc += cbSize;
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
memset(ppvinfo->lpvBuf, 0xaa, (size_t)cbSize);
|
||
|
#else
|
||
|
_fmemset(ppvinfo->lpvBuf, 0xaa, (size_t)cbSize);
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
lpv = ppvinfo->lpvBuf;
|
||
|
}
|
||
|
else
|
||
|
return lpv;
|
||
|
|
||
|
// end of section taken from pvalloc
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
memset(lpv, 0xbb, (size_t)cbSize);
|
||
|
#else
|
||
|
_fmemset(lpv, 0xbb, (size_t)cbSize);
|
||
|
#endif /* _WIN32 */
|
||
|
|
||
|
ppvinfoMore->lpvNext = lpv;
|
||
|
|
||
|
return lpv;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
- PvFree
|
||
|
-
|
||
|
* Purpose:
|
||
|
* This function frees memory allocated by PvAlloc or PvAllocMore.
|
||
|
* After the call, the pointer memory will be invalid and should
|
||
|
* not be referenced again.
|
||
|
* When memory is allocated by PvAlloc and PvAllocMore, which can
|
||
|
* contain several levels of pointers, all the application needs to
|
||
|
* do to free the entire structure is call this routine with the
|
||
|
* base pointer returned by the PvAlloc call.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* lpv - Pointer to memory to be freed.
|
||
|
*
|
||
|
* Returns:
|
||
|
* Void
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
BOOL PvFree(PV lpv)
|
||
|
{
|
||
|
PPVINFO ppvinfo;
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
CB cbSize;
|
||
|
CB ulBlockNum;
|
||
|
FILE *pFile = NULL;
|
||
|
CB cbFree = 0;
|
||
|
CB cbTotalBeforeFree = cbTotalAlloc;
|
||
|
char szFileName[80];
|
||
|
LPSTR lpszTemp = NULL;
|
||
|
char szBuff[128];
|
||
|
#endif
|
||
|
|
||
|
if(!lpv)
|
||
|
return 0;
|
||
|
|
||
|
ppvinfo = (PPVINFO)(((PB)lpv) - sizeof(PVINFO));
|
||
|
|
||
|
while(ppvinfo)
|
||
|
{
|
||
|
lpv = ppvinfo->lpvNext;
|
||
|
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
cbSize = ppvinfo->cbSize;
|
||
|
cbFree += ppvinfo->cbSize;
|
||
|
ulBlockNum = ppvinfo->ulBlockNum;
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
memset(ppvinfo->lpvBuf, 0xcc, (size_t)ppvinfo->cbSize);
|
||
|
#else
|
||
|
_fmemset(ppvinfo->lpvBuf, 0xcc, (size_t)ppvinfo->cbSize);
|
||
|
#endif /* _WIN32 */
|
||
|
|
||
|
#endif /* _PVALLOC_LOG */
|
||
|
|
||
|
if(GlobalUnlock(ppvinfo->hMem))
|
||
|
goto err; // Our lock count is non-zero
|
||
|
|
||
|
if(GlobalFree(ppvinfo->hMem))
|
||
|
goto err; // Failure
|
||
|
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
cbTotalAlloc -= cbSize;
|
||
|
#endif
|
||
|
|
||
|
if(lpv)
|
||
|
ppvinfo = (PPVINFO)(((PB)lpv) - sizeof(PVINFO));
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
|
||
|
if((cbTotalBeforeFree - cbTotalAlloc) != cbFree)
|
||
|
goto err;
|
||
|
|
||
|
// log to file
|
||
|
lpszTemp = getenv("TEMP");
|
||
|
|
||
|
if(lpszTemp)
|
||
|
strcpy(szFileName, lpszTemp);
|
||
|
else
|
||
|
strcpy(szFileName, "c:\\temp");
|
||
|
|
||
|
strcat(szFileName, "\\pvalloc.log");
|
||
|
|
||
|
pFile = fopen(szFileName,"a");
|
||
|
|
||
|
if (pFile == NULL)
|
||
|
goto err;
|
||
|
|
||
|
fprintf(pFile, "Block: \t%lu\t\t***PvFree***, Freeing %lu Bytes(Alloc and AllocMore)\tUnFreed: %ld Bytes\n",
|
||
|
ulBlockNum, cbFree, cbTotalAlloc);
|
||
|
if (pFile)
|
||
|
fclose(pFile);
|
||
|
|
||
|
// log to comm port
|
||
|
wsprintf(szBuff,"Block: \t%lu\t\t***PvFree***, Freeing %lu Bytes(Alloc and AllocMore)\tUnFreed: %ld Bytes\n",
|
||
|
ulBlockNum, cbFree, cbTotalAlloc);
|
||
|
OutputDebugString(szBuff);
|
||
|
|
||
|
#endif /* _PVALLOC_LOG */
|
||
|
|
||
|
return 0; // Success!
|
||
|
|
||
|
err:
|
||
|
#ifdef _PVALLOC_LOG
|
||
|
|
||
|
// find file to open
|
||
|
lpszTemp = getenv("TEMP");
|
||
|
|
||
|
if(lpszTemp)
|
||
|
strcpy(szFileName, lpszTemp);
|
||
|
else
|
||
|
strcpy(szFileName, "c:\\temp");
|
||
|
|
||
|
strcat(szFileName, "\\pvalloc.log");
|
||
|
|
||
|
|
||
|
pFile = fopen(szFileName,"a");
|
||
|
|
||
|
if (pFile == NULL)
|
||
|
return 1;
|
||
|
|
||
|
fprintf(pFile, "Block: %lu Failure freeing: %ld Bytes\tUnFreed: %ld Bytes\n",
|
||
|
ulBlockNum, cbSize, cbTotalAlloc);
|
||
|
if (pFile)
|
||
|
fclose(pFile);
|
||
|
|
||
|
#endif /* _PVALLOC_LOG */
|
||
|
|
||
|
return 1; // Failure!
|
||
|
}
|