www.pudn.com > helpview.zip > Winmem.c, change:1997-10-15,size:14459b


/* 
  
Copyright 1997 Willows Software, Inc.  
 
This library is free software; you can redistribute it and/or 
modify it under the terms of the GNU Library General Public License as 
published by the Free Software Foundation; either version 2 of the 
License, or (at your option) any later version. 
 
This library is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
Library General Public License for more details. 
 
You should have received a copy of the GNU Library General Public 
License along with this library; see the file COPYING.LIB.  If 
not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
Cambridge, MA 02139, USA. 
 
*/ 
 
/************************************************************************* 
* 
* WINMEM.C 
* General memory routines.      
* 
* Author: Paul E. Kissel 
* 
**************************************************************************/ 
 
/************************************* 
* 
*  System Includes 
* 
**************************************/ 
#include <string.h> 
 
 
/************************************* 
* 
*  Private Includes 
* 
**************************************/ 
#include "winmem.h" 
#include "msgbox.h" 
#include "twhlprc.h" 
#include "globals.h" 
 
 
/*********************************** 
** 
**  Private functions 
** 
***********************************/ 
 
static FPMEMORYPAGE AllocNewMemoryPage( FPMEMORYLIST fpMemoryList, WORD wSize ); 
 
 
 
/****************************** Memory Allocation Functions ******************************/ 
 
/************************************* 
* 
*  Allocate global memory and trap error. 
* 
**************************************/ 
BOOL GlobalAllocMem( HWND hWnd, HGLOBAL * hGlobal, DWORD dwSize  ) 
{ 
  /* Allocate memory. */ 
  *hGlobal = GlobalAlloc ( GHND | GMEM_SHARE, dwSize ) ; 
                               
  /* Error retrieving memory. */ 
  if ( *hGlobal == NULL )  
  { 
    /* If we get down to here then the command is not recognized. */  
    MsgBox( GetLibInst(), hWnd, IDS_ERRORTITLE, IDS_MEMORYALLOC, MB_ICONHAND | MB_OK ); 
    return FALSE; 
  } 
 
  /* Return it. */ 
  return TRUE; 
} 
 
 
/************************************* 
* 
*  Reallocate global memory and trap error. 
* 
**************************************/ 
BOOL GlobalReAllocMem( HWND hWnd, HGLOBAL * hGlobal, DWORD dwNewSize  ) 
{ 
  /* Allocate memory for menu list. */ 
  *hGlobal = GlobalReAlloc( *hGlobal, dwNewSize, GHND | GMEM_SHARE ) ; 
                               
  /* Error retrieving memory. */ 
  if ( *hGlobal == NULL )  
  { 
    /* Allocation error. */  
    MsgBox( GetLibInst(), hWnd, IDS_ERRORTITLE, IDS_MEMORYALLOC, MB_ICONHAND | MB_OK ); 
    return FALSE; 
  } 
 
  /* Return it. */ 
  return TRUE; 
} 
 
 
/****************************** Memory Error Checking Functions ******************************/ 
#ifdef DEBUGGINGON  
void MyGlobalFree( HGLOBAL hGlobal ) 
{ 
  HGLOBAL hReturn; 
 
  if( hGlobal == 0 ) 
  { 
    /* Allocation error. */  
    MsgBox( GetLibInst(), NULL, IDS_ERRORTITLE, IDS_MEMORYFREE, MB_ICONHAND | MB_OK ); 
    DebugBreak(); 
  } 
  else 
  { 
    hReturn = GlobalFree( hGlobal ); 
    if( hReturn == hGlobal ) 
    { 
      /* Allocation error. */  
      MsgBox( GetLibInst(), NULL, IDS_ERRORTITLE, IDS_MEMORYFREE, MB_ICONHAND | MB_OK ); 
    } 
  } 
} 
#endif                                  
 
 
/****************************** Copy Functions ******************************/ 
 
/***************************************** 
** 
**  Allocates a global memory buffer and  
**  copies string's data into the buffer. 
** 
*****************************************/ 
HGLOBAL CopyString( HWND hErrorWnd, char * fpString ) 
{ 
  short int nBufferSize; 
   
  HGLOBAL   hNewString; 
  char * fpNewString; 
   
                    
  /* Get size of filepath. Add 1 for NULL. */ 
  nBufferSize = strlen( fpString ) + sizeof( char ); 
 
  /* Allocate memory for filepath. */ 
  if( !GlobalAllocMem( hErrorWnd, &hNewString, nBufferSize ) ) 
  { 
    /* Failure. */ 
    return( NULL ); 
  } 
   
  /* Lock the new string. */ 
  fpNewString = ( char * ) GlobalLock( hNewString );  
 
  /* Save path data in the record. */   
  strcpy( fpNewString, fpString ); 
 
  /* Unlock the new string. */ 
  GlobalUnlock( hNewString );  
 
  /* Return new string. */ 
  return( hNewString ); 
} 
 
 
/****************************** Memory Paging Functions ******************************/ 
 
