/*** *expand.c - Win32 expand heap routine * * Copyright (c) 1991-1998, Microsoft Corporation. All rights reserved. * *Purpose: * *******************************************************************************/ #ifdef WINHEAP #include #include #include #include #include #include /*** *void *_expand(void *pblck, size_t newsize) - expand/contract a block of memory * in the heap * *Purpose: * Resizes a block in the heap to newsize bytes. newsize may be either * greater (expansion) or less (contraction) than the original size of * the block. The block is NOT moved. * * NOTES: * * (1) In this implementation, if the block cannot be grown to the * desired size, the resulting block will NOT be grown to the max * possible size. (That is, either it works or it doesn't.) * * (2) Unlike other implementations, you can NOT pass a previously * freed block to this routine and expect it to work. * *Entry: * void *pblck - pointer to block in the heap previously allocated * by a call to malloc(), realloc() or _expand(). * * size_t newsize - requested size for the resized block * *Exit: * Success: Pointer to the resized memory block (i.e., pblck) * Failure: NULL * *Uses: * *Exceptions: * If pblck does not point to a valid allocation block in the heap, * _expand() will behave unpredictably and probably corrupt the heap. * *******************************************************************************/ void * __cdecl _expand_base (void * pBlock, size_t newsize) { PHEADER pHeader; void * pvReturn; /* validate size */ if ( newsize > _HEAP_MAXREQ ) return NULL; if ( __active_heap == __V6_HEAP ) { #ifdef _MT _mlock( _HEAP_LOCK ); __try { #endif /* _MT */ // if allocation block lies within the small-block heap, // try to resize it there if ((pHeader = __sbh_find_block(pBlock)) != NULL) { pvReturn = NULL; if ( (newsize <= __sbh_threshold) && __sbh_resize_block(pHeader, pBlock, newsize) ) pvReturn = pBlock; } #ifdef _MT } __finally { _munlock( _HEAP_LOCK ); } #endif /* _MT */ if ( pHeader == NULL ) { // force nonzero size and round up to next paragraph if (newsize == 0) newsize = 1; newsize = (newsize + BYTES_PER_PARA - 1) & ~(BYTES_PER_PARA - 1); pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY, pBlock, newsize); } } else if ( __active_heap == __V5_HEAP ) { __old_sbh_region_t *preg; __old_sbh_page_t * ppage; __old_page_map_t * pmap; // force nonzero size and round up to next paragraph if (newsize == 0) newsize = 1; newsize = (newsize + _OLD_PARASIZE - 1) & ~(_OLD_PARASIZE - 1); #ifdef _MT _mlock(_HEAP_LOCK); __try { #endif /* _MT */ pmap = __old_sbh_find_block(pBlock, &preg, &ppage); // allocation block lies within the small-block heap, try to resize // it there. if ( pmap != NULL ) { // *pBlock lies within the small-block heap, try to resize it // there pvReturn = NULL; if ( (newsize <= __old_sbh_threshold) && __old_sbh_resize_block(preg, ppage, pmap, newsize >> _OLD_PARASHIFT) ) pvReturn = pBlock; return pvReturn; } #ifdef _MT } __finally { _munlock(_HEAP_LOCK); } #endif /* _MT */ if ( pmap == NULL ) pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY, pBlock, newsize); } else // __active_heap == __SYSTEM_HEAP { // force nonzero size and round up to next paragraph if (newsize == 0) newsize = 1; newsize = (newsize + BYTES_PER_PARA - 1) & ~(BYTES_PER_PARA - 1); pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY, pBlock, newsize); } return pvReturn; } #endif /* WINHEAP */