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 <precomp.h>
25 #include <malloc.h>
26
27 #define MSVCRT_size_t size_t
28 #define MSVCRT_intptr_t intptr_t
29 #define MSVCRT_wchar_t wchar_t
30 #define MSVCRT__HEAPBADNODE _HEAPBADNODE
31 #define MSVCRT__HEAPOK _HEAPOK
32 #define MSVCRT__HEAPEND _HEAPEND
33 #define MSVCRT__FREEENTRY _FREEENTRY
34 #define MSVCRT__USEDENTRY _USEDENTRY
35 #define MSVCRT__HEAPBADBEGIN _HEAPBADBEGIN
36 #define MSVCRT_EINVAL EINVAL
37 #define MSVCRT_ENOSYS ENOSYS
38 #define MSVCRT_ENOMEM ENOMEM
39 #define MSVCRT_ERANGE ERANGE
40 #define MSVCRT__TRUNCATE _TRUNCATE
41 #define MSVCRT__heapinfo _heapinfo
42 #define MSVCRT__errno _errno
43 #define MSVCRT_calloc calloc
44 #define MSVCRT_malloc malloc
45 #define MSVCRT_realloc realloc
46 #define MSVCRT_free free
47 #define MSVCRT_memcpy_s memcpy_s
48 #define MSVCRT_memmove_s memmove_s
49 #define MSVCRT_strncpy_s strncpy_s
50 #define msvcrt_set_errno _dosmaperr
51
52 /* MT */
53 #define LOCK_HEAP _mlock( _HEAP_LOCK )
54 #define UNLOCK_HEAP _munlock( _HEAP_LOCK )
55
56 /* _aligned */
57 #define SAVED_PTR(x) ((void *)((DWORD_PTR)((char *)x - sizeof(void *)) & \
58 ~(sizeof(void *) - 1)))
59 #define ALIGN_PTR(ptr, alignment, offset) ((void *) \
60 ((((DWORD_PTR)((char *)ptr + alignment + sizeof(void *) + offset)) & \
61 ~(alignment - 1)) - offset))
62
63 #define SB_HEAP_ALIGN 16
64
65 static HANDLE heap, sb_heap;
66
67 typedef int (CDECL *MSVCRT_new_handler_func)(MSVCRT_size_t size);
68
69 static MSVCRT_new_handler_func MSVCRT_new_handler;
70 static int MSVCRT_new_mode;
71
72 /* FIXME - According to documentation it should be 8*1024, at runtime it returns 16 */
73 static unsigned int MSVCRT_amblksiz = 16;
74 /* FIXME - According to documentation it should be 480 bytes, at runtime default is 0 */
75 static MSVCRT_size_t MSVCRT_sbh_threshold = 0;
76
msvcrt_heap_alloc(DWORD flags,MSVCRT_size_t size)77 static void* msvcrt_heap_alloc(DWORD flags, MSVCRT_size_t size)
78 {
79 if(size < MSVCRT_sbh_threshold)
80 {
81 void *memblock, *temp, **saved;
82
83 temp = HeapAlloc(sb_heap, flags, size+sizeof(void*)+SB_HEAP_ALIGN);
84 if(!temp) return NULL;
85
86 memblock = ALIGN_PTR(temp, SB_HEAP_ALIGN, 0);
87 saved = SAVED_PTR(memblock);
88 *saved = temp;
89 return memblock;
90 }
91
92 return HeapAlloc(heap, flags, size);
93 }
94
msvcrt_heap_realloc(DWORD flags,void * ptr,MSVCRT_size_t size)95 static void* msvcrt_heap_realloc(DWORD flags, void *ptr, MSVCRT_size_t size)
96 {
97 if(sb_heap && ptr && !HeapValidate(heap, 0, ptr))
98 {
99 /* TODO: move data to normal heap if it exceeds sbh_threshold limit */
100 void *memblock, *temp, **saved;
101 MSVCRT_size_t old_padding, new_padding, old_size;
102
103 saved = SAVED_PTR(ptr);
104 old_padding = (char*)ptr - (char*)*saved;
105 old_size = HeapSize(sb_heap, 0, *saved);
106 if(old_size == -1)
107 return NULL;
108 old_size -= old_padding;
109
110 temp = HeapReAlloc(sb_heap, flags, *saved, size+sizeof(void*)+SB_HEAP_ALIGN);
111 if(!temp) return NULL;
112
113 memblock = ALIGN_PTR(temp, SB_HEAP_ALIGN, 0);
114 saved = SAVED_PTR(memblock);
115 new_padding = (char*)memblock - (char*)temp;
116
117 if(new_padding != old_padding)
118 memmove(memblock, (char*)temp+old_padding, old_size>size ? size : old_size);
119
120 *saved = temp;
121 return memblock;
122 }
123
124 return HeapReAlloc(heap, flags, ptr, size);
125 }
126
msvcrt_heap_free(void * ptr)127 static BOOL msvcrt_heap_free(void *ptr)
128 {
129 if(sb_heap && ptr && !HeapValidate(heap, 0, ptr))
130 {
131 void **saved = SAVED_PTR(ptr);
132 return HeapFree(sb_heap, 0, *saved);
133 }
134
135 return HeapFree(heap, 0, ptr);
136 }
137
msvcrt_heap_size(void * ptr)138 static MSVCRT_size_t msvcrt_heap_size(void *ptr)
139 {
140 if(sb_heap && ptr && !HeapValidate(heap, 0, ptr))
141 {
142 void **saved = SAVED_PTR(ptr);
143 return HeapSize(sb_heap, 0, *saved);
144 }
145
146 return HeapSize(heap, 0, ptr);
147 }
148
149 /*********************************************************************
150 * ??2@YAPAXI@Z (MSVCRT.@)
151 */
MSVCRT_operator_new(MSVCRT_size_t size)152 void* CDECL DECLSPEC_HOTPATCH MSVCRT_operator_new(MSVCRT_size_t size)
153 {
154 void *retval;
155 int freed;
156 MSVCRT_new_handler_func handler;
157
158 do
159 {
160 retval = msvcrt_heap_alloc(0, size);
161 if(retval)
162 {
163 TRACE("(%ld) returning %p\n", size, retval);
164 return retval;
165 }
166
167 LOCK_HEAP;
168 handler = MSVCRT_new_handler;
169 if(handler)
170 freed = (*handler)(size);
171 else
172 freed = 0;
173 UNLOCK_HEAP;
174 } while(freed);
175
176 TRACE("(%ld) out of memory\n", size);
177 #if _MSVCR_VER >= 80
178 throw_exception(EXCEPTION_BAD_ALLOC, 0, "bad allocation");
179 #endif
180 return NULL;
181 }
182
183
184 /*********************************************************************
185 * ??2@YAPAXIHPBDH@Z (MSVCRT.@)
186 */
MSVCRT_operator_new_dbg(MSVCRT_size_t size,int type,const char * file,int line)187 void* CDECL MSVCRT_operator_new_dbg(MSVCRT_size_t size, int type, const char *file, int line)
188 {
189 return MSVCRT_operator_new( size );
190 }
191
192
193 /*********************************************************************
194 * ??3@YAXPAX@Z (MSVCRT.@)
195 */
MSVCRT_operator_delete(void * mem)196 void CDECL DECLSPEC_HOTPATCH MSVCRT_operator_delete(void *mem)
197 {
198 TRACE("(%p)\n", mem);
199 msvcrt_heap_free(mem);
200 }
201
202
203 /*********************************************************************
204 * ?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@)
205 */
MSVCRT__query_new_handler(void)206 MSVCRT_new_handler_func CDECL MSVCRT__query_new_handler(void)
207 {
208 return MSVCRT_new_handler;
209 }
210
211
212 /*********************************************************************
213 * ?_query_new_mode@@YAHXZ (MSVCRT.@)
214 */
MSVCRT__query_new_mode(void)215 int CDECL MSVCRT__query_new_mode(void)
216 {
217 return MSVCRT_new_mode;
218 }
219
220 /*********************************************************************
221 * ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@)
222 */
MSVCRT__set_new_handler(MSVCRT_new_handler_func func)223 MSVCRT_new_handler_func CDECL MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
224 {
225 MSVCRT_new_handler_func old_handler;
226 LOCK_HEAP;
227 old_handler = MSVCRT_new_handler;
228 MSVCRT_new_handler = func;
229 UNLOCK_HEAP;
230 return old_handler;
231 }
232
233 /*********************************************************************
234 * ?set_new_handler@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
235 */
MSVCRT_set_new_handler(void * func)236 MSVCRT_new_handler_func CDECL MSVCRT_set_new_handler(void *func)
237 {
238 TRACE("(%p)\n",func);
239 MSVCRT__set_new_handler(NULL);
240 return NULL;
241 }
242
243 /*********************************************************************
244 * ?_set_new_mode@@YAHH@Z (MSVCRT.@)
245 */
MSVCRT__set_new_mode(int mode)246 int CDECL MSVCRT__set_new_mode(int mode)
247 {
248 int old_mode;
249 LOCK_HEAP;
250 old_mode = MSVCRT_new_mode;
251 MSVCRT_new_mode = mode;
252 UNLOCK_HEAP;
253 return old_mode;
254 }
255
256 /*********************************************************************
257 * _callnewh (MSVCRT.@)
258 */
_callnewh(MSVCRT_size_t size)259 int CDECL _callnewh(MSVCRT_size_t size)
260 {
261 int ret = 0;
262 MSVCRT_new_handler_func handler = MSVCRT_new_handler;
263 if(handler)
264 ret = (*handler)(size) ? 1 : 0;
265 return ret;
266 }
267
268 /*********************************************************************
269 * _expand (MSVCRT.@)
270 */
_expand(void * mem,MSVCRT_size_t size)271 void* CDECL _expand(void* mem, MSVCRT_size_t size)
272 {
273 return msvcrt_heap_realloc(HEAP_REALLOC_IN_PLACE_ONLY, mem, size);
274 }
275
276 /*********************************************************************
277 * _heapchk (MSVCRT.@)
278 */
_heapchk(void)279 int CDECL _heapchk(void)
280 {
281 if (!HeapValidate(heap, 0, NULL) ||
282 (sb_heap && !HeapValidate(sb_heap, 0, NULL)))
283 {
284 msvcrt_set_errno(GetLastError());
285 return MSVCRT__HEAPBADNODE;
286 }
287 return MSVCRT__HEAPOK;
288 }
289
290 /*********************************************************************
291 * _heapmin (MSVCRT.@)
292 */
_heapmin(void)293 int CDECL _heapmin(void)
294 {
295 if (!HeapCompact( heap, 0 ) ||
296 (sb_heap && !HeapCompact( sb_heap, 0 )))
297 {
298 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
299 msvcrt_set_errno(GetLastError());
300 return -1;
301 }
302 return 0;
303 }
304
305 /*********************************************************************
306 * _heapwalk (MSVCRT.@)
307 */
_heapwalk(struct MSVCRT__heapinfo * next)308 int CDECL _heapwalk(struct MSVCRT__heapinfo* next)
309 {
310 PROCESS_HEAP_ENTRY phe;
311
312 if (sb_heap)
313 FIXME("small blocks heap not supported\n");
314
315 LOCK_HEAP;
316 phe.lpData = next->_pentry;
317 phe.cbData = (DWORD)next->_size;
318 phe.wFlags = next->_useflag == MSVCRT__USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
319
320 if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
321 !HeapValidate( heap, 0, phe.lpData ))
322 {
323 UNLOCK_HEAP;
324 msvcrt_set_errno(GetLastError());
325 return MSVCRT__HEAPBADNODE;
326 }
327
328 do
329 {
330 if (!HeapWalk( heap, &phe ))
331 {
332 UNLOCK_HEAP;
333 if (GetLastError() == ERROR_NO_MORE_ITEMS)
334 return MSVCRT__HEAPEND;
335 msvcrt_set_errno(GetLastError());
336 if (!phe.lpData)
337 return MSVCRT__HEAPBADBEGIN;
338 return MSVCRT__HEAPBADNODE;
339 }
340 } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
341
342 UNLOCK_HEAP;
343 next->_pentry = phe.lpData;
344 next->_size = phe.cbData;
345 next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? MSVCRT__USEDENTRY : MSVCRT__FREEENTRY;
346 return MSVCRT__HEAPOK;
347 }
348
349 /*********************************************************************
350 * _heapset (MSVCRT.@)
351 */
_heapset(unsigned int value)352 int CDECL _heapset(unsigned int value)
353 {
354 int retval;
355 struct MSVCRT__heapinfo heap;
356
357 memset( &heap, 0, sizeof(heap) );
358 LOCK_HEAP;
359 while ((retval = _heapwalk(&heap)) == MSVCRT__HEAPOK)
360 {
361 if (heap._useflag == MSVCRT__FREEENTRY)
362 memset(heap._pentry, value, heap._size);
363 }
364 UNLOCK_HEAP;
365 return retval == MSVCRT__HEAPEND? MSVCRT__HEAPOK : retval;
366 }
367
368 /*********************************************************************
369 * _heapadd (MSVCRT.@)
370 */
_heapadd(void * mem,MSVCRT_size_t size)371 int CDECL _heapadd(void* mem, MSVCRT_size_t size)
372 {
373 TRACE("(%p,%ld) unsupported in Win32\n", mem,size);
374 *MSVCRT__errno() = MSVCRT_ENOSYS;
375 return -1;
376 }
377
378 /*********************************************************************
379 * _get_heap_handle (MSVCRT.@)
380 */
_get_heap_handle(void)381 MSVCRT_intptr_t CDECL _get_heap_handle(void)
382 {
383 return (MSVCRT_intptr_t)heap;
384 }
385
386 /*********************************************************************
387 * _msize (MSVCRT.@)
388 */
_msize(void * mem)389 MSVCRT_size_t CDECL _msize(void* mem)
390 {
391 MSVCRT_size_t size = msvcrt_heap_size(mem);
392 if (size == ~(MSVCRT_size_t)0)
393 {
394 WARN(":Probably called with non wine-allocated memory, ret = -1\n");
395 /* At least the Win32 crtdll/msvcrt also return -1 in this case */
396 }
397 return size;
398 }
399
400 #if _MSVCR_VER>=80
401 /*********************************************************************
402 * _aligned_msize (MSVCR80.@)
403 */
_aligned_msize(void * p,MSVCRT_size_t alignment,MSVCRT_size_t offset)404 size_t CDECL _aligned_msize(void *p, MSVCRT_size_t alignment, MSVCRT_size_t offset)
405 {
406 void **alloc_ptr;
407
408 if(!MSVCRT_CHECK_PMT(p)) return -1;
409
410 if(alignment < sizeof(void*))
411 alignment = sizeof(void*);
412
413 alloc_ptr = SAVED_PTR(p);
414 return _msize(*alloc_ptr)-alignment-sizeof(void*);
415 }
416 #endif
417
418 /*********************************************************************
419 * calloc (MSVCRT.@)
420 */
MSVCRT_calloc(MSVCRT_size_t count,MSVCRT_size_t size)421 void* CDECL DECLSPEC_HOTPATCH MSVCRT_calloc(MSVCRT_size_t count, MSVCRT_size_t size)
422 {
423 MSVCRT_size_t bytes = count*size;
424
425 if (size && bytes / size != count)
426 {
427 *MSVCRT__errno() = MSVCRT_ENOMEM;
428 return NULL;
429 }
430
431 return msvcrt_heap_alloc(HEAP_ZERO_MEMORY, bytes);
432 }
433
434 #if _MSVCR_VER>=140
435 /*********************************************************************
436 * _calloc_base (UCRTBASE.@)
437 */
_calloc_base(MSVCRT_size_t count,MSVCRT_size_t size)438 void* CDECL _calloc_base(MSVCRT_size_t count, MSVCRT_size_t size)
439 {
440 return MSVCRT_calloc(count, size);
441 }
442 #endif
443
444 /*********************************************************************
445 * free (MSVCRT.@)
446 */
MSVCRT_free(void * ptr)447 void CDECL DECLSPEC_HOTPATCH MSVCRT_free(void* ptr)
448 {
449 msvcrt_heap_free(ptr);
450 }
451
452 #if _MSVCR_VER>=140
453 /*********************************************************************
454 * _free_base (UCRTBASE.@)
455 */
_free_base(void * ptr)456 void CDECL _free_base(void* ptr)
457 {
458 msvcrt_heap_free(ptr);
459 }
460 #endif
461
462 /*********************************************************************
463 * malloc (MSVCRT.@)
464 */
MSVCRT_malloc(MSVCRT_size_t size)465 void* CDECL MSVCRT_malloc(MSVCRT_size_t size)
466 {
467 void *ret = msvcrt_heap_alloc(0, size);
468 if (!ret)
469 *MSVCRT__errno() = MSVCRT_ENOMEM;
470 return ret;
471 }
472
473 #if _MSVCR_VER>=140
474 /*********************************************************************
475 * _malloc_base (UCRTBASE.@)
476 */
_malloc_base(MSVCRT_size_t size)477 void* CDECL _malloc_base(MSVCRT_size_t size)
478 {
479 return MSVCRT_malloc(size);
480 }
481 #endif
482
483 /*********************************************************************
484 * realloc (MSVCRT.@)
485 */
MSVCRT_realloc(void * ptr,MSVCRT_size_t size)486 void* CDECL DECLSPEC_HOTPATCH MSVCRT_realloc(void* ptr, MSVCRT_size_t size)
487 {
488 if (!ptr) return MSVCRT_malloc(size);
489 if (size) return msvcrt_heap_realloc(0, ptr, size);
490 MSVCRT_free(ptr);
491 return NULL;
492 }
493
494 #if _MSVCR_VER>=140
495 /*********************************************************************
496 * _realloc_base (UCRTBASE.@)
497 */
_realloc_base(void * ptr,MSVCRT_size_t size)498 void* CDECL _realloc_base(void* ptr, MSVCRT_size_t size)
499 {
500 return MSVCRT_realloc(ptr, size);
501 }
502 #endif
503
504 #if _MSVCR_VER>=80
505 /*********************************************************************
506 * _recalloc (MSVCR80.@)
507 */
_recalloc(void * mem,MSVCRT_size_t num,MSVCRT_size_t size)508 void* CDECL _recalloc(void *mem, MSVCRT_size_t num, MSVCRT_size_t size)
509 {
510 MSVCRT_size_t old_size;
511 void *ret;
512
513 if(!mem)
514 return MSVCRT_calloc(num, size);
515
516 size = num*size;
517 old_size = _msize(mem);
518
519 ret = MSVCRT_realloc(mem, size);
520 if(!ret) {
521 *MSVCRT__errno() = MSVCRT_ENOMEM;
522 return NULL;
523 }
524
525 if(size>old_size)
526 memset((BYTE*)ret+old_size, 0, size-old_size);
527 return ret;
528 }
529 #endif
530
531 /*********************************************************************
532 * __p__amblksiz (MSVCRT.@)
533 */
__p__amblksiz(void)534 unsigned int* CDECL __p__amblksiz(void)
535 {
536 return &MSVCRT_amblksiz;
537 }
538
539 /*********************************************************************
540 * _get_sbh_threshold (MSVCRT.@)
541 */
_get_sbh_threshold(void)542 MSVCRT_size_t CDECL _get_sbh_threshold(void)
543 {
544 return MSVCRT_sbh_threshold;
545 }
546
547 /*********************************************************************
548 * _set_sbh_threshold (MSVCRT.@)
549 */
_set_sbh_threshold(MSVCRT_size_t threshold)550 int CDECL _set_sbh_threshold(MSVCRT_size_t threshold)
551 {
552 #ifdef _WIN64
553 return 0;
554 #else
555 if(threshold > 1016)
556 return 0;
557
558 if(!sb_heap)
559 {
560 sb_heap = HeapCreate(0, 0, 0);
561 if(!sb_heap)
562 return 0;
563 }
564
565 MSVCRT_sbh_threshold = (threshold+0xf) & ~0xf;
566 return 1;
567 #endif
568 }
569
570 /*********************************************************************
571 * _aligned_free (MSVCRT.@)
572 */
_aligned_free(void * memblock)573 void CDECL _aligned_free(void *memblock)
574 {
575 TRACE("(%p)\n", memblock);
576
577 if (memblock)
578 {
579 void **saved = SAVED_PTR(memblock);
580 MSVCRT_free(*saved);
581 }
582 }
583
584 /*********************************************************************
585 * _aligned_offset_malloc (MSVCRT.@)
586 */
_aligned_offset_malloc(MSVCRT_size_t size,MSVCRT_size_t alignment,MSVCRT_size_t offset)587 void * CDECL _aligned_offset_malloc(MSVCRT_size_t size, MSVCRT_size_t alignment, MSVCRT_size_t offset)
588 {
589 void *memblock, *temp, **saved;
590 TRACE("(%lu, %lu, %lu)\n", size, alignment, offset);
591
592 /* alignment must be a power of 2 */
593 if ((alignment & (alignment - 1)) != 0)
594 {
595 *MSVCRT__errno() = MSVCRT_EINVAL;
596 return NULL;
597 }
598
599 /* offset must be less than size */
600 if (offset && offset >= size)
601 {
602 *MSVCRT__errno() = MSVCRT_EINVAL;
603 return NULL;
604 }
605
606 /* don't align to less than void pointer size */
607 if (alignment < sizeof(void *))
608 alignment = sizeof(void *);
609
610 /* allocate enough space for void pointer and alignment */
611 temp = MSVCRT_malloc(size + alignment + sizeof(void *));
612
613 if (!temp)
614 return NULL;
615
616 /* adjust pointer for proper alignment and offset */
617 memblock = ALIGN_PTR(temp, alignment, offset);
618
619 /* Save the real allocation address below returned address */
620 /* so it can be found later to free. */
621 saved = SAVED_PTR(memblock);
622 *saved = temp;
623
624 return memblock;
625 }
626
627 /*********************************************************************
628 * _aligned_malloc (MSVCRT.@)
629 */
_aligned_malloc(MSVCRT_size_t size,MSVCRT_size_t alignment)630 void * CDECL _aligned_malloc(MSVCRT_size_t size, MSVCRT_size_t alignment)
631 {
632 TRACE("(%lu, %lu)\n", size, alignment);
633 return _aligned_offset_malloc(size, alignment, 0);
634 }
635
636 /*********************************************************************
637 * _aligned_offset_realloc (MSVCRT.@)
638 */
_aligned_offset_realloc(void * memblock,MSVCRT_size_t size,MSVCRT_size_t alignment,MSVCRT_size_t offset)639 void * CDECL _aligned_offset_realloc(void *memblock, MSVCRT_size_t size,
640 MSVCRT_size_t alignment, MSVCRT_size_t offset)
641 {
642 void * temp, **saved;
643 MSVCRT_size_t old_padding, new_padding, old_size;
644 TRACE("(%p, %lu, %lu, %lu)\n", memblock, size, alignment, offset);
645
646 if (!memblock)
647 return _aligned_offset_malloc(size, alignment, offset);
648
649 /* alignment must be a power of 2 */
650 if ((alignment & (alignment - 1)) != 0)
651 {
652 *MSVCRT__errno() = MSVCRT_EINVAL;
653 return NULL;
654 }
655
656 /* offset must be less than size */
657 if (offset >= size)
658 {
659 *MSVCRT__errno() = MSVCRT_EINVAL;
660 return NULL;
661 }
662
663 if (size == 0)
664 {
665 _aligned_free(memblock);
666 return NULL;
667 }
668
669 /* don't align to less than void pointer size */
670 if (alignment < sizeof(void *))
671 alignment = sizeof(void *);
672
673 /* make sure alignment and offset didn't change */
674 saved = SAVED_PTR(memblock);
675 if (memblock != ALIGN_PTR(*saved, alignment, offset))
676 {
677 *MSVCRT__errno() = MSVCRT_EINVAL;
678 return NULL;
679 }
680
681 old_padding = (char *)memblock - (char *)*saved;
682
683 /* Get previous size of block */
684 old_size = _msize(*saved);
685 if (old_size == -1)
686 {
687 /* It seems this function was called with an invalid pointer. Bail out. */
688 return NULL;
689 }
690
691 /* Adjust old_size to get amount of actual data in old block. */
692 if (old_size < old_padding)
693 {
694 /* Shouldn't happen. Something's weird, so bail out. */
695 return NULL;
696 }
697 old_size -= old_padding;
698
699 temp = MSVCRT_realloc(*saved, size + alignment + sizeof(void *));
700
701 if (!temp)
702 return NULL;
703
704 /* adjust pointer for proper alignment and offset */
705 memblock = ALIGN_PTR(temp, alignment, offset);
706
707 /* Save the real allocation address below returned address */
708 /* so it can be found later to free. */
709 saved = SAVED_PTR(memblock);
710
711 new_padding = (char *)memblock - (char *)temp;
712
713 /*
714 Memory layout of old block is as follows:
715 +-------+---------------------+-+--------------------------+-----------+
716 | ... | "old_padding" bytes | | ... "old_size" bytes ... | ... |
717 +-------+---------------------+-+--------------------------+-----------+
718 ^ ^ ^
719 | | |
720 *saved saved memblock
721
722 Memory layout of new block is as follows:
723 +-------+-----------------------------+-+----------------------+-------+
724 | ... | "new_padding" bytes | | ... "size" bytes ... | ... |
725 +-------+-----------------------------+-+----------------------+-------+
726 ^ ^ ^
727 | | |
728 temp saved memblock
729
730 However, in the new block, actual data is still written as follows
731 (because it was copied by MSVCRT_realloc):
732 +-------+---------------------+--------------------------------+-------+
733 | ... | "old_padding" bytes | ... "old_size" bytes ... | ... |
734 +-------+---------------------+--------------------------------+-------+
735 ^ ^ ^
736 | | |
737 temp saved memblock
738
739 Therefore, min(old_size,size) bytes of actual data have to be moved
740 from the offset they were at in the old block (temp + old_padding),
741 to the offset they have to be in the new block (temp + new_padding == memblock).
742 */
743 if (new_padding != old_padding)
744 memmove((char *)memblock, (char *)temp + old_padding, (old_size < size) ? old_size : size);
745
746 *saved = temp;
747
748 return memblock;
749 }
750
751 /*********************************************************************
752 * _aligned_realloc (MSVCRT.@)
753 */
_aligned_realloc(void * memblock,MSVCRT_size_t size,MSVCRT_size_t alignment)754 void * CDECL _aligned_realloc(void *memblock, MSVCRT_size_t size, MSVCRT_size_t alignment)
755 {
756 TRACE("(%p, %lu, %lu)\n", memblock, size, alignment);
757 return _aligned_offset_realloc(memblock, size, alignment, 0);
758 }
759
760 /*********************************************************************
761 * memmove_s (MSVCRT.@)
762 */
MSVCRT_memmove_s(void * dest,MSVCRT_size_t numberOfElements,const void * src,MSVCRT_size_t count)763 int CDECL MSVCRT_memmove_s(void *dest, MSVCRT_size_t numberOfElements, const void *src, MSVCRT_size_t count)
764 {
765 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count);
766
767 if(!count)
768 return 0;
769
770 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL;
771 if (!MSVCRT_CHECK_PMT(src != NULL)) return MSVCRT_EINVAL;
772 if (!MSVCRT_CHECK_PMT_ERR( count <= numberOfElements, MSVCRT_ERANGE )) return MSVCRT_ERANGE;
773
774 memmove(dest, src, count);
775 return 0;
776 }
777
778 #if _MSVCR_VER>=100
779 /*********************************************************************
780 * wmemmove_s (MSVCR100.@)
781 */
wmemmove_s(MSVCRT_wchar_t * dest,MSVCRT_size_t numberOfElements,const MSVCRT_wchar_t * src,MSVCRT_size_t count)782 int CDECL wmemmove_s(MSVCRT_wchar_t *dest, MSVCRT_size_t numberOfElements,
783 const MSVCRT_wchar_t *src, MSVCRT_size_t count)
784 {
785 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count);
786
787 if (!count)
788 return 0;
789
790 /* Native does not seem to conform to 6.7.1.2.3 in
791 * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1225.pdf
792 * in that it does not zero the output buffer on constraint violation.
793 */
794 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL;
795 if (!MSVCRT_CHECK_PMT(src != NULL)) return MSVCRT_EINVAL;
796 if (!MSVCRT_CHECK_PMT_ERR(count <= numberOfElements, MSVCRT_ERANGE)) return MSVCRT_ERANGE;
797
798 memmove(dest, src, sizeof(MSVCRT_wchar_t)*count);
799 return 0;
800 }
801 #endif
802
803 /*********************************************************************
804 * memcpy_s (MSVCRT.@)
805 */
MSVCRT_memcpy_s(void * dest,MSVCRT_size_t numberOfElements,const void * src,MSVCRT_size_t count)806 int CDECL MSVCRT_memcpy_s(void *dest, MSVCRT_size_t numberOfElements, const void *src, MSVCRT_size_t count)
807 {
808 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count);
809
810 if(!count)
811 return 0;
812
813 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL;
814 if (!MSVCRT_CHECK_PMT(src != NULL))
815 {
816 memset(dest, 0, numberOfElements);
817 return MSVCRT_EINVAL;
818 }
819 if (!MSVCRT_CHECK_PMT_ERR( count <= numberOfElements, MSVCRT_ERANGE ))
820 {
821 memset(dest, 0, numberOfElements);
822 return MSVCRT_ERANGE;
823 }
824
825 memmove(dest, src, count);
826 return 0;
827 }
828
829 #if _MSVCR_VER>=100
830 /*********************************************************************
831 * wmemcpy_s (MSVCR100.@)
832 */
wmemcpy_s(MSVCRT_wchar_t * dest,MSVCRT_size_t numberOfElements,const MSVCRT_wchar_t * src,MSVCRT_size_t count)833 int CDECL wmemcpy_s(MSVCRT_wchar_t *dest, MSVCRT_size_t numberOfElements,
834 const MSVCRT_wchar_t *src, MSVCRT_size_t count)
835 {
836 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count);
837
838 if (!count)
839 return 0;
840
841 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL;
842
843 if (!MSVCRT_CHECK_PMT(src != NULL)) {
844 memset(dest, 0, numberOfElements*sizeof(MSVCRT_wchar_t));
845 return MSVCRT_EINVAL;
846 }
847 if (!MSVCRT_CHECK_PMT_ERR(count <= numberOfElements, MSVCRT_ERANGE)) {
848 memset(dest, 0, numberOfElements*sizeof(MSVCRT_wchar_t));
849 return MSVCRT_ERANGE;
850 }
851
852 memmove(dest, src, sizeof(MSVCRT_wchar_t)*count);
853 return 0;
854 }
855 #endif
856
857 /*********************************************************************
858 * strncpy_s (MSVCRT.@)
859 */
MSVCRT_strncpy_s(char * dest,MSVCRT_size_t numberOfElements,const char * src,MSVCRT_size_t count)860 int CDECL MSVCRT_strncpy_s(char *dest, MSVCRT_size_t numberOfElements,
861 const char *src, MSVCRT_size_t count)
862 {
863 MSVCRT_size_t i, end;
864
865 TRACE("(%s %lu %s %lu)\n", dest, numberOfElements, src, count);
866
867 if(!count) {
868 if(dest && numberOfElements)
869 *dest = 0;
870 return 0;
871 }
872
873 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL;
874 if (!MSVCRT_CHECK_PMT(src != NULL)) return MSVCRT_EINVAL;
875 if (!MSVCRT_CHECK_PMT(numberOfElements != 0)) return MSVCRT_EINVAL;
876
877 if(count!=MSVCRT__TRUNCATE && count<numberOfElements)
878 end = count;
879 else
880 end = numberOfElements-1;
881
882 for(i=0; i<end && src[i]; i++)
883 dest[i] = src[i];
884
885 if(!src[i] || end==count || count==MSVCRT__TRUNCATE) {
886 dest[i] = '\0';
887 return 0;
888 }
889
890 MSVCRT_INVALID_PMT("dest[numberOfElements] is too small", MSVCRT_EINVAL);
891 dest[0] = '\0';
892 return MSVCRT_EINVAL;
893 }
894
msvcrt_init_heap(void)895 BOOL msvcrt_init_heap(void)
896 {
897 #ifdef __REACTOS__
898 heap = GetProcessHeap();
899 #else
900 heap = HeapCreate(0, 0, 0);
901 #endif
902 return heap != NULL;
903 }
904
msvcrt_destroy_heap(void)905 void msvcrt_destroy_heap(void)
906 {
907 HeapDestroy(heap);
908 if(sb_heap)
909 HeapDestroy(sb_heap);
910 }
911