#define MEM_LIST_ADD   10       /* Default number of pages and increment size. */ 
#define SYS_RESERVED   16       /* Space reserved in a page by LocalInit(). */ 
#define PAGE_SIZE      0xFFFF   /* Initial page memory size for each page is 25K. */  
 
/*************************************************** 
* 
* Creates a MEMORYLIST structure that contains a  
* list of memory pages.  
* 
****************************************************/ 
BOOL AllocMemoryList( HGLOBAL * hMemoryList ) 
{ 
  FPMEMORYLIST fpMemoryList; 
   
  /* 
  ** Allocate the MEMORYLIST structure.  
  */ 
  *hMemoryList =  GlobalAlloc( GHND, sizeof(MEMORYLIST) ); 
  if( *hMemoryList == NULL ) 
  { 
    /* Failure. */ 
    return( FALSE ); 
  } 
 
  /* Lock MEMORYLIST structure. */ 
  fpMemoryList = ( FPMEMORYLIST ) GlobalLock( *hMemoryList ); 
   
  /* Init MEMORYLIST structure. */ 
   
  /* 
  ** Allocate the memory page list.  
  */ 
  fpMemoryList->wPagesInUse = 0; 
  fpMemoryList->wNumPages = MEM_LIST_ADD; 
  fpMemoryList->hPageList = GlobalAlloc( GHND, fpMemoryList->wNumPages * sizeof(MEMORYPAGE) ); 
  if( fpMemoryList->hPageList == NULL ) 
  { 
    /* Free MEMORYLIST structure. */ 
    GlobalUnlock( *hMemoryList  ); 
    MyGlobalFree( *hMemoryList ); 
     
    /* Failure. */ 
    return( FALSE ); 
  } 
 
  /* Lock memory page list. */ 
  fpMemoryList->TopPagePtr = (FPMEMORYPAGE) GlobalLock( fpMemoryList->hPageList ); 
 
  /* Unlock MEMORYLIST structure. */ 
  GlobalUnlock( *hMemoryList  ); 
 
  /* Success. */ 
  return( TRUE ); 
} 
 
 
/*************************************************** 
* 
* Adds more pages to the memory page list in a  
* MEMORYLIST structure.  
* 
****************************************************/ 
BOOL ReAllocMemList( FPMEMORYLIST fpMemoryList ) 
{ 
  /* Unlock the memory page list. */ 
  GlobalUnlock( fpMemoryList->hPageList ); 
 
  /* 
  ** ReAllocate the memory page list.  
  */ 
  fpMemoryList->wNumPages = fpMemoryList->wNumPages + MEM_LIST_ADD; 
 
  fpMemoryList->hPageList = GlobalReAlloc( fpMemoryList->hPageList,  
                            fpMemoryList->wNumPages * sizeof(MEMORYPAGE), 
                            GMEM_MOVEABLE | GMEM_ZEROINIT ); 
  if( fpMemoryList->hPageList == NULL ) 
  { 
    /* Failure. */ 
    return( FALSE ); 
  } 
 
  /* Lock page list. */ 
  fpMemoryList->TopPagePtr = (FPMEMORYPAGE) GlobalLock( fpMemoryList->hPageList ); 
   
  /* Success. */ 
  return( TRUE ); 
} 
 
 
/*************************************************** 
* 
* Free a MEMORYLIST structure that contains a  
* list of memory pages.  
* 
****************************************************/ 
void FreeMemoryList( HGLOBAL * hMemoryList ) 
{ 
  FPMEMORYLIST fpMemoryList; 
  FPMEMORYPAGE fpPage; 
  WORD wCounter; 
   
   
  /* Lock MEMORYLIST structure. */ 
  fpMemoryList = ( FPMEMORYLIST ) GlobalLock( *hMemoryList ); 
   
  /* 
  ** Free each page being used in the memory page list.  
  */ 
  fpPage = fpMemoryList->TopPagePtr; 
  for( wCounter = 0; wCounter < fpMemoryList->wPagesInUse; wCounter++ ) 
  { 
    /* Unlock page. */ 
    GlobalUnlock( fpPage->hGlobal ); 
     
    /* Free page. */ 
    MyGlobalFree( fpPage->hGlobal ); 
 
    /* Go to next page. */ 
    fpPage = fpPage + 1; 
  } 
 
  /* Free the memory page list. */ 
  GlobalUnlock( fpMemoryList->hPageList ); 
  GlobalFree( fpMemoryList->hPageList ); 
   
  /* Free MEMORYLIST structure. */ 
  GlobalUnlock( *hMemoryList  ); 
  MyGlobalFree( *hMemoryList  ); 
  *hMemoryList = NULL; 
} 
 
 
/*************************************************** 
* 
* Allocates another page of memory.  If all pages 
* in the list are used, more pages are added to the 
* list.  
* 
****************************************************/ 
static FPMEMORYPAGE AllocNewMemoryPage( FPMEMORYLIST fpMemoryList, WORD wSize ) 
{ 
  FPMEMORYPAGE fpPage; 
 
  /* If there is no unused page? */ 
  if( fpMemoryList->wPagesInUse == fpMemoryList->wNumPages ) 
  { 
    /* Allocate more usused pages. */ 
    if( ! ReAllocMemList( fpMemoryList ) ) 
    { 
      return FALSE; 
    } 
  }                  
 
  /* Goto next unused page. */ 
  fpPage = fpMemoryList->TopPagePtr + fpMemoryList->wPagesInUse; 
 
  /* Determine page size. */   
  if( wSize > PAGE_SIZE ) 
  { 
    fpPage->wBytesFree = wSize; 
  } 
  else 
  { 
    fpPage->wBytesFree = PAGE_SIZE; 
  } 
 
  /* Allocate page's space. */ 
  fpPage->hGlobal = GlobalAlloc( GPTR, fpPage->wBytesFree ); 
  if( fpPage->hGlobal == NULL ) 
  { 
    /* Failure. */ 
    return( NULL ); 
  } 
 
  /* Lock page. */ 
  fpPage->GlobalPtr = (BYTE *) GlobalLock( fpPage->hGlobal ); 
 
  /* One more used page in the memory pages list. */ 
  fpMemoryList->wPagesInUse = fpMemoryList->wPagesInUse + 1; 
   
  /* Return page. */ 
  return( fpPage ); 
} 
 
 
 
