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