Category : C++ Source Code
Archive   : NEWTK200.ZIP
Filename : NEWTDLL.CPP

 
Output of file : NEWTDLL.CPP contained in archive : NEWTK200.ZIP
// @(#) %M% V%I% %H%
//
// File name
// -------------
// NEWTDLL.CPP
//
// (c) Cavendish Software Ltd 1991, 1992
//
// Document References
// -------------------
// This is a general purpose module, and as such has no document references
//
// File Description
// ----------------
// Newtrack v2.0/Windows. DLL Section of NewTrack, a new/delete and
// open/close tracking and verification system.
//

// HEADER FILES
#include
#include
#include
#include
#include
#include


// ENUMERATED TYPES - Errors
enum TRK_ERROR
{
TKE_OK = 0, // No error
TKE_UNDERRUN, // Pointer Underrun
TKE_OVERRUN, // Pointer Overrun
TKE_BADPTR, // Invalid pointer
TKE_NULLPTR, // NULL Pointer
TKE_NOMEMORY, // Out of memory
TKE_NEWLEFTOVER // Unfreed allocations
};


// TYPE DEFINITIONS & CLASSES

// Block Structure. Used to track an allocation
struct NT_BLOCK
{
TRK_CALLER caller;
NT_PTR ptr;
NT_SIZE size;
NT_BLOCK *next;
NT_BLOCK *prev;

NT_BLOCK(NT_PTR _ptr, NT_SIZE _size, TRK_CALLER _caller) :
ptr(_ptr),
size(_size),
caller(_caller),

next(0),
prev(0)
{
// Nothing
}

~NT_BLOCK(void)
{ ptr = 0; size = 0; next = 0; prev = 0; caller = 0; }
};

// Task Structure. Contains info for a task
struct NT_TASK
{
HTASK taskid;
int tracking;
TRK_ERROR error;
NT_BLOCK *blocks;
unsigned long nallocs;
NT_TASK *next;
NT_TASK *prev;

NT_TASK(int _tracking = 0) :
tracking(_tracking),
error(TKE_OK),
blocks(0),
nallocs(0),
next(0),
prev(0)
{
taskid = GetCurrentTask();
}

// Adds a block to the list
void AddBlock(NT_PTR p, NT_SIZE size, TRK_CALLER caller);

// Removes a block from the list
void ExtractBlock(NT_BLOCK *blk);

// Validates a pointer, calling the error handler if invalid
NT_BLOCK *ValidPtr(NT_PTR p);

// Error handler
void HandleError(TRK_ERROR err, unsigned long count = 0);
};


// GLOBAL VARIABLES -- Error Messages
static char *errmsgs[]=
{
"No Error!",
"Pointer Underrun",
"Pointer Overrun",
"Invalid Pointer Passed to Delete",
"NULL Pointer Allocation",
"Out of Memory",
"%lu Unfreed Memory Allocations"
};


// GLOBAL VARIABLES
static NT_TASK *tasklist = 0;


// GLOBAL VARIABLES -- EXTERNALS
#ifndef __DLL__
extern int __newtrack;
#endif


// FUNCTION PROTOTYPES
NT_TASK *NT_FindTask(void);
void _hmemset(NT_PTR p, int c, NT_SIZE n);
void _hmemcpy(NT_PTR dest, NT_PTR src, NT_SIZE n);
int _hmemcmp(NT_PTR s1, NT_PTR s2, NT_SIZE n);





//
//
// Methods for Class: NT_TASK
//
//
void NT_TASK::AddBlock(NT_PTR p, NT_SIZE size, TRK_CALLER caller)
{
// Turn off NewTrack tracking to prevent loopback
#ifndef __DLL__
__newtrack = 0;
#endif

// Create a new block
NT_BLOCK *blk = new NT_BLOCK(p, size, caller);

// Turn NewTrack tracking back on
#ifndef __DLL__
__newtrack = 1;
#endif

// If there is already a list...
if (blocks)
{
// Find the last in the list
NT_BLOCK *b2 = blocks;
for (; b2->next; b2 = b2->next)
;

// Tack the new block onto the end
b2->next = blk;
blk->prev = b2;
}
else

// No list yet, so start it off...
blocks = blk;

// Increase count of allocations
nallocs++;
}