/*************************************************** 
* 
* Allocates memory inside of a page of memory.  
* 
****************************************************/ 
BYTE * MyAlloc( FPMEMORYLIST fpMemoryList, WORD wSize ) 
{ 
  FPMEMORYPAGE fpPage; 
  WORD wCounter; 
  BYTE * RetPtr; 
   
 
  /* Bad call. */ 
  if( wSize == 0 ) 
  { 
    /* Allocation error. */  
    MsgBox( GetLibInst(), NULL, IDS_ERRORTITLE, IDS_ALLOCZEROMEM, MB_ICONHAND | MB_OK ); 
    return( NULL ); 
  } 
   
  /* 
  ** For each page being used in the memory page list, 
  ** find one with the space available.  
  */ 
  fpPage = fpMemoryList->TopPagePtr; 
  for( wCounter = 0; wCounter < fpMemoryList->wPagesInUse; wCounter++ ) 
  {  
    if( fpPage->wBytesFree >= wSize ) 
    { 
      RetPtr = fpPage->GlobalPtr; 
 
      fpPage->wBytesFree = fpPage->wBytesFree - wSize; 
      fpPage->GlobalPtr = fpPage->GlobalPtr + wSize; 
     
      /* Success. */ 
      return( RetPtr ); 
    } 
     
    /* Go to next memory page. */ 
    fpPage = fpPage + 1; 
  } 
 
  /*  
  ** Didn't find a page with free space.  
  ** Alloc a new page of global memory. 
  */ 
 
  /* Allocate a new page. */ 
  fpPage = AllocNewMemoryPage( fpMemoryList, wSize ); 
 
  /* Error? */ 
  if( fpPage == NULL ) 
  { 
    return( NULL ); 
  } 
 
  RetPtr = fpPage->GlobalPtr; 
 
  fpPage->wBytesFree = fpPage->wBytesFree - wSize; 
  fpPage->GlobalPtr = fpPage->GlobalPtr + wSize; 
     
  /* Success. */ 
  return( RetPtr ); 
}  
 
 
#if 0 
/*************************************************** 
* 
* Allocates another page of memory.  If all pages 
* in the list are used, more pages are added to the 
* list.  
* 
****************************************************/ 
FPMEMORYPAGE AllocNewMemoryPage( FPMEMORYLIST fpMemoryList ) 
{ 
  FPMEMORYPAGE fpPage; 
 
  /* If there is no unused page? */ 
  if( fpMemoryList->wPagesInUse == fpMemoryList->wNumPages ) 
  { 
    /* Allocate more usused pages. */ 
    if( ! ReAllocMemList( fpMemoryList ) ) 
    { 
      return FALSE; 
    } 
  }                  
 
  /* Goto next unused page. */ 
  fpPage = fpMemoryList->TopPagePtr + fpMemoryList->wPagesInUse; 
   
  /* Allocate page's space. */ 
  fpPage->hGlobal = GlobalAlloc( GPTR, PAGE_SIZE ); 
  if( fpPage->hGlobal == NULL ) 
  { 
    /* Failure. */ 
    return( NULL ); 
  } 
 
  /* Lock page. */ 
  fpPage->GlobalPtr = (void *) GlobalLock( fpPage->hGlobal ); 
 
  /* Get page's segment. */ 
  fpPage->Segment = (UINT) SELECTOROF( fpPage->GlobalPtr ); 
 
  /* Initialize local heap. */ 
  LocalInit( fpPage->Segment, SYS_RESERVED, PAGE_SIZE - 1 );  
   
  /* One more used page in the memory pages list. */ 
  fpMemoryList->wPagesInUse = fpMemoryList->wPagesInUse + 1; 
   
  /* Return page. */ 
  return( fpPage ); 
} 
 
 
/*************************************************** 
* 
* Allocates memory inside of a page of memory.  
* 
****************************************************/ 
LPVOID MyAlloc( FPMEMORYLIST fpMemoryList, WORD wSize ) 
{ 
  FPMEMORYPAGE fpPage; 
  WORD wCounter; 
  UINT Segment; 
  HANDLE hMem; 
  static HANDLE hLastMem; 
 
  LPWORD PagePtr; 
   
   
  /* 
  ** For each page being used in the memory page list, 
  ** find one with the space available.  
  */ 
  hMem = NULL; 
  fpPage = fpMemoryList->TopPagePtr; 
  for( wCounter = 0; wCounter < fpMemoryList->wPagesInUse; wCounter++ ) 
  {  
    /* Can't have pointer indirection in __asm code so... */ 
    Segment = fpPage->Segment; 
 
    PagePtr = (LPWORD) MAKELP(Segment,0);   
 
    /* Use global alloc'd page's segment. */ 
    __asm 
    { 
      push    ds                ; Save the DS. 
      mov     ds, Segment       ; Get segment to allocate within. 
    } 
     
    /* Allocate the memory in the page. */ 
    hMem = LocalAlloc( LMEM_FIXED | LMEM_NOCOMPACT | LMEM_NODISCARD, wSize );  
     
    /* Restore DS. */ 
    __asm 
    { 
      pop     ds                  ; Restore the DS. 
    } 
     
    /* Got memory? */ 
    if( hMem != NULL )  
    {  
      hLastMem = hMem; 
      return( (LPVOID) MAKELONG( hMem, fpPage->Segment ) ); 
    } 
 
    /* Go to next memory page. */ 
    fpPage = fpPage + 1; 
  } 
 
  /*  
  ** Didn't find a page with free space.  
  ** Alloc a new page of global memory. 
  */ 
 
  /* Allocate a new page. */ 
  fpPage = AllocNewMemoryPage( fpMemoryList ); 
 
  /* Error? */ 
  if( fpPage == NULL ) 
  { 
    return( NULL ); 
  } 
 
  /* Can't have pointer indirection in __asm code so... */ 
  Segment = fpPage->Segment; 
 
  PagePtr = (LPWORD) MAKELP(Segment,0);   
 
  /* Use global alloc'd page's segment. */ 
  __asm 
  { 
    push  ds                ; Save the DS. 
    mov   ds, Segment       ; Get segment to allocate within. 
  } 
   
  /* Allocate the memory in the page. */ 
  hMem = LocalAlloc( LMEM_FIXED | LMEM_NOCOMPACT | LMEM_NODISCARD, wSize );  
   
  /* Restore DS. */ 
  __asm 
  { 
    pop   ds                  ; Restore the DS. 
  } 
 
  /* Error? */ 
  if( hMem == NULL ) 
  { 
    return NULL; 
  } 
 
  hLastMem = hMem; 
   
  /* Success. */ 
  return( (LPVOID) MAKELONG( hMem, fpPage->Segment ) ); 
}  
#endif