| 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 | }
|
|---|