/****************************************************************************
**
**  Name:  heap.c
**
**  Description:
**     This module implements a simple heap manager for malloc/free style
**  memory management.  It works with FAR pointers, so pointers can be freely
**  shared between applications and DLLs.  Allocation size is limited to <64K.
**  The primary advantage to using this heap manager is that few window 
**  handles are used.
**
**  Status: CODED         ( PRELIMINARY | CODED | REVIEWED | TESTED )
**
**  $Log:   S:/tbird/mt2_186/malloc/galloc.c_v  $
** 
**    Rev 1.1   26 Feb 1997 11:46:38   Judy
** 
**    Rev 1.0   23 Jul 1996 14:42:54   Judy
** Initial revision.
** 
**    Rev 1.0   07 Sep 1995 10:41:40   gene
** Initial revision.
** 
**    Rev 1.2   18 Mar 1993 09:54:46   nghia
** Added #pragma argsused to avoid compiler warning.
** Added #define _BORLANDC_ around WEP routine.
** Added a dummy HeapClean() routine.
** 
**    Rev 1.1   14 May 1992 14:20:32   courtney
** Add call to ErrInitDLL to initialize with errtext dll.
** 
**    Rev 1.0   16 Mar 1992 07:17:10   doug
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_186/malloc/galloc.c_v   1.1   26 Feb 1997 11:46:38   Judy  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
**  IMPLEMENTATION NOTES:
**  This implementation is a set of 64K heaps.  Within a heap, a boundary tag
**  scheme and first fit strategy is used (see "An Implementation of New and
**  Dispose using Boundary Tags", Branko J. Gerovac,  Pascal News # 19, 
**  September 1980).
**
**  Management of GlobalAlloc()'ed memory is done here.  Memory management
**  within individual 64K heap chunks is private to "chunk.c".
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#define _BORLANDC_

#ifndef  _BASEWIND_
#include "basewind.h"
#endif

#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef _CHUNK_
#include "chunk.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

				
#define ALLOC_FLAGS (GMEM_MOVEABLE | GMEM_ZEROINIT )


                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
/* None */
                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/



                       /****************************
                        *                          *
                        *     LOCAL VARIABLES      *
                        *                          *
                        ****************************/

/* Area information */

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/
#pragma argsused
/****************************************************************************
**
** FUNCTION: LibMain(HANDLE, WORD, WORD, LPSTR)
**
** PURPOSE:  Called by Windows when the DLL is loaded to perform
**           Library initialization.
**           In this case, it initializes the AreaInfo array and
**           GlobalAlloc()'s 1 area.
**
*****************************************************************************/
int FAR PASCAL LibMain(hModule, wDataSeg, cbHeapSize, lpszCmdLine)
HANDLE	hModule;
WORD    wDataSeg;
WORD    cbHeapSize;
LPSTR   lpszCmdLine;
{
       /* register with error text dll */
       ErrInitDLL(MODULE_HEAP, "malloc.dll");

       return( 1 ) ;
}


/****************************************************************************
**
**  TFree -- free memory alloc'ed via Malloc()
**
*****************************************************************************/
RETCODE EXPORT TFree( LPSTR randomPointer ) {
   HANDLE *hPtr;
   HANDLE handle;

   hPtr = (HANDLE *)(randomPointer - sizeof(HANDLE));
   handle = *hPtr;
   return(GlobalFree(handle));
}


/****************************************************************************
**
**  TMalloc -- allocate numBytes of memory or fail
**
*****************************************************************************/

LPSTR EXPORT TMalloc( U32 numBytes ) {
   HANDLE handle;
   LPSTR ptr;
   HANDLE *hPtr;
   U8 FAR *bytePtr;
   DWORD actualSize;
#ifdef TEST_CASE
   int i;
   U8 *testPtr;
#endif

   handle = GlobalAlloc( ALLOC_FLAGS, numBytes+sizeof(HANDLE));
   if (handle == (HANDLE)NULL) {
      ErrDisplayError(ER_HEAP_OUT_OF_MEMORY, FORCE_POPUP);
      return(NULL);
   }
   ptr = GlobalLock(handle);
   if (ptr==(LPSTR)NULL) {
      ErrDisplayError(ER_WINDOWS_MEMLOCK, FORCE_POPUP);
      return(NULL);
   }
   actualSize = GlobalSize(handle);
   
   /* move to the end to check limit */
   bytePtr = (U8 FAR *) (ptr + actualSize - numBytes - sizeof(HANDLE));

   /* keep handle as part of data so it can be freed eventually */
   hPtr = (HANDLE *)bytePtr;
   *hPtr = handle;
#ifdef TEST_CASE
   testPtr = ptr + actualSize - 1; /* set on last valid byte */
   for(i=0; i<100; i++) {
      *testPtr = 0x55; /* first should be ok, second should fail */
      testPtr++;
   }
#endif
   return(bytePtr+sizeof(HANDLE));
}

/****************************************************************************
**
**  HeapClean -- dummy
**
*****************************************************************************/
RETCODE EXPORT HeapClean( ) {
    
    return(GOOD);
}

#ifndef _BORLANDC_
/****************************************************************************
**
**  FUNCTION:  WEP(int)  {Windows Exip Procedure}
**
**  PURPOSE:  Performs cleanup tasks when the DLL is unloaded.  WEP() is
**            said on the net to be useless (crashes Windows if used for
**            anything).  We shall see!
**
*****************************************************************************/

int FAR PASCAL WEP (bSystemExit)
int  bSystemExit;
{
	
    return( 1 ) ;	/* 1 => success; but what else can we do? */
}
#endif
/******************************** E O F ***********************************/
