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