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