void NT_TASK::ExtractBlock(NT_BLOCK *blk)
{
// Point the previous block around
if (blk->prev)
blk->prev->next = blk->next;
else
blocks = blk->next;

// Point the next block around
if (blk->next)
blk->next->prev = blk->prev;

// Decrease the number of allocations
nallocs--;
}

// Validates the pointer as being allocated via NewTrack
NT_BLOCK *NT_TASK::ValidPtr(NT_PTR p)
{
NT_BLOCK *blk = blocks;

// See if we can find a match for the pointer
for (; blk; blk = blk->next)
if (blk->ptr == p)
break;

// If no match...
if (!blk)
{
// Tell the user
HandleError(TKE_BADPTR);
return 0;
}

// Check the pre-text is still there
if (_hmemcmp(p, (NT_PTR) NT_PRE_TEXT, NT_PRE_SIZE) != 0)
{
// Tell the user
HandleError(TKE_UNDERRUN);
return 0;
}

// Check the post-text is still there
if (_hmemcmp(p + blk->size - NT_POST_SIZE, (NT_PTR) NT_POST_TEXT,
NT_POST_SIZE) != 0)
{
// Tell the user
HandleError(TKE_OVERRUN);
return 0;
}

// The pointer is valid....return the block
return blk;
}

// Tells the user abouts the error, with the option to terminate app.
void NT_TASK::HandleError(TRK_ERROR err, unsigned long count)
{
char tmps[500];
sprintf(tmps, errmsgs[err], count);
strcat(tmps, " - Continue?");

// Tell the user
int ret = MessageBox(0, tmps, "NewTrack Error", MB_SYSTEMMODAL |
MB_ICONSTOP | MB_OKCANCEL);

// Abort the app if requested
if (ret != IDOK)
abort();

// Break into the debugger
asm int 3;

}





// FUNCTIONS

// Initialises NewTrack tracking for the current task
void _far _pascal NT_Initialise(void)
{
// Allocate Task info
NT_TASK *task = new NT_TASK(1);

// If this is the first task to use NewTrack, start the list off
if (!tasklist)
tasklist = task;
else
{
NT_TASK *last;

// Find the last task in the list
for (last = tasklist; last->next; last = last->next)
; // Nothing

// Add a new one onto the end
last->next = task;
task->prev = last;
}
}

// Terminates NewTrack tracking for the current task
unsigned long _far _pascal NT_Terminate(void)
{
unsigned long nallocs;
NT_BLOCK **blist = 0;
NT_TASK *task = NT_FindTask();

// If there are any unfreed pointers (for this task)
if ((nallocs = task->nallocs) > 0)
{
unsigned blsize;

// Make sure we can handle the number
if (nallocs > 0xfffe)
blsize = 0xfffe;
else
blsize = (unsigned) nallocs;

// Tell the user
task->HandleError(TKE_NEWLEFTOVER, nallocs);

// Create a shorthand array of unfreed blocks
blist = new NT_BLOCK *[blsize + 1];

// If we made it...
if (blist)
{
unsigned i;
NT_BLOCK *blk = task->blocks;

// Make up the list of unfreed blocks for this task
for (i = 0; blk; blk = blk->next, i++)
blist[i] = blk;

// Terminate the list
blist[i] = 0;
}
}

// If there are any unfreed allocs, break into the debugger
if (blist)
{
asm int 3

// Free up the shorthand list
if (blist)
delete blist;
}

// Point the previous task around us
if (task->prev)
task->prev->next = task->next;
else
tasklist = task->next;

// Point the next task around us
if (task->next)
task->next->prev = task->prev;

// Return number of allocations left over
return nallocs;
}

