Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
8.3 KiB

  1. /***
  2. *expand.c - Win32 expand heap routine
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 01-15-92 JCR Module created.
  10. * 02-04-92 GJF Replaced windows.h with oscalls.h.
  11. * 05-06-92 DJM ifndef out of POSIX build.
  12. * 09-23-92 SRW Change winheap code to call NT directly always
  13. * 10-15-92 SKS Removed the ill-named HEAP_GROWTH_ALLOWED flag
  14. * which was causing a bug: _expand was behaving like
  15. * realloc(), by moving the block when it could not be
  16. * grown in place. _expand() must NEVER move the block.
  17. * Also added a safety check to work around a bug in
  18. * HeapReAlloc, where it returns success even
  19. * when it fails to grow the block in place.
  20. * 10-28-92 SRW Change winheap code to call Heap????Ex calls
  21. * 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
  22. * 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
  23. * 11-16-92 SRW Heap???Ex functions renamed to Heap???
  24. * 10-21-93 GJF Replace _CALLTYPE1 with _cdecl. Cleaned up format.
  25. * 04-06-95 GJF Added support for debug heap.
  26. * 04-29-95 GJF Copied over from winheap and made conditional on
  27. * WINHEAP.
  28. * 05-22-95 GJF Test against _HEAP_MAXREQ before calling API. Also,
  29. * removed workaround for long-ago NT problem.
  30. * 05-24-95 CFW Official ANSI C++ new handler added.
  31. * 05-23-95 GJF Really removed workaround this time...
  32. * 03-04-96 GJF Added support for small-block heap. Moved heaphook
  33. * invocation to the very start of the function.
  34. * 04-10-96 GJF Return type of __sbh_find_block and __sbh_resize_block
  35. * changed to __map_t *.
  36. * 05-30-96 GJF Minor changes for latest version of small-block heap.
  37. * 05-22-97 RDK New small-block heap scheme implemented.
  38. * 09-26-97 BWT Fix POSIX
  39. * 11-05-97 GJF Small POSIX fix from Roger Lanser.
  40. * 12-17-97 GJF Exception-safe locking.
  41. * 07-28-98 JWM RTC update.
  42. * 09-29-98 GJF Bypass all small-block heap code when __sbh_initialized
  43. * is 0.
  44. * 11-16-98 GJF Merged in VC++ 5.0 version of small-block heap.
  45. * 12-02-98 GJF One too many munlocks!
  46. * 12-18-98 GJF Changes for 64-bit size_t.
  47. * 05-01-99 PML Disable small-block heap for Win64.
  48. * 05-26-99 KBF Updated RTC hook func params
  49. * 06-21-99 GJF Removed old small-block heap from static libs.
  50. * 08-04-00 PML Don't round allocation sizes when using system
  51. * heap (VS7#131005).
  52. * 02-20-02 BWT prefast fixes - don't return from try block
  53. *
  54. *******************************************************************************/
  55. #ifdef WINHEAP
  56. #include <cruntime.h>
  57. #include <malloc.h>
  58. #include <winheap.h>
  59. #include <windows.h>
  60. #include <mtdll.h>
  61. #include <dbgint.h>
  62. #include <rtcsup.h>
  63. /***
  64. *void *_expand(void *pblck, size_t newsize) - expand/contract a block of memory
  65. * in the heap
  66. *
  67. *Purpose:
  68. * Resizes a block in the heap to newsize bytes. newsize may be either
  69. * greater (expansion) or less (contraction) than the original size of
  70. * the block. The block is NOT moved.
  71. *
  72. * NOTES:
  73. *
  74. * (1) In this implementation, if the block cannot be grown to the
  75. * desired size, the resulting block will NOT be grown to the max
  76. * possible size. (That is, either it works or it doesn't.)
  77. *
  78. * (2) Unlike other implementations, you can NOT pass a previously
  79. * freed block to this routine and expect it to work.
  80. *
  81. *Entry:
  82. * void *pblck - pointer to block in the heap previously allocated
  83. * by a call to malloc(), realloc() or _expand().
  84. *
  85. * size_t newsize - requested size for the resized block
  86. *
  87. *Exit:
  88. * Success: Pointer to the resized memory block (i.e., pblck)
  89. * Failure: NULL
  90. *
  91. *Uses:
  92. *
  93. *Exceptions:
  94. * If pblck does not point to a valid allocation block in the heap,
  95. * _expand() will behave unpredictably and probably corrupt the heap.
  96. *
  97. *******************************************************************************/
  98. void * __cdecl _expand_base (void * pBlock, size_t newsize)
  99. {
  100. #ifdef _POSIX_
  101. return (HeapReAlloc( _crtheap,
  102. HEAP_REALLOC_IN_PLACE_ONLY,
  103. pBlock,
  104. (DWORD)newsize ));
  105. #else
  106. void * pvReturn;
  107. #ifdef HEAPHOOK
  108. /* call heap hook if installed */
  109. if (_heaphook)
  110. {
  111. void * pvReturn;
  112. if ((*_heaphook)(_HEAP_EXPAND, newsize, pBlock, (void *)&pvReturn))
  113. return pvReturn;
  114. }
  115. #endif /* HEAPHOOK */
  116. /* validate size */
  117. if ( newsize > _HEAP_MAXREQ )
  118. return NULL;
  119. #ifndef _WIN64
  120. if ( __active_heap == __V6_HEAP )
  121. {
  122. PHEADER pHeader;
  123. #ifdef _MT
  124. _mlock( _HEAP_LOCK );
  125. __try {
  126. #endif
  127. // if allocation block lies within the small-block heap,
  128. // try to resize it there
  129. if ((pHeader = __sbh_find_block(pBlock)) != NULL)
  130. {
  131. pvReturn = NULL;
  132. if ( (newsize <= __sbh_threshold) &&
  133. __sbh_resize_block(pHeader, pBlock, (int)newsize) )
  134. pvReturn = pBlock;
  135. }
  136. #ifdef _MT
  137. }
  138. __finally {
  139. _munlock( _HEAP_LOCK );
  140. }
  141. #endif
  142. if ( pHeader == NULL )
  143. {
  144. // force nonzero size and round up to next paragraph
  145. if (newsize == 0)
  146. newsize = 1;
  147. newsize = (newsize + BYTES_PER_PARA - 1) & ~(BYTES_PER_PARA - 1);
  148. pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY,
  149. pBlock, newsize);
  150. }
  151. }
  152. #ifdef CRTDLL
  153. else if ( __active_heap == __V5_HEAP )
  154. {
  155. __old_sbh_region_t *preg;
  156. __old_sbh_page_t * ppage;
  157. __old_page_map_t * pmap;
  158. // force nonzero size and round up to next paragraph
  159. if (newsize == 0)
  160. newsize = 1;
  161. newsize = (newsize + _OLD_PARASIZE - 1) & ~(_OLD_PARASIZE - 1);
  162. #ifdef _MT
  163. _mlock(_HEAP_LOCK);
  164. __try {
  165. #endif
  166. pmap = __old_sbh_find_block(pBlock, &preg, &ppage);
  167. // allocation block lies within the small-block heap, try to resize
  168. // it there.
  169. if ( pmap != NULL )
  170. {
  171. // *pBlock lies within the small-block heap, try to resize it
  172. // there
  173. pvReturn = NULL;
  174. if ( (newsize <= __old_sbh_threshold) &&
  175. __old_sbh_resize_block(preg, ppage, pmap,
  176. newsize >> _OLD_PARASHIFT) )
  177. pvReturn = pBlock;
  178. RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
  179. RTCCALLBACK(_RTC_Allocate_hook, (pvReturn, newsize, 0));
  180. }
  181. #ifdef _MT
  182. }
  183. __finally {
  184. _munlock(_HEAP_LOCK);
  185. }
  186. #endif
  187. if (pmap != NULL)
  188. return pvReturn;
  189. if ( pmap == NULL )
  190. pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY,
  191. pBlock, newsize);
  192. }
  193. #endif /* CRTDLL */
  194. else // __active_heap == __SYSTEM_HEAP
  195. #endif /* ndef _WIN64 */
  196. {
  197. // force nonzero size
  198. if (newsize == 0)
  199. newsize = 1;
  200. pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY,
  201. pBlock, newsize);
  202. }
  203. if (pvReturn)
  204. {
  205. RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
  206. RTCCALLBACK(_RTC_Allocate_hook, (pvReturn, newsize, 0));
  207. }
  208. return pvReturn;
  209. #endif /* _POSIX_ */
  210. }
  211. #endif /* WINHEAP */