| 1 | /* | 
|---|
| 2 | * msvcrt.dll heap functions | 
|---|
| 3 | * | 
|---|
| 4 | * Copyright 2000 Jon Griffiths | 
|---|
| 5 | * | 
|---|
| 6 | * This library is free software; you can redistribute it and/or | 
|---|
| 7 | * modify it under the terms of the GNU Lesser General Public | 
|---|
| 8 | * License as published by the Free Software Foundation; either | 
|---|
| 9 | * version 2.1 of the License, or (at your option) any later version. | 
|---|
| 10 | * | 
|---|
| 11 | * This library is distributed in the hope that it will be useful, | 
|---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 14 | * Lesser General Public License for more details. | 
|---|
| 15 | * | 
|---|
| 16 | * You should have received a copy of the GNU Lesser General Public | 
|---|
| 17 | * License along with this library; if not, write to the Free Software | 
|---|
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|---|
| 19 | * | 
|---|
| 20 | * Note: Win32 heap operations are MT safe. We only lock the new | 
|---|
| 21 | *       handler and non atomic heap operations | 
|---|
| 22 | */ | 
|---|
| 23 |  | 
|---|
| 24 | #include "msvcrt.h" | 
|---|
| 25 | #include "ms_errno.h" | 
|---|
| 26 |  | 
|---|
| 27 | #include "msvcrt/malloc.h" | 
|---|
| 28 | #include "msvcrt/stdlib.h" | 
|---|
| 29 | #include "mtdll.h" | 
|---|
| 30 |  | 
|---|
| 31 | #include "wine/debug.h" | 
|---|
| 32 |  | 
|---|
| 33 | WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); | 
|---|
| 34 |  | 
|---|
| 35 | /* MT */ | 
|---|
| 36 | #define LOCK_HEAP   _mlock( _HEAP_LOCK ) | 
|---|
| 37 | #define UNLOCK_HEAP _munlock( _HEAP_LOCK ) | 
|---|
| 38 |  | 
|---|
| 39 |  | 
|---|
| 40 | typedef void (*MSVCRT_new_handler_func)(unsigned long size); | 
|---|
| 41 |  | 
|---|
| 42 | static MSVCRT_new_handler_func MSVCRT_new_handler; | 
|---|
| 43 | static int MSVCRT_new_mode; | 
|---|
| 44 |  | 
|---|
| 45 |  | 
|---|
| 46 | /********************************************************************* | 
|---|
| 47 | *              ??2@YAPAXI@Z (MSVCRT.@) | 
|---|
| 48 | */ | 
|---|
| 49 | void* MSVCRT_operator_new(unsigned long size) | 
|---|
| 50 | { | 
|---|
| 51 | void *retval = HeapAlloc(GetProcessHeap(), 0, size); | 
|---|
| 52 | TRACE("(%ld) returning %p\n", size, retval); | 
|---|
| 53 | LOCK_HEAP; | 
|---|
| 54 | if(!retval && MSVCRT_new_handler) | 
|---|
| 55 | (*MSVCRT_new_handler)(size); | 
|---|
| 56 | UNLOCK_HEAP; | 
|---|
| 57 | return retval; | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 | /********************************************************************* | 
|---|
| 61 | *              ??3@YAXPAX@Z (MSVCRT.@) | 
|---|
| 62 | */ | 
|---|
| 63 | void MSVCRT_operator_delete(void *mem) | 
|---|
| 64 | { | 
|---|
| 65 | TRACE("(%p)\n", mem); | 
|---|
| 66 | HeapFree(GetProcessHeap(), 0, mem); | 
|---|
| 67 | } | 
|---|
| 68 |  | 
|---|
| 69 |  | 
|---|
| 70 | /********************************************************************* | 
|---|
| 71 | *              ?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@) | 
|---|
| 72 | */ | 
|---|
| 73 | MSVCRT_new_handler_func MSVCRT__query_new_handler(void) | 
|---|
| 74 | { | 
|---|
| 75 | return MSVCRT_new_handler; | 
|---|
| 76 | } | 
|---|
| 77 |  | 
|---|
| 78 |  | 
|---|
| 79 | /********************************************************************* | 
|---|
| 80 | *              ?_query_new_mode@@YAHXZ (MSVCRT.@) | 
|---|
| 81 | */ | 
|---|
| 82 | int MSVCRT__query_new_mode(void) | 
|---|
| 83 | { | 
|---|
| 84 | return MSVCRT_new_mode; | 
|---|
| 85 | } | 
|---|
| 86 |  | 
|---|
| 87 | /********************************************************************* | 
|---|
| 88 | *              ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@) | 
|---|
| 89 | */ | 
|---|
| 90 | MSVCRT_new_handler_func MSVCRT__set_new_handler(MSVCRT_new_handler_func func) | 
|---|
| 91 | { | 
|---|
| 92 | MSVCRT_new_handler_func old_handler; | 
|---|
| 93 | LOCK_HEAP; | 
|---|
| 94 | old_handler = MSVCRT_new_handler; | 
|---|
| 95 | MSVCRT_new_handler = func; | 
|---|
| 96 | UNLOCK_HEAP; | 
|---|
| 97 | return old_handler; | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | /********************************************************************* | 
|---|
| 101 | *              ?set_new_handler@@YAP6AXXZP6AXXZ@Z (MSVCRT.@) | 
|---|
| 102 | */ | 
|---|
| 103 | MSVCRT_new_handler_func MSVCRT_set_new_handler(void *func) | 
|---|
| 104 | { | 
|---|
| 105 | TRACE("(%p)\n",func); | 
|---|
| 106 | MSVCRT__set_new_handler(NULL); | 
|---|
| 107 | return NULL; | 
|---|
| 108 | } | 
|---|
| 109 |  | 
|---|
| 110 | /********************************************************************* | 
|---|
| 111 | *              ?_set_new_mode@@YAHH@Z (MSVCRT.@) | 
|---|
| 112 | */ | 
|---|
| 113 | int MSVCRT__set_new_mode(int mode) | 
|---|
| 114 | { | 
|---|
| 115 | int old_mode; | 
|---|
| 116 | LOCK_HEAP; | 
|---|
| 117 | old_mode = MSVCRT_new_mode; | 
|---|
| 118 | MSVCRT_new_mode = mode; | 
|---|
| 119 | UNLOCK_HEAP; | 
|---|
| 120 | return old_mode; | 
|---|
| 121 | } | 
|---|
| 122 |  | 
|---|
| 123 | /********************************************************************* | 
|---|
| 124 | *              _callnewh (MSVCRT.@) | 
|---|
| 125 | */ | 
|---|
| 126 | int _callnewh(unsigned long size) | 
|---|
| 127 | { | 
|---|
| 128 | if(MSVCRT_new_handler) | 
|---|
| 129 | (*MSVCRT_new_handler)(size); | 
|---|
| 130 | return 0; | 
|---|
| 131 | } | 
|---|
| 132 |  | 
|---|
| 133 | /********************************************************************* | 
|---|
| 134 | *              _expand (MSVCRT.@) | 
|---|
| 135 | */ | 
|---|
| 136 | void* _expand(void* mem, MSVCRT_size_t size) | 
|---|
| 137 | { | 
|---|
| 138 | return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, mem, size); | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | /********************************************************************* | 
|---|
| 142 | *              _heapchk (MSVCRT.@) | 
|---|
| 143 | */ | 
|---|
| 144 | int _heapchk(void) | 
|---|
| 145 | { | 
|---|
| 146 | if (!HeapValidate( GetProcessHeap(), 0, NULL)) | 
|---|
| 147 | { | 
|---|
| 148 | MSVCRT__set_errno(GetLastError()); | 
|---|
| 149 | return _HEAPBADNODE; | 
|---|
| 150 | } | 
|---|
| 151 | return _HEAPOK; | 
|---|
| 152 | } | 
|---|
| 153 |  | 
|---|
| 154 | /********************************************************************* | 
|---|
| 155 | *              _heapmin (MSVCRT.@) | 
|---|
| 156 | */ | 
|---|
| 157 | int _heapmin(void) | 
|---|
| 158 | { | 
|---|
| 159 | if (!HeapCompact( GetProcessHeap(), 0 )) | 
|---|
| 160 | { | 
|---|
| 161 | if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) | 
|---|
| 162 | MSVCRT__set_errno(GetLastError()); | 
|---|
| 163 | return -1; | 
|---|
| 164 | } | 
|---|
| 165 | return 0; | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | /********************************************************************* | 
|---|
| 169 | *              _heapwalk (MSVCRT.@) | 
|---|
| 170 | */ | 
|---|
| 171 | int _heapwalk(_HEAPINFO* next) | 
|---|
| 172 | { | 
|---|
| 173 | PROCESS_HEAP_ENTRY phe; | 
|---|
| 174 |  | 
|---|
| 175 | LOCK_HEAP; | 
|---|
| 176 | phe.lpData = next->_pentry; | 
|---|
| 177 | phe.cbData = next->_size; | 
|---|
| 178 | phe.wFlags = next->_useflag == _USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0; | 
|---|
| 179 |  | 
|---|
| 180 | if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY && | 
|---|
| 181 | !HeapValidate( GetProcessHeap(), 0, phe.lpData )) | 
|---|
| 182 | { | 
|---|
| 183 | UNLOCK_HEAP; | 
|---|
| 184 | MSVCRT__set_errno(GetLastError()); | 
|---|
| 185 | return _HEAPBADNODE; | 
|---|
| 186 | } | 
|---|
| 187 |  | 
|---|
| 188 | do | 
|---|
| 189 | { | 
|---|
| 190 | if (!HeapWalk( GetProcessHeap(), &phe )) | 
|---|
| 191 | { | 
|---|
| 192 | UNLOCK_HEAP; | 
|---|
| 193 | if (GetLastError() == ERROR_NO_MORE_ITEMS) | 
|---|
| 194 | return _HEAPEND; | 
|---|
| 195 | MSVCRT__set_errno(GetLastError()); | 
|---|
| 196 | if (!phe.lpData) | 
|---|
| 197 | return _HEAPBADBEGIN; | 
|---|
| 198 | return _HEAPBADNODE; | 
|---|
| 199 | } | 
|---|
| 200 | } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE)); | 
|---|
| 201 |  | 
|---|
| 202 | UNLOCK_HEAP; | 
|---|
| 203 | next->_pentry = phe.lpData; | 
|---|
| 204 | next->_size = phe.cbData; | 
|---|
| 205 | next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? _USEDENTRY : _FREEENTRY; | 
|---|
| 206 | return _HEAPOK; | 
|---|
| 207 | } | 
|---|
| 208 |  | 
|---|
| 209 | /********************************************************************* | 
|---|
| 210 | *              _heapset (MSVCRT.@) | 
|---|
| 211 | */ | 
|---|
| 212 | int _heapset(unsigned int value) | 
|---|
| 213 | { | 
|---|
| 214 | int retval; | 
|---|
| 215 | _HEAPINFO heap; | 
|---|
| 216 |  | 
|---|
| 217 | memset( &heap, 0, sizeof(_HEAPINFO) ); | 
|---|
| 218 | LOCK_HEAP; | 
|---|
| 219 | while ((retval = _heapwalk(&heap)) == _HEAPOK) | 
|---|
| 220 | { | 
|---|
| 221 | if (heap._useflag == _FREEENTRY) | 
|---|
| 222 | memset(heap._pentry, value, heap._size); | 
|---|
| 223 | } | 
|---|
| 224 | UNLOCK_HEAP; | 
|---|
| 225 | return retval == _HEAPEND? _HEAPOK : retval; | 
|---|
| 226 | } | 
|---|
| 227 |  | 
|---|
| 228 | /********************************************************************* | 
|---|
| 229 | *              _heapadd (MSVCRT.@) | 
|---|
| 230 | */ | 
|---|
| 231 | int _heapadd(void* mem, MSVCRT_size_t size) | 
|---|
| 232 | { | 
|---|
| 233 | TRACE("(%p,%d) unsupported in Win32\n", mem,size); | 
|---|
| 234 | *MSVCRT__errno() = MSVCRT_ENOSYS; | 
|---|
| 235 | return -1; | 
|---|
| 236 | } | 
|---|
| 237 |  | 
|---|
| 238 | /********************************************************************* | 
|---|
| 239 | *              _msize (MSVCRT.@) | 
|---|
| 240 | */ | 
|---|
| 241 | MSVCRT_size_t _msize(void* mem) | 
|---|
| 242 | { | 
|---|
| 243 | long size = HeapSize(GetProcessHeap(),0,mem); | 
|---|
| 244 | if (size == -1) | 
|---|
| 245 | { | 
|---|
| 246 | WARN(":Probably called with non wine-allocated memory, ret = -1\n"); | 
|---|
| 247 | /* At least the Win32 crtdll/msvcrt also return -1 in this case */ | 
|---|
| 248 | } | 
|---|
| 249 | return size; | 
|---|
| 250 | } | 
|---|
| 251 |  | 
|---|
| 252 | /********************************************************************* | 
|---|
| 253 | *              calloc (MSVCRT.@) | 
|---|
| 254 | */ | 
|---|
| 255 | void* MSVCRT_calloc(MSVCRT_size_t size, MSVCRT_size_t count) | 
|---|
| 256 | { | 
|---|
| 257 | return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count ); | 
|---|
| 258 | } | 
|---|
| 259 |  | 
|---|
| 260 | /********************************************************************* | 
|---|
| 261 | *              free (MSVCRT.@) | 
|---|
| 262 | */ | 
|---|
| 263 | void MSVCRT_free(void* ptr) | 
|---|
| 264 | { | 
|---|
| 265 | dprintf(("MSVCRT_free %x ptr",ptr)); | 
|---|
| 266 | HeapFree(GetProcessHeap(),0,ptr); | 
|---|
| 267 | } | 
|---|
| 268 |  | 
|---|
| 269 | void* MSVCRT(memset)(void* ptr,int fill,MSVCRT(size_t) size) | 
|---|
| 270 | { | 
|---|
| 271 | dprintf(("MSVCRT_memset %x(%d bytes) with %d",ptr,size,fill)); | 
|---|
| 272 | return memset(ptr,fill,size); | 
|---|
| 273 | } | 
|---|
| 274 |  | 
|---|
| 275 |  | 
|---|
| 276 | void* MSVCRT(memcpy)(void* ptr,const void* ptr2,MSVCRT(size_t) size) | 
|---|
| 277 | { | 
|---|
| 278 | dprintf(("MSVCRT_memcpy %x->%x (%d bytes)",ptr2,ptr,size)); | 
|---|
| 279 | return memcpy(ptr,ptr2,size); | 
|---|
| 280 | } | 
|---|
| 281 |  | 
|---|
| 282 |  | 
|---|
| 283 | /********************************************************************* | 
|---|
| 284 | *                  malloc (MSVCRT.@) | 
|---|
| 285 | */ | 
|---|
| 286 | void* MSVCRT_malloc(MSVCRT_size_t size) | 
|---|
| 287 | { | 
|---|
| 288 | void *ret = HeapAlloc(GetProcessHeap(),0,size); | 
|---|
| 289 | dprintf(("MSVCRT_malloc of %d size returned %x",size,ret)); | 
|---|
| 290 | if (!ret) | 
|---|
| 291 | MSVCRT__set_errno(GetLastError()); | 
|---|
| 292 | return ret; | 
|---|
| 293 | } | 
|---|
| 294 |  | 
|---|
| 295 | /********************************************************************* | 
|---|
| 296 | *              realloc (MSVCRT.@) | 
|---|
| 297 | */ | 
|---|
| 298 | void* MSVCRT_realloc(void* ptr, MSVCRT_size_t size) | 
|---|
| 299 | { | 
|---|
| 300 | dprintf(("MSVCRT_realloc %x",ptr)); | 
|---|
| 301 | return HeapReAlloc(GetProcessHeap(), 0, ptr, size); | 
|---|
| 302 | } | 
|---|