Update the address of the Free Software Foundation.
[wine] / dlls / msvcrt / heap.c
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "mtdll.h"
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
29
30 /* MT */
31 #define LOCK_HEAP   _mlock( _HEAP_LOCK )
32 #define UNLOCK_HEAP _munlock( _HEAP_LOCK )
33
34
35 typedef void (*MSVCRT_new_handler_func)(unsigned long size);
36
37 static MSVCRT_new_handler_func MSVCRT_new_handler;
38 static int MSVCRT_new_mode;
39
40 /* FIXME - According to documentation it should be 8*1024, at runtime it returns 16 */ 
41 static unsigned int MSVCRT_amblksiz = 16;
42 /* FIXME - According to documentation it should be 480 bytes, at runtime default is 0 */
43 static size_t MSVCRT_sbh_threshold = 0;
44
45 /*********************************************************************
46  *              ??2@YAPAXI@Z (MSVCRT.@)
47  */
48 void* MSVCRT_operator_new(unsigned long size)
49 {
50   void *retval = HeapAlloc(GetProcessHeap(), 0, size);
51   TRACE("(%ld) returning %p\n", size, retval);
52   LOCK_HEAP;
53   if(!retval && MSVCRT_new_handler)
54     (*MSVCRT_new_handler)(size);
55   UNLOCK_HEAP;
56   return retval;
57 }
58
59 /*********************************************************************
60  *              ??3@YAXPAX@Z (MSVCRT.@)
61  */
62 void MSVCRT_operator_delete(void *mem)
63 {
64   TRACE("(%p)\n", mem);
65   HeapFree(GetProcessHeap(), 0, mem);
66 }
67
68
69 /*********************************************************************
70  *              ?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@)
71  */
72 MSVCRT_new_handler_func MSVCRT__query_new_handler(void)
73 {
74   return MSVCRT_new_handler;
75 }
76
77
78 /*********************************************************************
79  *              ?_query_new_mode@@YAHXZ (MSVCRT.@)
80  */
81 int MSVCRT__query_new_mode(void)
82 {
83   return MSVCRT_new_mode;
84 }
85
86 /*********************************************************************
87  *              ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@)
88  */
89 MSVCRT_new_handler_func MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
90 {
91   MSVCRT_new_handler_func old_handler;
92   LOCK_HEAP;
93   old_handler = MSVCRT_new_handler;
94   MSVCRT_new_handler = func;
95   UNLOCK_HEAP;
96   return old_handler;
97 }
98
99 /*********************************************************************
100  *              ?set_new_handler@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
101  */
102 MSVCRT_new_handler_func MSVCRT_set_new_handler(void *func)
103 {
104   TRACE("(%p)\n",func);
105   MSVCRT__set_new_handler(NULL);
106   return NULL;
107 }
108
109 /*********************************************************************
110  *              ?_set_new_mode@@YAHH@Z (MSVCRT.@)
111  */
112 int MSVCRT__set_new_mode(int mode)
113 {
114   int old_mode;
115   LOCK_HEAP;
116   old_mode = MSVCRT_new_mode;
117   MSVCRT_new_mode = mode;
118   UNLOCK_HEAP;
119   return old_mode;
120 }
121
122 /*********************************************************************
123  *              _callnewh (MSVCRT.@)
124  */
125 int _callnewh(unsigned long size)
126 {
127   if(MSVCRT_new_handler)
128     (*MSVCRT_new_handler)(size);
129   return 0;
130 }
131
132 /*********************************************************************
133  *              _expand (MSVCRT.@)
134  */
135 void* _expand(void* mem, MSVCRT_size_t size)
136 {
137   return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, mem, size);
138 }
139
140 /*********************************************************************
141  *              _heapchk (MSVCRT.@)
142  */
143 int _heapchk(void)
144 {
145   if (!HeapValidate( GetProcessHeap(), 0, NULL))
146   {
147     msvcrt_set_errno(GetLastError());
148     return MSVCRT__HEAPBADNODE;
149   }
150   return MSVCRT__HEAPOK;
151 }
152
153 /*********************************************************************
154  *              _heapmin (MSVCRT.@)
155  */
156 int _heapmin(void)
157 {
158   if (!HeapCompact( GetProcessHeap(), 0 ))
159   {
160     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
161       msvcrt_set_errno(GetLastError());
162     return -1;
163   }
164   return 0;
165 }
166
167 /*********************************************************************
168  *              _heapwalk (MSVCRT.@)
169  */
170 int _heapwalk(struct MSVCRT__heapinfo* next)
171 {
172   PROCESS_HEAP_ENTRY phe;
173
174   LOCK_HEAP;
175   phe.lpData = next->_pentry;
176   phe.cbData = next->_size;
177   phe.wFlags = next->_useflag == MSVCRT__USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
178
179   if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
180       !HeapValidate( GetProcessHeap(), 0, phe.lpData ))
181   {
182     UNLOCK_HEAP;
183     msvcrt_set_errno(GetLastError());
184     return MSVCRT__HEAPBADNODE;
185   }
186
187   do
188   {
189     if (!HeapWalk( GetProcessHeap(), &phe ))
190     {
191       UNLOCK_HEAP;
192       if (GetLastError() == ERROR_NO_MORE_ITEMS)
193          return MSVCRT__HEAPEND;
194       msvcrt_set_errno(GetLastError());
195       if (!phe.lpData)
196         return MSVCRT__HEAPBADBEGIN;
197       return MSVCRT__HEAPBADNODE;
198     }
199   } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
200
201   UNLOCK_HEAP;
202   next->_pentry = phe.lpData;
203   next->_size = phe.cbData;
204   next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? MSVCRT__USEDENTRY : MSVCRT__FREEENTRY;
205   return MSVCRT__HEAPOK;
206 }
207
208 /*********************************************************************
209  *              _heapset (MSVCRT.@)
210  */
211 int _heapset(unsigned int value)
212 {
213   int retval;
214   struct MSVCRT__heapinfo heap;
215
216   memset( &heap, 0, sizeof(heap) );
217   LOCK_HEAP;
218   while ((retval = _heapwalk(&heap)) == MSVCRT__HEAPOK)
219   {
220     if (heap._useflag == MSVCRT__FREEENTRY)
221       memset(heap._pentry, value, heap._size);
222   }
223   UNLOCK_HEAP;
224   return retval == MSVCRT__HEAPEND? MSVCRT__HEAPOK : retval;
225 }
226
227 /*********************************************************************
228  *              _heapadd (MSVCRT.@)
229  */
230 int _heapadd(void* mem, MSVCRT_size_t size)
231 {
232   TRACE("(%p,%d) unsupported in Win32\n", mem,size);
233   *MSVCRT__errno() = MSVCRT_ENOSYS;
234   return -1;
235 }
236
237 /*********************************************************************
238  *              _msize (MSVCRT.@)
239  */
240 MSVCRT_size_t _msize(void* mem)
241 {
242   long size = HeapSize(GetProcessHeap(),0,mem);
243   if (size == -1)
244   {
245     WARN(":Probably called with non wine-allocated memory, ret = -1\n");
246     /* At least the Win32 crtdll/msvcrt also return -1 in this case */
247   }
248   return size;
249 }
250
251 /*********************************************************************
252  *              calloc (MSVCRT.@)
253  */
254 void* MSVCRT_calloc(MSVCRT_size_t size, MSVCRT_size_t count)
255 {
256   return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
257 }
258
259 /*********************************************************************
260  *              free (MSVCRT.@)
261  */
262 void MSVCRT_free(void* ptr)
263 {
264   HeapFree(GetProcessHeap(),0,ptr);
265 }
266
267 /*********************************************************************
268  *                  malloc (MSVCRT.@)
269  */
270 void* MSVCRT_malloc(MSVCRT_size_t size)
271 {
272   void *ret = HeapAlloc(GetProcessHeap(),0,size);
273   if (!ret)
274     msvcrt_set_errno(GetLastError());
275   return ret;
276 }
277
278 /*********************************************************************
279  *              realloc (MSVCRT.@)
280  */
281 void* MSVCRT_realloc(void* ptr, MSVCRT_size_t size)
282 {
283   if (!ptr) return MSVCRT_malloc(size);
284   if (size) return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
285   MSVCRT_free(ptr);
286   return NULL;
287 }
288
289 /*********************************************************************
290  *              __p__amblksiz (MSVCRT.@)
291  */
292 unsigned int* __p__amblksiz(void)
293 {
294   return &MSVCRT_amblksiz;
295 }
296
297 /*********************************************************************
298  *              _get_sbh_threshold (MSVCRT.@)
299  */
300 size_t _get_sbh_threshold(void)
301 {
302   return MSVCRT_sbh_threshold;
303 }
304
305 /*********************************************************************
306  *              _set_sbh_threshold (MSVCRT.@)
307  */
308 int _set_sbh_threshold(size_t threshold)
309 {
310   if(threshold > 1016)
311      return 0;
312   else
313      MSVCRT_sbh_threshold = threshold;
314   return 1;
315 }