NT4/private/sdktools/vctools/cvpack/dmalloc.c
2020-09-30 17:12:29 +02:00

224 lines
4.8 KiB
C

// dmalloc.c
//
#include "compact.h"
#define __DMALLOC_C__ 1 /* prevent redef of malloc et.al. */
#include "dmalloc.h" // public header file
#include "dmalloc_.h" // private header file
DMPRE dmprePrototype = {0x12345678, 0, 0, 0, 0, 0, 0, 0x9abcdef0};
DMSUF dmsufPrototype = {0x0fedcba9, 0x87654321};
void (*pfnDmallocError)(char *szReason, void *pvBadBlock);
int fDmallocInitialized = 0, fDmallocUsed = 0;
DMPRE dmpreLinkedListAnchor;
void
InitDmallocPfn(void (*pfnError)(char *szReason, void *pvBadBlock))
{
if (fDmallocUsed && !fDmallocInitialized)
(*pfnError)("can't initialize ... dmalloc already used", 0);
else {
fDmallocInitialized = 1;
pfnDmallocError = pfnError;
dmpreLinkedListAnchor.pdmpreNext = &dmpreLinkedListAnchor;
dmpreLinkedListAnchor.pdmprePrev = &dmpreLinkedListAnchor;
}
}
void *
D_malloc(size_t cb)
{
DMPRE *pdmpre;
fDmallocUsed = 1;
if (!fDmallocInitialized)
return malloc(cb);
CheckDmallocHeap();
pdmpre = (DMPRE *)malloc(sizeof(DMPRE) + cb + sizeof(DMSUF));
if (pdmpre == 0)
return 0;
InitBlockPdmpre(pdmpre, cb);
return PvUserFromPdmpre(pdmpre);
}
void * D_calloc(size_t cElement, size_t cbElement)
{
void *pv;
fDmallocUsed = 1;
if (!fDmallocInitialized)
return calloc(cElement, cbElement);
CheckDmallocHeap();
pv = D_malloc(cElement * cbElement);
if (pv == 0)
return 0;
memset(pv, 0, cElement * cbElement);
return pv;
}
void * D_realloc(void *pv, size_t cb)
{
DMPRE *pdmpre;
DMSUF *pdmsuf;
fDmallocUsed = 1;
if (!fDmallocInitialized)
return realloc(pv, cb);
if (pv == 0)
return D_malloc(cb);
CheckDmallocHeap();
pdmpre = PdmpreFromPvUser(pv);
pdmsuf = (DMSUF *)((char *)pv + cb);
CheckBlockPdmpre(pdmpre);
ClearBlockPdmpre(pdmpre);
pdmpre = realloc(pdmpre, cb + sizeof(DMPRE) + sizeof(DMSUF));
if (pdmpre == 0)
return 0;
InitBlockPdmpre(pdmpre, cb);
return PvUserFromPdmpre(pdmpre);
}
void D_free(void *pv)
{
fDmallocUsed = 1;
if (!fDmallocInitialized) {
free(pv);
return;
}
CheckDmallocHeap();
CheckBlockPdmpre(PdmpreFromPvUser(pv));
ClearBlockPdmpre(PdmpreFromPvUser(pv));
free(PdmpreFromPvUser(pv));
}
char *
D_strdup(const char *szIn)
{
// We are counting bytes here so use strlen instead of _mbslen(), or
// any other _MBCS functions.
size_t cb = strlen(szIn) + 1;
char *szOut = D_malloc(cb);
_tcscpy(szOut, szIn);
return szOut;
}
void
InitBlockPdmpre(DMPRE *pdmpre, size_t cbUser)
{
DMSUF UNALIGNED *pdmsuf = (DMSUF UNALIGNED *)((char *)PvUserFromPdmpre(pdmpre) + cbUser);
memcpy(pdmpre, &dmprePrototype, sizeof(DMPRE));
memcpy(pdmsuf, &dmsufPrototype, sizeof(DMSUF));
pdmpre->cbUser = cbUser;
pdmpre->ulNotCbUser = ~cbUser;
pdmpre->pdmpreCur = pdmpre;
pdmpre->pdmpreNext = dmpreLinkedListAnchor.pdmpreNext;
dmpreLinkedListAnchor.pdmpreNext->pdmprePrev = pdmpre;
UpdateLinksPdmpre(dmpreLinkedListAnchor.pdmpreNext);
pdmpre->pdmprePrev = &dmpreLinkedListAnchor;
dmpreLinkedListAnchor.pdmpreNext = pdmpre;
UpdateLinksPdmpre(pdmpre);
}
void
CheckBlockPdmpre(DMPRE *pdmpre)
{
DMPRE dmpreT;
DMSUF *pdmsuf, dmsufT;
void *pvUser;
pvUser = PvUserFromPdmpre(pdmpre);
if (pdmpre->cbUser != ~pdmpre->ulNotCbUser) {
(*pfnDmallocError)("dmalloc: block prefix (size) corrupted", pvUser);
return;
}
pdmsuf = (DMSUF *)((char *)pvUser + pdmpre->cbUser);
memcpy(&dmpreT, pdmpre, sizeof(DMPRE));
dmpreT.cbUser = dmpreT.ulNotCbUser = 0;
dmpreT.pdmpreNext = dmpreT.pdmprePrev = dmpreT.pdmpreCur = 0;
dmpreT.ulChecksum = 0;
if (memcmp(&dmpreT, &dmprePrototype, sizeof(DMPRE)) != 0) {
(*pfnDmallocError)("dmalloc: block prefix corrupted", pvUser);
return;
}
memcpy(&dmsufT, pdmsuf, sizeof(DMSUF));
if (memcmp(&dmsufT, &dmsufPrototype, sizeof(DMSUF)) != 0) {
(*pfnDmallocError)("dmalloc: block suffix corrupted", pvUser);
return;
}
if (pdmpre->ulChecksum !=
((unsigned long)pdmpre->pdmpreNext ^
(unsigned long)pdmpre->pdmprePrev ^
~(unsigned long)pdmpre->pdmpreCur)) {
(*pfnDmallocError)("dmalloc: block prefix links corrupted", pvUser);
return;
}
// Things look OK.
}
void
ClearBlockPdmpre(DMPRE *pdmpre)
{
DMSUF UNALIGNED *pdmsuf = (DMSUF UNALIGNED *)((char *)pdmpre + sizeof(DMPRE) + pdmpre->cbUser);
// Unhook it from the list.
//
pdmpre->pdmprePrev->pdmpreNext = pdmpre->pdmpreNext;
UpdateLinksPdmpre(pdmpre->pdmprePrev);
pdmpre->pdmpreNext->pdmprePrev = pdmpre->pdmprePrev;
UpdateLinksPdmpre(pdmpre->pdmpreNext);
memset(pdmpre, 0xbd, sizeof(DMPRE));
memset(pdmsuf, 0xbd, sizeof(DMSUF));
}
void
CheckDmallocHeap()
{
DMPRE *pdmpre;
pdmpre = &dmpreLinkedListAnchor;
while ((pdmpre = pdmpre->pdmpreNext) != &dmpreLinkedListAnchor) {
CheckBlockPdmpre(pdmpre);
}
}
void
UpdateLinksPdmpre(DMPRE *pdmpre)
{
pdmpre->ulChecksum = (unsigned long)pdmpre->pdmpreNext ^
(unsigned long)pdmpre->pdmprePrev ^
~(unsigned long)pdmpre->pdmpreCur;
}