ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

heap.c
Go to the documentation of this file.
00001 /*
00002  * msvcrt.dll heap functions
00003  *
00004  * Copyright 2000 Jon Griffiths
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  * Note: Win32 heap operations are MT safe. We only lock the new
00021  *       handler and non atomic heap operations
00022  */
00023 
00024 #include <precomp.h>
00025 #include <malloc.h>
00026 
00027 /* MT */
00028 #define LOCK_HEAP   _mlock( _HEAP_LOCK )
00029 #define UNLOCK_HEAP _munlock( _HEAP_LOCK )
00030 
00031 /* _aligned */
00032 #define SAVED_PTR(x) ((void *)((DWORD_PTR)((char *)x - sizeof(void *)) & \
00033                                ~(sizeof(void *) - 1)))
00034 #define ALIGN_PTR(ptr, alignment, offset) ((void *) \
00035     ((((DWORD_PTR)((char *)ptr + alignment + sizeof(void *) + offset)) & \
00036       ~(alignment - 1)) - offset))
00037 
00038 
00039 typedef int (CDECL *MSVCRT_new_handler_func)(size_t size);
00040 
00041 static MSVCRT_new_handler_func MSVCRT_new_handler;
00042 static int MSVCRT_new_mode;
00043 
00044 /* FIXME - According to documentation it should be 8*1024, at runtime it returns 16 */
00045 static unsigned int MSVCRT_amblksiz = 16;
00046 /* FIXME - According to documentation it should be 480 bytes, at runtime default is 0 */
00047 static size_t MSVCRT_sbh_threshold = 0;
00048 
00049 /*********************************************************************
00050  *      ??2@YAPAXI@Z (MSVCRT.@)
00051  */
00052 void* CDECL MSVCRT_operator_new(size_t size)
00053 {
00054   void *retval;
00055   int freed;
00056 
00057   do
00058   {
00059     retval = HeapAlloc(GetProcessHeap(), 0, size);
00060     if(retval)
00061     {
00062       TRACE("(%ld) returning %p\n", size, retval);
00063       return retval;
00064     }
00065 
00066     LOCK_HEAP;
00067     if(MSVCRT_new_handler)
00068       freed = (*MSVCRT_new_handler)(size);
00069     else
00070       freed = 0;
00071     UNLOCK_HEAP;
00072   } while(freed);
00073 
00074   TRACE("(%ld) out of memory\n", size);
00075   return NULL;
00076 }
00077 
00078 
00079 /*********************************************************************
00080  *      ??2@YAPAXIHPBDH@Z (MSVCRT.@)
00081  */
00082 void* CDECL MSVCRT_operator_new_dbg(size_t size, int type, const char *file, int line)
00083 {
00084     return MSVCRT_operator_new( size );
00085 }
00086 
00087 
00088 /*********************************************************************
00089  *      ??3@YAXPAX@Z (MSVCRT.@)
00090  */
00091 void CDECL MSVCRT_operator_delete(void *mem)
00092 {
00093   TRACE("(%p)\n", mem);
00094   HeapFree(GetProcessHeap(), 0, mem);
00095 }
00096 
00097 
00098 /*********************************************************************
00099  *      ?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@)
00100  */
00101 MSVCRT_new_handler_func CDECL MSVCRT__query_new_handler(void)
00102 {
00103   return MSVCRT_new_handler;
00104 }
00105 
00106 
00107 /*********************************************************************
00108  *      ?_query_new_mode@@YAHXZ (MSVCRT.@)
00109  */
00110 int CDECL MSVCRT__query_new_mode(void)
00111 {
00112   return MSVCRT_new_mode;
00113 }
00114 
00115 /*********************************************************************
00116  *      ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@)
00117  */
00118 MSVCRT_new_handler_func CDECL MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
00119 {
00120   MSVCRT_new_handler_func old_handler;
00121   LOCK_HEAP;
00122   old_handler = MSVCRT_new_handler;
00123   MSVCRT_new_handler = func;
00124   UNLOCK_HEAP;
00125   return old_handler;
00126 }
00127 
00128 /*********************************************************************
00129  *      ?set_new_handler@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
00130  */
00131 MSVCRT_new_handler_func CDECL MSVCRT_set_new_handler(void *func)
00132 {
00133   TRACE("(%p)\n",func);
00134   MSVCRT__set_new_handler(NULL);
00135   return NULL;
00136 }
00137 
00138 /*********************************************************************
00139  *      ?_set_new_mode@@YAHH@Z (MSVCRT.@)
00140  */
00141 int CDECL MSVCRT__set_new_mode(int mode)
00142 {
00143   int old_mode;
00144   LOCK_HEAP;
00145   old_mode = MSVCRT_new_mode;
00146   MSVCRT_new_mode = mode;
00147   UNLOCK_HEAP;
00148   return old_mode;
00149 }
00150 
00151 /*********************************************************************
00152  *      _callnewh (MSVCRT.@)
00153  */
00154 int CDECL _callnewh(size_t size)
00155 {
00156   if(MSVCRT_new_handler)
00157     (*MSVCRT_new_handler)(size);
00158   return 0;
00159 }
00160 
00161 /*********************************************************************
00162  *      _expand (MSVCRT.@)
00163  */
00164 void* CDECL _expand(void* mem, size_t size)
00165 {
00166   return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, mem, size);
00167 }
00168 
00169 /*********************************************************************
00170  *      _heapchk (MSVCRT.@)
00171  */
00172 int CDECL _heapchk(void)
00173 {
00174   if (!HeapValidate( GetProcessHeap(), 0, NULL))
00175   {
00176     _dosmaperr(GetLastError());
00177     return _HEAPBADNODE;
00178   }
00179   return _HEAPOK;
00180 }
00181 
00182 /*********************************************************************
00183  *      _heapmin (MSVCRT.@)
00184  */
00185 int CDECL _heapmin(void)
00186 {
00187   if (!HeapCompact( GetProcessHeap(), 0 ))
00188   {
00189     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
00190       _dosmaperr(GetLastError());
00191     return -1;
00192   }
00193   return 0;
00194 }
00195 
00196 /*********************************************************************
00197  *      _heapwalk (MSVCRT.@)
00198  */
00199 int CDECL _heapwalk(_HEAPINFO* next)
00200 {
00201   PROCESS_HEAP_ENTRY phe;
00202 
00203   LOCK_HEAP;
00204   phe.lpData = next->_pentry;
00205   phe.cbData = (DWORD)next->_size;
00206   phe.wFlags = next->_useflag == _USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
00207 
00208   if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
00209       !HeapValidate( GetProcessHeap(), 0, phe.lpData ))
00210   {
00211     UNLOCK_HEAP;
00212     _dosmaperr(GetLastError());
00213     return _HEAPBADNODE;
00214   }
00215 
00216   do
00217   {
00218     if (!HeapWalk( GetProcessHeap(), &phe ))
00219     {
00220       UNLOCK_HEAP;
00221       if (GetLastError() == ERROR_NO_MORE_ITEMS)
00222          return _HEAPEND;
00223       _dosmaperr(GetLastError());
00224       if (!phe.lpData)
00225         return _HEAPBADBEGIN;
00226       return _HEAPBADNODE;
00227     }
00228   } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
00229 
00230   UNLOCK_HEAP;
00231   next->_pentry = phe.lpData;
00232   next->_size = phe.cbData;
00233   next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? _USEDENTRY : _FREEENTRY;
00234   return _HEAPOK;
00235 }
00236 
00237 /*********************************************************************
00238  *      _heapset (MSVCRT.@)
00239  */
00240 int CDECL _heapset(unsigned int value)
00241 {
00242   int retval;
00243   _HEAPINFO heap;
00244 
00245   memset( &heap, 0, sizeof(heap) );
00246   LOCK_HEAP;
00247   while ((retval = _heapwalk(&heap)) == _HEAPOK)
00248   {
00249     if (heap._useflag == _FREEENTRY)
00250       memset(heap._pentry, value, heap._size);
00251   }
00252   UNLOCK_HEAP;
00253   return retval == _HEAPEND? _HEAPOK : retval;
00254 }
00255 
00256 /*********************************************************************
00257  *      _heapadd (MSVCRT.@)
00258  */
00259 int CDECL _heapadd(void* mem, size_t size)
00260 {
00261   TRACE("(%p,%ld) unsupported in Win32\n", mem,size);
00262   *_errno() = ENOSYS;
00263   return -1;
00264 }
00265 
00266 /*********************************************************************
00267  *      _heapadd (MSVCRT.@)
00268  */
00269 intptr_t CDECL _get_heap_handle(void)
00270 {
00271     return (intptr_t)GetProcessHeap();
00272 }
00273 
00274 /*********************************************************************
00275  *      _msize (MSVCRT.@)
00276  */
00277 size_t CDECL _msize(void* mem)
00278 {
00279   size_t size = HeapSize(GetProcessHeap(),0,mem);
00280   if (size == ~(size_t)0)
00281   {
00282     WARN(":Probably called with non wine-allocated memory, ret = -1\n");
00283     /* At least the Win32 crtdll/msvcrt also return -1 in this case */
00284   }
00285   return size;
00286 }
00287 
00288 /*********************************************************************
00289  *      calloc (MSVCRT.@)
00290  */
00291 void* CDECL calloc(size_t size, size_t count)
00292 {
00293   return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
00294 }
00295 
00296 /*********************************************************************
00297  *      free (MSVCRT.@)
00298  */
00299 void CDECL free(void* ptr)
00300 {
00301   if(ptr == NULL) return;
00302   HeapFree(GetProcessHeap(),0,ptr);
00303 }
00304 
00305 /*********************************************************************
00306  *                  malloc (MSVCRT.@)
00307  */
00308 void* CDECL malloc(size_t size)
00309 {
00310   void *ret = HeapAlloc(GetProcessHeap(),0,size);
00311   if (!ret)
00312       *_errno() = ENOMEM;
00313   return ret;
00314 }
00315 
00316 /*********************************************************************
00317  *      realloc (MSVCRT.@)
00318  */
00319 void* CDECL realloc(void* ptr, size_t size)
00320 {
00321   if (!ptr) return malloc(size);
00322   if (size) return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
00323   free(ptr);
00324   return NULL;
00325 }
00326 
00327 /*********************************************************************
00328  *      __p__amblksiz (MSVCRT.@)
00329  */
00330 unsigned int* CDECL __p__amblksiz(void)
00331 {
00332   return &MSVCRT_amblksiz;
00333 }
00334 
00335 /*********************************************************************
00336  *      _get_sbh_threshold (MSVCRT.@)
00337  */
00338 size_t CDECL _get_sbh_threshold(void)
00339 {
00340   return MSVCRT_sbh_threshold;
00341 }
00342 
00343 /*********************************************************************
00344  *      _set_sbh_threshold (MSVCRT.@)
00345  */
00346 int CDECL _set_sbh_threshold(size_t threshold)
00347 {
00348   if(threshold > 1016)
00349      return 0;
00350   else
00351      MSVCRT_sbh_threshold = threshold;
00352   return 1;
00353 }
00354 
00355 /*********************************************************************
00356  *      _aligned_free (MSVCRT.@)
00357  */
00358 void CDECL _aligned_free(void *memblock)
00359 {
00360     TRACE("(%p)\n", memblock);
00361 
00362     if (memblock)
00363     {
00364         void **saved = SAVED_PTR(memblock);
00365         free(*saved);
00366     }
00367 }
00368 
00369 /*********************************************************************
00370  *      _aligned_offset_malloc (MSVCRT.@)
00371  */
00372 void * CDECL _aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
00373 {
00374     void *memblock, *temp, **saved;
00375     TRACE("(%lu, %lu, %lu)\n", size, alignment, offset);
00376 
00377     /* alignment must be a power of 2 */
00378     if ((alignment & (alignment - 1)) != 0)
00379     {
00380         *_errno() = EINVAL;
00381         return NULL;
00382     }
00383 
00384     /* offset must be less than size */
00385     if (offset >= size)
00386     {
00387         *_errno() = EINVAL;
00388         return NULL;
00389     }
00390 
00391     /* don't align to less than void pointer size */
00392     if (alignment < sizeof(void *))
00393         alignment = sizeof(void *);
00394 
00395     /* allocate enough space for void pointer and alignment */
00396     temp = malloc(size + alignment + sizeof(void *));
00397 
00398     if (!temp)
00399         return NULL;
00400 
00401     /* adjust pointer for proper alignment and offset */
00402     memblock = ALIGN_PTR(temp, alignment, offset);
00403 
00404     /* Save the real allocation address below returned address */
00405     /* so it can be found later to free. */
00406     saved = SAVED_PTR(memblock);
00407     *saved = temp;
00408 
00409     return memblock;
00410 }
00411 
00412 /*********************************************************************
00413  *      _aligned_malloc (MSVCRT.@)
00414  */
00415 void * CDECL _aligned_malloc(size_t size, size_t alignment)
00416 {
00417     TRACE("(%lu, %lu)\n", size, alignment);
00418     return _aligned_offset_malloc(size, alignment, 0);
00419 }
00420 
00421 /*********************************************************************
00422  *      _aligned_offset_realloc (MSVCRT.@)
00423  */
00424 void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
00425                                      size_t alignment, size_t offset)
00426 {
00427     void * temp, **saved;
00428     size_t old_padding, new_padding, old_size;
00429     TRACE("(%p, %lu, %lu, %lu)\n", memblock, size, alignment, offset);
00430 
00431     if (!memblock)
00432         return _aligned_offset_malloc(size, alignment, offset);
00433 
00434     /* alignment must be a power of 2 */
00435     if ((alignment & (alignment - 1)) != 0)
00436     {
00437         *_errno() = EINVAL;
00438         return NULL;
00439     }
00440 
00441     /* offset must be less than size */
00442     if (offset >= size)
00443     {
00444         *_errno() = EINVAL;
00445         return NULL;
00446     }
00447 
00448     if (size == 0)
00449     {
00450         _aligned_free(memblock);
00451         return NULL;
00452     }
00453 
00454     /* don't align to less than void pointer size */
00455     if (alignment < sizeof(void *))
00456         alignment = sizeof(void *);
00457 
00458     /* make sure alignment and offset didn't change */
00459     saved = SAVED_PTR(memblock);
00460     if (memblock != ALIGN_PTR(*saved, alignment, offset))
00461     {
00462         *_errno() = EINVAL;
00463         return NULL;
00464     }
00465 
00466     old_padding = (char *)memblock - (char *)*saved;
00467 
00468     /* Get previous size of block */
00469     old_size = _msize(*saved);
00470     if (old_size == -1)
00471     {
00472         /* It seems this function was called with an invalid pointer. Bail out. */
00473         return NULL;
00474     }
00475 
00476     /* Adjust old_size to get amount of actual data in old block. */
00477     if (old_size < old_padding)
00478     {
00479         /* Shouldn't happen. Something's weird, so bail out. */
00480         return NULL;
00481     }
00482     old_size -= old_padding;
00483 
00484     temp = realloc(*saved, size + alignment + sizeof(void *));
00485 
00486     if (!temp)
00487         return NULL;
00488 
00489     /* adjust pointer for proper alignment and offset */
00490     memblock = ALIGN_PTR(temp, alignment, offset);
00491 
00492     /* Save the real allocation address below returned address */
00493     /* so it can be found later to free. */
00494     saved = SAVED_PTR(memblock);
00495 
00496     new_padding = (char *)memblock - (char *)temp;
00497 
00498 /*
00499    Memory layout of old block is as follows:
00500    +-------+---------------------+-+--------------------------+-----------+
00501    |  ...  | "old_padding" bytes | | ... "old_size" bytes ... |    ...    |
00502    +-------+---------------------+-+--------------------------+-----------+
00503            ^                     ^ ^
00504            |                     | |
00505         *saved               saved memblock
00506 
00507    Memory layout of new block is as follows:
00508    +-------+-----------------------------+-+----------------------+-------+
00509    |  ...  |    "new_padding" bytes      | | ... "size" bytes ... |  ...  |
00510    +-------+-----------------------------+-+----------------------+-------+
00511            ^                             ^ ^
00512            |                             | |
00513           temp                       saved memblock
00514 
00515    However, in the new block, actual data is still written as follows
00516    (because it was copied by MSVCRT_realloc):
00517    +-------+---------------------+--------------------------------+-------+
00518    |  ...  | "old_padding" bytes |   ... "old_size" bytes ...     |  ...  |
00519    +-------+---------------------+--------------------------------+-------+
00520            ^                             ^ ^
00521            |                             | |
00522           temp                       saved memblock
00523 
00524    Therefore, min(old_size,size) bytes of actual data have to be moved
00525    from the offset they were at in the old block (temp + old_padding),
00526    to the offset they have to be in the new block (temp + new_padding == memblock).
00527 */
00528     if (new_padding != old_padding)
00529         memmove((char *)memblock, (char *)temp + old_padding, (old_size < size) ? old_size : size);
00530 
00531     *saved = temp;
00532 
00533     return memblock;
00534 }
00535 
00536 /*********************************************************************
00537  *      _aligned_realloc (MSVCRT.@)
00538  */
00539 void * CDECL _aligned_realloc(void *memblock, size_t size, size_t alignment)
00540 {
00541     TRACE("(%p, %lu, %lu)\n", memblock, size, alignment);
00542     return _aligned_offset_realloc(memblock, size, alignment, 0);
00543 }
00544 
00545 /*********************************************************************
00546  *      memmove_s (MSVCRT.@)
00547  */
00548 int CDECL memmove_s(void *dest, size_t numberOfElements, const void *src, size_t count)
00549 {
00550     TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count);
00551 
00552     if(!count)
00553         return 0;
00554 
00555     if(!dest || !src) {
00556         if(dest)
00557             memset(dest, 0, numberOfElements);
00558 
00559         *_errno() = EINVAL;
00560         return EINVAL;
00561     }
00562 
00563     if(count > numberOfElements) {
00564         memset(dest, 0, numberOfElements);
00565 
00566         *_errno() = ERANGE;
00567         return ERANGE;
00568     }
00569 
00570     memmove(dest, src, count);
00571     return 0;
00572 }
00573 
00574 /*********************************************************************
00575  *      strncpy_s (MSVCRT.@)
00576  */
00577 int CDECL strncpy_s(char *dest, size_t numberOfElements,
00578         const char *src, size_t count)
00579 {
00580     size_t i, end;
00581 
00582     TRACE("(%s %lu %s %lu)\n", dest, numberOfElements, src, count);
00583 
00584     if(!count)
00585         return 0;
00586 
00587     if (!MSVCRT_CHECK_PMT(dest != NULL) || !MSVCRT_CHECK_PMT(src != NULL) ||
00588         !MSVCRT_CHECK_PMT(numberOfElements != 0)) {
00589         *_errno() = EINVAL;
00590         return EINVAL;
00591     }
00592 
00593     if(count!=_TRUNCATE && count<numberOfElements)
00594         end = count;
00595     else
00596         end = numberOfElements-1;
00597 
00598     for(i=0; i<end && src[i]; i++)
00599         dest[i] = src[i];
00600 
00601     if(!src[i] || end==count || count==_TRUNCATE) {
00602         dest[i] = '\0';
00603         return 0;
00604     }
00605 
00606     MSVCRT_INVALID_PMT("dest[numberOfElements] is too small");
00607     dest[0] = '\0';
00608     *_errno() = EINVAL;
00609     return EINVAL;
00610 }

Generated on Sun May 27 2012 04:19:17 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.