// Transforms a pointer p into a NewTrack pointer by adding a
// header & trailer.
NT_PTR _far _pascal NT_New(void far *_p, NT_SIZE size, TRK_CALLER caller)
{
NT_TASK *task = NT_FindTask();
NT_PTR p = (NT_PTR) _p;

// If tracking is turned off, drop out straight away
if (!task || !task->tracking)
return p;

// If we ran out of memory, tell the user
if (!p)
{
task->HandleError(TKE_NOMEMORY);
return 0;
}

// Set the pre-text and post-text, and initialise the rest
_hmemcpy(p, (NT_PTR) NT_PRE_TEXT, NT_PRE_SIZE);
_hmemcpy(p + size - NT_POST_SIZE, (NT_PTR) NT_POST_TEXT, NT_POST_SIZE);
_hmemset(p + NT_PRE_SIZE, NT_NEWFILL, size - NT_PRE_SIZE - NT_POST_SIZE);

// Add the block to the tasks' list
task->AddBlock(p, size, caller);

// Return the pointer *after* our pre-text
return p + NT_PRE_SIZE;
}

// Transforms a NewTrack pointer into an oridinary pointer by
// removing the header.
void far * _far _pascal NT_Delete(NT_PTR p)
{
NT_TASK *task = NT_FindTask();
NT_BLOCK *blk;

// Is there any tracking running at all?
if (!task || !task->tracking)
return p;

// Restore the pointer to that returned by malloc()
p -= NT_PRE_SIZE;

// If we have a valid pointer
if ((blk = task->ValidPtr(p)) != 0)
{
// Extract block from the list
task->ExtractBlock(blk);

// Fill in the block with known "garbage"
_hmemset(p, NT_DELFILL, blk->size);

// Turn off NewTrack tracking to prevent loopback
#ifndef __DLL__
__newtrack = 0;
#endif

// Delete the block
delete blk;

// Turn NewTrack tracking back on
#ifndef __DLL__
__newtrack = 1;
#endif
}
else
return 0;

// Return the pointer to be freed by the real task
return (void far *)p;
};

// Finds the NT_TASK structure for the current task
NT_TASK *NT_FindTask(void)
{
NT_TASK *task = tasklist;

// Find the NT_TASK for the current task
for (; task; task = task->next)
if (task->taskid == GetCurrentTask())
break;

// Return the found task
return task;
}

// Returns the number of allocations
unsigned long NT_EXPORT _far _pascal NT_NAllocs(void)
{
NT_TASK *task = NT_FindTask();

return (task) ? task->nallocs : 0;
}

// Returns the real size to allocate; called by new() so that the task can allocate
NT_SIZE _far _pascal NT_NewSize(unsigned long size)
{
return size + NT_PRE_SIZE + NT_POST_SIZE;
}





//
//
// Helper functions
//
//

// Huge memset() - sets n bytes of data to c
void _hmemset(NT_PTR p, int c, NT_SIZE n)
{
for (; n; p++, n--)
*p = c;
}

// Huge memcpy() - copies n bytes from src to dest
void _hmemcpy(NT_PTR dest, NT_PTR src, NT_SIZE n)
{
for (; n; n--, dest++, src++)
*dest = *src;
}

// Huge memcmp() - compares n bytes of s1 with s2
int _hmemcmp(NT_PTR s1, NT_PTR s2, NT_SIZE n)
{
for (; n && *s1 == *s2; n--, s1++, s2++)
;

return (n) ? ((int)(s1 - s2)) : 0;
}





//
//
// DLL specific Functions
//
//
#ifdef __DLL__
#pragma argsused
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSegment, WORD wHeapSize, LPSTR lpszCmdLine)
{
if (wHeapSize != 0)
UnlockData(0);
return (1);
}

#pragma argsused
int FAR PASCAL WEP(int bSystemExit)
{
return (1);
}
#endif


  3 Responses to “Category : C++ Source Code
Archive   : NEWTK200.ZIP
Filename : NEWTDLL.CPP

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/