Updated.
[wine] / dlls / msvcrt / heap.c
1 /*
2  * msvcrt.dll heap functions
3  *
4  * Copyright 2000 Jon Griffiths
5  *
6  * Note: Win32 heap operations are MT safe. We only lock the new
7  *       handler and non atomic heap operations
8  */
9
10 #include "msvcrt.h"
11
12 DEFAULT_DEBUG_CHANNEL(msvcrt);
13
14 /* MT */
15 extern CRITICAL_SECTION MSVCRT_heap_cs;
16 #define LOCK_HEAP      EnterCriticalSection(&MSVCRT_heap_cs)
17 #define UNLOCK_HEAP    LeaveCriticalSection(&MSVCRT_heap_cs)
18
19 /* heap function constants */
20 #define MSVCRT_HEAPEMPTY    -1
21 #define MSVCRT_HEAPOK       -2
22 #define MSVCRT_HEAPBADBEGIN -3
23 #define MSVCRT_HEAPBADNODE  -4
24 #define MSVCRT_HEAPEND      -5
25 #define MSVCRT_HEAPBADPTR   -6
26 #define MSVCRT_FREEENTRY    0
27 #define MSVCRT_USEDENTRY    1
28
29 typedef struct MSVCRT_heapinfo
30 {
31   int * _pentry;
32   size_t _size;
33   int    _useflag;
34 } MSVCRT_HEAPINFO;
35
36 typedef void (*MSVCRT_new_handler_func)(void);
37
38 static MSVCRT_new_handler_func MSVCRT_new_handler;
39 static int MSVCRT_new_mode;
40
41 /*********************************************************************
42  *              operator_new (MSVCRT.@)
43  */
44 void *__cdecl MSVCRT_operator_new(unsigned long size)
45 {
46   void *retval = HeapAlloc(GetProcessHeap(), 0, size);
47   TRACE("(%ld) returning %p\n", size, retval);
48   LOCK_HEAP;
49   if(retval && MSVCRT_new_handler)
50     (*MSVCRT_new_handler)();
51   UNLOCK_HEAP;
52   return retval;
53 }
54
55 /*********************************************************************
56  *              operator_delete (MSVCRT.@)
57  */
58 void __cdecl MSVCRT_operator_delete(void *mem)
59 {
60   TRACE("(%p)\n", mem);
61   HeapFree(GetProcessHeap(), 0, mem);
62 }
63
64
65 /*********************************************************************
66  *              ?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@)
67  */
68 MSVCRT_new_handler_func __cdecl MSVCRT__query_new_handler(void)
69 {
70   return MSVCRT_new_handler;
71 }
72
73
74 /*********************************************************************
75  *              ?_query_new_mode@@YAHXZ (MSVCRT.@)
76  */
77 int __cdecl MSVCRT__query_new_mode(void)
78 {
79   return MSVCRT_new_mode;
80 }
81
82 /*********************************************************************
83  *              ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@)
84  */
85 MSVCRT_new_handler_func __cdecl MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
86 {
87   MSVCRT_new_handler_func old_handler;
88   LOCK_HEAP;
89   old_handler = MSVCRT_new_handler;
90   MSVCRT_new_handler = func;
91   UNLOCK_HEAP;
92   return old_handler;
93 }
94
95 /*********************************************************************
96  *              ?_set_new_mode@@YAHH@Z (MSVCRT.@)
97  */
98 int __cdecl MSVCRT__set_new_mode(int mode)
99 {
100   int old_mode;
101   LOCK_HEAP;
102   old_mode = MSVCRT_new_mode;
103   MSVCRT_new_mode = mode;
104   UNLOCK_HEAP;
105   return old_mode;
106 }
107
108 /*********************************************************************
109  *              _expand (MSVCRT.@)
110  */
111 void *__cdecl MSVCRT__expand(void *mem, unsigned int size)
112 {
113   return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, mem, size);
114 }
115
116 /*********************************************************************
117  *              _heapchk (MSVCRT.@)
118  */
119 int __cdecl MSVCRT__heapchk(void)
120 {
121   if (!HeapValidate( GetProcessHeap(), 0, NULL))
122   {
123     MSVCRT__set_errno(GetLastError());
124     return MSVCRT_HEAPBADNODE;
125   }
126   return MSVCRT_HEAPOK;
127 }
128
129 /*********************************************************************
130  *              _heapmin (MSVCRT.@)
131  */
132 int __cdecl MSVCRT__heapmin(void)
133 {
134   if (!HeapCompact( GetProcessHeap(), 0 ))
135   {
136     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
137       MSVCRT__set_errno(GetLastError());
138     return -1;
139   }
140   return 0;
141 }
142
143 /*********************************************************************
144  *              _heapwalk (MSVCRT.@)
145  */
146 int __cdecl MSVCRT__heapwalk(MSVCRT_HEAPINFO *next)
147 {
148   PROCESS_HEAP_ENTRY phe;
149
150   LOCK_HEAP;
151   phe.lpData = next->_pentry;
152   phe.cbData = next->_size;
153   phe.wFlags = next->_useflag == MSVCRT_USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
154
155   if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
156       !HeapValidate( GetProcessHeap(), 0, phe.lpData ))
157   {
158     UNLOCK_HEAP;
159     MSVCRT__set_errno(GetLastError());
160     return MSVCRT_HEAPBADNODE;
161   }
162
163   do
164   {
165     if (!HeapWalk( GetProcessHeap(), &phe ))
166     {
167       UNLOCK_HEAP;
168       if (GetLastError() == ERROR_NO_MORE_ITEMS)
169          return MSVCRT_HEAPEND;
170       MSVCRT__set_errno(GetLastError());
171       if (!phe.lpData)
172         return MSVCRT_HEAPBADBEGIN;
173       return MSVCRT_HEAPBADNODE;
174     }
175   } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
176
177   UNLOCK_HEAP;
178   next->_pentry = phe.lpData;
179   next->_size = phe.cbData;
180   next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? MSVCRT_USEDENTRY : MSVCRT_FREEENTRY;
181   return MSVCRT_HEAPOK;
182 }
183
184 /*********************************************************************
185  *              _heapset (MSVCRT.@)
186  */
187 int __cdecl MSVCRT__heapset(unsigned int value)
188 {
189   int retval;
190   MSVCRT_HEAPINFO heap;
191
192   memset( &heap, 0, sizeof(MSVCRT_HEAPINFO) );
193   LOCK_HEAP;
194   while ((retval = MSVCRT__heapwalk(&heap)) == MSVCRT_HEAPOK)
195   {
196     if (heap._useflag == MSVCRT_FREEENTRY)
197       memset(heap._pentry, value, heap._size);
198   }
199   UNLOCK_HEAP;
200   return retval == MSVCRT_HEAPEND? MSVCRT_HEAPOK : retval;
201 }
202
203 /*********************************************************************
204  *              _msize (MSVCRT.@)
205  */
206 long __cdecl MSVCRT__msize(void *mem)
207 {
208   long size = HeapSize(GetProcessHeap(),0,mem);
209   if (size == -1)
210   {
211     WARN(":Probably called with non wine-allocated memory, ret = -1\n");
212     /* At least the Win32 crtdll/msvcrt also return -1 in this case */
213   }
214   return size;
215 }
216
217 /*********************************************************************
218  *              calloc (MSVCRT.@)
219  */
220 void *__cdecl MSVCRT_calloc(unsigned int size, unsigned int count)
221 {
222   return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
223 }
224
225 /*********************************************************************
226  *              free (MSVCRT.@)
227  */
228 void __cdecl MSVCRT_free(void *ptr)
229 {
230   HeapFree(GetProcessHeap(),0,ptr);
231 }
232
233 /*********************************************************************
234  *                  malloc (MSVCRT.@)
235  */
236 void * __cdecl MSVCRT_malloc(unsigned int size)
237 {
238   void *ret = HeapAlloc(GetProcessHeap(),0,size);
239   if (!ret)
240     MSVCRT__set_errno(GetLastError());
241   return ret;
242 }
243
244 /*********************************************************************
245  *              realloc (MSVCRT.@)
246  */
247 void *__cdecl MSVCRT_realloc(void *ptr, unsigned int size)
248 {
249   return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
250 }