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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 381 MSVCRT_intptr_t CDECL _get_heap_handle(void) 382 { 383 return (MSVCRT_intptr_t)heap; 384 } 385 386 /********************************************************************* 387 * _msize (MSVCRT.@) 388 */ 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 */ 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 */ 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 */ 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 */ 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 */ 456 void CDECL _free_base(void* ptr) 457 { 458 msvcrt_heap_free(ptr); 459 } 460 #endif 461 462 /********************************************************************* 463 * malloc (MSVCRT.@) 464 */ 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 */ 477 void* CDECL _malloc_base(MSVCRT_size_t size) 478 { 479 return MSVCRT_malloc(size); 480 } 481 #endif 482 483 /********************************************************************* 484 * realloc (MSVCRT.@) 485 */ 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 */ 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 */ 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 */ 534 unsigned int* CDECL __p__amblksiz(void) 535 { 536 return &MSVCRT_amblksiz; 537 } 538 539 /********************************************************************* 540 * _get_sbh_threshold (MSVCRT.@) 541 */ 542 MSVCRT_size_t CDECL _get_sbh_threshold(void) 543 { 544 return MSVCRT_sbh_threshold; 545 } 546 547 /********************************************************************* 548 * _set_sbh_threshold (MSVCRT.@) 549 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 905 void msvcrt_destroy_heap(void) 906 { 907 HeapDestroy(heap); 908 if(sb_heap) 909 HeapDestroy(sb_heap); 910 } 911